Skip to content

Commit

Permalink
Refactor graders
Browse files Browse the repository at this point in the history
Namely:
- handle cases where both ends of a Wire are on walls
- organize source and its hierarchy
- add direct imports
- use InflationGrader with Helmholtz nozzle example (works very poorly, needs more TLC)
  • Loading branch information
FranzBangar committed Jan 3, 2025
1 parent 57577b1 commit 4df1dbd
Show file tree
Hide file tree
Showing 37 changed files with 293 additions and 240 deletions.
2 changes: 2 additions & 0 deletions examples/advanced/edge_grading.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# NOT FINISHED!
# TODO: add operation.grade_edge() and show its usage in this example
import os

import classy_blocks as cb
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced/inflation_grader.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# A terrible blocking of a rectangle for displaying InflationGrader capabilities
import os

import numpy as np

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

mesh = cb.Mesh()

Expand Down Expand Up @@ -39,7 +39,7 @@
vertex = list(finder.find_in_sphere(point))[0]
vertex.translate([0, 0.8, 0])

grader = InflationGrader(mesh, 5e-3, 0.1)
grader = cb.InflationGrader(mesh, 5e-3, 0.1)
grader.grade(take="max")

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
5 changes: 3 additions & 2 deletions examples/advanced/smooth_grader.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# A terrible blocking of a rectangle for displaying SmoothGrader capabilities

import os

import numpy as np

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

mesh = cb.Mesh()

Expand All @@ -28,7 +29,7 @@

mesh.set_default_patch("walls", "wall")
mesh.block_list.update()
grader = SmoothGrader(mesh, 0.05)
grader = cb.SmoothGrader(mesh, 0.05)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
27 changes: 7 additions & 20 deletions examples/chaining/helmholtz_nozzle.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,45 +23,29 @@
l_outlet = 80e-3

# cell sizing
cell_size = 1.5e-3
bl_size = 0.15e-3
c2c_expansion = 1.1
axial_expansion = 2 # make cells in non-interesting places longer to save on count
first_cell_size = 0.01e-3
bulk_cell_size = 1.5e-3

mesh = cb.Mesh()

# inlet
inlet = cb.Cylinder([0, 0, 0], [l_inlet, 0, 0], [0, 0, r_inlet])
inlet.chop_axial(start_size=cell_size * axial_expansion, end_size=cell_size)
inlet.chop_tangential(start_size=cell_size)

inlet.set_start_patch("inlet")
inlet.set_outer_patch("wall")
mesh.add(inlet)

# nozzle
nozzle = cb.Frustum.chain(inlet, l_nozzle, r_nozzle)
# cell sizing: make sure bl_size is correct here
nozzle.chop_axial(length_ratio=0.5, start_size=cell_size * axial_expansion, end_size=cell_size)
nozzle.chop_axial(length_ratio=0.5, start_size=cell_size, end_size=bl_size)
nozzle.chop_radial(end_size=bl_size, c2c_expansion=1 / c2c_expansion)
nozzle.set_outer_patch("wall")
mesh.add(nozzle)

# chamber: inner cylinder
chamber_inner = cb.Cylinder.chain(nozzle, l_chamber_inner)
# create smaller cells at inlet and outlet but leave them bigger in the middle;
chamber_inner.chop_axial(length_ratio=0.25, start_size=bl_size, end_size=cell_size)
chamber_inner.chop_axial(length_ratio=0.25, start_size=cell_size, end_size=cell_size * axial_expansion)

chamber_inner.chop_axial(length_ratio=0.25, start_size=cell_size * axial_expansion, end_size=cell_size)
chamber_inner.chop_axial(length_ratio=0.25, start_size=cell_size, end_size=bl_size)
mesh.add(chamber_inner)

# chamber outer: expanded ring; the end face will be moved when the mesh is assembled
chamber_outer = cb.ExtrudedRing.expand(chamber_inner, r_chamber_outer - r_inlet)
chamber_outer.chop_radial(length_ratio=0.5, start_size=bl_size, c2c_expansion=c2c_expansion)
chamber_outer.chop_radial(length_ratio=0.5, end_size=bl_size, c2c_expansion=1 / c2c_expansion)
chamber_outer.set_start_patch("wall")
chamber_outer.set_end_patch("wall")
chamber_outer.set_outer_patch("wall")
Expand All @@ -78,10 +62,13 @@

