Test if a subspace

Hi all!

I’m trying to determine if a function space is a subspace for a wrapper that I’m writing. My current method is to run a try block searching for a RunTimeError on the the collapse() function. Is there another attribute available though the python API I could use?

MWE:

import dolfinx 
import basix
from mpi4py import MPI

def is_subspace(space):
    try:
        space.collapse()
        return True
    except RuntimeError as e:
        if "Function space is not a subspace" in str(e):
            return False
        else:
            raise

# Define mesh
mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 20, 20, dolfinx.mesh.CellType.quadrilateral)

# Define poly, quad, and mixed elements
PE = basix.ufl.element('CG', mesh.basix_cell(), degree=1)
QE = basix.ufl.element('CG', mesh.basix_cell(), degree=1, shape=(mesh.topology.dim,))
ME = basix.ufl.mixed_element([QE, PE])

# Define function spaces
V = dolfinx.fem.functionspace(mesh, ME)
V_subspace = V.sub(0)
W =  dolfinx.fem.functionspace(mesh, PE)

# Check if the space is a subspace of a mixed function space
print(is_subspace(V_subspace)) # ---> Returns true
print(is_subspace(W))  # ---> Returns false

I think you can use the V.component() (dolfinx.fem — DOLFINx 0.9.0 documentation) to determine this, i.e.

import dolfinx
import basix
from mpi4py import MPI


def is_subspace(space):
    if len(space.component()) == 0:
        return False
    else:
        return True


# Define mesh
mesh = dolfinx.mesh.create_unit_square(
    MPI.COMM_WORLD, 20, 20, dolfinx.mesh.CellType.quadrilateral
)

# Define poly, quad, and mixed elements
PE = basix.ufl.element("CG", mesh.basix_cell(), degree=1)
QE = basix.ufl.element("CG", mesh.basix_cell(), degree=1, shape=(mesh.topology.dim,))
ME = basix.ufl.mixed_element([QE, PE])

# Define function spaces
V = dolfinx.fem.functionspace(mesh, ME)
V_subspace = V.sub(0)
W = dolfinx.fem.functionspace(mesh, PE)
W_subspace = V.sub(1)
V1 = V.sub(0).sub(1)

V1_collapsed, _ = V1.collapse()

assert is_subspace(V_subspace)
assert is_subspace(W_subspace)
assert not is_subspace(V)
assert is_subspace(V1)
assert not is_subspace(V1_collapsed)