Skip to content

Commit b5698d3

Browse files
committed
Make it possible to reconstruct mesh with new coordinate element degree.
1 parent f36aeac commit b5698d3

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/io4dolfinx/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
read_point_data,
3232
)
3333
from .snapshot import snapshot_checkpoint
34+
from .utils import reconstruct_mesh
3435

3536
meta = metadata("io4dolfinx")
3637
__version__ = meta["Version"]
@@ -62,4 +63,5 @@
6263
"get_backend",
6364
"write_cell_data",
6465
"write_point_data",
66+
"reconstruct_mesh",
6567
]

src/io4dolfinx/utils.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
from mpi4py import MPI
1616

17+
import basix.ufl
1718
import dolfinx
1819
import numpy as np
1920
import numpy.typing as npt
21+
import ufl
2022
from packaging.version import Version
2123

2224
__all__ = [
@@ -27,6 +29,7 @@
2729
"unroll_dofmap",
2830
"compute_insert_position",
2931
"unroll_insert_position",
32+
"reconstruct_mesh",
3033
]
3134

3235

@@ -196,3 +199,62 @@ def compute_dofmap_pos(
196199
local_cell[indicator] = cell_indicator[markers].reshape(-1)
197200
dof_pos[indicator] = local_indices[markers].reshape(-1)
198201
return local_cell, dof_pos
202+
203+
204+
def reconstruct_mesh(mesh: dolfinx.mesh.Mesh, coordinate_element_degree: int) -> dolfinx.mesh.Mesh:
205+
"""
206+
Make a copy of a mesh and potentially change the element of the coordinate element.
207+
208+
Note:
209+
The topology is shared with the original mesh but the geometry is reconstructed.
210+
211+
Args:
212+
mesh: Mesh to reconstruct
213+
coordinate_element_degree: Degree to use for coordinate element
214+
215+
Returns:
216+
The new mesh
217+
218+
"""
219+
# Extract cell properties
220+
ud = mesh.ufl_domain()
221+
assert ud is not None
222+
c_el = ud.ufl_coordinate_element()
223+
family = c_el.family_name
224+
lvar = c_el.lagrange_variant
225+
ct = c_el.cell_type
226+
227+
# Create new UFL element
228+
new_c_el = basix.ufl.element(
229+
family,
230+
ct,
231+
coordinate_element_degree,
232+
shape=(mesh.geometry.dim,),
233+
lagrange_variant=lvar,
234+
dtype=mesh.geometry.x.dtype,
235+
)
236+
237+
# Extract new node coordinates
238+
V_tmp = dolfinx.fem.functionspace(mesh, new_c_el)
239+
gdim = mesh.geometry.dim
240+
x = V_tmp.tabulate_dof_coordinates()[:, :gdim]
241+
242+
# Create new geoemtry
243+
geom_imap = V_tmp.dofmap.index_map
244+
geom_dofmap = V_tmp.dofmap.list
245+
num_nodes_local = geom_imap.size_local + geom_imap.num_ghosts
246+
original_input_indices = geom_imap.local_to_global(np.arange(num_nodes_local, dtype=np.int32))
247+
coordinate_element = dolfinx.fem.coordinate_element(
248+
mesh.topology.cell_type, coordinate_element_degree, lvar, dtype=mesh.geometry.x.dtype
249+
)
250+
# Could use create_geometry here when things are fixed
251+
geom = dolfinx.mesh.Geometry(
252+
mesh.geometry._cpp_object.__class__(
253+
geom_imap, geom_dofmap, coordinate_element._cpp_object, x, original_input_indices
254+
)
255+
)
256+
257+
# Create new mesh
258+
new_top = mesh.topology
259+
cpp_mesh = mesh._cpp_object.__class__(mesh.comm, new_top._cpp_object, geom._cpp_object)
260+
return dolfinx.mesh.Mesh(cpp_mesh, ufl.Mesh(new_c_el))

0 commit comments

Comments
 (0)