|
14 | 14 |
|
15 | 15 | from mpi4py import MPI |
16 | 16 |
|
| 17 | +import basix.ufl |
17 | 18 | import dolfinx |
18 | 19 | import numpy as np |
19 | 20 | import numpy.typing as npt |
| 21 | +import ufl |
20 | 22 | from packaging.version import Version |
21 | 23 |
|
22 | 24 | __all__ = [ |
|
27 | 29 | "unroll_dofmap", |
28 | 30 | "compute_insert_position", |
29 | 31 | "unroll_insert_position", |
| 32 | + "reconstruct_mesh", |
30 | 33 | ] |
31 | 34 |
|
32 | 35 |
|
@@ -196,3 +199,62 @@ def compute_dofmap_pos( |
196 | 199 | local_cell[indicator] = cell_indicator[markers].reshape(-1) |
197 | 200 | dof_pos[indicator] = local_indices[markers].reshape(-1) |
198 | 201 | 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 | + type(mesh.geometry._cpp_object)( |
| 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 = type(mesh._cpp_object)(mesh.comm, new_top._cpp_object, geom._cpp_object) |
| 260 | + return dolfinx.mesh.Mesh(cpp_mesh, ufl.Mesh(new_c_el)) |
0 commit comments