Skip to content

Commit 7c10c22

Browse files
add Topology.partition_interfaces
1 parent a0c90c7 commit 7c10c22

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

nutils/topology.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,35 @@ def interfaces_spaces_unchecked(self, __spaces: FrozenSet[str]) -> 'Topology':
11201120

11211121
raise NotImplementedError
11221122

1123+
def partition_interfaces(self, part_indices: Sequence[int]) -> 'Topology':
1124+
'''Return the interfaces between all parts of an element partition.
1125+
1126+
Given a partition of elements, this function returns the subset of
1127+
interfaces that face two different parts. The orientation of the
1128+
interfaces is arbitrary.
1129+
1130+
Parameters
1131+
----------
1132+
part_indices : sequence or :class:`numpy.ndarray` of :class:`int`
1133+
For each element the index of the part the element belongs to.
1134+
1135+
Returns
1136+
-------
1137+
:class:`Topology`
1138+
The interfaces between all parts of the element partition, a subset
1139+
of :attr:`Topology.interfaces`.
1140+
'''
1141+
1142+
part_indices = function.Array.cast(part_indices)
1143+
if part_indices.dtype not in (bool, int):
1144+
raise ValueError(f'expected a sequence of integer part indices but got a sequence of type {part_indices.dtype}')
1145+
if part_indices.shape != (len(self),):
1146+
raise ValueError(f'expected a sequence of {len(self)} integer part indices but got an array with shape {part_indices.shape}')
1147+
interfaces = self.interfaces
1148+
part_indices = numpy.take(part_indices, self.f_index)
1149+
isnt_partition_interface = interfaces.elementwise_stack(part_indices == function.opposite(part_indices))
1150+
return interfaces.compress(~function.eval(isnt_partition_interface))
1151+
11231152
def basis_discont(self, degree: int) -> function.Basis:
11241153
'discontinuous shape functions'
11251154

tests/test_topology.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,11 @@ def test_elementwise_stack_mul(self):
627627
stack = self.topo.elementwise_stack(numpy.stack([self.topo1.f_index, self.topo2.f_index]), axis=1)
628628
self.assertEqual(function.eval(stack).tolist(), desired.tolist())
629629

630+
def test_partition_interfaces(self):
631+
centers = self.topo.partition_interfaces([0, 0, 1, 2, 1, 1]).sample('gauss', 0).eval(self.geom).tolist()
632+
centers.sort()
633+
self.assertAllAlmostEqual(centers, [[0.5, 2.0], [1.0, 0.5], [1.0, 1.5], [1.5, 1.0]])
634+
630635

631636
class NewWithGroupAliases(TestCase, CommonTests, ConformingTests):
632637

@@ -1365,6 +1370,11 @@ def setUp(self):
13651370
self.desired_references = [element.LineReference()**2]*4
13661371
self.desired_vertices = [[[x, y] for x in X for y in Y] for X in pairwise(range(3)) for Y in pairwise(range(3))]
13671372

1373+
def test_partition_interfaces(self):
1374+
centers = self.topo.partition_interfaces([0, 0, 1, 2]).sample('gauss', 0).eval(self.geom).tolist()
1375+
centers.sort()
1376+
self.assertAllAlmostEqual(centers, [[1.0, 0.5], [1.0, 1.5], [1.5, 1.0]])
1377+
13681378

13691379
class UnionTopology(TestCase, CommonTests, TransformChainsTests):
13701380

0 commit comments

Comments
 (0)