# outlet pipe
outlet = cb.Cylinder.chain(chamber_inner, l_outlet)
outlet.chop_axial(length_ratio=0.5, start_size=bl_size, end_size=cell_size)
outlet.chop_axial(length_ratio=0.5, start_size=cell_size, end_size=cell_size * axial_expansion)
outlet.set_outer_patch("wall")
outlet.set_end_patch("outlet")
mesh.add(outlet)

mesh.modify_patch("wall", "wall")

grader = cb.InflationGrader(mesh, first_cell_size, bulk_cell_size)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
3 changes: 1 addition & 2 deletions examples/chaining/labyrinth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from typing import List

import classy_blocks as cb
from classy_blocks.grading.autograding.grader import FixedCountGrader
from classy_blocks.util import functions as f

mesh = cb.Mesh()
Expand Down Expand Up @@ -34,7 +33,7 @@

mesh.set_default_patch("walls", "wall")

grader = FixedCountGrader(mesh, 5)
grader = cb.FixedCountGrader(mesh, 5)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
3 changes: 1 addition & 2 deletions examples/chaining/tank.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os

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

# a cylindrical tank with round end caps
diameter = 0.5
Expand All @@ -25,7 +24,7 @@
mesh.add(start_cap)
mesh.add(end_cap)

grader = SimpleGrader(mesh, 0.05)
grader = cb.SimpleGrader(mesh, 0.05)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
8 changes: 3 additions & 5 deletions examples/optimization/duct.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@

optimizer.optimize(tolerance=0.01)

# Quick'n'dirty chopping, don't do this at home
for operation in shape.operations:
for axis in range(3):
operation.chop(axis, count=10)

mesh.add(shape)

grader = cb.SmoothGrader(mesh, 0.08)
grader.grade()

mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
3 changes: 1 addition & 2 deletions examples/shape/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import numpy as np

import classy_blocks as cb
from classy_blocks.grading.autograding.grader import SmoothGrader
from classy_blocks.types import PointType
from classy_blocks.util import functions as f

Expand Down Expand Up @@ -65,7 +64,7 @@ def add_edges(self) -> None:
mesh.add(shape)
mesh.assemble()

grader = SmoothGrader(mesh, 0.03)
grader = cb.SmoothGrader(mesh, 0.03)
grader.grade(take="max")

mesh.set_default_patch("walls", "wall")
Expand Down
3 changes: 1 addition & 2 deletions examples/shape/cylinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import classy_blocks as cb
from classy_blocks.construct.flat.sketches.disk import DiskBase
from classy_blocks.grading.autograding.grader import SmoothGrader

DiskBase.core_ratio = 0.4 # Default is 0.8

Expand Down Expand Up @@ -36,7 +35,7 @@
mesh.block_list.update()

# automatic grading
grader = SmoothGrader(mesh, 0.1)
grader = cb.SmoothGrader(mesh, 0.1)
grader.grade()

mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
3 changes: 1 addition & 2 deletions examples/shape/quarter_cylinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import classy_blocks as cb
from classy_blocks.construct.flat.sketches.disk import QuarterDisk
from classy_blocks.grading.autograding.grader import SmoothGrader
from classy_blocks.util import functions as f

mesh = cb.Mesh()
Expand All @@ -21,7 +20,7 @@

mesh.assemble()

grader = SmoothGrader(mesh, 0.05)
grader = cb.SmoothGrader(mesh, 0.05)
grader.grade()

mesh.set_default_patch("walls", "wall")
Expand Down
9 changes: 9 additions & 0 deletions src/classy_blocks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
from .construct.shapes.shell import Shell
from .construct.shapes.sphere import Hemisphere
from .construct.stack import ExtrudedStack, RevolvedStack, TransformedStack
from .grading.autograding.fixed.grader import FixedCountGrader
from .grading.autograding.inflation.grader import InflationGrader
from .grading.autograding.simple.grader import SimpleGrader
from .grading.autograding.smooth.grader import SmoothGrader
from .mesh import Mesh
from .modify.find.geometric import GeometricFinder
from .modify.find.shape import RoundSolidFinder
Expand Down Expand Up @@ -136,4 +140,9 @@
"NJoint",
"TJoint",
"LJoint",
# Autograding
"FixedCountGrader",
"SimpleGrader",
"SmoothGrader",
"InflationGrader",
]
2 changes: 0 additions & 2 deletions src/classy_blocks/construct/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from classy_blocks.util import functions as f
from classy_blocks.util.constants import DTYPE, TOL

