Skip to content

Commit 37f7512

Browse files
committed
WIP, now losing boundary markers
1 parent b32c2ed commit 37f7512

File tree

4 files changed

+114
-26
lines changed

4 files changed

+114
-26
lines changed

firedrake/cython/dmcommon.pyx

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3921,15 +3921,16 @@ def submesh_create_cell_closure_cell_submesh(PETSc.DM subdm,
39213921
return subcell_closure
39223922

39233923

3924-
def set_coordinate_section_and_such(mesh, coordinates):
3924+
def make_geometry_dm(coordinates) -> PETSc.DM:
39253925
cdef:
3926-
PETSc.DM plex
3926+
PETSc.DM topology_dm, geometry_dm
39273927
PETSc.Section vector_section
39283928
PetscInt gdim
39293929

3930-
plex = mesh.topology_dm
3930+
topology_dm = coordinates.function_space().mesh().topology_dm
3931+
geometry_dm = topology_dm.clone()
39313932
coordinate_element = coordinates.ufl_element()
3932-
gdim = plex.getCoordinateDim()
3933+
gdim = topology_dm.getCoordinateDim()
39333934

39343935
# the existing section has the correct numbering but is scalar, expand to gdim
39353936
scalar_dm = coordinates.function_space().dm
@@ -3950,11 +3951,67 @@ def set_coordinate_section_and_such(mesh, coordinates):
39503951

39513952
if coordinate_element.family() == "Lagrange":
39523953
# apparently gdim ignored in this call and set explicitly below
3953-
CHKERR(DMSetCoordinateSection(plex.dm, gdim, vector_section.sec))
3954-
plex.setCoordinateDim(gdim)
3955-
plex.setCoordinatesLocal(coordinates.dat._vec)
3954+
CHKERR(DMSetCoordinateSection(geometry_dm.dm, gdim, vector_section.sec))
3955+
geometry_dm.setCoordinateDim(gdim)
3956+
geometry_dm.setCoordinatesLocal(coordinates.dat._vec)
39563957
else:
3957-
plex.setCellCoordinateDM(plex.getCoordinateDM().clone())
3958-
plex.setCellCoordinateSection(gdim, vector_section) # gdim ignored
3959-
plex.setCoordinateDim(gdim)
3960-
plex.setCellCoordinatesLocal(coordinates.dat._vec)
3958+
geometry_dm.setCellCoordinateDM(geometry_dm.getCoordinateDM().clone())
3959+
geometry_dm.setCellCoordinateSection(gdim, vector_section) # gdim ignored
3960+
geometry_dm.setCoordinateDim(gdim)
3961+
geometry_dm.setCellCoordinatesLocal(coordinates.dat._vec)
3962+
3963+
return geometry_dm
3964+
3965+
3966+
def dmplex_migrate(PETSc.DM dm, PETSc.SF sf) -> PETSc.DM:
3967+
cdef:
3968+
PETSc.DM migrated_dm
3969+
3970+
migrated_dm = PETSc.DMPlex().create(comm=dm.comm)
3971+
CHKERR(DMPlexMigrate(dm.dm, sf.sf, migrated_dm.dm))
3972+
return migrated_dm
3973+
3974+
3975+
def densify_sf(PETSc.DM topology_dm, PETSc.SF sparse_sf) -> PETSc.SF:
3976+
cdef:
3977+
PETSc.SF dense_sf
3978+
PetscInt dof_nroots, dof_nleaves
3979+
PetscInt *ilocal_new = NULL
3980+
PetscSFNode *iremote_new = NULL
3981+
PETSc.SF point_sf
3982+
PetscInt nroots, nleaves
3983+
const PetscInt *ilocal = NULL
3984+
const PetscSFNode *iremote = NULL
3985+
PETSc.Section local_sec
3986+
PetscInt pStart, pEnd, p, dof, off, m, n, i, j
3987+
np.ndarray local_offsets
3988+
np.ndarray remote_offsets
3989+
3990+
pStart, pEnd = topology_dm.getChart()
3991+
nPoints = pEnd - pStart
3992+
CHKERR(PetscSFGetGraph(sparse_sf.sf, &nroots, &nleaves, &ilocal, &iremote))
3993+
3994+
CHKERR(PetscMalloc1(nPoints, &ilocal_new))
3995+
CHKERR(PetscMalloc1(nPoints, &iremote_new))
3996+
for p in range(pStart, pEnd):
3997+
ilocal_new[p] = p
3998+
iremote_new[p].rank = topology_dm.comm.rank
3999+
iremote_new[p].index = p
4000+
4001+
for i in range(nleaves):
4002+
p = ilocal[i] if ilocal else i
4003+
iremote_new[p].rank = iremote[i].rank
4004+
iremote_new[p].index = iremote[i].index
4005+
4006+
dense_sf = PETSc.SF().create(comm=sparse_sf.comm)
4007+
CHKERR(PetscSFSetGraph(dense_sf.sf, nPoints, nPoints, ilocal_new, PETSC_OWN_POINTER, iremote_new, PETSC_OWN_POINTER))
4008+
return dense_sf
4009+
4010+
4011+
def dmplex_create_overlap_migration_sf(PETSc.DM topology_dm, PETSc.SF overlap_sf) -> PETSc.SF:
4012+
cdef:
4013+
PETSc.SF migration_sf
4014+
4015+
migration_sf = PETSc.SF().create(comm=topology_dm.comm)
4016+
CHKERR(DMPlexCreateOverlapMigrationSF(topology_dm.dm, overlap_sf.sf, &migration_sf.sf))
4017+
return migration_sf

firedrake/cython/petschdr.pxi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ cdef extern from "petscdmplex.h" nogil:
5757
int DMPlexSetSubpointMap(PETSc.PetscDM,PETSc.PetscDMLabel)
5858

5959
int DMSetCoordinateSection(PETSc.PetscDM,PetscInt,PETSc.PetscSection)
60+
int DMPlexMigrate(PETSc.PetscDM,PETSc.PetscSF,PETSc.PetscDM)
61+
int DMPlexCreateOverlapMigrationSF(PETSc.PetscDM,PETSc.PetscSF,PETSc.PetscSF*)
62+
6063

6164
cdef extern from "petscdmlabel.h" nogil:
6265
struct _n_DMLabel

firedrake/mesh.py

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ def _from_cell_list(dim, cells, coords, comm, name=None):
543543
return plex
544544

545545

546-
class AbstractMeshTopology(object, metaclass=abc.ABCMeta):
546+
class AbstractMeshTopology(metaclass=abc.ABCMeta):
547547
"""A representation of an abstract mesh topology without a concrete
548548
PETSc DM implementation"""
549549

@@ -1186,6 +1186,7 @@ def _add_overlap(self):
11861186
dmcommon.set_adjacency_callback(self.topology_dm)
11871187
original_name = self.topology_dm.getName()
11881188
sfBC = self.topology_dm.distributeOverlap(overlap)
1189+
self.overlap_sf = sfBC
11891190
self.topology_dm.setName(original_name)
11901191
self.sfBC = self.sfBC.compose(sfBC) if self.sfBC else sfBC
11911192
dmcommon.clear_adjacency_callback(self.topology_dm)
@@ -1194,6 +1195,7 @@ def _add_overlap(self):
11941195
# Default is FEM (vertex star) adjacency.
11951196
original_name = self.topology_dm.getName()
11961197
sfBC = self.topology_dm.distributeOverlap(overlap)
1198+
self.overlap_sf = sfBC
11971199
self.topology_dm.setName(original_name)
11981200
self.sfBC = self.sfBC.compose(sfBC) if self.sfBC else sfBC
11991201
self._grown_halos = True
@@ -2242,6 +2244,7 @@ def __new__(cls, element, comm):
22422244
cargo = MeshGeometryCargo(uid)
22432245
assert isinstance(element, finat.ufl.FiniteElementBase)
22442246
ufl.Mesh.__init__(mesh, element, ufl_id=mesh.uid, cargo=cargo)
2247+
22452248
return mesh
22462249

22472250
@MeshGeometryMixin._ad_annotate_init
@@ -2253,9 +2256,15 @@ def __init__(self, coordinates):
22532256
coordinates : CoordinatelessFunction
22542257
The `CoordinatelessFunction` containing the coordinates.
22552258
2259+
Notes
2260+
-----
2261+
At the time this constructor is called the mesh is fully distributed.
2262+
22562263
"""
22572264
topology = coordinates.function_space().mesh()
22582265

2266+
self.geometry_dm = dmcommon.make_geometry_dm(coordinates)
2267+
22592268
# this is codegen information so we attach it to the MeshGeometry rather than its cargo
22602269
self.extruded = isinstance(topology, ExtrudedMeshTopology)
22612270
self.variable_layers = self.extruded and topology.variable_layers
@@ -2272,9 +2281,9 @@ def __init__(self, coordinates):
22722281
self._spatial_index = None
22732282
self._saved_coordinate_dat_version = coordinates.dat.dat_version
22742283

2275-
# NOTE: This is only ever called with a fully distributed, overlapping
2276-
# mesh
2277-
dmcommon.set_coordinate_section_and_such(self, coordinates)
2284+
@property
2285+
def cell_closure_list(self):
2286+
return self.dm.getCoordinateDM().getAttr("cell_closure_list")
22782287

22792288
def _ufl_signature_data_(self, *args, **kwargs):
22802289
return (type(self), self.extruded, self.variable_layers,
@@ -2288,7 +2297,7 @@ def init(self):
22882297
if hasattr(self, '_callback'):
22892298
self._callback(self)
22902299

2291-
def _init_topology(self, topology):
2300+
def _init_topology(self, topology, geometry_dm):
22922301
"""Initialise the topology.
22932302
22942303
:arg topology: The :class:`.MeshTopology` object.
@@ -2302,12 +2311,24 @@ def _init_topology(self, topology):
23022311
import firedrake.function as function
23032312

23042313
self._topology = topology
2314+
self._input_geometry_dm = geometry_dm
23052315

23062316
def callback(self):
23072317
"""Finish initialisation."""
23082318
del self._callback
23092319
# Finish the initialisation of mesh topology
23102320
self.topology.init()
2321+
# geometry_dm = self._input_geometry_dm.migrate(self.topology.overlap_sf)
2322+
2323+
# make the overlap SF dense
2324+
# dense_overlap_sf = dmcommon.densify_sf(self.topology.topology_dm, self.topology.overlap_sf)
2325+
# breakpoint()
2326+
# migration_sf = dmcommon.dmplex_create_overlap_migration_sf(self.topology.topology_dm, self.topology.overlap_sf)
2327+
# geometry_dm = dmcommon.dmplex_migrate(self._input_geometry_dm, dense_overlap_sf)
2328+
# geometry_dm = dmcommon.dmplex_migrate(self._input_geometry_dm, self.topology.overlap_sf)
2329+
# geometry_dm = dmcommon.dmplex_migrate(self._input_geometry_dm, migration_sf)
2330+
geometry_dm = dmcommon.dmplex_migrate(self._input_geometry_dm, self.topology.sfBC)
2331+
23112332
coordinates_fs = functionspace.FunctionSpace(self.topology, self.ufl_coordinate_element())
23122333

23132334
# reordered_coords only needs to reorder the coordinates
@@ -2316,7 +2337,7 @@ def callback(self):
23162337
# anything. Otherwise, we have the set the correct section.
23172338
# TODO: Ask Matt if there is a nice way to do this.
23182339

2319-
coordinates_data = dmcommon.reordered_coords(topology.topology_dm, coordinates_fs.dm.getDefaultSection(),
2340+
coordinates_data = dmcommon.reordered_coords(geometry_dm, coordinates_fs.dm.getDefaultSection(),
23202341
(self.num_vertices(), self.geometric_dimension()))
23212342
coordinates = function.CoordinatelessFunction(coordinates_fs,
23222343
val=coordinates_data,
@@ -2879,8 +2900,9 @@ def make_mesh_from_coordinates(coordinates, name, tolerance=0.5):
28792900
return mesh
28802901

28812902

2882-
def make_mesh_from_mesh_topology(topology, name, tolerance=0.5):
2883-
"""Make mesh from tpology.
2903+
# Should be make_mesh_from_geometry_dm
2904+
def make_mesh_from_mesh_topology(topology, geometry_dm, name, tolerance=0.5):
2905+
"""Make mesh from topology.
28842906
28852907
Parameters
28862908
----------
@@ -2901,13 +2923,13 @@ def make_mesh_from_mesh_topology(topology, name, tolerance=0.5):
29012923
# TODO: meshfile might indicates higher-order coordinate element
29022924
cell = topology.ufl_cell()
29032925
geometric_dim = topology.topology_dm.getCoordinateDim()
2904-
if not topology.topology_dm.getCoordinatesLocalized():
2926+
if not geometry_dm.getCoordinatesLocalized():
29052927
element = finat.ufl.VectorElement("Lagrange", cell, 1, dim=geometric_dim)
29062928
else:
29072929
element = finat.ufl.VectorElement("DQ" if cell in [ufl.quadrilateral, ufl.hexahedron] else "DG", cell, 1, dim=geometric_dim, variant="equispaced")
29082930
# Create mesh object
29092931
mesh = MeshGeometry.__new__(MeshGeometry, element, topology.comm)
2910-
mesh._init_topology(topology)
2932+
mesh._init_topology(topology, geometry_dm)
29112933
mesh.name = name
29122934
mesh._tolerance = tolerance
29132935
return mesh
@@ -3105,17 +3127,23 @@ def Mesh(meshfile, **kwargs):
31053127
raise RuntimeError("Mesh file %s has unknown format '%s'."
31063128
% (meshfile, ext[1:]))
31073129
plex.setName(_generate_default_mesh_topology_name(name))
3130+
31083131
# Create mesh topology
3109-
topology = MeshTopology(plex, name=plex.getName(), reorder=reorder,
3132+
# Pass the coordinate DM because we only want the topology here
3133+
topology = MeshTopology(plex.getCoordinateDM(), name=plex.getName(), reorder=reorder,
31103134
distribution_parameters=distribution_parameters,
31113135
distribution_name=kwargs.get("distribution_name"),
31123136
permutation_name=kwargs.get("permutation_name"),
31133137
comm=user_comm)
3138+
3139+
# distributed_plex = dmcommon.dmplex_migrate(plex, topology.sfBC)
3140+
distributed_plex = plex
3141+
31143142
if netgen and isinstance(meshfile, netgen.libngpy._meshing.Mesh):
31153143
netgen_firedrake_mesh.createFromTopology(topology, name=name, comm=user_comm)
31163144
mesh = netgen_firedrake_mesh.firedrakeMesh
31173145
else:
3118-
mesh = make_mesh_from_mesh_topology(topology, name)
3146+
mesh = make_mesh_from_mesh_topology(topology, distributed_plex, name)
31193147
mesh._tolerance = tolerance
31203148
return mesh
31213149

@@ -4576,13 +4604,13 @@ def RelabeledMesh(mesh, indicator_functions, subdomain_ids, **kwargs):
45764604
distribution_parameters_noop = {"partition": False,
45774605
"overlap_type": (DistributedMeshOverlapType.NONE, 0)}
45784606
reorder_noop = None
4579-
tmesh1 = MeshTopology(plex1, name=plex1.getName(), reorder=reorder_noop,
4607+
tmesh1 = MeshTopology(plex1.getCoordinateDM(), name=plex1.getName(), reorder=reorder_noop,
45804608
distribution_parameters=distribution_parameters_noop,
45814609
perm_is=tmesh._dm_renumbering,
45824610
distribution_name=tmesh._distribution_name,
45834611
permutation_name=tmesh._permutation_name,
45844612
comm=tmesh.comm)
4585-
return make_mesh_from_mesh_topology(tmesh1, name1)
4613+
return make_mesh_from_mesh_topology(tmesh1, plex1, name1)
45864614

45874615

45884616
@PETSc.Log.EventDecorator()

firedrake/mg/mesh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def MeshHierarchy(mesh, refinement_levels,
131131
raise RuntimeError("Cannot create a NetgenHierarchy from a mesh that has not been generated by\
132132
Netgen.")
133133

134-
cdm = mesh.topology_dm
134+
cdm = mesh._input_geometry_dm
135135
cdm.setRefinementUniform(True)
136136
dms = []
137137
if mesh.comm.size > 1 and mesh._grown_halos:

0 commit comments

Comments
 (0)