Matrix construction question using Scifem real space

Good day everyone!
I am trying to understand the assembly process used in the real function space example. For example, in the following code:

bcs = []
main_assembly = False
try:
    b = dolfinx.fem.petsc.assemble_vector_block(L_compiled, a_compiled, bcs=bcs)
except AttributeError:
    main_assembly = True
    b = dolfinx.fem.petsc.assemble_vector(L_compiled, kind="mpi")
    apply_lifting_and_set_bc(b, a_compiled, bcs=bcs)
uh = dolfinx.fem.Function(V, name="u")

if main_assembly:
    # We start by inserting the value in the real space
    rh = dolfinx.fem.Function(R)
    rh.x.array[0] = h
    # Next we need to add this value to the existing right hand side vector.
    # Therefore we create assign 0s to the primal space
    b_real_space = b.duplicate()
    uh.x.array[:] = 0
    # Transfer the data to `b_real_space`
    dolfinx.fem.petsc.assign([uh, rh], b_real_space)
    # And accumulate the values in the right hand side vector
    b.axpy(1, b_real_space)
    # We destroy the temporary work vector after usage
    b_real_space.destroy()
else:
    from dolfinx.cpp.la.petsc import scatter_local_vectors, get_local_vectors
    if Version(dolfinx.__version__) < Version("0.9.0"):
        maps = [(V.dofmap.index_map, V.dofmap.index_map_bs), (R.dofmap.index_map, R.dofmap.index_map_bs)]
    else:
        maps = [(Wi.dofmap.index_map, Wi.dofmap.index_map_bs) for Wi in W.ufl_sub_spaces()]

    b_local = get_local_vectors(b, maps)
    b_local[1][:] = h
    scatter_local_vectors(
            b,
            b_local,
            maps,
        )
    b.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)

My question is, what are the try/except blocks doing? I am at a loss trying to understand the purpose of these tests or how they work. Is it because the matrix/vector assembly needs to be different depending on where the extra DoFs resulting from the real space get allocated in the MPI environment?

I would be grateful for a brief explanation or a reference. Cheers!

The API of DOLFINx changed between v0.9 and v0.10.
main_assembly here indicates that we are on v0.10.0.
I’ll update the example to reflect this.

If I understand your response, DOLFINx versions 0.9 and lower do not need to use this partitioning?

I’ve updated the documentation to reflect it:Real function spaces — scifem

if Version(dolfinx.__version__) < Version("0.10.0"):
    A = dolfinx.fem.petsc.assemble_matrix_block(a_compiled)
else:
    A = dolfinx.fem.petsc.assemble_matrix(a_compiled)
A.assemble()
if Version(dolfinx.__version__) < Version("0.10.0"):
    b = dolfinx.fem.petsc.assemble_vector_block(L_compiled, a_compiled, bcs=bcs)
else:
    b = dolfinx.fem.petsc.assemble_vector(L_compiled, kind="mpi")
    apply_lifting_and_set_bc(b, a_compiled, bcs=bcs)

and

1 Like

Great! That clears things up alot! Thanks.