2525from pyop2 .mpi import (
2626 MPI , COMM_WORLD , temp_internal_comm
2727)
28- from functools import cached_property , reduce
28+ from functools import cached_property
2929from pyop2 .utils import as_tuple
3030import petsctools
3131from petsctools import OptionsManager , get_external_packages
@@ -4854,17 +4854,86 @@ def Submesh(mesh, subdim=None, subdomain_id=None, label_name=None, name=None, ig
48544854 ridges to be contained in the quad mesh are shared by at most two
48554855 facets to make the quad mesh orientation algorithm work.
48564856
4857+ Examples
4858+ --------
4859+
4860+ Mark a cell subdomain and construct a codim-0 submesh from all cells in the subdomain
4861+
4862+ >>> mesh = UnitSquareMesh(4, 4)
4863+ >>> x, y = SpatialCoordinate(mesh)
4864+ >>> DG = FunctionSpace(mesh, "DG", 0)
4865+ >>> cell_marker = assemble(interpolate(conditional(lt(x, 0.5), 1, 0), DG))
4866+ >>> mesh.mark_entities(cell_marker, 111)
4867+ >>> submesh = Submesh(mesh, subdomain_id=111)
4868+
4869+ Mark a facet subdomain and construct a codim-1 submesh from all facets in the subdomain
4870+
4871+ >>> mesh = UnitSquareMesh(4, 4)
4872+ >>> x, y = SpatialCoordinate(mesh)
4873+ >>> DGT = FunctionSpace(mesh, "DGT", 0)
4874+ >>> facet_marker = assemble(interpolate(conditional(lt(abs(x-0.5), 1E-12), 1, 0), DGT))
4875+ >>> mesh.mark_entities(facet_marker, 222)
4876+ >>> submesh = Submesh(mesh, dim=mesh.topological_dimension-1, subdomain_id=222)
4877+
4878+ Construct a codim-0 submesh of the union of multiple subdomains by passing a list
4879+
4880+ >>> mesh = UnitSquareMesh(4, 4)
4881+ >>> x, y = SpatialCoordinate(mesh)
4882+ >>> DG = FunctionSpace(mesh, "DG", 0)
4883+ >>> mesh.mark_entities(assemble(interpolate(conditional(lt(x, 0.5), 1, 0), DG)), 1)
4884+ >>> mesh.mark_entities(assemble(interpolate(conditional(lt(y, 0.5), 1, 0), DG)), 2)
4885+ >>> submesh = Submesh(mesh, subdomain_id=[1, 2])
4886+
4887+ Construct a codim-0 submesh of the intersection of multiple subdomains by passing a nested list
4888+
4889+ >>> mesh = UnitSquareMesh(4, 4)
4890+ >>> x, y = SpatialCoordinate(mesh)
4891+ >>> DG = FunctionSpace(mesh, "DG", 0)
4892+ >>> mesh.mark_entities(assemble(interpolate(conditional(lt(x, 0.5), 1, 0), DG)), 1)
4893+ >>> mesh.mark_entities(assemble(interpolate(conditional(lt(y, 0.5), 1, 0), DG)), 2)
4894+ >>> submesh = Submesh(mesh, subdomain_id=[(1, 2)])
4895+
4896+ Construct a codim-1 submesh of all the facets (the skeleton mesh)
4897+
4898+ >>> mesh = UnitSquareMesh(4, 4)
4899+ >>> submesh = Submesh(mesh, subdim=1)
4900+
4901+ Construct a codim-1 submesh of the entire boundary
4902+
4903+ >>> mesh = UnitSquareMesh(4, 4)
4904+ >>> submesh = Submesh(mesh, subdomain_id="on_boundary")
4905+
4906+ Construct a codim-1 submesh of the union of multiple boundaries
4907+
4908+ >>> mesh = UnitSquareMesh(4, 4)
4909+ >>> submesh = Submesh(mesh, subdim=mesh.topological_dimension-1, subdomain_id=[1, 2, 3])
4910+
4911+ Construct a codim-0 submesh of the part of the mesh owned by each MPI rank
4912+
4913+ >>> mesh = UnitSquareMesh(4, 4)
4914+ >>> submesh = Submesh(mesh, comm=COMM_SELF)
4915+
48574916 """
48584917 if not isinstance (mesh , MeshGeometry ):
48594918 raise TypeError ("Parent mesh must be a `MeshGeometry`" )
48604919 if isinstance (mesh .topology , ExtrudedMeshTopology ):
48614920 raise NotImplementedError ("Can not create a submesh of an ``ExtrudedMesh``" )
48624921 elif isinstance (mesh .topology , VertexOnlyMeshTopology ):
48634922 raise NotImplementedError ("Can not create a submesh of a ``VertexOnlyMesh``" )
4923+
4924+ if subdomain_id == "on_boundary" :
4925+ if subdim is None :
4926+ subdim = mesh .topological_dimension - 1
4927+ elif subdim != mesh .topological_dimension - 1 :
4928+ raise ValueError ('subdomain_id="on_boundary" requires subdim=dim-1' )
4929+ if label_name is None :
4930+ label_name = "exterior_facets"
4931+ elif label_name != "exterior_facets" :
4932+ raise ValueError ('subdomain_id="on_boundary" requires label_name="exterior_facets"' )
4933+ subdomain_id = 1
4934+
48644935 if subdim is None :
48654936 subdim = mesh .topological_dimension
4866- if subdomain_id == "on_boundary" :
4867- subdim = subdim - 1
48684937 plex = mesh .topology_dm
48694938 dim = plex .getDimension ()
48704939 if subdim not in {dim , dim - 1 }:
@@ -4883,13 +4952,9 @@ def Submesh(mesh, subdim=None, subdomain_id=None, label_name=None, name=None, ig
48834952
48844953 # Parse non-integer subdomain_id
48854954 if isinstance (subdomain_id , str ):
4886- if subdomain_id == "on_boundary" :
4887- subdomain_id = tuple (mesh .exterior_facets .unique_markers )
4888- else :
4889- raise ValueError (f"Submesh construction got invalid subdomain_id { subdomain_id } ." )
4890-
4891- if isinstance (subdomain_id , Sequence ):
4892- # Create a temporary DMLabel with the union of the labels in the list
4955+ raise ValueError (f"Submesh construction got invalid subdomain_id { subdomain_id } ." )
4956+ elif isinstance (subdomain_id , Sequence ):
4957+ # Take the union of the labels in the list
48934958 iset = PETSc .IS ().createGeneral ([], comm = mesh .comm )
48944959 for sub in subdomain_id :
48954960 if isinstance (sub , Sequence ):
@@ -4898,6 +4963,7 @@ def Submesh(mesh, subdim=None, subdomain_id=None, label_name=None, name=None, ig
48984963 else :
48994964 cur = plex .getStratumIS (label_name , sub )
49004965 iset = iset .union (cur )
4966+ # Create a temporary label
49014967 label_name = "temp_label"
49024968 subdomain_id = 1
49034969 plex .createLabel (label_name )
0 commit comments