1111from functools import cached_property
1212
1313from firedrake import utils
14+ from firedrake .petsc import PETSc
1415from firedrake .cython import mgimpl as impl
1516from .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
198226def ExtrudedMeshHierarchy (base_hierarchy , height , base_layer = - 1 , refinement_ratio = 2 , layers = None ,
0 commit comments