Compile a form with ufl.Coefficients

I would like to compile a form and provide the functions to be assembled later on at assembly time. Is this possible? I read from the ufl documentation that I should use Coefficient but I can’t compile a form with coefficients.

MWE:

from dolfinx import fem, mesh, cpp
import ufl
from mpi4py import MPI
import numpy as np

comm = MPI.COMM_WORLD
rank = comm.Get_rank()

points_side = 4
domain = mesh.create_unit_square(comm, points_side, points_side,
                               mesh.CellType.quadrilateral,
                               )
v = fem.functionspace(domain, ("Lagrange", 1))
f   = fem.Function(v)
c = ufl.Coefficient(v) # will be f later on
l_ufl = c*c*ufl.dx
l = fem.form(l_ufl) # AttributeError: 'Coefficient' object has no attribute '_cpp_object'

This is currently being worked on in Data independent form compilation for Python interface by jorgensd · Pull Request #3263 · FEniCS/dolfinx · GitHub

For the time being, just use f instead of c, and update the values stored in f later on in the code.

1 Like

I am trying to use the feature since the branch has been merged. The example provided by @dokken during implementation doesn’t run anymore. Where can I find examples?

EDIT: I could write an example by reading one of the tests. The only awkward thing is that the Python wrapper of the function space can’t be passed directly:

from dolfinx import fem, mesh, cpp
import ufl
from mpi4py import MPI
import numpy as np

comm = MPI.COMM_WORLD
rank = comm.Get_rank()

points_side = 4
domain = mesh.create_unit_square(comm, points_side, points_side,
                               mesh.CellType.quadrilateral,
                               )
v = fem.functionspace(domain, ("Lagrange", 1))
f   = fem.Function(v)
c = ufl.Coefficient(v) # will be f later on
v = ufl.TrialFunction(v)
l_ufl = c*v*ufl.dx

l_compiled = fem.compile_form(MPI.COMM_WORLD, l_ufl)
l_form     = fem.create_form(l_compiled, [v.ufl_function_space()], domain, {}, {c: f}, {})

EDIT2: It seems that fem.Constants have to be provided in the constants map:

from dolfinx import fem, mesh, cpp
import ufl
from mpi4py import MPI
import numpy as np

comm = MPI.COMM_WORLD
rank = comm.Get_rank()

points_side = 2
domain = mesh.create_unit_square(comm, points_side, points_side,
                               mesh.CellType.quadrilateral,
                               )
V = fem.functionspace(domain, ("Lagrange", 1))

rho = fem.Constant(domain, float(1))
cp  = fem.Constant(domain, float(1))
u   = fem.Function(V)
uc = ufl.Coefficient(V)
v = ufl.TrialFunction(V)
a_ufl = rho*cp*uc*v*ufl.dx
a_ufl = ufl.derivative(a_ufl, uc)

a_compiled = fem.compile_form(MPI.COMM_WORLD, a_ufl)
a_form     = fem.create_form(a_compiled, [v.ufl_function_space(),v.ufl_function_space()], domain, {}, {uc: u}, {rho:rho,cp:cp})

A = fem.assemble_matrix(a_form)