Skip to content

Commit

Permalink
Add InflationGrader logic
Browse files Browse the repository at this point in the history
Doesn't work because WireInfo.starts_at_wall (and ends) doesn't work
correctly. Have to rewrite the logic in Probe.
  • Loading branch information
FranzBangar committed Nov 17, 2024
1 parent b303c71 commit 4a9b280
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 12 deletions.
41 changes: 41 additions & 0 deletions examples/advanced/inflation_grader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os

import numpy as np

import classy_blocks as cb
from classy_blocks.grading.autograding.grader import InflationGrader

mesh = cb.Mesh()

base = cb.Grid([0, 0, 0], [3, 2, 0], 3, 2)

shape = cb.ExtrudedShape(base, 1)

# turn one block around to test grader's skillz
shape.grid[1][0].rotate(np.pi, [0, 0, 1])

mesh.add(shape)

mesh.set_default_patch("boundary", "patch")
for i in (0, 1, 2):
shape.operations[i].set_patch("front", "walls")
mesh.modify_patch("walls", "wall")

# move some points to get a mesh with uneven blocks
mesh.assemble()
finder = cb.GeometricFinder(mesh)

move_points = [[0, 1, 1], [2, 1, 1], [3, 1, 1]]

for point in move_points:
vertex = list(finder.find_in_sphere(point))[0]
vertex.translate([0, 0.8, 0])


# TODO: Hack! mesh.assemble() won't work here but wires et. al. must be updated
mesh.block_list.update()

grader = InflationGrader(mesh, 1e-3, 0.1)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
7 changes: 4 additions & 3 deletions src/classy_blocks/grading/autograding/grader.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ class GraderBase:
1. Set count
If there's a wire on the wall - determine 'wall' count (low-re grading etc)
If not, determine 'bulk' count
That involves the 'take' keyword so that appropriate block is taken as a reference;
2. Chop 'cramped' blocks
That involves the 'take' keyword so that appropriate block is taken as a reference;
If there's a wire that has a count, defined by user, use that unconditionally
2. Chop 'squeezed' blocks
Where there's not enough space to fit graded cells, use a simple grading
(or whatever the grader defines)
3. Chop other blocks
optionally use multigrading to match neighbours' cell sizes
"""
Expand Down
71 changes: 62 additions & 9 deletions src/classy_blocks/grading/autograding/params/inflation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ class Layer(abc.ABC):
start_size: float
c2c_expansion: float

def __init__(self, max_length: float):
self.max_length = max_length
def __init__(self, remainder: float):
# remaining length of the wire
self.remainder = remainder

@property
@abc.abstractmethod
Expand All @@ -26,7 +27,7 @@ def length(self) -> float:
@property
def count(self) -> int:
"""Returns cell count in this layer"""
length = min(self.length, self.max_length)
length = min(self.length, self.remainder)
return gr.get_count__start_size__c2c_expansion(length, self.start_size, self.c2c_expansion)

@property
Expand All @@ -41,7 +42,26 @@ def end_size(self) -> float:
@property
def is_final(self) -> bool:
"""Returns True if this layer is the last (no more space for additional ones)"""
return self.length >= self.max_length
return self.length >= self.remainder

def get_chop(self, total_count: int, invert: bool) -> Chop:
"""Returns a Chop with either this layer's count or given one,
whichever is lower"""
# length ratios will be normalized later
if invert:
return Chop(
length_ratio=self.length,
end_size=self.end_size,
c2c_expansion=1 / self.c2c_expansion,
count=max(self.count, total_count),
)

return Chop(
length_ratio=self.length,
start_size=self.start_size,
c2c_expansion=self.c2c_expansion,
count=max(self.count, total_count),
)

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

@property
def length(self):
return min(self.max_length, self.start_size * self.thickness_factor)
return min(self.remainder, self.start_size * self.thickness_factor)


class BufferLayer(Layer):
Expand Down Expand Up @@ -100,17 +120,17 @@ def last_size(self):


class BulkLayer(Layer):
def __init__(self, cell_size: float, remaning_length: float):
def __init__(self, cell_size: float, remainder: float):
self.start_size = cell_size

self.cell_size = cell_size
self.c2c_expansion = 1

super().__init__(remaning_length)
super().__init__(remainder)

@property
def length(self):
return self.max_length
return self.remainder

@property
def last_size(self):
Expand Down Expand Up @@ -145,6 +165,26 @@ def is_done(self) -> bool:

return self.remaining_length <= 0

def get_chops(self, total_count: int, invert: bool) -> List[Chop]:
chops: List[Chop] = []

for layer in self.layers:
chop = layer.get_chop(total_count, invert)
chops.append(chop)

total_count -= layer.count

if total_count <= 0:
break

# normalize length_ratios
ratios = [chop.length_ratio for chop in chops]

for chop in chops:
chop.length_ratio = chop.length_ratio / sum(ratios)

return chops


class InflationGraderParams(SmoothGraderParams):
"""See description of InflationGrader"""
Expand All @@ -165,6 +205,7 @@ def __init__(
self.bl_thickness_factor = bl_thickness_factor
self.buffer_expansion = buffer_expansion

# use SmoothGrader's logic for bulk chops
self.cell_size = self.bulk_cell_size

def get_inflation_layer(self, max_length: float) -> InflationLayer:
Expand Down Expand Up @@ -195,6 +236,8 @@ def get_stack(self, length: float) -> LayerStack:
return stack

def get_count(self, length: float, starts_at_wall: bool, ends_at_wall: bool):
print(starts_at_wall, ends_at_wall)

if not (starts_at_wall or ends_at_wall):
return super().get_count(length, False, False)

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

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

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

raise NotImplementedError
stack = self.get_stack(info.length)

if info.starts_at_wall and info.ends_at_wall:
raise NotImplementedError

if info.ends_at_wall:
return list(reversed(stack.get_chops(count, True)))

return stack.get_chops(count, False)

0 comments on commit 4a9b280

Please sign in to comment.