Skip to content

Commit 4f35337

Browse files
committed
Add chop smoothing via grading for HighRe grader
Need a better objective function because this doesn't help much.
1 parent b866d36 commit 4f35337

File tree

4 files changed

+136
-32
lines changed

4 files changed

+136
-32
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import os
2+
3+
import classy_blocks as cb
4+
from classy_blocks.grading.autograding.grader import HighReGrader, SimpleGrader
5+
from classy_blocks.grading.autograding.params import HighReChopParams, SimpleChopParams
6+
7+
mesh = cb.Mesh()
8+
9+
base = cb.Grid([0, 0, 0], [3, 2, 0], 3, 2)
10+
11+
shape = cb.ExtrudedShape(base, 1)
12+
mesh.add(shape)
13+
mesh.assemble()
14+
finder = cb.GeometricFinder(mesh)
15+
16+
move_points = [[0, 1, 1], [2, 1, 1], [3, 1, 1]]
17+
18+
for point in move_points:
19+
vertex = list(finder.find_in_sphere(point))[0]
20+
vertex.translate([0, 0.8, 0])
21+
22+
# TODO! Un-hack
23+
mesh.block_list.update()
24+
25+
mesh.set_default_patch("walls", "wall")
26+
27+
params = HighReChopParams(0.1)
28+
grader = HighReGrader(mesh, params)
29+
grader.grade(take="max")
30+
31+
params = SimpleChopParams(0.1)
32+
grader = SimpleGrader(mesh, params)
33+
# grader.grade()
34+
35+
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")

src/classy_blocks/grading/autograding/grader.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from typing import get_args
1+
from typing import Set, get_args
22

33
from classy_blocks.grading.autograding.params import ChopParams, FixedCountParams, HighReChopParams, SimpleChopParams
44
from classy_blocks.grading.autograding.probe import Probe
5+
from classy_blocks.items.wires.wire import Wire
56
from classy_blocks.mesh import Mesh
67
from classy_blocks.types import ChopTakeType, DirectionType
78

@@ -14,13 +15,45 @@ def __init__(self, mesh: Mesh, params: ChopParams):
1415
self.mesh.assemble()
1516
self.probe = Probe(self.mesh)
1617

18+
def _get_end_size(self, wires: Set[Wire]):
19+
"""Returns average size of wires' last cell"""
20+
if len(wires) == 0:
21+
return 0
22+
23+
return sum(wire.grading.end_size for wire in wires) / len(wires)
24+
25+
def _get_start_size(self, wires: Set[Wire]):
26+
"""Returns average size of wires' first cell"""
27+
if len(wires) == 0:
28+
return 0
29+
30+
return sum(wire.grading.start_size for wire in wires) / len(wires)
31+
1732
def grade_axis(self, axis: DirectionType, take: ChopTakeType) -> None:
1833
for row in self.probe.get_rows(axis):
19-
length = row.get_length(take)
20-
count = self.params.get_count(length)
34+
# determine count
35+
wires = row.get_wires()
36+
37+
for wire in wires:
38+
if wire.is_defined:
39+
# there's a wire with a defined count already, use that
40+
count = wire.grading.count
41+
break
42+
else:
43+
# take length from a row, as requested
44+
length = row.get_length(take)
45+
count = self.params.get_count(length)
2146

2247
for wire in row.get_wires():
23-
chops = self.params.get_chops(count, wire.length)
48+
# don't touch defined wires
49+
if wire.is_defined:
50+
# TODO: test
51+
continue
52+
53+
size_before = self._get_end_size(wire.before)
54+
size_after = self._get_start_size(wire.after)
55+
chops = self.params.get_chops(count, wire.length, size_before, size_after)
56+
2457
for chop in chops:
2558
wire.grading.add_chop(chop)
2659

src/classy_blocks/grading/autograding/params.py

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import warnings
44
from typing import List, Tuple
55

6-
from classy_blocks.grading import relations as gr
6+
import scipy.optimize
7+
8+
import classy_blocks.grading.relations as gr
79
from classy_blocks.grading.chop import Chop
810
from classy_blocks.types import ChopTakeType
911

@@ -20,23 +22,13 @@ def sum_length(start_size: float, count: int, c2c_expansion: float) -> float:
2022
return length
2123

2224

23-
def sum_count(lengths: List[float], chops: List[Chop]):
24-
count = 0
25-
26-
for i, chop in enumerate(chops):
27-
length = lengths[i]
28-
count += chop.calculate(length).count
29-
30-
return count
31-
32-
3325
class ChopParams(abc.ABC):
3426
@abc.abstractmethod
3527
def get_count(self, length: float) -> int:
3628
"""Calculates count based on given length - used once only"""
3729

3830
@abc.abstractmethod
39-
def get_chops(self, count: int, length: float) -> List[Chop]:
31+
def get_chops(self, count: int, length: float, size_before: float = 0, size_after: float = 0) -> List[Chop]:
4032
"""Fixes cell count but modifies chops so that proper cell sizing will be obeyed"""
4133
# That depends on inherited classes' philosophy
4234

