I’ve been following the development of scifem, specifically for using “real” type elements and function spaces from Legacy Dolfin.
Currently, it appears that mixed spaces involving scifem real spaces must be defined using the ufl.MixedFunctionSpace syntax:
W = ufl.MixedFunctionSpace(V, R)
Our existing framework (currently built on dolfinx v0.9.0) relies heavily on the MixedElement approach for defining and splitting spaces:
mixed_element = basix.ufl.mixed_element([real_element, lagrange_element])
W = dolfinx.fem.functionspace(mesh, mixed_element)`
My questions:
Is there currently a way to use scifem real elements within a standard basix.ufl.mixed_element (or similar) ?
If not, are there plans to support this?
Avoiding a full refactor from MixedElement to MixedFunctionSpace would be ideal for our workflow, since our current splitting logic is built around the former. Any advice or insight on the roadmap is greatly appreciated!
A support through basix.ufl.mixed_element is not planned, for many reasons:
The real element is a very special element, it shares the same basis functions as a DG-0 element, but with global support (and a single degree of freedom). This is not trivial to get through the basix->ufl->ffcx->dolfinx stack. I’d of course like to move the real element into DOLFINx (as that is where I believe it should exist, not basix. But I haven’t found much support from the other developers for this).
Furthermore, use basix.ufl.mixed_element is very bad (memory wise) for problems where there isn’t coupling between all components (i.e. every trial function for each subspace interacts with every test function from the other sub-elements. This is illustrated in the comment: Only used mixed function spaces by jhdark · Pull Request #1042 · festim-dev/FESTIM · GitHub
Using ufl.MixedFunctionSpace is the proper, scalable way of doing blocked problems.
Changing from basix.ufl.mixed_element to ufl.MixedFunctionSpace should not be to hard, as v0.10.0 introduces NonlinearProblem and LinearProblem for forms made through this constructor, using ufl.extract_blocks(a), ufl.extract_blocks(L), ufl.extract_blocks(F) on the various blocked problems.