Skip to content

Commit c70979e

Browse files
committed
Add search for vertices on wall patches to Probe
1 parent 536b0c4 commit c70979e

File tree

3 files changed

+124
-3
lines changed

3 files changed

+124
-3
lines changed

src/classy_blocks/grading/autograding/probe.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import functools
2-
from typing import Dict, List, Optional, get_args
2+
from typing import Dict, List, Optional, Set, get_args
33

44
from classy_blocks.base.exceptions import BlockNotFoundError, NoInstructionError
55
from classy_blocks.items.block import Block
6+
from classy_blocks.items.vertex import Vertex
67
from classy_blocks.items.wires.axis import Axis
78
from classy_blocks.items.wires.wire import Wire
89
from classy_blocks.mesh import Mesh
9-
from classy_blocks.types import ChopTakeType, DirectionType
10+
from classy_blocks.optimize.grid import HexGrid
11+
from classy_blocks.types import ChopTakeType, DirectionType, OrientType
12+
from classy_blocks.util.constants import FACE_MAP
1013

1114

1215
@functools.lru_cache(maxsize=3000) # that's for 1000 blocks
@@ -18,6 +21,20 @@ def get_block_from_axis(mesh: Mesh, axis: Axis) -> Block:
1821
raise RuntimeError("Block for Axis not found!")
1922

2023

24+
@functools.lru_cache(maxsize=2)
25+
def get_defined_wall_vertices(mesh: Mesh) -> Set[Vertex]:
26+
"""Returns vertices that are on the 'wall' patches"""
27+
wall_vertices: set[Vertex] = set()
28+
29+
# explicitly defined walls
30+
for patch in mesh.patches:
31+
if patch.kind == "wall":
32+
for side in patch.sides:
33+
wall_vertices.update(set(side.vertices))
34+
35+
return wall_vertices
36+
37+
2138
class Instruction:
2239
"""A descriptor that tells in which direction the specific block can be chopped."""
2340

@@ -151,10 +168,46 @@ class Probe:
151168

152169
def __init__(self, mesh: Mesh):
153170
self.mesh = mesh
171+
172+
# maps blocks to rows
154173
self.catalogue = Catalogue(self.mesh)
155174

175+
# finds blocks' neighbours
176+
self.grid = HexGrid.from_mesh(self.mesh)
177+
156178
def get_row_blocks(self, block: Block, direction: DirectionType) -> List[Block]:
157179
return self.catalogue.get_row_blocks(block, direction)
158180

159181
def get_rows(self, direction: DirectionType) -> List[Row]:
160182
return self.catalogue.rows[direction]
183+
184+
def get_explicit_wall_vertices(self, block: Block) -> Set[Vertex]:
185+
"""Returns vertices from a block that lie on explicitly defined wall patches"""
186+
mesh_vertices = get_defined_wall_vertices(self.mesh)
187+
block_vertices = set(block.vertices)
188+
189+
return block_vertices.intersection(mesh_vertices)
190+
191+
def get_default_wall_vertices(self, block: Block) -> Set[Vertex]:
192+
"""Returns vertices that lie on default 'wall' patch"""
193+
wall_vertices: Set[Vertex] = set()
194+
195+
# other sides when mesh has a default wall patch
196+
if self.mesh.patch_list.default["kind"] == "wall":
197+
# find block boundaries
198+
block_index = self.mesh.blocks.index(block)
199+
cell = self.grid.cells[block_index]
200+
201+
# sides with no neighbours are on boundary
202+
boundaries: List[OrientType] = [
203+
orient for orient, neighbours in cell.neighbours.items() if neighbours is None
204+
]
205+
206+
for orient in boundaries:
207+
wall_vertices.union({block.vertices[i] for i in FACE_MAP[orient]})
208+
209+
return wall_vertices
210+
211+
def get_wall_vertices(self, block: Block) -> Set[Vertex]:
212+
"""Returns vertices that are on the 'wall' patches"""
213+
return self.get_explicit_wall_vertices(block).union(self.get_default_wall_vertices(block))

