How to operate on a fem.Function and maintain type/attributes without interpolating?

Hello,

Quick question here. I want to operate on a fem.Function of a vector function space, like matrix multiplication, and return a function in the same space. A similar question is https://fenicsproject.discourse.group/t/dolfinx-fem-function-function-add-with-dolfinx-fem-function-function/9328, however, it was a simple addition operation of another function or interpolation. I have a simple example below, and I’d like for it to work without interpolation, if possible.

Thank you.

from dolfinx import mesh, fem
import ufl

nx, ny = 10,10
domain = mesh.create_rectangle(comm=MPI.COMM_WORLD, points=((-1., -1.), (1., 1.)),n=(nx, ny), cell_type=mesh.CellType.triangle)

# Vector function space
W = fem.VectorFunctionSpace(domain, ("CG",1), dim = 4)

# create a function
u1 = fem.Function(W)

# create a function modified from u1
u2 = ufl.Identity(4)*u1 # <--- Returns a different type than u1

# try to access u2's DOFs... Attribute error
u2.x.array

The above returns the error

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[24], line 15
     12 u2 = ufl.Identity(4)*u1 # <--- Returns a different type than u1
     14 # try to access u2's DOFs
---> 15 u2.x.array

AttributeError: 'ComponentTensor' object has no attribute 'x'

Note that

Is a ufl-expression. To map a UFL expression to a function space, you need to use interpolate.
Specifically, you need to use the u2expr=dolfinx.fem.Expression(u2, W.element.interpolation_points())
and
u3 = Function(W)
u3.interpolate(u2expr).

Is there a specific reason for trying to avoid interpolation?

And what is the actual matrix you want to use?

Thank you. I want to avoid interpolating because I do not want to lose any information/accuracy, and I do not know enough about *.interpolate() to know if that will happen.

The actual matrix is a change of variables matrix. So it would be a function of combinations of a,b,c,d = ufl.split(u1).

If your matrix is a function of a,b,c,d then each component will be a product of aa,ab, ac, ba, b*b, etc.
This function is in a higher function space than your original function, and thus it should either:

  1. be kept as an ufl expression, and sent into the appropriate variational form.
  2. interpolated into a higher order function space, where these products are included.

In general, you choose the accuracy of your interpolation, as you can chose the space to interpolate into.