Skip to content

Commit 9009018

Browse files
committed
Start fixing entity_maps with backwards compatibility
1 parent f4017d5 commit 9009018

File tree

8 files changed

+192
-73
lines changed

8 files changed

+192
-73
lines changed

examples/advection_diffusion_multi_material.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ def velocity_func(x):
8080
return values
8181

8282
mesh2, mt2, ct2 = generate_mesh(n=10)
83-
submesh, submesh_to_mesh, v_map = dolfinx.mesh.create_submesh(
84-
mesh2, ct2.dim, ct2.find(4)
85-
)[0:3]
83+
submesh, cell_map, v_map = dolfinx.mesh.create_submesh(mesh2, ct2.dim, ct2.find(4))[
84+
0:3
85+
]
8686
v_cg = basix.ufl.element(
8787
"Lagrange", submesh.topology.cell_name(), 2, shape=(submesh.geometry.dim,)
8888
)

examples/multi_material_2d.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def half(x):
107107

108108
my_model.temperature = 500.0 # lambda x: 300 + 10 * x[1] + 100 * x[0]
109109

110-
my_model.settings = F.Settings(atol=None, rtol=1e-5, transient=False)
110+
my_model.settings = F.Settings(atol=1e-5, rtol=1e-5, transient=False)
111111

112112
my_model.exports = [
113113
F.VTXSpeciesExport(f"u_{subdomain.id}.bp", field=H, subdomain=subdomain)
@@ -120,7 +120,20 @@ def half(x):
120120
# -------------------- post processing --------------------
121121

122122
# derived quantities
123-
entity_maps = {sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains}
123+
# Check for DOLFINx version compatibility
124+
try:
125+
from dolfinx.mesh import EntityMap # noqa: F401
126+
127+
legacy_entity_map = False
128+
entity_map_wrapper = lambda e_map: list(e_map.values())
129+
entity_maps = [sd.cell_map for sd in my_model.volume_subdomains]
130+
except ImportError:
131+
legacy_entity_map = True
132+
entity_map_wrapper = lambda e_map: e_map
133+
entity_maps = {
134+
sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains
135+
}
136+
124137

125138
ds_b = ufl.Measure("ds", domain=bottom_domain.submesh, subdomain_data=bottom_domain.ft)
126139
ds_t = ufl.Measure("ds", domain=top_domain.submesh, subdomain_data=top_domain.ft)
@@ -143,18 +156,26 @@ def half(x):
143156
* ds(1),
144157
entity_maps=entity_maps,
145158
)
146-
print(dolfinx.fem.assemble_scalar(form))
147159

148-
entity_maps[mesh] = bottom_domain.submesh_to_mesh
160+
161+
def assemble_and_print(form: dolfinx.fem.Form):
162+
loc_val = dolfinx.fem.assemble_scalar(form)
163+
glob_val = mesh.comm.allreduce(loc_val, op=MPI.SUM)
164+
if MPI.COMM_WORLD.rank == 0:
165+
print(glob_val, flush=True)
166+
167+
168+
assemble_and_print(form)
169+
149170

150171
form = dolfinx.fem.form(bottom_domain.u.sub(0) * dx_b)
151-
print(dolfinx.fem.assemble_scalar(form))
172+
assemble_and_print(form)
152173

153174
form = dolfinx.fem.form(
154175
my_model.temperature_fenics * dx_b,
155-
entity_maps={mesh: bottom_domain.submesh_to_mesh},
176+
entity_maps=entity_map_wrapper({mesh: bottom_domain.cell_map}),
156177
)
157-
print(dolfinx.fem.assemble_scalar(form))
178+
assemble_and_print(form)
158179

159180
D = bottom_domain.material.get_diffusion_coefficient(
160181
my_model.mesh.mesh, my_model.temperature_fenics, H
@@ -166,15 +187,15 @@ def half(x):
166187
n_b,
167188
)
168189
* ds_b(id_interface),
169-
entity_maps={mesh: bottom_domain.submesh_to_mesh},
190+
entity_maps=entity_map_wrapper({mesh: bottom_domain.cell_map}),
170191
)
171-
print(dolfinx.fem.assemble_scalar(form))
192+
assemble_and_print(form)
172193
form = dolfinx.fem.form(
173194
ufl.dot(
174195
D * ufl.grad(top_domain.u.sub(0)),
175196
n_t,
176197
)
177198
* ds_t(id_interface),
178-
entity_maps={mesh: top_domain.submesh_to_mesh},
199+
entity_maps=entity_map_wrapper({mesh: top_domain.cell_map}),
179200
)
180-
print(dolfinx.fem.assemble_scalar(form))
201+
assemble_and_print(form)