src/classy_blocks/mesh.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from classy_blocks.construct.shape import Shape
99
from classy_blocks.construct.stack import Stack
1010
from classy_blocks.items.block import Block
11+
from classy_blocks.items.patch import Patch
1112
from classy_blocks.items.vertex import Vertex
1213
from classy_blocks.lists.block_list import BlockList
1314
from classy_blocks.lists.edge_list import EdgeList
@@ -243,6 +244,10 @@ def is_assembled(self) -> bool:
243244
def vertices(self) -> List[Vertex]:
244245
return self.vertex_list.vertices
245246

247+
@property
248+
def patches(self) -> List[Patch]:
249+
return list(self.patch_list.patches.values())
250+
246251
@property
247252
def operations(self) -> List[Operation]:
248253
"""Returns a list of operations from all entities in depot"""

tests/test_grading/test_probe.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
from typing import get_args
1+
from typing import Set, get_args
22

33
from parameterized import parameterized
44

55
from classy_blocks.grading.autograding.probe import Probe, get_block_from_axis
6+
from classy_blocks.items.vertex import Vertex
67
from classy_blocks.mesh import Mesh
8+
from classy_blocks.modify.find.shape import RoundSolidFinder
79
from classy_blocks.types import DirectionType
810
from tests.test_grading.test_autograde import AutogradeTestsBase
911

@@ -98,3 +100,64 @@ def test_get_blocks_cylinder(self, axis, row, blocks):
98100
indexes.add(block.index)
99101

100102
self.assertSetEqual(indexes, blocks)
103+
104+
def test_wall_vertices_defined(self) -> None:
105+
"""Catch wall vertices from explicitly defined wall patches"""
106+
cylinder = self.get_cylinder()
107+
cylinder.set_outer_patch("outer")
108+
109+
self.mesh.add(cylinder)
110+
self.mesh.modify_patch("outer", "wall")
111+
self.mesh.assemble()
112+
113+
probe = Probe(self.mesh)
114+
115+
finder = RoundSolidFinder(self.mesh, cylinder)
116+
shell_vertices = finder.find_shell(True).union(finder.find_shell(False))
117+
wall_vertices: Set[Vertex] = set()
118+
119+
for block in self.mesh.blocks:
120+
wall_vertices.update(probe.get_explicit_wall_vertices(block))
121+
122+
self.assertSetEqual(shell_vertices, wall_vertices)
123+
124+
def test_wall_vertices_default(self) -> None:
125+
"""Catch wall vertices from default patch"""
126+
cylinder = self.get_cylinder()
127+
cylinder.set_start_patch("inlet")
128+
cylinder.set_end_patch("outlet")
129+
130+
self.mesh.set_default_patch("outer", "wall")
131+
self.mesh.assemble()
132+
133+
probe = Probe(self.mesh)
134+
135+
finder = RoundSolidFinder(self.mesh, cylinder)
136+
shell_vertices = finder.find_shell(True).union(finder.find_shell(False))
137+
wall_vertices: Set[Vertex] = set()
138+
139+
for block in self.mesh.blocks:
140+
wall_vertices.update(probe.get_default_wall_vertices(block))
141+
142+
self.assertSetEqual(shell_vertices, wall_vertices)
143+
144+
def test_wall_vertices_combined(self) -> None:
145+
cylinder = self.get_cylinder()
146+
cylinder.set_end_patch("outlet")
147+
148+
cylinder.set_start_patch("bottom")
149+
self.mesh.modify_patch("bottom", "wall")
150+
151+
self.mesh.set_default_patch("outer", "wall")
152+
self.mesh.assemble()
153+
154+
probe = Probe(self.mesh)
155+
156+
finder = RoundSolidFinder(self.mesh, cylinder)
157+
shell_vertices = finder.find_shell(True).union(finder.find_shell(False)).union(finder.find_core(False))
158+
wall_vertices: Set[Vertex] = set()
159+
160+
for block in self.mesh.blocks:
161+
wall_vertices.update(probe.get_default_wall_vertices(block))
162+
163+
self.assertSetEqual(shell_vertices, wall_vertices)

0 commit comments

Comments
 (0)