Extract dof index on different cell-subdomains

Hi, I am looking for extracting the dofs index on each subdomain (divided according to geometry coordinates, or partitioned by METIS in mpirun), so I can probably assemble sub-block matrix by looking into entries of original big matrix. Finally additive Schwarz preconditioner can be applied.
(R1 and R2 after permutation according to dof sequence are what im trying to get, figure1 is a example for 1d case when dofs are arranged sequentially)
1646664708(1)

1646664633(1)

1646664662(1)

I created a UnitSquare with celltag 1 when x<=0.5 and 2 when x>=0.5. I tried assemble the matrix in cases that integral with dx(1), dx(2) or both, but matrix patterns are same.

import dolfinx
import numpy as np
import matplotlib.pyplot as plt
import ufl
from mpi4py import MPI
from dolfinx import mesh

msh = mesh.create_unit_square(MPI.COMM_WORLD, 4, 4, cell_type = mesh.CellType.quadrilateral)
tdim = msh.topology.dim

# cell tag
num_cells = msh.topology.index_map(tdim).size_local + \
            msh.topology.index_map(tdim).num_ghosts

marker1 = lambda x: x[0]<=0.5+1e-7
indices1 = mesh.locate_entities(msh, 2, marker1)
marker2 = lambda x: x[0]>=0.5-1e-7
indices2 = mesh.locate_entities(msh, 2, marker2)

cell_marker = np.zeros(num_cells, dtype=np.int32)
cell_marker[indices1] = 1
cell_marker[indices2] = 2
cell_tag = dolfinx.mesh.MeshTags(msh, dim=2, indices=np.arange(num_cells),
                                         values=cell_marker)

dx = ufl.Measure('dx', subdomain_data=cell_tag, domain=msh)
V = dolfinx.fem.FunctionSpace(msh,("CG",1))
uD = dolfinx.fem.Function(V)   
uD.interpolate(lambda x: x[0]-x[0]+1)
u,v = ufl.TrialFunction(V), ufl.TestFunction(V)

msh.topology.create_connectivity(tdim-1, tdim)
boundary_facets =  np.flatnonzero(dolfinx.mesh.compute_boundary_facets(msh.topology)) # substitutive: facet_marker + np.where   
boundary_dofs = dolfinx.fem.locate_dofs_topological(V, tdim-1, boundary_facets)
bc = dolfinx.fem.dirichletbc(uD, boundary_dofs)
bcs = [bc]

a1 = ufl.inner(u,v) * dx(1) 
a2 = ufl.inner(u,v) * dx(2)
a = ufl.inner(u,v) * dx(1) + ufl.inner(u,v) * dx(2)
a_block = dolfinx.fem.form([[a1,None], [None,a2]])

A1 = dolfinx.fem.petsc.assemble_matrix(dolfinx.fem.form(a1), bcs=bcs)
A1.assemble()
A2 = dolfinx.fem.petsc.assemble_matrix(dolfinx.fem.form(a2), bcs=bcs)
A2.assemble()
A = dolfinx.fem.petsc.assemble_matrix(dolfinx.fem.form(a), bcs=bcs)
A.assemble()
A_block = dolfinx.fem.petsc.assemble_matrix_block(a_block, bcs=bcs)
A_block.assemble()

print('norm:',A1.norm(),A2.norm(),A.norm(),A_block.norm())
Matrix1 = np.real(A1.getValues(range(A1.getSize()[0]), range(A1.getSize()[1])))
Matrix2 = np.real(A1.getValues(range(A2.getSize()[0]), range(A2.getSize()[1])))
Matrix = np.real(A1.getValues(range(A.getSize()[0]), range(A.getSize()[1])))
Matrix_block = np.real(A_block.getValues(range(A_block.getSize()[0]), range(A_block.getSize()[1])))

fig, axs = plt.subplots(2,2)
fig.set_size_inches(15,15)
plt.subplot(2,2,1)
plt.spy(Matrix1)
plt.subplot(2,2,2)
plt.spy(Matrix2)
plt.subplot(2,2,3)
plt.spy(Matrix)
plt.subplot(2,2,4)
plt.spy(Matrix_block)


Why matrix patterns are same after assembling? I must have misunderstood the function of assemble_matrix(). And how to achieve my goal (extrct dof index(different to mesh.dofmap when fem order>1) and assemble subdomains into a block diagnol form)? Great thanks.

You had some typos in your code extracting matrix data;

should be

Matrix1 = np.real(A1.getValues(range(A1.getSize()[0]), range(A1.getSize()[1])))
Matrix2 = np.real(A2.getValues(range(A2.getSize()[0]), range(A2.getSize()[1])))
Matrix = np.real(A.getValues(range(A.getSize()[0]), range(A.getSize()[1])))
Matrix_block = np.real(A_block.getValues(
    range(A_block.getSize()[0]), range(A_block.getSize()[1])))

which gives the picture:

1 Like

And it is a lot easier to spot the structure if you do skewed split, say at 0.3


def marker1(x): return x[0] <= 0.3+1e-7


indices1 = mesh.locate_entities(msh, 2, marker1)
def marker2(x): return x[0] >= 0.3-1e-7

giving

1 Like

Thanks Dokken. Skewed split does give a easier spot.