examples/multi_material_2d_bis.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ def half(x):
146146

147147

148148
# derived quantities
149-
entity_maps = {sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains}
150-
entity_maps[mesh] = bottom_domain.submesh_to_mesh
149+
151150

152151
ds = ufl.Measure("ds", domain=mesh, subdomain_data=my_model.facet_meshtags)
153152
ds_b = ufl.Measure("ds", domain=bottom_domain.submesh, subdomain_data=bottom_domain.ft)
@@ -164,23 +163,35 @@ def half(x):
164163
form = dolfinx.fem.form(bottom_domain.u.sub(1) * dx_b)
165164
print(dolfinx.fem.assemble_scalar(form))
166165

166+
# Check for DOLFINx version compatibility
167+
try:
168+
from dolfinx.mesh import EntityMap # noqa: F401
169+
170+
legacy_entity_map = False
171+
entity_map_wrapper = lambda e_map: list(e_map.values())
172+
except ImportError:
173+
legacy_entity_map = True
174+
entity_map_wrapper = lambda e_map: e_map
175+
176+
167177
form = dolfinx.fem.form(
168178
my_model.temperature_fenics * dx_b,
169-
entity_maps={mesh: bottom_domain.submesh_to_mesh},
179+
entity_maps=entity_map_wrapper({mesh: bottom_domain.cell_map}),
170180
)
171181
print(dolfinx.fem.assemble_scalar(form))
172182

173183
D = bottom_domain.material.get_diffusion_coefficient(
174184
my_model.mesh.mesh, my_model.temperature_fenics, H
175185
)
176186
id_interface = 5
187+
177188
form = dolfinx.fem.form(
178189
ufl.dot(
179190
D * ufl.grad(bottom_domain.u.sub(0)),
180191
n_b,
181192
)
182193
* ds_b(id_interface),
183-
entity_maps={mesh: bottom_domain.submesh_to_mesh},
194+
entity_maps=entity_map_wrapper({mesh: bottom_domain.cell_map}),
184195
)
185196
print(dolfinx.fem.assemble_scalar(form))
186197
form = dolfinx.fem.form(
@@ -189,19 +200,26 @@ def half(x):
189200
n_t,
190201
)
191202
* ds_t(id_interface),
192-
entity_maps={mesh: top_domain.submesh_to_mesh},
203+
entity_maps=entity_map_wrapper({mesh: top_domain.cell_map}),
193204
)
194205
print(dolfinx.fem.assemble_scalar(form))
195206

196207

197208
# using submesh function
198209
u = H.subdomain_to_post_processing_solution[bottom_domain]
210+
if legacy_entity_map:
211+
entity_maps = {
212+
sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains
213+
}
214+
else:
215+
entity_maps = [sd.cell_map for sd in my_model.volume_subdomains]
216+
199217
form = dolfinx.fem.form(
200218
ufl.dot(
201219
D * ufl.grad(u),
202220
n_b,
203221
)
204222
* ds(bottom_surface.id),
205-
entity_maps={sd.submesh: sd.parent_to_submesh for sd in my_model.volume_subdomains},
223+
entity_maps=entity_maps,
206224
)
207225
print(dolfinx.fem.assemble_scalar(form))

