Skip to content

Commit 4a9b280

Browse files
committed
Add InflationGrader logic
Doesn't work because WireInfo.starts_at_wall (and ends) doesn't work correctly. Have to rewrite the logic in Probe.
1 parent b303c71 commit 4a9b280

File tree

3 files changed

+107
-12
lines changed

3 files changed

+107
-12
lines changed

examples/advanced/inflation_grader.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
3+
import numpy as np
4+
5+
import classy_blocks as cb
6+
from classy_blocks.grading.autograding.grader import InflationGrader
7+
8+
mesh = cb.Mesh()
9+
10+
base = cb.Grid([0, 0, 0], [3, 2, 0], 3, 2)
11+
12+
shape = cb.ExtrudedShape(base, 1)
13+
14+
# turn one block around to test grader's skillz
15+
shape.grid[1][0].rotate(np.pi, [0, 0, 1])
16+
17+
mesh.add(shape)
18+
19+
mesh.set_default_patch("boundary", "patch")
20+
for i in (0, 1, 2):
21+
shape.operations[i].set_patch("front", "walls")
22+
mesh.modify_patch("walls", "wall")
23+
24+
# move some points to get a mesh with uneven blocks
25+
mesh.assemble()
26+
finder = cb.GeometricFinder(mesh)
27+
28+
move_points = [[0, 1, 1], [2, 1, 1], [3, 1, 1]]
29+
30+
for point in move_points:
31+
vertex = list(finder.find_in_sphere(point))[0]
32+
vertex.translate([0, 0.8, 0])
33+
34+
35+
# TODO: Hack! mesh.assemble() won't work here but wires et. al. must be updated
36+
mesh.block_list.update()
37+
38+
grader = InflationGrader(mesh, 1e-3, 0.1)
39+
grader.grade()
40+
41+
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")

