-
Notifications
You must be signed in to change notification settings - Fork 167
Support MatIS and BDDC #4405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release
Are you sure you want to change the base?
Support MatIS and BDDC #4405
Conversation
firedrake/assemble.py
Outdated
if mat_type == "is": | ||
rlgmap = unghosted_lgmap(sparsity._dsets[0].lgmap, test.function_space()) | ||
clgmap = unghosted_lgmap(sparsity._dsets[1].lgmap, trial.function_space()) | ||
sparsity._lgmaps = (rlgmap, clgmap) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This encodes the boundary conditions into the definition of the matrix, which is a bit bizarre. Why can't MATIS set lgmaps after the fact?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not encode BCs, just the removal of repeated ghost dofs. This is the correct way of using MatIS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way we handle BCs on matrices requires changing the LGmap after creating the matrix. This is not possible for a MatIS, as the LGMap is what defines it. If you change the LGMap then the matrix is destroyed.
For MatIS, BCs are never imposed on the LGMap. Instead we assemble the matrix without BCs, and we zero out the BC rows and columns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a bunch of the indexing is wrong when constructing the masked lgmaps?
firedrake/assemble.py
Outdated
depth = mesh_dm.getDepth() | ||
start, end = mesh_dm.getDepthStratum(depth) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AKA getHeightStratum(0)
firedrake/assemble.py
Outdated
continue | ||
off = section.getOffset(p) | ||
# Local indices within W | ||
W_indices = slice(block_size * off, block_size * (off + dof)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If block
is True
and lgmap
has block_size > 1
then this produces out of bounds indices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or conversely, if this is a mixed space where one component has block size > 1, then this masks out dofs even when running on a single process (which seems wrong).
firedrake/assemble.py
Outdated
W_indices = slice(block_size * off, block_size * (off + dof)) | ||
own.extend(W_local_ises_indices[W_indices]) | ||
|
||
mask = numpy.setdiff1d(range(len(lgmap.indices)), own) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're trying to mask out those entries in lgmap.indices
which belong to dofs that are not reachable from owned cells?
I think for a non-mixed space, this is (if block=True
):
cmap = V.cell_node_map()
mask = np.setdiff1d(
cmap.values_with_halo[cmap.iterset.size:],
cmap.values[:cmap.iterset.size],
)
For a mixed space, you need to index through to local_ises
, I think like this?
mask_pieces = []
for i, W in enumerate(V):
iset = V.dof_dset.local_ises[i]
cmap = W.cell_node_map()
to_mask = np.setdiff1d(cmap.values_with_halo[cmap.iterset.size:], cmap.values[:cmap.iterset.size])
bs = iset.block_size
if bs > 1:
to_mask = np.concatenate([i + bs * to_mask for i in range(bs)])
mask_pieces.append(iset.indices[to_mask])
mask = np.concatenate(mask_pieces)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cell_node_map
is not defined for extruded meshes, but also there is no DM for extruded. The correct thing is to execute a pyop2 kernel that visits only the dofs that are reachable from owned cells.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only VectorElements
or TensorElements
can have blocksize != 1
. Any MixedElement
has blocksize = 1
@@ -1366,6 +1369,18 @@ def _make_sparsity(test, trial, mat_type, sub_mat_type, maps_and_regions): | |||
except SparsityFormatError: | |||
raise ValueError("Monolithic matrix assembly not supported for systems " | |||
"with R-space blocks") | |||
|
|||
# TODO reconstruct dof_dset with the unghosted lgmap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ksagiyam is it possible to get a RestrictedFunctionSpace
with the unghosted FunctionSpace
(the space that corresponds to DistributedMeshOverlapType.None
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, if I reconstruct the FunctionSpace with the mesh without the overlap, would I get consistent dof orderings? How do I recover the mesh without overlap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can make a RestrictedFunctionSpace
with boundary_set=ghost entities
.
DoF ordering on each entity is the same only for CG and DG spaces (assuming that cone orderings are preserved). Otherwise DoFs depend on the global vertex numbers, which are arbitrary.
I think what we want is to be able to pass ignore_halos=True
to op2.Sparsity
and have op2.DataSet.lgmap
(and similar) return the correct lgmap in the first place depending on the value of ignore_halos
?
cleanup test
…e into pbrubeck/matis
cf36ddc
to
fb11865
Compare
fb11865
to
6e30284
Compare
06d250b
to
68fb7aa
Compare
76c9a91
to
f4a86f7
Compare
f4a86f7
to
c715954
Compare
a929a79
to
6b7d89e
Compare
bsize=1, | ||
comm=self.comm) | ||
if self.mat_type == "is": | ||
# FIXME monolithic lgmaps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pbrubeck Is this still broken? We can do mixed Poisson H(div) x L2 if we have monolithic l2gmaps
Description
Support
assemble(a, mat_type="is")