src/festim/helpers_discontinuity.py

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,19 @@ def transfer_meshtags_to_submesh(
1212
# Invert map from sub-mesh to parent-mesh to parent-mesh to sub-mesh
1313
tdim = mesh.topology.dim
1414
cell_imap = mesh.topology.index_map(tdim)
15-
num_cells = cell_imap.size_local + cell_imap.num_ghosts
16-
mesh_to_submesh = np.full(num_cells, -1)
17-
mesh_to_submesh[sub_cell_to_parent] = np.arange(
18-
len(sub_cell_to_parent), dtype=np.int32
19-
)
15+
try:
16+
from dolfinx.mesh import EntityMap # noqa: F401
17+
18+
legacy_entity_map = False
19+
except ImportError:
20+
legacy_entity_map = True
21+
22+
if legacy_entity_map:
23+
num_cells = cell_imap.size_local + cell_imap.num_ghosts
24+
mesh_to_submesh = np.full(num_cells, -1)
25+
mesh_to_submesh[sub_cell_to_parent] = np.arange(
26+
len(sub_cell_to_parent), dtype=np.int32
27+
)
2028

2129
# Compute and access various entity to vertex and vertex to
2230
# entity connectivity for parent and sub-mesh.
@@ -38,22 +46,51 @@ def transfer_meshtags_to_submesh(
3846
p_f_to_v = mesh.topology.connectivity(entity_tag.dim, 0)
3947
p_f_to_c = mesh.topology.connectivity(entity_tag.dim, mesh.topology.dim)
4048
sub_to_parent_entity_map = np.full(num_child_entities, -1, dtype=np.int32)
41-
for facet, value in zip(entity_tag.indices, entity_tag.values):
42-
facet_found = False
43-
for cell in p_f_to_c.links(facet):
44-
if facet_found:
45-
break
46-
if (child_cell := mesh_to_submesh[cell]) != -1:
47-
for child_facet in c_c_to_e.links(child_cell):
48-
child_vertices = c_e_to_v.links(child_facet)
49-
child_vertices_as_parent = sub_vertex_to_parent[child_vertices]
50-
is_facet = np.isin(
51-
child_vertices_as_parent, p_f_to_v.links(facet)
52-
).all()
53-
if is_facet:
54-
child_markers[child_facet] = value
55-
facet_found = True
56-
sub_to_parent_entity_map[child_facet] = facet
49+
50+
if legacy_entity_map:
51+
for facet, value in zip(entity_tag.indices, entity_tag.values):
52+
facet_found = False
53+
for cell in p_f_to_c.links(facet):
54+
if facet_found:
55+
break
56+
if (child_cell := mesh_to_submesh[cell]) != -1:
57+
for child_facet in c_c_to_e.links(child_cell):
58+
child_vertices = c_e_to_v.links(child_facet)
59+
child_vertices_as_parent = sub_vertex_to_parent[child_vertices]
60+
is_facet = np.isin(
61+
child_vertices_as_parent, p_f_to_v.links(facet)
62+
).all()
63+
if is_facet:
64+
child_markers[child_facet] = value
65+
facet_found = True
66+
sub_to_parent_entity_map[child_facet] = facet
67+
else:
68+
for facet, value in zip(entity_tag.indices, entity_tag.values):
69+
facet_found = False
70+
parent_cells = p_f_to_c.links(facet)
71+
sub_cells = sub_cell_to_parent.sub_topology_to_topology(
72+
parent_cells, inverse=True
73+
)
74+
75+
for child_cell in sub_cells:
76+
if facet_found:
77+
break
78+
if child_cell != -1:
79+
for child_facet in c_c_to_e.links(child_cell):
80+
child_vertices = c_e_to_v.links(child_facet)
81+
child_vertices_as_parent = (
82+
sub_vertex_to_parent.sub_topology_to_topology(
83+
child_vertices, inverse=False
84+
)
85+
)
86+
is_facet = np.isin(
87+
child_vertices_as_parent, p_f_to_v.links(facet)
88+
).all()
89+
if is_facet:
90+
child_markers[child_facet] = value
91+
facet_found = True
92+
sub_to_parent_entity_map[child_facet] = facet
93+
5794
tags = dolfinx.mesh.meshtags(
5895
submesh,
5996
entity_tag.dim,

src/festim/hydrogen_transport_problem.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,10 +1392,14 @@ def mixed_term(u, v, n):
13921392

13931393
n = ufl.FacetNormal(mesh)
13941394
cr = ufl.Circumradius(mesh)
1395-
1396-
entity_maps = {
1397-
sd.submesh: sd.parent_to_submesh for sd in self.volume_subdomains
1398-
}
1395+
try:
1396+
from dolfinx.mesh import EntityMap
1397+
1398+
entity_maps = [sd.cell_map for sd in self.volume_subdomains]
1399+
except ImportError:
1400+
entity_maps = {
1401+
sd.submesh: sd.parent_to_submesh for sd in self.volume_subdomains
1402+
}
13991403
for interface in self.interfaces:
14001404
gamma = interface.penalty_term
14011405

@@ -1532,8 +1536,16 @@ def create_solver(self):
15321536
)
15331537
self.solver.max_iterations = self.settings.max_iterations
15341538
self.solver.convergence_criterion = self.settings.convergence_criterion
1535-
self.solver.atol = self.settings.atol
1536-
self.solver.rtol = self.settings.rtol
1539+
self.solver.atol = (
1540+
self.settings.atol
1541+
if not callable(self.settings.rtol)
1542+
else self.settings.rtol(float(self.t))
1543+
)
1544+
self.solver.rtol = (
1545+
self.settings.rtol
1546+
if not callable(self.settings.rtol)
1547+
else self.settings.rtol(float(self.t))
1548+
)
15371549

15381550
def create_flux_values_fenics(self):
15391551
"""For each particle flux create the ``value_fenics`` attribute"""

src/festim/subdomain/interface.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ def __init__(
3434

3535
def pad_parent_maps(self):
3636
"""Workaround to make sparsity-pattern work without skips"""
37+
try:
38+
# No padding needed for latest version of DOLFINx
39+
from dolfinx.mesh import EntityMap # noqa: F401
40+
41+
return
42+
except ImportError:
43+
pass
3744

3845
if Version(dolfinx.__version__) == Version("0.9.0"):
3946
args = (
@@ -68,7 +75,7 @@ def compute_mapped_interior_facet_data(self, mesh):
6875
Returns
6976
integration_data: Integration data for interior facets
7077
"""
71-
assert (not self.subdomains[0].padded) and (not self.subdomains[1].padded)
78+
7279
mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim)
7380

7481
if Version(dolfinx.__version__) == Version("0.9.0"):
@@ -89,8 +96,23 @@ def compute_mapped_interior_facet_data(self, mesh):
8996

9097
ordered_integration_data = integration_data.reshape(-1, 4).copy()
9198

92-
mapped_cell_0 = self.subdomains[0].parent_to_submesh[integration_data[0::4]]
93-
mapped_cell_1 = self.subdomains[0].parent_to_submesh[integration_data[2::4]]
99+
try:
100+
# No padding needed for latest version of DOLFINx
101+
from dolfinx.mesh import EntityMap # noqa: F401
102+
103+
mapped_cell_0 = self.subdomains[0].cell_map.sub_topology_to_topology(
104+
integration_data[0::4], inverse=True
105+
)
106+
mapped_cell_1 = self.subdomains[0].cell_map.sub_topology_to_topology(
107+
integration_data[2::4], inverse=True
108+
)
109+
legacy_entity_map = False
110+
111+
except ImportError:
112+
assert (not self.subdomains[0].padded) and (not self.subdomains[1].padded)
113+
mapped_cell_0 = self.subdomains[0].parent_to_submesh[integration_data[0::4]]
114+
mapped_cell_1 = self.subdomains[0].parent_to_submesh[integration_data[2::4]]
115+
legacy_entity_map = True
94116

95117
switch = mapped_cell_1 > mapped_cell_0
96118
# Order restriction on one side
@@ -100,9 +122,14 @@ def compute_mapped_interior_facet_data(self, mesh):
100122
]
101123

102124
# Check that other restriction lies in other interface
103-
domain1_cell = self.subdomains[1].parent_to_submesh[
104-
ordered_integration_data[:, 2]
105-
]
125+
if legacy_entity_map:
126+
domain1_cell = self.subdomains[1].parent_to_submesh[
127+
ordered_integration_data[:, 2]
128+
]
129+
else:
130+
domain1_cell = self.subdomains[1].cell_map.sub_topology_to_topology(
131+
ordered_integration_data[:, 2], inverse=True
132+
)
106133
assert (domain1_cell >= 0).all()
107134

108135
return (self.id, ordered_integration_data.reshape(-1))

0 commit comments

Comments
 (0)