Hi there,
Is there any way to make a deepcopy of a mesh? I naively tried
from dolfinx.generation import UnitSquareMesh
from dolfinx.cpp.mesh import CellType
import copy
comm = MPI.COMM_WORLD
no_elem = 32
mesh_II = UnitSquareMesh(comm, no_elem, no_elem, CellType.triangle)
mesh_I = copy.deepcopy(mesh_II)
which results in
cannot pickle 'dolfinx.cpp.mesh.Mesh' object
Best,
Mario
dokken
April 1, 2022, 1:35pm
2
Consider the following:
from dolfinx.mesh import create_unit_square, CellType, Mesh
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
no_elem = 5
mesh_II = create_unit_square(comm, no_elem, no_elem, CellType.triangle)
mesh_I = Mesh(mesh_II.comm, mesh_II.topology, mesh_II.geometry, mesh_II.ufl_domain())
mesh_I.geometry.x[:, 0] += 1
geom_II = mesh_II.geometry.x.copy()
geom_II[:, 0] += 1
assert(np.allclose(geom_II, mesh_I.geometry.x))
print(np.isclose(mesh_II.geometry.x, mesh_I.geometry.x))
print(mesh_II.geometry.x, mesh_I.geometry.x)
Is there a specific reason you would like to deepcopy your mesh?
1 Like
cannot import name 'create_unit_square' from 'dolfinx.mesh'
Which version of dolfinx do you use? I’m using 0.3.0 from the ubuntu 20.04 repository (the same happens within a docker container using 0.3.0).
By the way, the deepcopy of the mesh seems promising for problems where I take results of a solution on static mesh_I as input for mesh_II (different physics/equation), which is slightly deformed. For a parallel run, the sizes of the (sub-)vectors are generally not the same if I define the same mesh twice.
dokken
April 1, 2022, 2:57pm
4
Im using the main branch of dolfinx.
It would be a bit more tricky to do this with the 0.3.0 version.
Hmm, the same happens using 0.3.1.dev0 (docker pull dolfinx/dolfinx:latest). What means ‘main branch’? Is there a docker container available?
dokken
April 1, 2022, 3:12pm
6
Could you print the output of
import dolfinx.common
print(dolfinx.common.git_commit_hash)
Im using 9e2e2662b238d87be1378d812f29ec6e16b7410c
for 0.3.1.dev0 (docker pull dolfinx/dolfinx:latest) the output is:
8380c060f82b33f511404bc43524856edffac834
Sorry for the confusion. I didn’t update the container. Now the output is
36f8a4f4ba59ce682698e6e158a0c7abaff6fded
But back to the main topic. Your example works well, but because of some API changes, I would like to do this under 0.3.0. You mean, it’s a bit tricky. Can you please give a hint?
Thanks for your help @dokken
Probably it’s more convenient to wait for dolfinx 0.4.0 and consider all other API changes consecutively.
dokken
April 5, 2022, 9:24am
10
Does this still work for v0.10.0? Below, I’m seeing that mesh_II.geometry.x is modified when mesh_I.geometry.x is changed
from dolfinx.mesh import create_unit_square, CellType, Mesh
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
import dolfinx.common
print(dolfinx.common.git_commit_hash)
no_elem = 5
mesh_II = create_unit_square(comm, no_elem, no_elem, CellType.triangle)
mesh_I = Mesh(mesh_II, mesh_II.ufl_domain())
print(mesh_II.geometry.x[-1, 0])
mesh_I.geometry.x[:, 0] += 1
print(mesh_I.geometry.x[-1, 0])
print(mesh_II.geometry.x[-1, 0])
geom_II = mesh_II.geometry.x.copy()
geom_II[:, 0] += 1
assert(np.allclose(geom_II, mesh_I.geometry.x))
print(np.isclose(mesh_II.geometry.x, mesh_I.geometry.x))
print(mesh_II.geometry.x, mesh_I.geometry.x)
The output I get is
601b058a51f6a8f3cea11811048283f00855e18d
0.0
1.0
1.0
Traceback (most recent call last):
File "/workspace-gen2/tests/test_translation_unknown.py", line 139, in <module>
copy_mesh()
File "/workspace-gen2/tests/test_translation_unknown.py", line 131, in copy_mesh
assert(np.allclose(geom_II, mesh_I.geometry.x))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
Looks like this issue in v0.10.0 is resolved using mesh.create_mesh:
from dolfinx.mesh import create_unit_square, CellType, create_mesh
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
import dolfinx.common
print(dolfinx.common.git_commit_hash)
no_elem = 5
mesh_II = create_unit_square(comm, no_elem, no_elem, CellType.triangle)
mesh_I = create_mesh(comm, mesh_II.geometry.dofmap, mesh_II.ufl_domain(), mesh_II.geometry.x)
mesh_I.geometry.x[:, 0] += 1
geom_II = mesh_II.geometry.x.copy()
geom_II[:, 0] += 1
assert(np.allclose(geom_II, mesh_I.geometry.x))
print(np.isclose(mesh_II.geometry.x, mesh_I.geometry.x))
print(mesh_II.geometry.x, mesh_I.geometry.x)
dokken
February 10, 2026, 1:15pm
13
This is how one should do this for v0.10.0:
from dolfinx.mesh import create_unit_square, CellType, Mesh
from mpi4py import MPI
import numpy as np
import ufl
comm = MPI.COMM_WORLD
import dolfinx.common
print(dolfinx.common.git_commit_hash)
no_elem = 5
mesh_II = create_unit_square(comm, no_elem, no_elem, CellType.triangle)
# Extract correct CPP mesh constructor
if mesh_II.geometry.x.dtype == np.float32:
_cpp_mesh = dolfinx.cpp.mesh.Mesh_float32
elif mesh_II.geometry.x.dtype == np.float64:
_cpp_mesh = dolfinx.cpp.mesh.Mesh_float64
# Initialize C++ mesh
cpp_mesh = _cpp_mesh(mesh_II.comm, mesh_II.topology._cpp_object, mesh_II.geometry._cpp_object)
# Initialize Python wrapper with new symbolic numbering in the `ufl.Mesh`
mesh_I = Mesh(cpp_mesh, ufl.Mesh(mesh_II.ufl_domain().ufl_coordinate_element()))
print(mesh_II.geometry.x[-1, 0])
mesh_I.geometry.x[:, 0] += 1
print(mesh_I.geometry.x[-1, 0])
print(mesh_II.geometry.x[-1, 0])
geom_II = mesh_II.geometry.x.copy()
geom_II[:, 0] += 1
assert(np.allclose(geom_II, mesh_I.geometry.x))
print(np.isclose(mesh_II.geometry.x, mesh_I.geometry.x))
print(mesh_II.geometry.x, mesh_I.geometry.x)
dokken
February 23, 2026, 9:27am
14
I’ve made a convenience function: Add copy mesh function by jorgensd · Pull Request #188 · scientificcomputing/scifem · GitHub
Note that this is strictly not a deepcopy, as the topology is shared between the two meshes.
I don’t see this as problematic, as it just reduces the overhead of recomputing connectivity and entity permutations
1 Like