Skip to content

Commit 2045c82

Browse files
Fix assign for MixedFunctionSpace and correct 'ancester' typo (#4888)
Add submesh_youngest_common_ancestor to MeshSequenceGeometry so that assign between functions on distinct but equal MixedFunctionSpaces works. This fixes a regression introduced by #4849 where extract_unique_domain with expand_mesh_sequence=False returns a MeshSequenceGeometry that lacks the method. Also corrects the spelling of 'ancester' to 'ancestor' throughout. Fixes #4887 Fixes g-adopt/g-adopt#452
1 parent fb3078f commit 2045c82

File tree

5 files changed

+39
-19
lines changed

5 files changed

+39
-19
lines changed

firedrake/assign.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ def __init__(self, assignee, expression, subset=None):
167167
elif len(source_meshes) == 1:
168168
target_mesh = extract_unique_domain(assignee, expand_mesh_sequence=False)
169169
source_mesh, = source_meshes
170-
if target_mesh is source_mesh:
170+
if target_mesh == source_mesh:
171171
pass
172-
elif target_mesh.submesh_youngest_common_ancester(source_mesh) is None:
172+
elif target_mesh.submesh_youngest_common_ancestor(source_mesh) is None:
173173
raise ValueError(
174174
"All functions in the expression must be defined on a single domain "
175175
"that is in the same submesh family as domain of the assignee"

firedrake/interpolation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def _interpolator(self):
183183

184184
submesh_interp_implemented = (
185185
all(isinstance(m.topology, MeshTopology) for m in [target_mesh, source_mesh])
186-
and target_mesh.submesh_ancesters[-1] is source_mesh.submesh_ancesters[-1]
186+
and target_mesh.submesh_ancestors[-1] is source_mesh.submesh_ancestors[-1]
187187
and target_mesh.topological_dimension == source_mesh.topological_dimension
188188
)
189189
if target_mesh is source_mesh or submesh_interp_implemented:

firedrake/mesh.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -940,15 +940,15 @@ def unique(self):
940940
# submesh
941941

942942
@utils.cached_property
943-
def submesh_ancesters(self):
944-
"""Tuple of submesh ancesters."""
943+
def submesh_ancestors(self):
944+
"""Tuple of submesh ancestors."""
945945
if self.submesh_parent:
946-
return (self, ) + self.submesh_parent.submesh_ancesters
946+
return (self, ) + self.submesh_parent.submesh_ancestors
947947
else:
948948
return (self, )
949949

950-
def submesh_youngest_common_ancester(self, other):
951-
"""Return the youngest common ancester of self and other.
950+
def submesh_youngest_common_ancestor(self, other):
951+
"""Return the youngest common ancestor of self and other.
952952
953953
Parameters
954954
----------
@@ -958,18 +958,18 @@ def submesh_youngest_common_ancester(self, other):
958958
Returns
959959
-------
960960
AbstractMeshTopology or None
961-
Youngest common ancester or None if not found.
961+
Youngest common ancestor or None if not found.
962962
963963
"""
964964
# self --- ... --- m --- common --- common --- common
965965
# /
966966
# other --- ... --- m
967-
self_ancesters = list(self.submesh_ancesters)
968-
other_ancesters = list(other.submesh_ancesters)
967+
self_ancestors = list(self.submesh_ancestors)
968+
other_ancestors = list(other.submesh_ancestors)
969969
c = None
970-
while self_ancesters and other_ancesters:
971-
a = self_ancesters.pop()
972-
b = other_ancesters.pop()
970+
while self_ancestors and other_ancestors:
971+
a = self_ancestors.pop()
972+
b = other_ancestors.pop()
973973
if a is b:
974974
c = a
975975
else:
@@ -1014,17 +1014,17 @@ def submesh_map_composed(self, other, other_integral_type, other_subset_points):
10141014
Tuple of `op2.ComposedMap` from other to self, integral_type on self, and points on self.
10151015
10161016
"""
1017-
common = self.submesh_youngest_common_ancester(other)
1017+
common = self.submesh_youngest_common_ancestor(other)
10181018
if common is None:
10191019
raise ValueError(f"Unable to create composed map between (sub)meshes: {self} and {other} are unrelated")
10201020
maps = []
10211021
integral_type = other_integral_type
10221022
subset_points = other_subset_points
1023-
aa = other.submesh_ancesters
1023+
aa = other.submesh_ancestors
10241024
for a in aa[:aa.index(common)]:
10251025
m, integral_type, subset_points = a.submesh_map_child_parent(integral_type, subset_points)
10261026
maps.append(m)
1027-
bb = self.submesh_ancesters
1027+
bb = self.submesh_ancestors
10281028
for b in reversed(bb[:bb.index(common)]):
10291029
m, integral_type, subset_points = b.submesh_map_child_parent(integral_type, subset_points, reverse=True)
10301030
maps.append(m)
@@ -1727,7 +1727,7 @@ def trans_mesh_entity_map(self, base_mesh, base_integral_type, base_subdomain_id
17271727
`tuple` of `op2.ComposedMap` from base_mesh to `self` and integral_type on `self`.
17281728
17291729
"""
1730-
common = self.submesh_youngest_common_ancester(base_mesh)
1730+
common = self.submesh_youngest_common_ancestor(base_mesh)
17311731
if common is None:
17321732
raise NotImplementedError(f"Currently only implemented for (sub)meshes in the same family: got {self} and {base_mesh}")
17331733
elif base_mesh is self:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from firedrake import *
2+
import numpy as np
3+
4+
5+
def test_single_mesh_mixed_assign():
6+
"""Assigning between functions on separately constructed but equivalent
7+
MixedFunctionSpaces should work and preserve values."""
8+
mesh = UnitSquareMesh(4, 4)
9+
V = VectorFunctionSpace(mesh, "CG", 1)
10+
W = FunctionSpace(mesh, "CG", 1)
11+
12+
z = Function(MixedFunctionSpace([V, W]))
13+
z.subfunctions[0].assign(Constant((1.0, 2.0)))
14+
z.subfunctions[1].assign(3.0)
15+
16+
w = Function(MixedFunctionSpace([V, W]))
17+
w.assign(z)
18+
19+
assert np.allclose(w.subfunctions[0].dat.data_ro, [1.0, 2.0])
20+
assert np.allclose(w.subfunctions[1].dat.data_ro, 3.0)

tsfc/driver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def validate_domains(form):
189189
# Check that all domains are related to each other
190190
domain = itg.ufl_domain()
191191
for other_domain in itg.extra_domain_integral_type_map():
192-
if domain.submesh_youngest_common_ancester(other_domain) is None:
192+
if domain.submesh_youngest_common_ancestor(other_domain) is None:
193193
raise MismatchingDomainError("Assembly of forms over unrelated meshes is not supported. "
194194
"Try using Submeshes or cross-mesh interpolation.")
195195

0 commit comments

Comments
 (0)