@@ -48,7 +40,7 @@ class FixedCountParams(ChopParams):
4840
def get_count(self, _length):
4941
return self.count
5042

51-
def get_chops(self, count, _length) -> List[Chop]:
43+
def get_chops(self, count, _length, _size_before=0, _size_after=0) -> List[Chop]:
5244
return [Chop(count=count)]
5345

5446

@@ -60,7 +52,7 @@ class SimpleChopParams(ChopParams):
6052
def get_count(self, length: float):
6153
return int(length / self.cell_size)
6254

63-
def get_chops(self, count, _length):
55+
def get_chops(self, count, _length, _size_before=0, _size_after=0):
6456
return [Chop(count=count)]
6557

6658

@@ -69,17 +61,61 @@ class HighReChopParams(ChopParams):
6961
cell_size: float
7062

7163
def get_count(self, length: float):
72-
# the first chop defines the count; it's a very simple one
73-
return int(length / self.cell_size)
74-
75-
def get_chops(self, count: int, _):
76-
# TODO: adjust length ratio for smoothest transition in the middle of block
77-
return [
78-
Chop(length_ratio=0.5, count=count // 2, start_size=self.cell_size),
79-
Chop(length_ratio=0.5, count=count // 2, end_size=self.cell_size),
64+
# the first chop defines the count;
65+
count = int(length / self.cell_size)
66+
# it must be divisible by 2
67+
if count % 2 != 0:
68+
count += 1
69+
70+
return count
71+
72+
def get_chops(self, count, length, size_before=0, size_after=0):
73+
# length of the wire that was used to set count
74+
if size_before == 0:
75+
size_before = self.cell_size
76+
if size_after == 0:
77+
size_after = self.cell_size
78+
79+
chops = [
80+
Chop(count=count // 2),
81+
Chop(count=count // 2),
8082
]
8183

84+
def objfun(params):
85+
chops[0].length_ratio = params[0]
86+
chops[1].length_ratio = 1 - params[0]
87+
88+
chops[0].total_expansion = params[1]
89+
chops[1].total_expansion = params[2]
90+
91+
data_1 = chops[0].calculate(length)
92+
data_2 = chops[1].calculate(length)
8293

94+
ofstart = (size_before - data_1.start_size) ** 2
95+
ofmid1 = (data_1.end_size - self.cell_size) ** 2
96+
ofmid2 = (data_2.start_size - self.cell_size) ** 2
97+
ofend = (data_2.end_size - size_after) ** 2
98+
99+
return max([ofstart, ofmid1, ofmid2, ofend])
100+
101+
initial = [0.5, 1, 1]
102+
bounds = (
103+
(0.1, 0.9),
104+
(0.1, 10),
105+
(0.1, 10),
106+
)
107+
result = scipy.optimize.minimize(objfun, initial, bounds=bounds).x
108+
109+
chops[0].length_ratio = result[0]
110+
chops[1].length_ratio = 1 - result[0]
111+
112+
chops[0].total_expansion = result[1]
113+
chops[1].total_expansion = result[2]
114+
115+
return chops
116+
117+
118+
# INVALID! Next on list
83119
@dataclasses.dataclass
84120
class LowReChopParams(ChopParams):
85121
"""Parameters for mesh grading for Low-Re cases.
@@ -164,16 +200,17 @@ def get_count(self, length: float):
164200

165201
if remaining_length <= 0:
166202
warnings.warn("Stopping chops at boundary layer (not enough space)!", stacklevel=1)
167-
return sum_count([length], chops)
203+
# return chops
204+
return 0
168205

169206
# buffer
170207
buffer, buffer_size = self._get_buffer_chop(last_bl_size)
171208
buffer.length_ratio = buffer_size / length
172209
chops.append(buffer)
173210
if buffer_size >= remaining_length:
174211
warnings.warn("Stopping chops at buffer layer (not enough space)!", stacklevel=1)
175-
176-
return sum_count([self.boundary_layer_thickness, buffer_size], chops)
212+
# return chops
213+
return 1
177214

178215
# bulk
179216
remaining_length = remaining_length - buffer_size
@@ -182,7 +219,7 @@ def get_count(self, length: float):
182219
chops.append(bulk)
183220

184221
# return chops
185-
return sum_count([self.boundary_layer_thickness, buffer_size, remaining_length], chops)
222+
return 1
186223

187-
def get_chops(self, count: int, length: float) -> List[Chop]:
224+
def get_chops(self, count, length, size_before=0, size_after=0) -> List[Chop]:
188225
raise NotImplementedError("TODO!")

src/classy_blocks/mesh.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,3 @@ def operations(self) -> List[Operation]:
258258
@property
259259
def blocks(self) -> List[Block]:
260260
return self.block_list.blocks
261-
return self.block_list.blocks

0 commit comments

Comments
 (0)