# TODO! Tests


class Array(ElementBase):
def __init__(self, points: PointListType):
Expand Down
1 change: 0 additions & 1 deletion src/classy_blocks/construct/shapes/frustum.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def __init__(
radius_vector_1 = radius_point_1 - axis_point_1
radius_1 = f.norm(radius_vector_1)

# TODO: TEST
diff = np.dot(axis, radius_vector_1)
if diff > TOL:
raise FrustumCreationError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def get_pieces(self, indexes: List[int]) -> List[Piece]:
return pieces

def get_chops(self, number: int) -> List[Chop]:
if self.is_simple:
if self.is_simple or self.count < 3:
# don't bother
return [Chop(count=self.count)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
from typing import List

import numpy as np
import scipy.interpolate
import scipy.optimize

from classy_blocks.grading.autograding.params.approximator import Approximator
from classy_blocks.grading.autograding.params.layers import InflationLayer
from classy_blocks.grading.autograding.approximator import Approximator
from classy_blocks.grading.chop import Chop
from classy_blocks.types import FloatListType
from classy_blocks.util.constants import TOL
Expand Down Expand Up @@ -87,58 +85,3 @@ def get_chops(self, pieces: int) -> List[Chop]:
def get_last_size(self) -> float:
coords = self.get_smooth_coords()
return coords[-2] - coords[-3]


@dataclasses.dataclass
class SmoothDistributor(DistributorBase):
def get_ideal_ratios(self):
# In a smooth grader, we want all cells to be as similar to their neighbours as possible
return super().get_ideal_ratios()

def get_ratio_weights(self):
weights = np.ones(self.count + 1)
# Enforce stricter policy on the first few cells
# to match size_before and size_after
for i in (0, 1, 2, 3):
w = 2 ** (3 - i)
weights[i] = w
weights[-i - 1] = w

return weights


@dataclasses.dataclass
class InflationDistributor(SmoothDistributor):
c2c_expansion: float
bl_thickness_factor: int
buffer_expansion: float
bulk_size: float

@property
def is_simple(self) -> bool:
return False

def get_ideal_ratios(self):
# TODO: combine this logic and LayerStack;
# possibly package all parameters into a separate dataclass
ratios = super().get_ideal_ratios()

# Ideal growth ratio in boundary layer is user-specified c2c_expansion;
inflation_layer = InflationLayer(self.size_before, self.c2c_expansion, self.bl_thickness_factor, 1e12)
inflation_count = inflation_layer.count

ratios[:inflation_count] = self.c2c_expansion

# add a buffer layer if needed
last_inflation_size = inflation_layer.end_size
if self.bulk_size > self.buffer_expansion * last_inflation_size:
buffer_count = int(np.log(self.bulk_size / last_inflation_size) / np.log(self.buffer_expansion)) + 1
ratios[inflation_count : inflation_count + buffer_count] = self.buffer_expansion

return ratios

def get_ratio_weights(self):
# using the same weights as in SmoothDistributor
# can trigger overflow warnings but doesn't produce
# better chops; thus, keep it simple
return np.ones(self.count + 1)
11 changes: 11 additions & 0 deletions src/classy_blocks/grading/autograding/fixed/grader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from classy_blocks.grading.autograding.fixed.rules import FixedCountRules
from classy_blocks.grading.autograding.graders import GraderBase
from classy_blocks.mesh import Mesh


class FixedCountGrader(GraderBase):
"""The simplest possible mesh grading: use a constant cell count for all axes on all blocks;
useful during mesh building and some tutorial cases"""

def __init__(self, mesh: Mesh, count: int = 8):
super().__init__(mesh, FixedCountRules(count))
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import dataclasses
from typing import List

from classy_blocks.grading.autograding.params.base import ChopParams
from classy_blocks.grading.autograding.rules import ChopRules
from classy_blocks.grading.chop import Chop


@dataclasses.dataclass
class FixedCountGraderParams(ChopParams):
class FixedCountRules(ChopRules):
count: int = 8

def get_count(self, _length, _start_at_wall, _end_at_wall):
Expand Down
Loading

0 comments on commit 4df1dbd

Please sign in to comment.