Change subdomain_data of form without recompiling

I understand this was possible in Fenics. How to go about this in the latest version of Fenicsx? In this example I would like to integrate on the right half of the square without recompiling my form:

from dolfinx import fem, mesh
import ufl
from mpi4py import MPI

els_side = 4
domain  = mesh.create_unit_square(MPI.COMM_WORLD, els_side, els_side)
left_els = mesh.locate_entities(domain, domain.topology.dim, lambda x : x[0] <= 0.5)
right_els = mesh.locate_entities(domain, domain.topology.dim, lambda x : x[0] >= 0.5)

V = fem.functionspace(domain, ("Lagrange", 1),)

v = ufl.TestFunction(V)
dV = ufl.dx(subdomain_data=[(1, left_els)])
l_ufl = v * dV(1)
l_com = fem.form(l_ufl)
L = fem.assemble_vector(l_com)
print(L.array)

The best way of updating subdomain data without re-compilation is quite explicit, and found with dolfinx.fem.compile_form and dolfinx.fem.create_form, as outlined in: FEniCS release notes | FEniCS Project

If you do not like the implicitness, note that dolfinx.fem.form doesn’t recompile code if it can find the kernel in the cache-directory, and the only additional cost is cache-lookup.

1 Like

Thank you. Here is the completed example code:

  els_side = 4
  domain  = mesh.create_unit_square(MPI.COMM_WORLD, els_side, els_side)
  left_els = mesh.locate_entities(domain, domain.topology.dim, lambda x : x[0] <= 0.5)
  right_els = mesh.locate_entities(domain, domain.topology.dim, lambda x : x[0] >= 0.5)

  V = fem.functionspace(domain, ("Lagrange", 1),)

  v = ufl.TestFunction(V)
  l_ufl = v * ufl.dx(1)

  compiled_form = fem.compile_form(
          MPI.COMM_WORLD, l_ufl, form_compiler_options={"scalar_type": np.float64}
  )

  lform = fem.create_form(compiled_form, [V],
                         mesh=domain,
                         subdomains={fem.IntegralType.cell : [(1, left_els)]},
                         coefficient_map={},
                         constant_map={})
  rform = fem.create_form(compiled_form, [V],
                         mesh=domain,
                         subdomains={fem.IntegralType.cell : [(1, right_els)]},
                         coefficient_map={},
                         constant_map={})

  L_left = fem.assemble_vector(lform)
  L_right = fem.assemble_vector(rform)