Skip to content

Commit 4655a39

Browse files
committed
RobustTransferManager
1 parent a8a36d9 commit 4655a39

12 files changed

Lines changed: 502 additions & 21 deletions

File tree

firedrake/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ def init_petsc():
102102
NonNestedHierarchy, SemiCoarsenedExtrudedHierarchy, SubmeshHierarchy,
103103
prolong, restrict, inject, TransferManager,
104104
OpenCascadeMeshHierarchy, AdaptiveMeshHierarchy,
105-
AdaptiveTransferManager
105+
AdaptiveTransferManager,
106+
CoarsePatchTransferManager,
107+
FinePatchTransferManager,
106108
)
107109
from firedrake.norms import errornorm, norm # noqa: F401
108110
from firedrake.nullspace import VectorSpaceBasis, MixedVectorSpaceBasis # noqa: F401

firedrake/functionspace.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,17 @@ def RestrictedFunctionSpace(function_space, boundary_set=[], name=None):
336336
An optional name for the function space.
337337
338338
"""
339-
return impl.WithGeometry(impl.RestrictedFunctionSpace(function_space,
340-
boundary_set=boundary_set,
341-
name=name),
342-
function_space.mesh())
339+
if not isinstance(function_space, (impl.WithGeometry, impl.FiredrakeDualSpace)):
340+
raise TypeError(f"Can't make restricted space with {type(function_space).__name__}")
341+
342+
make_space = type(function_space)
343+
mesh = function_space.mesh()
344+
345+
if function_space.boundary_set:
346+
boundary_set = frozenset(boundary_set) | function_space.boundary_set
347+
function_space = function_space.function_space
348+
349+
return make_space(impl.RestrictedFunctionSpace(function_space.topological,
350+
boundary_set=boundary_set,
351+
name=name),
352+
mesh)

firedrake/mg/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
from firedrake.mg.opencascade_mh import OpenCascadeMeshHierarchy # noqa F401
1111
from firedrake.mg.adaptive_hierarchy import AdaptiveMeshHierarchy # noqa F401
1212
from firedrake.mg.adaptive_transfer_manager import AdaptiveTransferManager # noqa: F401
13+
from firedrake.mg.robust_transfer_manager import ( # noqa: F401
14+
CoarsePatchTransferManager, FinePatchTransferManager,
15+
)

firedrake/mg/kernels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def restrict_kernel(Vf, Vc):
345345

346346

347347
def inject_kernel(Vf, Vc):
348-
if Vc.finat_element.is_dg():
348+
if Vc.finat_element.is_dg() and Vf.ufl_element() == Vc.ufl_element():
349349
hierarchy, level = utils.get_level(Vc.mesh())
350350
if Vf.extruded:
351351
assert Vc.extruded

firedrake/mg/mesh.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from functools import cached_property
1212

1313
from firedrake import utils
14+
from firedrake.petsc import PETSc
1415
from firedrake.cython import mgimpl as impl
1516
from .utils import set_level
1617

@@ -29,6 +30,8 @@ class HierarchyBase(object):
2930
:arg refinements_per_level: number of mesh refinements each
3031
multigrid level should "see".
3132
:arg nested: Is this mesh hierarchy nested?
33+
:arg coarse_facet_label: Optional subdomain ID to label the coarse facets on
34+
each level of the hierarchy.
3235
3336
.. note::
3437
@@ -37,14 +40,15 @@ class HierarchyBase(object):
3740
:func:`ExtrudedMeshHierarchy`, or :func:`NonNestedHierarchy`.
3841
"""
3942
def __init__(self, meshes, coarse_to_fine_cells, fine_to_coarse_cells,
40-
refinements_per_level=1, nested=False):
43+
refinements_per_level=1, nested=False, coarse_facet_label=None):
4144
petsctools.cite("Mitchell2016")
4245
self._meshes = tuple(meshes)
4346
self.meshes = tuple(meshes[::refinements_per_level])
4447
self.coarse_to_fine_cells = coarse_to_fine_cells
4548
self.fine_to_coarse_cells = fine_to_coarse_cells
4649
self.refinements_per_level = refinements_per_level
4750
self.nested = nested
51+
self._coarse_facet_label = coarse_facet_label
4852
for level, m in enumerate(meshes):
4953
set_level(m, self, Fraction(level, refinements_per_level))
5054
for level, m in enumerate(self):
@@ -79,7 +83,8 @@ def MeshHierarchy(mesh, refinement_levels,
7983
netgen_flags=False,
8084
reorder=None,
8185
distribution_parameters=None, callbacks=None,
82-
mesh_builder=firedrake.Mesh):
86+
mesh_builder=firedrake.Mesh,
87+
coarse_facet_label=None):
8388
"""Build a hierarchy of meshes by uniformly refining a coarse mesh.
8489
8590
Parameters
@@ -109,6 +114,10 @@ def MeshHierarchy(mesh, refinement_levels,
109114
callback receives the refined DM (and the current level).
110115
mesh_builder
111116
Function to turn a DM into a ``Mesh``. Used by pyadjoint.
117+
coarse_facet_label : int | None
118+
Optional subdomain ID to label the coarse facets on each
119+
level of the hierarchy.
120+
112121
Returns
113122
-------
114123
A :py:class:`HierarchyBase` object representing the
@@ -139,11 +148,29 @@ def MeshHierarchy(mesh, refinement_levels,
139148
else:
140149
before = after = lambda dm, i: None
141150
for i in range(refinement_levels*refinements_per_level):
151+
if coarse_facet_label is not None:
152+
# Create a temporary label on all the facets of the coarse dm
153+
# to label every coarse facet on the fine dm
154+
fstart, fend = cdm.getHeightStratum(1)
155+
iset = PETSc.IS().createStride(fend-fstart, first=fstart, comm=cdm.comm)
156+
cdm.createLabel("temp_label")
157+
label = cdm.getLabel("temp_label")
158+
label.setStratumIS(1, iset)
159+
142160
if i % refinements_per_level == 0:
143161
before(cdm, i)
144162
rdm = cdm.refine()
145163
if i % refinements_per_level == 0:
146164
after(rdm, i)
165+
166+
if coarse_facet_label is not None:
167+
# Move coarse_facet_label into FACE_SETS_LABEL
168+
iset = rdm.getLabel("temp_label").getStratumIS(1)
169+
label = rdm.getLabel(dmcommon.FACE_SETS_LABEL)
170+
label.setStratumIS(coarse_facet_label, iset)
171+
rdm.removeLabel("temp_label")
172+
cdm.removeLabel("temp_label")
173+
147174
dms.append(rdm)
148175
cdm = rdm
149176
# Fix up coords if refining embedded circle or sphere
@@ -192,7 +219,8 @@ def MeshHierarchy(mesh, refinement_levels,
192219
fine_to_coarse_cells = dict((Fraction(i, refinements_per_level), f2c)
193220
for i, f2c in enumerate(fine_to_coarse_cells))
194221
return HierarchyBase(meshes, coarse_to_fine_cells, fine_to_coarse_cells,
195-
refinements_per_level, nested=True)
222+
refinements_per_level, nested=True,
223+
coarse_facet_label=coarse_facet_label)
196224

197225

198226
def ExtrudedMeshHierarchy(base_hierarchy, height, base_layer=-1, refinement_ratio=2, layers=None,

0 commit comments

Comments
 (0)