src/classy_blocks/grading/autograding/grader.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ class GraderBase:
2121
1. Set count
2222
If there's a wire on the wall - determine 'wall' count (low-re grading etc)
2323
If not, determine 'bulk' count
24-
25-
That involves the 'take' keyword so that appropriate block is taken as a reference;
26-
2. Chop 'cramped' blocks
24+
That involves the 'take' keyword so that appropriate block is taken as a reference;
25+
If there's a wire that has a count, defined by user, use that unconditionally
26+
2. Chop 'squeezed' blocks
2727
Where there's not enough space to fit graded cells, use a simple grading
28+
(or whatever the grader defines)
2829
3. Chop other blocks
2930
optionally use multigrading to match neighbours' cell sizes
3031
"""

src/classy_blocks/grading/autograding/params/inflation.py

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class Layer(abc.ABC):
1515
start_size: float
1616
c2c_expansion: float
1717

18-
def __init__(self, max_length: float):
19-
self.max_length = max_length
18+
def __init__(self, remainder: float):
19+
# remaining length of the wire
20+
self.remainder = remainder
2021

2122
@property
2223
@abc.abstractmethod
@@ -26,7 +27,7 @@ def length(self) -> float:
2627
@property
2728
def count(self) -> int:
2829
"""Returns cell count in this layer"""
29-
length = min(self.length, self.max_length)
30+
length = min(self.length, self.remainder)
3031
return gr.get_count__start_size__c2c_expansion(length, self.start_size, self.c2c_expansion)
3132

3233
@property
@@ -41,7 +42,26 @@ def end_size(self) -> float:
4142
@property
4243
def is_final(self) -> bool:
4344
"""Returns True if this layer is the last (no more space for additional ones)"""
44-
return self.length >= self.max_length
45+
return self.length >= self.remainder
46+
47+
def get_chop(self, total_count: int, invert: bool) -> Chop:
48+
"""Returns a Chop with either this layer's count or given one,
49+
whichever is lower"""
50+
# length ratios will be normalized later
51+
if invert:
52+
return Chop(
53+
length_ratio=self.length,
54+
end_size=self.end_size,
55+
c2c_expansion=1 / self.c2c_expansion,
56+
count=max(self.count, total_count),
57+
)
58+
59+
return Chop(
60+
length_ratio=self.length,
61+
start_size=self.start_size,
62+
c2c_expansion=self.c2c_expansion,
63+
count=max(self.count, total_count),
64+
)
4565

4666
def __repr__(self):
4767
return f"{self.length}-{self.count}"
@@ -57,7 +77,7 @@ def __init__(self, wall_size: float, c2c_expansion: float, thickness_factor: int
5777

5878
@property
5979
def length(self):
60-
return min(self.max_length, self.start_size * self.thickness_factor)
80+
return min(self.remainder, self.start_size * self.thickness_factor)
6181

6282

6383
class BufferLayer(Layer):
@@ -100,17 +120,17 @@ def last_size(self):
100120

101121

102122
class BulkLayer(Layer):
103-
def __init__(self, cell_size: float, remaning_length: float):
123+
def __init__(self, cell_size: float, remainder: float):
104124
self.start_size = cell_size
105125

106126
self.cell_size = cell_size
107127
self.c2c_expansion = 1
108128

109-
super().__init__(remaning_length)
129+
super().__init__(remainder)
110130

111131
@property
112132
def length(self):
113-
return self.max_length
133+
return self.remainder
114134

115135
@property
116136
def last_size(self):
@@ -145,6 +165,26 @@ def is_done(self) -> bool:
145165

146166
return self.remaining_length <= 0
147167

168+
def get_chops(self, total_count: int, invert: bool) -> List[Chop]:
169+
chops: List[Chop] = []
170+
171+
for layer in self.layers:
172+
chop = layer.get_chop(total_count, invert)
173+
chops.append(chop)
174+
175+
total_count -= layer.count
176+
177+
if total_count <= 0:
178+
break
179+
180+
# normalize length_ratios
181+
ratios = [chop.length_ratio for chop in chops]
182+
183+
for chop in chops:
184+
chop.length_ratio = chop.length_ratio / sum(ratios)
185+
186+
return chops
187+
148188

149189
class InflationGraderParams(SmoothGraderParams):
150190
"""See description of InflationGrader"""
@@ -165,6 +205,7 @@ def __init__(
165205
self.bl_thickness_factor = bl_thickness_factor
166206
self.buffer_expansion = buffer_expansion
167207

208+
# use SmoothGrader's logic for bulk chops
168209
self.cell_size = self.bulk_cell_size
169210

170211
def get_inflation_layer(self, max_length: float) -> InflationLayer:
@@ -195,6 +236,8 @@ def get_stack(self, length: float) -> LayerStack:
195236
return stack
196237

197238
def get_count(self, length: float, starts_at_wall: bool, ends_at_wall: bool):
239+
print(starts_at_wall, ends_at_wall)
240+
198241
if not (starts_at_wall or ends_at_wall):
199242
return super().get_count(length, False, False)
200243

@@ -211,6 +254,8 @@ def is_squeezed(self, count: int, info: WireInfo) -> bool:
211254
if not (info.starts_at_wall or info.ends_at_wall):
212255
return super().is_squeezed(count, info)
213256

257+
# a squeezed wire is one that can't fit all layers
258+
# or one that can't fit all cells
214259
stack = self.get_stack(info.length)
215260

216261
if len(stack.layers) == 3:
@@ -222,4 +267,12 @@ def get_chops(self, count, info: WireInfo) -> List[Chop]:
222267
if not (info.starts_at_wall or info.ends_at_wall):
223268
return super().get_chops(count, info)
224269

225-
raise NotImplementedError
270+
stack = self.get_stack(info.length)
271+
272+
if info.starts_at_wall and info.ends_at_wall:
273+
raise NotImplementedError
274+
275+
if info.ends_at_wall:
276+
return list(reversed(stack.get_chops(count, True)))
277+
278+
return stack.get_chops(count, False)

0 commit comments

Comments
 (0)