Showing preview only (904K chars total). Download the full file or copy to clipboard to get everything.
Repository: damogranlabs/classy_blocks
Branch: development
Commit: 16e4160b930a
Files: 294
Total size: 829.0 KB
Directory structure:
gitextract_gjyxw34u/
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── workflows/
│ └── build_ci.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CITATION.cff
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── docs/
│ └── optimization/
│ └── quality-criteria.ods
├── examples/
│ ├── advanced/
│ │ ├── chop_preserve.py
│ │ ├── collapsed.py
│ │ ├── edge_grading.py
│ │ ├── merged.py
│ │ └── project.py
│ ├── assembly/
│ │ ├── l_joint.py
│ │ ├── n_joint.py
│ │ └── t_joint.py
│ ├── bug.py
│ ├── case/
│ │ ├── Allrun.mesh
│ │ ├── case.foam
│ │ ├── constant/
│ │ │ └── geometry/
│ │ │ └── terrain.stl
│ │ └── system/
│ │ ├── collapseDict
│ │ ├── controlDict
│ │ ├── fvSchemes
│ │ └── fvSolution
│ ├── chaining/
│ │ ├── flywheel.py
│ │ ├── helmholtz_nozzle.py
│ │ ├── labyrinth.py
│ │ ├── orifice_plate.py
│ │ ├── tank.py
│ │ ├── test_tube.py
│ │ └── venturi_tube.py
│ ├── complex/
│ │ ├── airfoil/
│ │ │ └── airfoil.py
│ │ ├── cyclone/
│ │ │ ├── README
│ │ │ ├── __init__.py
│ │ │ ├── cyclone.py
│ │ │ ├── geometry.py
│ │ │ ├── parameters.py
│ │ │ └── regions/
│ │ │ ├── __init__.py
│ │ │ ├── body.py
│ │ │ ├── core.py
│ │ │ ├── fillaround.py
│ │ │ ├── inlet.py
│ │ │ ├── inner_ring.py
│ │ │ ├── pipe.py
│ │ │ ├── region.py
│ │ │ └── skirt.py
│ │ ├── gear/
│ │ │ ├── gear.py
│ │ │ ├── involute_gear.py
│ │ │ └── tooth.py
│ │ ├── heater/
│ │ │ ├── heater.py
│ │ │ └── parameters.py
│ │ ├── karman.py
│ │ └── plate/
│ │ ├── parameters.py
│ │ └── plate.py
│ ├── modification/
│ │ └── move_vertex.py
│ ├── operation/
│ │ ├── box.py
│ │ ├── channel.py
│ │ ├── connector.py
│ │ ├── extrude.py
│ │ ├── loft.py
│ │ ├── revolve.py
│ │ └── wedge.py
│ ├── optimization/
│ │ ├── diffuser_free.py
│ │ ├── diffuser_line.py
│ │ ├── duct.py
│ │ └── simple.py
│ ├── shape/
│ │ ├── custom.py
│ │ ├── cylinder.py
│ │ ├── elbow.py
│ │ ├── extruded_ring.py
│ │ ├── frustum.py
│ │ ├── hemisphere.py
│ │ ├── one_core_cylinder.py
│ │ ├── quarter_cylinder.py
│ │ ├── revolved_ring.py
│ │ ├── shell.py
│ │ ├── splined/
│ │ │ ├── combined_example.py
│ │ │ ├── spline_ring.py
│ │ │ ├── spline_ring_whole_half_quarter.py
│ │ │ └── spline_round.py
│ │ ├── torus.py
│ │ └── wrapped_cylinder.py
│ ├── stack/
│ │ ├── cube.py
│ │ └── fusilli.py
│ └── transform/
│ └── mirror.py
├── pyproject.toml
├── src/
│ └── classy_blocks/
│ ├── __init__.py
│ ├── assemble/
│ │ ├── __init__.py
│ │ ├── assembler.py
│ │ ├── depot.py
│ │ ├── dump.py
│ │ └── settings.py
│ ├── base/
│ │ ├── __init__.py
│ │ ├── element.py
│ │ ├── exceptions.py
│ │ └── transforms.py
│ ├── cbtyping.py
│ ├── construct/
│ │ ├── __init__.py
│ │ ├── assemblies/
│ │ │ ├── assembly.py
│ │ │ └── joints.py
│ │ ├── curves/
│ │ │ ├── __init__.py
│ │ │ ├── analytic.py
│ │ │ ├── curve.py
│ │ │ ├── discrete.py
│ │ │ ├── interpolated.py
│ │ │ └── interpolators.py
│ │ ├── edges.py
│ │ ├── flat/
│ │ │ ├── __init__.py
│ │ │ ├── face.py
│ │ │ ├── sketch.py
│ │ │ └── sketches/
│ │ │ ├── __init__.py
│ │ │ ├── annulus.py
│ │ │ ├── disk.py
│ │ │ ├── grid.py
│ │ │ ├── mapped.py
│ │ │ └── spline_round.py
│ │ ├── operations/
│ │ │ ├── __init__.py
│ │ │ ├── box.py
│ │ │ ├── connector.py
│ │ │ ├── extrude.py
│ │ │ ├── loft.py
│ │ │ ├── operation.py
│ │ │ ├── revolve.py
│ │ │ └── wedge.py
│ │ ├── point.py
│ │ ├── series.py
│ │ ├── shape.py
│ │ ├── shapes/
│ │ │ ├── __init__.py
│ │ │ ├── cylinder.py
│ │ │ ├── elbow.py
│ │ │ ├── frustum.py
│ │ │ ├── rings.py
│ │ │ ├── round.py
│ │ │ ├── shell.py
│ │ │ └── sphere.py
│ │ └── stack.py
│ ├── grading/
│ │ ├── __init__.py
│ │ ├── analyze/
│ │ │ ├── __init__.py
│ │ │ ├── catalogue.py
│ │ │ ├── probe.py
│ │ │ └── row.py
│ │ ├── define/
│ │ │ ├── __init__.py
│ │ │ ├── chop.py
│ │ │ ├── collector.py
│ │ │ ├── grading.py
│ │ │ └── relations.py
│ │ └── graders/
│ │ ├── __init__.py
│ │ ├── auto.py
│ │ ├── fixed.py
│ │ ├── inflation.py
│ │ ├── manager.py
│ │ └── simple.py
│ ├── items/
│ │ ├── __init__.py
│ │ ├── block.py
│ │ ├── edges/
│ │ │ ├── __init__.py
│ │ │ ├── arcs/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── angle.py
│ │ │ │ ├── arc.py
│ │ │ │ ├── arc_base.py
│ │ │ │ └── origin.py
│ │ │ ├── curve.py
│ │ │ ├── edge.py
│ │ │ ├── factory.py
│ │ │ ├── line.py
│ │ │ └── project.py
│ │ ├── patch.py
│ │ ├── side.py
│ │ ├── vertex.py
│ │ └── wires/
│ │ ├── __init__.py
│ │ ├── axis.py
│ │ ├── manager.py
│ │ └── wire.py
│ ├── lists/
│ │ ├── __init__.py
│ │ ├── block_list.py
│ │ ├── edge_list.py
│ │ ├── face_list.py
│ │ ├── patch_list.py
│ │ └── vertex_list.py
│ ├── lookup/
│ │ ├── __init__.py
│ │ ├── cell_registry.py
│ │ ├── connection_registry.py
│ │ ├── face_registry.py
│ │ └── point_registry.py
│ ├── mesh.py
│ ├── modify/
│ │ ├── __init__.py
│ │ ├── find/
│ │ │ ├── __init__.py
│ │ │ ├── finder.py
│ │ │ ├── geometric.py
│ │ │ └── shape.py
│ │ └── reorient/
│ │ ├── __init__.py
│ │ └── viewpoint.py
│ ├── optimize/
│ │ ├── __init__.py
│ │ ├── cell.py
│ │ ├── clamps/
│ │ │ ├── __init__.py
│ │ │ ├── clamp.py
│ │ │ ├── curve.py
│ │ │ ├── free.py
│ │ │ └── surface.py
│ │ ├── connection.py
│ │ ├── grid.py
│ │ ├── junction.py
│ │ ├── links.py
│ │ ├── optimizer.py
│ │ ├── quality.py
│ │ ├── record.py
│ │ ├── report.py
│ │ └── smoother.py
│ ├── util/
│ │ ├── __init__.py
│ │ ├── constants.py
│ │ ├── frame.py
│ │ ├── functions.py
│ │ └── tools.py
│ └── write/
│ ├── __init__.py
│ ├── formats.py
│ ├── vtk.py
│ └── writer.py
├── tests/
│ ├── __init__.py
│ ├── fixtures/
│ │ ├── __init__.py
│ │ ├── block.py
│ │ ├── data.py
│ │ └── mesh.py
│ ├── helpers/
│ │ ├── __init__.py
│ │ └── collect_outputs.py
│ ├── test_assemble.py
│ ├── test_bugs/
│ │ ├── __init__.py
│ │ └── test_grading.py
│ ├── test_construct/
│ │ ├── __init__.py
│ │ ├── test_assembly.py
│ │ ├── test_chaining.py
│ │ ├── test_curves/
│ │ │ ├── __init__.py
│ │ │ ├── test_analytic.py
│ │ │ ├── test_discrete.py
│ │ │ ├── test_interpolated.py
│ │ │ └── test_interpolators.py
│ │ ├── test_edge_data.py
│ │ ├── test_flat/
│ │ │ ├── __init__.py
│ │ │ ├── test_annulus.py
│ │ │ ├── test_disk.py
│ │ │ ├── test_face.py
│ │ │ └── test_sketch.py
│ │ ├── test_operation/
│ │ │ ├── __init__.py
│ │ │ ├── test_box.py
│ │ │ ├── test_connector.py
│ │ │ ├── test_extrude.py
│ │ │ ├── test_operation.py
│ │ │ └── test_wedge.py
│ │ ├── test_point.py
│ │ ├── test_shape.py
│ │ ├── test_shell.py
│ │ └── test_stack.py
│ ├── test_grading/
│ │ ├── __init__.py
│ │ ├── test_catalogue.py
│ │ ├── test_collector.py
│ │ ├── test_edge_grading.py
│ │ ├── test_grading.py
│ │ ├── test_inflation.py
│ │ ├── test_layers.py
│ │ ├── test_probe.py
│ │ └── test_relations.py
│ ├── test_items/
│ │ ├── __init__.py
│ │ ├── test_axis.py
│ │ ├── test_block.py
│ │ ├── test_edge.py
│ │ ├── test_patch.py
│ │ ├── test_side.py
│ │ ├── test_vertex.py
│ │ └── test_wire.py
│ ├── test_lists/
│ │ ├── __init__.py
│ │ ├── test_edge_list.py
│ │ ├── test_face_list.py
│ │ └── test_patch_list.py
│ ├── test_mesh.py
│ ├── test_modify/
│ │ ├── __init__.py
│ │ ├── test_finder.py
│ │ └── test_reorient.py
│ ├── test_optimize/
│ │ ├── __init__.py
│ │ ├── optimize_fixtures.py
│ │ ├── test_cell.py
│ │ ├── test_clamps.py
│ │ ├── test_grid.py
│ │ ├── test_links.py
│ │ ├── test_optimizer.py
│ │ ├── test_quality.py
│ │ └── test_smoother.py
│ ├── test_propagation.py
│ └── test_util/
│ ├── __init__.py
│ ├── test_frame.py
│ ├── test_functions.py
│ ├── test_imports.py
│ └── test_tools.py
└── tox.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
[*.bat]
indent_style = tab
end_of_line = crlf
[LICENSE]
insert_final_newline = false
[Makefile]
indent_style = tab
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
* classy_blocks version:
* Python version:
* Operating System:
### Description
Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.
### What I Did
```
Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.
```
================================================
FILE: .github/workflows/build_ci.yml
================================================
name: Test and analyze
on: [ push ]
jobs:
pytests:
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install -U pip tox
- name: pytest
run: |
tox -e py
Analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.13
uses: actions/setup-python@v4
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install -U pip tox
- name: analysis
run: |
tox -e analysis
================================================
FILE: .gitignore
================================================
# Why not include workspace and its settings/tasks/cfgs in git so others can benefit?
#.vscode
#*.code-workspace
venv_*/
tmp
# openfoam case files and results from testing
polyMesh/
cellToRegion
blockMeshDict
log.*
*.vtk
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# OpenFOAM files
*.gz
log.*
postProcessing
*~
*/processor*
*/[0-9]*
*/[0-9]*.[0-9]*
*/!0.org
*/constant/extendedFeatureEdgeMesh
*.eMesh
*polyMesh
*/constant/cellToRegion
*.obj
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
tests/outputs
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# IDEs on hold
.idea
.vscode
# Mac specific
.DS_Store
================================================
FILE: .pre-commit-config.yaml
================================================
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: check-toml
- id: end-of-file-fixer
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.9.9"
hooks:
# Run the linter.
- id: ruff
args: [--fix]
- id: ruff
args: [--select, I, --fix]
# Run the formatter.
- id: ruff-format
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.10.0]
### Added
- Edge grading:
- Added `Operation.chop_edge(corner_1, corner_2, ...)` that offers
fine-control of grading of each edge; see `examples/advanced/edge_grading.py`
for more info
- Automatic grading:
- A complete rewrite of automatic graders (`FixedCountGrader`, `SimpleGrader`)
- Resurrected `InflationGrader` and this time it works (proved on the cyclone case)
- Example for spline sketches/shapes
- Optimization:
- Added manual clipping to bounds
(scipy's methods often ignore them)
### Changed
- Optimization
- Bugfix: optimization with links now takes more distant neighbours into account
(a problem with certain cases)
### Removed
- Automatic grading: removed `SmoothGrader`
(proves to be useless in real world and difficult to control);
better to use edge grading (see `.chop_edge()`)
## [1.9.6]
### Added
- Convenience methods:
- `Curve.get_closest_point()`
- A new VTK writer for sketches: `classy_blocks.write.vtk.sketch_to_vtk()`, useful for debugging sketches alone
- Make `SketchOptimizer` work on all sketches, not just `cb.MappedSketch`
### Changed
- Bugfix: mirror a point over an arbitrary plane; also now supports mirroring a point array
- Bugfix: when finding points to connect clamps to junctions before optimization, do not call transform() on clamps or it will move them, making the optimizer unable to find actual junctions
- Bugfix: ignore optimization iterations with zero or negative improvement
## [1.9.5]
### Added
- A WrappedDisk example
### Changed
- Bugfix: inner edges on OneCoreDisk
- Bugfix: inner edges on WrappedDisk
- Bugfix: WrappedDisk chopping instructions
## [1.9.4]
### Added
- Reintroduce sorting of vertices according to their influence on mesh quality prior to optimization (a.k.a. sensitivity)
### Changed
- Bugfix: rollback on badly initialized clamps
- Favour non-ortho/aspect during optimization (produces better meshes)
## [1.9.3]
### Added
- `trust-constr` optimization algorithm
- pass arbitrary options to `scipy.optimize.minimize`
### Changed
- Bugfix: always use grid quality when checking for rollback
## [1.9.2]
- Bugfix: mixed grid and junction qualities
## [1.9.1]
- Bugfix: multiple projections to the same surface
### Removed
- Mapper class (not exposed as a public API) and replaced with lookup classes
## [1.9.0]
### Added
- Optimization refactor: Optimizers now have a `.config` attribute
that the user can change for fine adjustments
- New classy_blocks logo
### Changed
- Optimization refactor: quality functions are now more reliable and yield better quality once finished
### Removed
- Removed Python 3.8 support
## [1.8.0]
### Added
- Hex*/QuadGrid objects now support `merge_tol` for merging approximately coincident points
### Changed
- Improvement on performance of mesh assembly (5x+)
- Improvement on performance of optimization (20x+)
- Minor API change: use `mesh.settings.property` instead of `mesh.settings['property']`
- Chopping propagation now doesn't overwrite already defined wires within the same block; it's possible to chop two surrounding blocks and the middle one will have different gradings on appropriate wires
- Bugfixes:
- Correct center point of OneCoreDisk
- Correct inner angle calculation for optimization
## [1.7.1]
### Changed
- Bugfix: wrong grading propagation on inverted wires
## [1.7.0]
### Added
- Automatic grading:
- `FixedCountGrader`: simple and quick, grades all blocks in all directions with the same number. Useful while developing meshes - settings blocking etc.
- `SimpleGrader`: quick and good for cases where blocks do not differ much in size. Sets simple-graded counts on blocks based on wanted cell size.
- `SmoothGrader`: Tries to stretch and squeeze cells within blocks by using two graded chops in each direction. The idea is to try to keep difference in cell size between neighbouring blocks as little as possible. Blocks that cannot maintain required cell size are simply/uniformly chopped.
- Possibility to define rings by their inner radius
- Spline round shapes
- Cylinders:
- Add symmetry patch to SemiCylinder
- New examples:
- Quarter cylinder
- One core cylinder
- `ShapeOptimizer` can optimize shapes _before_ they are added to mesh
### Changed
- Renamed `classy_blocks.typing` module to `classy_blocks.cbtyping` due to name clash
- Bugfixes
## [1.6.4]
### Added
- MappedSketch.merge() method
### Changed
- Improved blocking in cyclone example
## [1.6.3]
### Changed
- Bugfix: sorting of cells by sensitivity
- Bugfix: sensitivity calculation moved clamps around
- Output of optimization reports
- Optimization will now skip cells that were made illegal during optimization
### Removed
- Quality caching (produced invalid results and did not speed up optimization)
## [1.6.2]
### Added
- QuarterSplineRound and QuarterSplineRoundRing; cylinders and rings with an arbitrary, parametrized spline cross-section
- Lofts and Shapes, created with spline side-edges (when multiple sketches for mid-sections are provided)
- Examples for splined shapes (as above)
### Changed
- Bugfixes
## [1.6.1]
### Added
- Assemblies and *Joints
- Examples thereof
### Changed
- Some bugfixes
## [1.6.0]
### Added
- Array element; handling multiple points at once (makes transforms faster)
- Complete overhaul of Optimization:
- Optimizer has become SketchOptimizer or MeshOptimizer
- MappedSketch is now smoothed by SketchSmoother
- Mesh can also be smoothed by MeshSmoother
- Gear example
### Changed
- Cell quality: adjusted calculation so that it works for quadrangles and hexahedrons
- Clamps no longer refer to Vertex objects but only store points as locations
- Links same as clamps above, locations only
### Removed
- QuadMap is no longer needed (handled by Grid classes)
## [1.5.3]
### Added
- RoundSolidShape.remove_inner_edges() can now remove edges from a specific face (start, end or both)
### Changed
- Bugfix: invalid cells in round shapes (due to wrong spline point calculation)
## [1.5.2]
### Added
- Spline edges on QuarterDisk, HalfDisk and Disk (FourCoreDisk) to improve mesh quality
- Face.remove_edges() to reset all edges to simple lines
- RoundSolidShape.remove_inner_edges() to get rid of splines in case the vertices need to be moved (in optimization, for example)
### Changed
- Updated affected tutorials (diffusers, cyclone)
## [1.5.1]
### Added
- Optimization:
- Choice of solver (different problems require - work best - with different solvers)
- Richer output (timing, relative improvement) for easier choice of solver
- Curves:
- get_param_at_length()
- Direct imports of various classes
- A new example: custom sketch
- Mesh:
- assemble(): an option to skip creating edges; most useful when assembling mesh before optimization but later a backport() will be called
### Changed
- Improved optimization speed
## [1.5.0]
### Added
- Curves:
- get_tangent()
- get_normal()
- get_binormal()
- Mapped sketch
- Definition of any fixed-blocking sketch
- Automatic laplacian smoothing (fixed outer edges, movable inner vertices)
- Sketches
- OneCoreDisk
- FourCoreDisk (the default Disk for Shapes)
- WrappedDisk
- Oval
- WrappedDisk
- Grid (A cartesian array of rectangular faces in XY plane)
- grid property of Sketch/Shape/Stack
- Stacks
- LoftedShape: a generic shape from 2 Sketches with the same number of faces
- Examples: Heater, Fusilli
- Mesh.delete() will omit given operation from blockMeshDict but its data stays in mesh (chops, patches, etc.)
### Changed
- Definitions of Disks sketches
- All off-the-shelf Shapes are now a LoftedShape
- Calling .transform() with a Mirror transformation will warn about creating an inverted block
## [1.4.1]
### Changed
- Improved optimization output
### Removed
- Relaxation within optimization
- Numerical integration of analytic curve lengths; use discretization instead
## [1.4.0]
### Added
- Channel example
- Cyclone example
- Mirror transform on points, operations, shapes, mirror example
- Operation:
- `get_closest_face()`, `get_closest_side()`, `get_normal_face()`
- Connector operation
- Geometric finders: find_on_plane()
- functions.point_to_line_distance()
### Changed
- Optimization improvements:
- Default parameters for clamp optimization
- Clamps are sorted by sensitivity, not "junction quality" as before (improves optimization speed)
- Clamp parameters follow domain scale (Read more below)
- Raise an Exception when adding more than one Clamp for the same vertex
#### Clamp Parameters
Previously:
- RadialClamp had a single parameter, the _angle_ of the point (and change thereof)
- In Linelamp the parameter _t_ went from 0 to 1 regardless of the distance between points
This created difficulties with optimization algorithms with extra large or very small domains.
Optimization speed also drastically changing with simply scaling the dimensions.
This has been changed:
- RadialClamp's parameter is now multiplied with radius so it means actual _distance_
- LineClamp's parameter now goes from 0 to _distance between points_
When working with CurveClamps, this kind of _automatic_ correction cannot be made so it is advisable
that parameter is of a similar magnitudes than points' coordinates.
### Removed
- Junction.delta() is now handled by optimization automatically
## [1.3.3]
### Added
- Airfoil example
- Translation and Rotational Link: move together with vertices being optimized (see the airfoil example)
### Changed
- Renamed ParametricCurveClamp to CurveClamp (takes Curve object of any kind)
- Interpolated curves' indexes are now between 0 and 1 (easier to work with than using len(points) every time)
- Optimization driver:
- Termination tolerance is now based on initial improvement instead of quality
- Relaxation starts at 0.5 by default and increases linearly to 1 in a given number of relaxed iterations
### Removed
- Curve.get_closest_param() now finds initial_param automatically
## [1.3.2] Curves
### Added
- *Curve objects for dealing with edge specification and optimization
## [1.3.1] Optimization/Backport
### Added
- mesh.clear() removes lists of all items that were populated during mesh.assemble()
- mesh.backport() updates user supplied operations' points with results of optimization/modification
### Changed
- Optimizer: under-relaxation for the first optimization iterations
## [1.3.0] Blocking Optimization
### Added
- **Blocking Optimization**
- Finders for easier fetching vertices, generated by mesh.assemble()
- GeometricFinder lists vertices inside searchable geometric entities
- RoundSolidFinder identifies vertices on core/shell of round solids
- An Optimizer class that handles blocking optimization
- Clamp classes that define degrees of freedom of optimizing points:
- Free (3 DoF)
- Slide along a curve (line, parametric curve) (1 DoF)
- Move on a surface (parametric surface) (2 DoF)
- **Reorienting Operations and Faces**
- `Face`:
- `shift()` method to rotate points around
- `reorient()` method that rotates points so that they start nearest to given position
- `ViewpointOrienter`: a class for auto-orienting operation's points based on specified points 'in front' and 'above' the operation.
### Changed
- Projection Behaviour
- Calling .project() on a Point/Vertex will add the new geometry instead of replacing it.
- Calling .project_edge() on an Operation will add the new geometry instead of replacing it.
- Calling .project_side() on an Operation will add the new geometry to edges instead of replacing them (but will replace existing label for the side)
## [1.2.0] Shell Shape
### Added
- A Shell Shape, created from arbitrary set of faces
### Changed
- Operation.get_face() will not auto-reorder faces (causes confusion for users)
### Fixed
- A bug where Operation.project_face(..., points=True) won't project vertices
## [1. 1. 0] Default Extrude Direction
### Added
- Extrude now takes a vector of a float. If a float is given, direction is normal of the base face.
## [1. 0. 0] Refactor
A complete overhaul of all objects in an attempt to create a proper SOLID-obeying
package with type hinting, static typing and no python-ish duck-typing hacks.
### Added
- examples and showcases from `classy_examples` repo
- static type analysis, formatting, linting
- Origin and Angle edges (Foundation and ESI alternatives to arc)
- Projection of vertices to geometry
- Import convention `import classy_blocks as cb` and direct imports of user-usable objects from `cb`, like `cb.Mesh, cb.Loft, cb.Arc`
- `Operation.faces` property that creates new faces on-the-fly for easier chaining of new operations
- A Frame object that simplifies addressing edges/wires/other stuff between pairs of vertices on a hexahedron
- ExtrudedRing.fill() method has been added to create cylinders inside rings
### Changed
- Major package layout refactor
- Edge specification (Arc, Origin, Angle, Project, Spline, PolyLine objects)
- Reverted Face specification for operations
- The Block object is not directly available to the user as it makes no sense to do so
- Import convention: `import classy_blocks as cb` for examples
- Changed examples so that an example file runs directly instead of calling run.py (that created a lot of confusion)
- Box() is now an operation (previously Shape)
- simplified cylinder and sphere creation
- Chaining of elbows/cylinders/etc always with start_face parameters (instead of negative length)
### Removed
- *Wall shapes will be created later with a different approach
- Examples with *Wall shapes will be recreated later with new approaches
- airfoil2d example requires blocking optimization so it will be recreated when that feature is available
- sphere example will be recreated when 'offset' is available
- block.from_points has been removed (use Loft)
- T-joint will be added when a skew transform is implemented
## [0.0.1] Status Quo
### Added
examples and showcases from classy_examples repo
static type analysis, formatting, linting
### Changed
Major package layout refactor
Major CI refactor
### Removed
Some dependencies, docs and other stuff that is not ready ATM
================================================
FILE: CITATION.cff
================================================
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
title: classy_blocks
abstract: "A Python library for generating block-structured meshes in OpenFOAM and other CFD workflows."
repository-code: "https://github.com/damogranlabs/classy_blocks"
license: "MIT"
doi: 10.5281/zenodo.16785017
authors:
- family-names: Jurkovič
given-names: Nejc
keywords:
- "CFD"
- "OpenFOAM"
- "meshing"
- "block-structured"
- "blockMesh"
- "blockMeshDict"
- "geometry"
- "modeling"
- "hexahedral"
- "parametric"
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
Contributions are welcome, and they are greatly appreciated! Every
little bit helps, and credit will always be given.
You can contribute in many ways:
## Types of Contributions
### Report Bugs
Report bugs at [Github Issues](https://github.com/FranzBangar/classy_blocks/issues).
If you are reporting a bug, please include:
- Your operating system name and version.
- Any details about your local setup that might be helpful in
troubleshooting.
- Detailed steps to reproduce the bug.
### Fix Bugs
Look through the GitHub issues for bugs. Anything tagged with \"bug\"
and \"help wanted\" is open to whoever wants to implement it.
### Implement Features
Look through the GitHub issues for features. Anything tagged with
\"enhancement\" and \"help wanted\" is open to whoever wants to
implement it.
### Write Documentation
classy_blocks could always use more documentation, whether as part of
the official classy_blocks docs, in docstrings, or even on the web in
blog posts, articles, and such.
### Submit Feedback
The best way to send feedback is to file an issue at [Github Issues](https://github.com/FranzBangar/classy_blocks/issues).
If you are proposing a feature:
- Explain in detail how it would work.
- Keep the scope as narrow as possible, to make it easier to
implement.
- Remember that this is a volunteer-driven project, and that
contributions are welcome :)
## Get Started!
Ready to contribute? Here\'s how to set up `classy_blocks` for local development.
1. Fork the `classy_blocks` repo on GitHub
2. Clone your fork locally:
``` shell
$ git clone git@github.com:your_name_here/classy_blocks.git
```
3. Create a branch for local development:
``` shell
$ git checkout -b name-of-your-bugfix-or-feature
```
Now you can make your changes locally.
4. Prepare and activate virtual environment, update pip:
``` shell
$ python -m venv venv
$ "venv/bin/activate"
$ python -m pip install -U pip
```
5. Install required dependencies (based on what you want to
contribute). - Small fixes like documentation, typo or similar: no need
to install anything. Do your change and submit PR.
Code/test/examples fixes: install local `classy_block` package and development requirements:
``` shell
$ python -m pip install -e .[dev]
```
6. Install `pre-commit` hook by [official docs](https://pre-commit.com/#3-install-the-git-hook-scripts).
``` shell
$ pre-commit install
```
7. If code changes were made: check that your changes pass tests, typing,
formatting and other rules.
``` shell
$ python -m pytest
$ ruff check --fix src tests
$ mypy src tests
```
Make sure you test on all python versions. Help yourself with `tox` configurations.
1. Commit your changes and push your branch to GitHub:
``` shell
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
```
2. Submit a pull request through the GitHub website.
## Pull Request Guidelines
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
Check the results of GitHub actions and make sure that nothing was broken.
2. If the pull request adds functionality, the docs should be updated.
Put your new functionality into a function with a docstring, and add
the feature to the list in [README.md]("https://github.com/damogranlabs/classy_blocks/blob/master/README.md")
and/or [CHANGELOG.md](https://github.com/damogranlabs/classy_blocks/blob/master/CHANGELOG.md).
## Uploading To PyPi
Just follow the official documentation:
- [Generate distribution](https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives)
- [Upload to PyPi](https://packaging.python.org/en/latest/tutorials/packaging-projects/#uploading-the-distribution-archives)
## Tips
* To run a subset of tests:
``` shell
$ python -m pytest -k TestGrading
```
Follow official `pytest` documentation: https://docs.pytest.org/en/7.3.x/how-to/usage.html#usage
* `tox` is not installed by default, as it is only dependency of GitHub Actions.
Install it manually if required.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022, Nejc Jurkovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================

Python classes for easier creation of OpenFOAM's blockMesh dictionaries.
# About
`blockMesh` is a very powerful mesher but creating even simple meshes requires a lot of manual work. Attempts to simplify or parametrize blockMeshDicts with `#calc` or `m4` often become cryptic and hard to maintain.
`classy_blocks` aims to reduce this overhead by providing a more intuitive workflow, reusable building blocks and automatic helpers for constructing and optimizing block-structured hexahedral meshes. Nonetheless, it is not an automatic mesher, so some geometries are better suited than others.
## Tutorial
Check out the [classy_blocks tutorial on damogranlabs.com](https://damogranlabs.com/2023/04/classy_blocks-tutorial-part-1-the-basics/)!
## Useful For
### Fields
- Turbomachinery (impellers, propellers)
- Microfluidics
- Flow around buildings
- Heat transfer (PCB models, heatsinks)
- Airfoils (2D)
- Solids (heat transfer, mechanical stresses)
### Cases
- Simpler rotational geometry (immersed rotors, mixers, cyclones)
- Pipes/channels
- Tanks/plenums/containers
- External aerodynamics of blunt bodies
- Modeling thin geometry (seals, labyrinths)
- Parametric studies
- Background meshes for snappy (cylindrical, custom)
- 2D and axisymmetric cases
- Overset meshes
## Not Good For
- External aerodynamics of vehicles (too complex to mesh manually, without refinement generates too many cells)
- Complex geometry in general
- One-off simulations (use automatic meshers)
# How To Use It
- To install the current _stable_ version from pypi, use `pip install classy_blocks`
- To download the cutting-edge development version, install the development branch from Github: `pip install git+https://github.com/damogranlabs/classy_blocks.git@development`
- If you want to run examples, follow instructions in [Examples](#examples)
- If you want to contribute, follow instructions in [CONTRIBUTING.md](CONTRIBUTING.md)
# Features
## Workflow
As opposed to blockMesh where the user is expected to manually enter pre-calculated vertices, edges, blocks and whatnot, classy_blocks tries to mimic procedural modeling of modern 3D CAD programs. Here, a Python script contains steps that describe geometry of blocks, their cell count, grading, patches and so on. At the end, the procedure is translated directly to blockMeshDict and no manual editing of the latter should be required.
## Building Elements
_Unchecked items are not implemented yet but are on a TODO list_
- [x] Manual definition of a Block with Vertices, Edges and Faces
- [x] Operations (Loft, Extrude, Revolve)
- [x] Loft
- [x] Extrude
- [x] Revolve
- [x] Wedge (a shortcut to Revolve for 2D axisymmetric cases)
- [ ] Three-sided pyramid (for axisymmetric cases through the axis)
- [x] Connector (A Loft between two existing Operations)
- [x] Sketches (collections of 2D faces) of common cross-sections
- [x] Quarter and Semi circle
- [x] Circle
- [x] Boxed circle
- [x] Oval with straight sides
- [x] Ellipse (and ovals in various configurations)
- [x] Cartesian grid
- [x] Simple way of creating custom Sketches
- [x] Easy shape creation from Sketches
- [x] Predefined Shapes
- [x] Box (shortcut to Block aligned with coordinate system)
- [x] Elbow (bent pipe of various diameters/cross-sections)
- [x] Cone Frustum (truncated cone)
- [x] Cylinder
- [x] Ring (annulus)
- [x] Hemisphere
- [x] Stacks (collections of similar Shapes stacked on top of each other)
- [x] Predefined parametric Objects
- [x] T-joint (round pipes)
- [x] X-joint
- [x] N-joint (multiple pipes)
- [x] Other building tools
- [x] Use existing Operation's Face to generate a new Operation
- [x] Chain Shape's start/end surface to generate a new Shape
- [x] Expand Shape's outer surface to generate a new Shape (Cylinder/Annulus > Annulus)
- [x] Contract Shape's inner surface into a new Shape (Annulus > Cylinder/Annulus)
- [x] Offset Operation's faces to form new operations (Shell)
## Modifiers
After blocks have been placed, it is possible to create new geometry based on placed blocks or to modify them.
- [x] Move Vertex/Edge/Face
- [x] Delete a Block created by a Shape or Object
- [x] Project Vertex/Edge/Face
- [x] Optimize point position of a sketch/shape (with arbitrarily constrained movement)
## Meshing Specification
- [x] Simple definition of all supported kinds of edges with a dedicated class (Arc/Origin/Angle/Spline/PolyLine/Project)
- [x] Automatic sorting/reorienting of block vertices based on specified _front_ and _top_ points
- [x] Automatic calculation of cell count and grading by specifying any of a number of parameters (cell-to-cell expansion ratio, start cell width, end cell width, total expansion ratio)
- [x] [Edge grading](https://www.openfoam.com/documentation/user-guide/4-mesh-generation-and-conversion/4.3-mesh-generation-with-the-blockmesh-utility#x13-450004.3.1.3) (separate specification for each edge)
- [x] Automatic propagation of grading and cell count from a single block to all connected blocks as required by blockMesh
- [x] Projections of vertices, edges and block faces to geometry (triangulated and [searchable surfaces](https://www.openfoam.com/documentation/guides/latest/doc/guide-meshing-snappyhexmesh-geometry.html#meshing-snappyhexmesh-searchable-objects))
- [x] Face merging as described by [blockMesh user guide](https://www.openfoam.com/documentation/user-guide/4-mesh-generation-and-conversion/4.3-mesh-generation-with-the-blockmesh-utility#x13-470004.3.2). Breaks the pure-hexahedral-mesh rule but can often save the day for trickier geometries. Automatic duplication of points on merged block faces
- [x] Auto grading for high-Re meshes
- [x] Auto grading for Low-Re meshes: boundary layer with specified cell-to-cell expansion, transition with 2:1 (or user-defined) expansion, and specified 'bulk' cell size
# Examples
How to run:
- Install `classy_blocks` as described above
- `cd` to directory of the chosen example
- Run `python <example.py>`; that will write blockMeshDict to examples/case
- Run `blockMesh` on the case
- Open `examples/case/case.foam` in ParaView to view the result
For instance:
```bash
cd examples/chaining
python tank.py
blockMesh -case ../case
```
## Operations
Analogous to a sketch in 3D CAD software, a Face is a set of 4 vertices and 4 edges.
An _Operation_ is a 3D shape obtained by swiping a Face into 3rd dimension by a specified rule. Here is a Revolve as an example:
```python
# a quadrangle with one curved side
base = cb.Face(
[ # quad vertices
[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0]
],
[ # edges: None specifies a straight edge
cb.Arc([0.5, -0.2, 0]),
None,
None,
None
]
)
revolve = cb.Revolve(
base, # face to revolve
f.deg2rad(45), # revolve angle
[0, -1, 0], # axis
[-2, 0, 0] # origin
)
revolve.chop(0, count=15) # first edge
revolve.chop(1, count=15) # second edge
revolve.chop(2, start_size=0.05) # revolve direction
mesh.add(revolve)
```

> See `examples/operations` for an example of each operation.
## Shapes
Some basic shapes are ready-made so that there's no need for workout with Operations.
A simple Cylinder:
```python
inlet = cb.Cylinder([x_start, 0, 0], [x_end, 0, 0], [0, 0, radius])
inlet.chop_radial(count=n_cells_radial, end_size=boundary_layer_thickness)
inlet.chop_axial(start_size=axial_cell_size, end_size=2*axial_cell_size)
inlet.chop_tangential(count=n_cells_tangential)
inlet.set_start_patch('inlet')
inlet.set_outer_patch('wall')
inlet.set_end_patch('outlet')
mesh.add(inlet)
```
> See `examples/shape` for use of each _shape_
3D pipes with twists and turns (chained Elbow and Cylinder Shapes)

### Chaining and Expanding/Contracting
Useful for Shapes, mostly for piping and rotational geometry; An existing Shape's start or end sketch can be reused as a
starting sketch for a new Shape, as long as they are compatible.
For instance, an `Elbow` can be _chained_ to a `Cylinder` just like joining pipes in plumbing.
Moreover, most shapes* can be expanded to form a _wall_ version of the same shape. For instance, expanding a `Cylinder` creates an `ExtrudedRing` or an `ExtrudedRing` can be filled to obtain a `Cylinder` that fills it.
A simple tank with rounded edges

A flywheel in a case. Construction starts with a Cylinder which is then expanded and chained from left towards right. VTK Blocking output for debug is shown in the middle

Venturi tube

> See `examples/chaining` for an example of each operation.
## Custom Sketches and Shapes
A Sketch is a collection of faces - essentially a 2D geometric object, split into quadrangles. Each Face in a Sketch is transformed into 3D space, creating a Shape.
A number of predefined Sketches is available to choose from but it's easy to create a custom one.
```python
disk_in_square = cb.WrappedDisk(start_point, corner_point, disk_diameter/2, normal)
shape = cb.ExtrudedShape(disk_in_square, length)
```
### Sketch Smoothing and Optimization
Points that define a custom sketch can only be placed approximately. Their positions can then be defined by Laplacian smoothing or optimization to obtain best face quality.
> See `examples/shape/custom` for an example with a custom sketch.
## Stacks
A collection of similar Shapes; a Stack is created by starting with a Sketch, then transforming it a number of times, obtaining Shapes, stacked on top of each other.
An Oval sketch, translated and rotated to obtain a Shape from which a Stack is made.

A `Grid` sketch, consisting of 3x3 faces is Extruded 2 times to obtain a Stack. The bottom-middle box is removed from the mesh so that flow around a cube can be studied:
```python
base = Grid(point_1, point_2, 3, 3)
stack = ExtrudedStack(base, side * 2, 2)
# ...
mesh.delete(stack.grid[0][1][1])
```

> See `examples/stack/cube.py` for the full script.
An electric heater in water, a mesh with two cellZones. The heater zone with surrounding fuild of square cross-section is an extruded `WrappedDisk` followed by a `RevolvedStack` of the same cross-sections. The center is then filled with a `SemiCylinder`.

> See `examples/complex/heater` for the full script.
## Assemblies
A collection of pre-assembled parametric Shapes, ready to be used for further construction.
Three pipes, joined in a single point.

## Projection To Geometry
[Any geometry that snappyHexMesh understands](https://www.openfoam.com/documentation/guides/latest/doc/guide-meshing-snappyhexmesh-geometry.html)
is also supported by blockMesh.
That includes searchable surfaces such as spheres and cylinders and triangulated surfaces.
Projecting a block side to a geometry is straightforward; edges, however, can be projected to a single geometry (will 'snap' to the closest point) or to an intersection of two surfaces, which will define it exactly.
Geometry is specified as a simple dictionary of strings and is thrown in blockMeshDict exactly as provided by the user.
```python
geometry = {
'terrain': [
'type triSurfaceMesh',
'name terrain',
'file "terrain.stl"',
],
'left_wall': [
'type searchablePlane',
'planeType pointAndNormal',
'point (-1 0 0)',
'normal (1 0 0)',
]
}
box = cb.Box([-1., -1., -1.], [1., 1., 1.])
box.project_side('bottom', 'terrain')
box.project_edge(0, 1, 'terrain')
box.project_edge(3, 0, ['terrain', 'left_wall'])
```
Edges and faces, projected to an STL surface

Mesh for studying flow around a sphere. Edges and faces of inner ('wall') and outer ('prismatic layers') cells are projected to a searchableSphere, adding no additional requirements for STL geometry.

## Face Merging
Simply provide names of patches to be merged and call `mesh.merge_patches(<master>, <slave>)`.
classy_blocks will take care of point duplication and whatnot.
```python
box = cb.Box([-0.5, -0.5, 0], [0.5, 0.5, 1])
for i in range(3):
box.chop(i, count=25)
box.set_patch('top', 'box_top')
mesh.add(box)
cylinder = cb.Cylinder(
[0, 0, 1],
[0, 0, 2],
[0.25, 0, 1]
)
cylinder.chop_axial(count=10)
cylinder.chop_radial(count=10)
cylinder.chop_tangential(count=20)
cylinder.set_bottom_patch('cylinder_bottom')
mesh.add(cylinder)
mesh.merge_patches('box_top', 'cylinder_bottom')
```
## Offsetting Faces
It is possible to create new blocks by offsetting existing blocks' faces.
As an example, a sphere can be created by offsetting all six faces of a simple box,
then projected to a `searchableSphere`.
> See `examples/shapes/shell.py` for the sphere tutorial.
## Automatic Blocking Optimization
Once an approximate blocking is established, one can fetch specific vertices and specifies certain degrees of freedom along which those vertices will be moved to get blocks of better quality.
Block is treated as a single cell for which OpenFOAM's cell quality criteria are calculated and optimized per user's instructions.
Points can move freely (3 degrees of freedom), along a specified line/curve (1 DoF) or surface (2 DoF).
```python
# [...] A simple setup with two cylinders of different radii,
# connected by a short conical frustum that has bad cells
# [...]
mesh.assemble()
# Find inside vertices at connecting frustum
finder = cb.RoundSolidFinder(mesh, frustum)
inner_vertices = finder.find_core(True).union(finder.find_core(False))
optimizer = cb.Optimizer(mesh)
# Move chosen vertices along a line, parallel to x-axis
for vertex in inner_vertices:
clamp = cb.LineClamp(vertex, vertex.position, vertex.position + f.vector(1, 0, 0))
optimizer.add_clamp(clamp)
optimizer.optimize()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
```
The result (basic blocking > optimized):

> See `examples/optimization` for the diffuser example.
Airfoil core with blunt trailing edge (imported points from NACA generator) and adjustable angle of attack. Exact blocking is determined by in-situ optimization
(see `examples/complex/airfoil.py`). A simulation-ready mesh needs additional blocks to expand domain further away from the airfoil.

## Chopping
In classy_blocks lingo, _chopping_ means setting block's cell count and optionally grading. For best control it can be specified manually with something like `operation.chop(axis, start_size=..., c2c_expansion=...)` (or any other supported combination of parameters) but it only needs to be done on a single block in a _row_ of connected blocks. All touching blocks will inherit user-specified chops automatically.
### Edge Grading
When setting cell counts and expansion ratios, it is possible to specify which value to keep constant. When propagating chops through the mesh this will keep the required value constant. For instance, thickness of the first cell at the wall can be maintained to keep desired `y+` throughout the mesh. This is done by simply specifying a `preserve="..."` keyword.
Example: a block chopped in a classic way where cell sizes will increase when block size increases:

The same case but with a specified `preserve="start_size"` keyword for the bottom and `preserve="end_size"` for the top edge:

It is also possible to locate a specific edge and modify its grading by using `operation.chop_edge(corner_1, corner_2, ...)`. For example, this cylinder with wall boundary layers has some edges manually redefined:

### Automatic Grading
classy_blocks offers automatic graders that will set cell counts and gradings throughout the whole mesh with no user intervention:
- `FixedCountGrader` will simply set the same cell count on all blocks (useful for debugging during mesh development).
- `SimpleGrader` will try to maintain user-specified cell size (a high-Re mesh).
- `InflationGrader` will require the user to set wall patches first, then it will set cell sizes on the wall to maintain required first cell thickness,
make a boundary (inflation) layer that will maintain specified cell-to-cell expansion. Between the last boundary-layer cell and the bulk, a _buffer_ layer will be created with a larger (user-specified) cell-to-cell expansion to save on cell count.
All automatic graders will only grade what the user has not chopped yet - so it's easy to override grader's doings by manually chopping shapes first.
> Check out `examples/complex/cyclone` to see that almost no manual chopping is required to grade the whole mesh!
## Debugging
By default, a `debug.vtk` file is created where each block represents a hexahedral cell.
By showing `block_ids` with a proper color scale the blocking can be visualized.
This is useful when blockMesh fails with errors reporting invalid/inside-out blocks but VTK will
happily show anything.
## Also
2D mesh for studying Karman Vortex Street

A parametric, Low-Re mesh of a real-life impeller _(not included in examples)_

A gear, made from a curve of a single tooth, calculated by
[py_gear_gen](https://github.com/heartworm/py_gear_gen)

A complex example: parametric, Low-Re mesh of a cyclone

> See `examples/complex/cyclone` for a full example of a complex building workflow.
# Prerequisites
Package (python) dependencies can be found in _pyproject.toml_ file.
Other dependencies that must be installed:
- python3.9 and higher
- OpenFoam: .org or .com version is supported, foam-extend's blockMesh doesn't support multigrading but is otherwise also compatible. BlockMesh is not required to run Python scripts. There is an ongoing effort to create VTK meshes from within classy_blocks. See the wip_mesher branch for the latest updates.
# Technical Information
There's no official documentation yet so here are some tips for easier navigation through source.
## The Process, Roughly
1. User writes a script that defines operations/shapes/objects, their edges, projections, cell counts, whatever is needed.
1. All the stuff is added to mesh.
1. Mesh converts user entered data into vertices, blocks, edges and whatnot.
1. The mesh can be written at that point; or,
1. Modification of placed geometry, either by manually moving vertices or by utilizing some sort of optimization algorithm.
1. Output of optimized/modified mesh.
## Support?
If you are stuck, try reading the [classy_blocks tutorial on damogranlabs.com](https://damogranlabs.com/2023/04/classy_blocks-tutorial-part-1-the-basics/).
You are free to join the [OpenFOAM Discord channel](https://discord.gg/P9p9eHn) where classy_blocks users and developers hang out.
If you have collosal plans for meshing but no resources, write an email to [Nejc Jurkovic](mailto:kandelabr@gmail.com) and we'll discuss your options.
================================================
FILE: examples/advanced/chop_preserve.py
================================================
"""demonstrates the 'preserve' keyword to .chop() method"""
import os
import classy_blocks as cb
mesh = cb.Mesh()
start = cb.Box([0, 0, 0], [1, 1, 0.1])
start.chop(0, start_size=0.1)
start.chop(1, length_ratio=0.5, start_size=0.01, c2c_expansion=1.2, preserve="start_size")
start.chop(1, length_ratio=0.5, end_size=0.01, c2c_expansion=1 / 1.2, preserve="end_size")
start.chop(2, count=1)
mesh.add(start)
expand_start = start.get_face("right")
expand = cb.Loft(expand_start, expand_start.copy().translate([1, 0, 0]).scale(2))
expand.chop(2, start_size=0.1)
mesh.add(expand)
contract_start = expand.get_face("top")
contract = cb.Loft(contract_start, contract_start.copy().translate([1, 0, 0]).scale(0.25))
contract.chop(2, start_size=0.1)
mesh.add(contract)
end = cb.Extrude(contract.get_face("top"), 1)
end.chop(2, start_size=0.1)
mesh.add(end)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/advanced/collapsed.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
bottom_face = cb.Face([[0, 0, 0], [1, 0, 0], [0.5, 1, 0], [0.5, 1, 0]])
top_face = cb.Face([[0, 0, 1], [1, 0.5, 1], [1, 0.5, 1], [0, 1, 1]])
loft = cb.Loft(bottom_face, top_face)
extrude = cb.Extrude(top_face, 1)
revolve_face = cb.Face([[2, 0, 0], [3, 0, 0], [3, 1, 0], [2, 1, 0]])
revolve = cb.Revolve(revolve_face, 1, [1, 0, 0], [0, 0, 0])
mesh.add(loft)
mesh.add(extrude)
mesh.add(revolve)
mesh.assemble()
grader = cb.FixedCountGrader(mesh)
grader.grade()
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/advanced/edge_grading.py
================================================
"""A simple cylinder but with custom grading of selected edges"""
import os
import classy_blocks as cb
mesh = cb.Mesh()
axis_point_1 = [0, 0, 0]
axis_point_2 = [1, 0, 0]
radius_point_1 = [0, 1, 0]
cylinder = cb.Cylinder(axis_point_1, axis_point_2, radius_point_1)
cylinder.set_start_patch("inlet")
cylinder.set_end_patch("outlet")
cylinder.set_outer_patch("walls")
# Chop and grade
bl_thickness = 1e-3
core_size = 0.1
# Edge chopping can only be done on a completely specified mesh;
cylinder.chop_axial(count=30)
cylinder.chop_radial(start_size=core_size, end_size=bl_thickness)
cylinder.chop_tangential(start_size=core_size)
# After all edges have been specified (chopped),
# specific ones can be changed manually.
# Keep in mind that count is already fixed and cannot be changed.
# Case 1: remove grading
cylinder.shell[0].chop_edge(0, 1, c2c_expansion=1)
# Case 2: make a thicker first cell
cylinder.shell[1].chop_edge(0, 1, end_size=5 * bl_thickness)
# Case 3: weird random multigrading
cylinder.shell[2].chop_edge(0, 1, length_ratio=0.5, count=2)
cylinder.shell[2].chop_edge(0, 1, c2c_expansion=1 / 1.5)
# Case 4: chop one block differently so that neighbour block will be edge-graded
cylinder.shell[1].chop(2, count=30, start_size=0.01)
mesh.add(cylinder)
cylinder.set_start_patch("walls")
cylinder.set_end_patch("walls")
mesh.modify_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/advanced/merged.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
# two boxes, connected with a geometrically identical
# but different cell count
coarse_box = cb.Box([-0.5, -0.5, 0], [0.5, 0.5, 1])
for i in (0, 1, 2):
coarse_box.chop(i, count=10)
coarse_box.set_patch("bottom", "inlet")
coarse_box.set_patch("top", "box_slave")
mesh.add(coarse_box)
fine_box = coarse_box.copy().translate([0, 0, 1])
for i in (0, 1, 2):
fine_box.unchop(i)
fine_box.chop(i, count=25)
fine_box.set_patch("bottom", "box_master")
fine_box.set_patch("top", "cylinder_master")
mesh.add(fine_box)
# merge the boxes
mesh.merge_patches("box_master", "box_slave")
# add another cylinder on top; this will have no
# coincident points
cylinder = cb.Cylinder([0, 0, 2], [0, 0, 3], [0.25, 0, 2])
cylinder.chop_axial(count=10)
cylinder.chop_radial(count=10)
cylinder.chop_tangential(count=10)
cylinder.set_start_patch("cylinder_slave")
cylinder.set_end_patch("outlet")
mesh.add(cylinder)
mesh.merge_patches("cylinder_master", "cylinder_slave")
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/advanced/project.py
================================================
import os
import classy_blocks as cb
geometry = {
"terrain": [
"type triSurfaceMesh",
"name terrain",
'file "terrain.stl"',
],
"left_wall": [
"type searchablePlane",
"planeType pointAndNormal",
"point (-1 0 0)",
"normal (1 0 0)",
"pointAndNormalDict { point (-1 0 0); normal (1 0 0); }", # ESI version
],
"front_wall": [
"type searchablePlane",
"planeType pointAndNormal",
"point (0 -1 0)",
"normal (0 1 0)",
"pointAndNormalDict { point (0 -1 0); normal (0 1 0); }", # ESI version
],
}
mesh = cb.Mesh()
# 'miss' the vertices deliberately;
# project them to geometry later
box = cb.Box([-0.9, -0.9, -0.9], [1.0, 1.0, 1.0])
# project misplaced vertices
box.project_corner(0, ["terrain", "left_wall", "front_wall"])
box.project_corner(1, "terrain")
box.project_corner(2, "terrain")
# project a face to geometry;
# when using Loft/Extrude/Revolve, you could specify
# those when creating a Face; you'd still have to
# project other sides this way
box.project_side("bottom", "terrain")
# projection of an edge to a surface will move it in various directions,
# depending on the geometry, distorting the box's side
box.project_edge(0, 1, "terrain")
# to avoid that, project an edge to two surfaces;
# this will make it stick to their intersection
box.project_edge(3, 0, ["terrain", "left_wall"])
# an edge can remain 'not projected' but this can cause
# bad quality cells if geometries differ enough
# extrude.block.project_edge(1, 2, 'terrain')
# extrude.block.project_edge(2, 3, 'terrain')
# extrude.block.project_edge(3, 0, 'terrain')
for axis in (0, 1, 2):
box.chop(axis, count=20)
box.set_patch("bottom", "terrain")
mesh.add(box)
mesh.set_default_patch("atmosphere", "patch")
mesh.add_geometry(geometry)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/assembly/l_joint.py
================================================
import os
import classy_blocks as cb
from classy_blocks.construct.assemblies.joints import LJoint
from classy_blocks.util import functions as f
mesh = cb.Mesh()
axis_point_1 = [0.0, 0.0, 0.0]
axis_point_2 = [5.0, 5.0, 0.0]
radius_point_1 = [0.0, 0.0, 2.0]
joint = LJoint(axis_point_1, axis_point_2, radius_point_1)
cell_size = f.norm(radius_point_1) / 10
joint.chop_axial(start_size=cell_size * 5, end_size=cell_size)
joint.chop_radial(start_size=cell_size, end_size=cell_size / 10)
joint.chop_tangential(start_size=cell_size)
joint.set_outer_patch("walls")
joint.set_hole_patch(0, "inlet")
joint.set_hole_patch(1, "outlet")
mesh.add(joint)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/assembly/n_joint.py
================================================
import os
import classy_blocks as cb
from classy_blocks.construct.assemblies.joints import NJoint
from classy_blocks.util import functions as f
mesh = cb.Mesh()
axis_point_1 = [0.0, 0.0, 0.0]
axis_point_2 = [5.0, 5.0, 0.0]
radius_point_1 = [0.0, 0.0, 2.0]
joint = NJoint(axis_point_1, axis_point_2, radius_point_1, 3)
cell_size = f.norm(radius_point_1) / 10
joint.chop_axial(start_size=cell_size * 5, end_size=cell_size)
joint.chop_radial(start_size=cell_size, end_size=cell_size / 10)
joint.chop_tangential(start_size=cell_size)
joint.set_outer_patch("walls")
joint.set_hole_patch(0, "inlet")
joint.set_hole_patch(1, "outlet_1")
joint.set_hole_patch(2, "outlet_2")
mesh.add(joint)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/assembly/t_joint.py
================================================
import os
import classy_blocks as cb
from classy_blocks.construct.assemblies.joints import TJoint
from classy_blocks.util import functions as f
mesh = cb.Mesh()
axis_point_1 = [0.0, 0.0, 0.0]
axis_point_2 = [5.0, 5.0, 0.0]
radius_point_1 = [0.0, 0.0, 2.0]
joint = TJoint(axis_point_1, axis_point_2, radius_point_1)
cell_size = f.norm(radius_point_1) / 10
joint.chop_axial(start_size=cell_size * 5, end_size=cell_size)
joint.chop_radial(start_size=cell_size, end_size=cell_size / 10)
joint.chop_tangential(start_size=cell_size)
joint.set_outer_patch("walls")
joint.set_hole_patch(0, "inlet")
joint.set_hole_patch(1, "outlet_1")
joint.set_hole_patch(2, "outlet_2")
mesh.add(joint)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/bug.py
================================================
import numpy as np
import classy_blocks as cb
box = cb.Box([0, 0, 0], [1, 1, 1])
base_face = box.bottom_face
neighbour_face = base_face.copy().translate([4, 0, 0])
common_face = base_face.copy().rotate(np.pi / 2, [0, 1, 0]).translate([2, 0, 2])
left_loft = cb.Loft(base_face, common_face)
right_loft = cb.Loft(neighbour_face, common_face.copy().shift(2).invert())
for axis in range(3):
left_loft.chop(axis, start_size=0.05, total_expansion=5)
right_loft.chop(2, count=10)
mesh = cb.Mesh()
mesh.add(left_loft)
mesh.add(right_loft)
mesh.write("case/system/blockMeshDict", debug_path="debug.vtk")
================================================
FILE: examples/case/Allrun.mesh
================================================
#!/bin/bash
cd "${0%/*}" || exit
source $WM_PROJECT_DIR/bin/tools/RunFunctions
source $WM_PROJECT_DIR/bin/tools/CleanFunctions
cleanCase
touch case.foam
runApplication blockMesh
runApplication checkMesh -constant
runApplication setsToZones -noFlipMap -constant
cat log.checkMesh
================================================
FILE: examples/case/case.foam
================================================
================================================
FILE: examples/case/constant/geometry/terrain.stl
================================================
solid terrain
facet normal -0.024250 -0.041091 -0.998861
outer loop
vertex 0.750000 -0.750000 -1.004215
vertex 1.000000 -0.750000 -1.010285
vertex 1.000000 -1.000000 -1.000000
endloop
endfacet
facet normal 0.000000 -0.016859 -0.999858
outer loop
vertex 0.750000 -0.750000 -1.004215
vertex 1.000000 -1.000000 -1.000000
vertex 0.750000 -1.000000 -1.000000
endloop
endfacet
facet normal -0.443104 -0.488797 -0.751489
outer loop
vertex -0.250000 -0.750000 -0.822242
vertex -0.000000 -0.750000 -0.969651
vertex -0.000000 -1.000000 -0.807041
endloop
endfacet
facet normal -0.120582 -0.179942 -0.976259
outer loop
vertex -0.250000 -0.750000 -0.822242
vertex -0.000000 -1.000000 -0.807041
vertex -0.250000 -1.000000 -0.776163
endloop
endfacet
facet normal -0.702447 0.195577 -0.684337
outer loop
vertex -0.250000 0.250000 -1.028510
vertex -0.000000 0.250000 -1.285126
vertex -0.000000 0.000000 -1.356573
endloop
endfacet
facet normal -0.560580 0.394713 -0.727978
outer loop
vertex -0.250000 0.250000 -1.028510
vertex -0.000000 0.000000 -1.356573
vertex -0.250000 0.000000 -1.164061
endloop
endfacet
facet normal 0.718016 0.025483 -0.695560
outer loop
vertex 0.750000 0.250000 -1.299716
vertex 1.000000 0.250000 -1.041645
vertex 1.000000 0.000000 -1.050804
endloop
endfacet
facet normal 0.761426 0.128877 -0.635312
outer loop
vertex 0.750000 0.250000 -1.299716
vertex 1.000000 0.000000 -1.050804
vertex 0.750000 0.000000 -1.350430
endloop
endfacet
facet normal -0.003102 0.085318 -0.996349
outer loop
vertex 0.250000 0.250000 -1.375672
vertex 0.500000 0.250000 -1.376451
vertex 0.500000 0.000000 -1.397858
endloop
endfacet
facet normal 0.164177 0.248885 -0.954517
outer loop
vertex 0.250000 0.250000 -1.375672
vertex 0.500000 0.000000 -1.397858
vertex 0.250000 0.000000 -1.440858
endloop
endfacet
facet normal -0.108058 0.267877 -0.957374
outer loop
vertex 0.250000 0.750000 -1.215000
vertex 0.500000 0.750000 -1.243217
vertex 0.500000 0.500000 -1.313168
endloop
endfacet
facet normal -0.107787 0.268133 -0.957333
outer loop
vertex 0.250000 0.750000 -1.215000
vertex 0.500000 0.500000 -1.313168
vertex 0.250000 0.500000 -1.285021
endloop
endfacet
facet normal 0.693720 0.042652 -0.718981
outer loop
vertex 0.750000 0.750000 -1.276436
vertex 1.000000 0.750000 -1.035220
vertex 1.000000 0.500000 -1.050051
endloop
endfacet
facet normal 0.716199 0.089436 -0.692142
outer loop
vertex 0.750000 0.750000 -1.276436
vertex 1.000000 0.500000 -1.050051
vertex 0.750000 0.500000 -1.308740
endloop
endfacet
facet normal -0.308379 0.057996 -0.949494
outer loop
vertex -0.750000 0.250000 -0.879763
vertex -0.500000 0.250000 -0.960958
vertex -0.500000 0.000000 -0.976228
endloop
endfacet
facet normal -0.515177 -0.192949 -0.835083
outer loop
vertex -0.750000 0.250000 -0.879763
vertex -0.500000 0.000000 -0.976228
vertex -0.750000 0.000000 -0.821999
endloop
endfacet
facet normal -0.009779 -0.042150 -0.999063
outer loop
vertex -0.750000 0.750000 -0.997553
vertex -0.500000 0.750000 -1.000000
vertex -0.500000 0.500000 -0.989453
endloop
endfacet
facet normal -0.077516 -0.109624 -0.990946
outer loop
vertex -0.750000 0.750000 -0.997553
vertex -0.500000 0.500000 -0.989453
vertex -0.750000 0.500000 -0.969896
endloop
endfacet
facet normal -0.202669 0.085588 -0.975500
outer loop
vertex -0.250000 0.750000 -1.000000
vertex -0.000000 0.750000 -1.051940
vertex -0.000000 0.500000 -1.073874
endloop
endfacet
facet normal -0.283384 0.000000 -0.959006
outer loop
vertex -0.250000 0.750000 -1.000000
vertex -0.000000 0.500000 -1.073874
vertex -0.250000 0.500000 -1.000000
endloop
endfacet
facet normal 0.090939 0.300921 -0.949303
outer loop
vertex -0.750000 -0.750000 -0.773644
vertex -0.500000 -0.750000 -0.749696
vertex -0.500000 -1.000000 -0.828943
endloop
endfacet
facet normal 0.387183 0.550744 -0.739439
outer loop
vertex -0.750000 -0.750000 -0.773644
vertex -0.500000 -1.000000 -0.828943
vertex -0.750000 -1.000000 -0.959848
endloop
endfacet
facet normal -0.530624 -0.447490 -0.719855
outer loop
vertex -0.750000 -0.250000 -0.767011
vertex -0.500000 -0.250000 -0.951293
vertex -0.500000 -0.500000 -0.795883
endloop
endfacet
facet normal -0.237277 -0.126036 -0.963231
outer loop
vertex -0.750000 -0.250000 -0.767011
vertex -0.500000 -0.500000 -0.795883
vertex -0.750000 -0.500000 -0.734300
endloop
endfacet
facet normal -0.465774 -0.553780 -0.690204
outer loop
vertex -0.250000 -0.250000 -1.166940
vertex -0.000000 -0.250000 -1.335649
vertex -0.000000 -0.500000 -1.135064
endloop
endfacet
facet normal -0.213413 -0.330632 -0.919314
outer loop
vertex -0.250000 -0.250000 -1.166940
vertex -0.000000 -0.500000 -1.135064
vertex -0.250000 -0.500000 -1.077028
endloop
endfacet
facet normal 0.108859 -0.014277 -0.993955
outer loop
vertex 0.250000 -0.750000 -1.030971
vertex 0.500000 -0.750000 -1.003591
vertex 0.500000 -1.000000 -1.000000
endloop
endfacet
facet normal -0.041027 -0.163146 -0.985748
outer loop
vertex 0.250000 -0.750000 -1.030971
vertex 0.500000 -1.000000 -1.000000
vertex 0.250000 -1.000000 -0.989595
endloop
endfacet
facet normal 0.191868 -0.659198 -0.727079
outer loop
vertex 0.250000 -0.250000 -1.404968
vertex 0.500000 -0.250000 -1.338995
vertex 0.500000 -0.500000 -1.112336
endloop
endfacet
facet normal 0.307112 -0.577923 -0.756100
outer loop
vertex 0.250000 -0.250000 -1.404968
vertex 0.500000 -0.500000 -1.112336
vertex 0.250000 -0.500000 -1.213881
endloop
endfacet
facet normal 0.753183 -0.049161 -0.655972
outer loop
vertex 0.750000 -0.250000 -1.337537
vertex 1.000000 -0.250000 -1.050489
vertex 1.000000 -0.500000 -1.031753
endloop
endfacet
facet normal 0.355515 -0.559897 -0.748414
outer loop
vertex 0.750000 -0.250000 -1.337537
vertex 1.000000 -0.500000 -1.031753
vertex 0.750000 -0.500000 -1.150509
endloop
endfacet
facet normal 0.004670 -0.599025 -0.800716
outer loop
vertex 0.500000 -0.250000 -1.338995
vertex 0.750000 -0.250000 -1.337537
vertex 0.750000 -0.500000 -1.150509
endloop
endfacet
facet normal -0.112406 -0.667420 -0.736149
outer loop
vertex 0.500000 -0.250000 -1.338995
vertex 0.750000 -0.500000 -1.150509
vertex 0.500000 -0.500000 -1.112336
endloop
endfacet
facet normal 0.186150 -0.050603 -0.981217
outer loop
vertex 0.500000 0.000000 -1.397858
vertex 0.750000 0.000000 -1.350430
vertex 0.750000 -0.250000 -1.337537
endloop
endfacet
facet normal 0.005676 -0.229181 -0.973367
outer loop
vertex 0.500000 0.000000 -1.397858
vertex 0.750000 -0.250000 -1.337537
vertex 0.500000 -0.250000 -1.338995
endloop
endfacet
facet normal 0.767829 -0.000807 -0.640655
outer loop
vertex 0.750000 0.000000 -1.350430
vertex 1.000000 0.000000 -1.050804
vertex 1.000000 -0.250000 -1.050489
endloop
endfacet
facet normal 0.753662 -0.033851 -0.656390
outer loop
vertex 0.750000 0.000000 -1.350430
vertex 1.000000 -0.250000 -1.050489
vertex 0.750000 -0.250000 -1.337537
endloop
endfacet
facet normal -0.215134 -0.593051 -0.775892
outer loop
vertex -0.000000 -0.250000 -1.335649
vertex 0.250000 -0.250000 -1.404968
vertex 0.250000 -0.500000 -1.213881
endloop
endfacet
facet normal -0.238789 -0.607704 -0.757413
outer loop
vertex -0.000000 -0.250000 -1.335649
vertex 0.250000 -0.500000 -1.213881
vertex -0.000000 -0.500000 -1.135064
endloop
endfacet
facet normal -0.316557 -0.134798 -0.938947
outer loop
vertex -0.000000 0.000000 -1.356573
vertex 0.250000 0.000000 -1.440858
vertex 0.250000 -0.250000 -1.404968
endloop
endfacet
facet normal -0.266328 -0.080393 -0.960524
outer loop
vertex -0.000000 0.000000 -1.356573
vertex 0.250000 -0.250000 -1.404968
vertex -0.000000 -0.250000 -1.335649
endloop
endfacet
facet normal 0.165124 -0.226039 -0.960021
outer loop
vertex 0.250000 0.000000 -1.440858
vertex 0.500000 0.000000 -1.397858
vertex 0.500000 -0.250000 -1.338995
endloop
endfacet
facet normal 0.252731 -0.137493 -0.957717
outer loop
vertex 0.250000 0.000000 -1.440858
vertex 0.500000 -0.250000 -1.338995
vertex 0.250000 -0.250000 -1.404968
endloop
endfacet
facet normal -0.235202 -0.158703 -0.958902
outer loop
vertex -0.000000 -0.750000 -0.969651
vertex 0.250000 -0.750000 -1.030971
vertex 0.250000 -1.000000 -0.989595
endloop
endfacet
facet normal -0.522078 -0.465040 -0.714963
outer loop
vertex -0.000000 -0.750000 -0.969651
vertex 0.250000 -1.000000 -0.989595
vertex -0.000000 -1.000000 -0.807041
endloop
endfacet
facet normal -0.246582 -0.572241 -0.782137
outer loop
vertex -0.000000 -0.500000 -1.135064
vertex 0.250000 -0.500000 -1.213881
vertex 0.250000 -0.750000 -1.030971
endloop
endfacet
facet normal -0.200410 -0.540606 -0.817056
outer loop
vertex -0.000000 -0.500000 -1.135064
vertex 0.250000 -0.750000 -1.030971
vertex -0.000000 -0.750000 -0.969651
endloop
endfacet
facet normal 0.349043 -0.373790 -0.859331
outer loop
vertex 0.250000 -0.500000 -1.213881
vertex 0.500000 -0.500000 -1.112336
vertex 0.500000 -0.750000 -1.003591
endloop
endfacet
facet normal 0.088046 -0.588180 -0.803923
outer loop
vertex 0.250000 -0.500000 -1.213881
vertex 0.500000 -0.750000 -1.003591
vertex 0.250000 -0.750000 -1.030971
endloop
endfacet
facet normal -0.630214 -0.262763 -0.730606
outer loop
vertex -0.500000 -0.250000 -0.951293
vertex -0.250000 -0.250000 -1.166940
vertex -0.250000 -0.500000 -1.077028
endloop
endfacet
facet normal -0.690678 -0.381790 -0.614166
outer loop
vertex -0.500000 -0.250000 -0.951293
vertex -0.250000 -0.500000 -1.077028
vertex -0.500000 -0.500000 -0.795883
endloop
endfacet
facet normal -0.600655 0.009207 -0.799455
outer loop
vertex -0.500000 0.000000 -0.976228
vertex -0.250000 0.000000 -1.164061
vertex -0.250000 -0.250000 -1.166940
endloop
endfacet
facet normal -0.651311 -0.075312 -0.755065
outer loop
vertex -0.500000 0.000000 -0.976228
vertex -0.250000 -0.250000 -1.166940
vertex -0.500000 -0.250000 -0.951293
endloop
endfacet
facet normal -0.608781 -0.066169 -0.790574
outer loop
vertex -0.250000 0.000000 -1.164061
vertex -0.000000 0.000000 -1.356573
vertex -0.000000 -0.250000 -1.335649
endloop
endfacet
facet normal -0.559354 0.009546 -0.828874
outer loop
vertex -0.250000 0.000000 -1.164061
vertex -0.000000 -0.250000 -1.335649
vertex -0.250000 -0.250000 -1.166940
endloop
endfacet
facet normal -0.066181 -0.129457 -0.989374
outer loop
vertex -1.000000 -0.250000 -0.750288
vertex -0.750000 -0.250000 -0.767011
vertex -0.750000 -0.500000 -0.734300
endloop
endfacet
facet normal 0.276537 0.216659 -0.936262
outer loop
vertex -1.000000 -0.250000 -0.750288
vertex -0.750000 -0.500000 -0.734300
vertex -1.000000 -0.500000 -0.808140
endloop
endfacet
facet normal -0.249750 -0.208009 -0.945704
outer loop
vertex -1.000000 0.000000 -0.755977
vertex -0.750000 0.000000 -0.821999
vertex -0.750000 -0.250000 -0.767011
endloop
endfacet
facet normal -0.066726 -0.022698 -0.997513
outer loop
vertex -1.000000 0.000000 -0.755977
vertex -0.750000 -0.250000 -0.767011
vertex -1.000000 -0.250000 -0.750288
endloop
endfacet
facet normal -0.523161 -0.084584 -0.848026
outer loop
vertex -0.750000 0.000000 -0.821999
vertex -0.500000 0.000000 -0.976228
vertex -0.500000 -0.250000 -0.951293
endloop
endfacet
facet normal -0.584261 -0.174338 -0.792619
outer loop
vertex -0.750000 0.000000 -0.821999
vertex -0.500000 -0.250000 -0.951293
vertex -0.750000 -0.250000 -0.767011
endloop
endfacet
facet normal 0.519629 0.510358 -0.685215
outer loop
vertex -1.000000 -0.750000 -0.963231
vertex -0.750000 -0.750000 -0.773644
vertex -0.750000 -1.000000 -0.959848
endloop
endfacet
facet normal 0.156929 0.143709 -0.977098
outer loop
vertex -1.000000 -0.750000 -0.963231
vertex -0.750000 -1.000000 -0.959848
vertex -1.000000 -1.000000 -1.000000
endloop
endfacet
facet normal 0.280093 0.149243 -0.948301
outer loop
vertex -1.000000 -0.500000 -0.808140
vertex -0.750000 -0.500000 -0.734300
vertex -0.750000 -0.750000 -0.773644
endloop
endfacet
facet normal 0.541684 0.443122 -0.714298
outer loop
vertex -1.000000 -0.500000 -0.808140
vertex -0.750000 -0.750000 -0.773644
vertex -1.000000 -0.750000 -0.963231
endloop
endfacet
facet normal -0.235426 -0.176569 -0.955719
outer loop
vertex -0.750000 -0.500000 -0.734300
vertex -0.500000 -0.500000 -0.795883
vertex -0.500000 -0.750000 -0.749696
endloop
endfacet
facet normal 0.094210 0.154775 -0.983448
outer loop
vertex -0.750000 -0.500000 -0.734300
vertex -0.500000 -0.750000 -0.749696
vertex -0.750000 -0.750000 -0.773644
endloop
endfacet
facet normal 0.000000 0.000000 -1.000000
outer loop
vertex -0.500000 0.750000 -1.000000
vertex -0.250000 0.750000 -1.000000
vertex -0.250000 0.500000 -1.000000
endloop
endfacet
facet normal -0.042115 -0.042115 -0.998225
outer loop
vertex -0.500000 0.750000 -1.000000
vertex -0.250000 0.500000 -1.000000
vertex -0.500000 0.500000 -0.989453
endloop
endfacet
facet normal 0.000000 0.000000 -1.000000
outer loop
vertex -0.500000 1.000000 -1.000000
vertex -0.250000 1.000000 -1.000000
vertex -0.250000 0.750000 -1.000000
endloop
endfacet
facet normal 0.000000 0.000000 -1.000000
outer loop
vertex -0.500000 1.000000 -1.000000
vertex -0.250000 0.750000 -1.000000
vertex -0.500000 0.750000 -1.000000
endloop
endfacet
facet normal -0.025983 0.178374 -0.983620
outer loop
vertex -0.250000 1.000000 -1.000000
vertex -0.000000 1.000000 -1.006604
vertex -0.000000 0.750000 -1.051940
endloop
endfacet
facet normal -0.203416 0.000000 -0.979092
outer loop
vertex -0.250000 1.000000 -1.000000
vertex -0.000000 0.750000 -1.051940
vertex -0.250000 0.750000 -1.000000
endloop
endfacet
facet normal -0.033401 -0.109894 -0.993382
outer loop
vertex -1.000000 0.750000 -0.989147
vertex -0.750000 0.750000 -0.997553
vertex -0.750000 0.500000 -0.969896
endloop
endfacet
facet normal -0.269839 -0.339232 -0.901171
outer loop
vertex -1.000000 0.750000 -0.989147
vertex -0.750000 0.500000 -0.969896
vertex -1.000000 0.500000 -0.895038
endloop
endfacet
facet normal -0.000000 -0.009787 -0.999952
outer loop
vertex -1.000000 1.000000 -1.000000
vertex -0.750000 1.000000 -1.000000
vertex -0.750000 0.750000 -0.997553
endloop
endfacet
facet normal -0.033573 -0.043346 -0.998496
outer loop
vertex -1.000000 1.000000 -1.000000
vertex -0.750000 0.750000 -0.997553
vertex -1.000000 0.750000 -0.989147
endloop
endfacet
facet normal -0.000000 0.000000 -1.000000
outer loop
vertex -0.750000 1.000000 -1.000000
vertex -0.500000 1.000000 -1.000000
vertex -0.500000 0.750000 -1.000000
endloop
endfacet
facet normal -0.009787 -0.009787 -0.999904
outer loop
vertex -0.750000 1.000000 -1.000000
vertex -0.500000 0.750000 -1.000000
vertex -0.750000 0.750000 -0.997553
endloop
endfacet
facet normal -0.262345 -0.217237 -0.940204
outer loop
vertex -1.000000 0.250000 -0.810005
vertex -0.750000 0.250000 -0.879763
vertex -0.750000 0.000000 -0.821999
endloop
endfacet
facet normal -0.249938 -0.204532 -0.946413
outer loop
vertex -1.000000 0.250000 -0.810005
vertex -0.750000 0.000000 -0.821999
vertex -1.000000 0.000000 -0.755977
endloop
endfacet
facet normal -0.271132 -0.326461 -0.905489
outer loop
vertex -1.000000 0.500000 -0.895038
vertex -0.750000 0.500000 -0.969896
vertex -0.750000 0.250000 -0.879763
endloop
endfacet
facet normal -0.255406 -0.311336 -0.915335
outer loop
vertex -1.000000 0.500000 -0.895038
vertex -0.750000 0.250000 -0.879763
vertex -1.000000 0.250000 -0.810005
endloop
endfacet
facet normal -0.077487 -0.112904 -0.990580
outer loop
vertex -0.750000 0.500000 -0.969896
vertex -0.500000 0.500000 -0.989453
vertex -0.500000 0.250000 -0.960958
endloop
endfacet
facet normal -0.292197 -0.324364 -0.899671
outer loop
vertex -0.750000 0.500000 -0.969896
vertex -0.500000 0.250000 -0.960958
vertex -0.750000 0.250000 -0.879763
endloop
endfacet
facet normal -0.130650 0.127053 -0.983254
outer loop
vertex 0.500000 0.750000 -1.243217
vertex 0.750000 0.750000 -1.276436
vertex 0.750000 0.500000 -1.308740
endloop
endfacet
facet normal 0.017054 0.269415 -0.962873
outer loop
vertex 0.500000 0.750000 -1.243217
vertex 0.750000 0.500000 -1.308740
vertex 0.500000 0.500000 -1.313168
endloop
endfacet
facet normal 0.013121 0.675103 -0.737606
outer loop
vertex 0.500000 1.000000 -1.052068
vertex 0.750000 1.000000 -1.047621
vertex 0.750000 0.750000 -1.276436
endloop
endfacet
facet normal -0.104973 0.604040 -0.790010
outer loop
vertex 0.500000 1.000000 -1.052068
vertex 0.750000 0.750000 -1.276436
vertex 0.500000 0.750000 -1.243217
endloop
endfacet
facet normal 0.184971 0.136698 -0.973190
outer loop
vertex 0.750000 1.000000 -1.047621
vertex 1.000000 1.000000 -1.000104
vertex 1.000000 0.750000 -1.035220
endloop
endfacet
facet normal 0.579871 0.550060 -0.600986
outer loop
vertex 0.750000 1.000000 -1.047621
vertex 1.000000 0.750000 -1.035220
vertex 0.750000 0.750000 -1.276436
endloop
endfacet
facet normal -0.531867 0.228393 -0.815447
outer loop
vertex -0.000000 0.750000 -1.051940
vertex 0.250000 0.750000 -1.215000
vertex 0.250000 0.500000 -1.285021
endloop
endfacet
facet normal -0.643799 0.066879 -0.762266
outer loop
vertex -0.000000 0.750000 -1.051940
vertex 0.250000 0.500000 -1.285021
vertex -0.000000 0.500000 -1.073874
endloop
endfacet
facet normal -0.139771 0.547808 -0.824846
outer loop
vertex -0.000000 1.000000 -1.006604
vertex 0.250000 1.000000 -1.048966
vertex 0.250000 0.750000 -1.215000
endloop
endfacet
facet normal -0.540111 0.150169 -0.828088
outer loop
vertex -0.000000 1.000000 -1.006604
vertex 0.250000 0.750000 -1.215000
vertex -0.000000 0.750000 -1.051940
endloop
endfacet
facet normal -0.009855 0.607367 -0.794360
outer loop
vertex 0.250000 1.000000 -1.048966
vertex 0.500000 1.000000 -1.052068
vertex 0.500000 0.750000 -1.243217
endloop
endfacet
facet normal -0.093611 0.550809 -0.829365
outer loop
vertex 0.250000 1.000000 -1.048966
vertex 0.500000 0.750000 -1.243217
vertex 0.250000 0.750000 -1.215000
endloop
endfacet
facet normal -0.330744 0.238108 -0.913188
outer loop
vertex -0.000000 0.250000 -1.285126
vertex 0.250000 0.250000 -1.375672
vertex 0.250000 0.000000 -1.440858
endloop
endfacet
facet normal -0.308364 0.261398 -0.914649
outer loop
vertex -0.000000 0.250000 -1.285126
vertex 0.250000 0.000000 -1.440858
vertex -0.000000 0.000000 -1.356573
endloop
endfacet
facet normal -0.621825 0.266968 -0.736248
outer loop
vertex -0.000000 0.500000 -1.073874
vertex 0.250000 0.500000 -1.285021
vertex 0.250000 0.250000 -1.375672
endloop
endfacet
facet normal -0.266629 0.622066 -0.736167
outer loop
vertex -0.000000 0.500000 -1.073874
vertex 0.250000 0.250000 -1.375672
vertex -0.000000 0.250000 -1.285126
endloop
endfacet
facet normal -0.108504 0.243941 -0.963701
outer loop
vertex 0.250000 0.500000 -1.285021
vertex 0.500000 0.500000 -1.313168
vertex 0.500000 0.250000 -1.376451
endloop
endfacet
facet normal -0.002926 0.340886 -0.940100
outer loop
vertex 0.250000 0.500000 -1.285021
vertex 0.500000 0.250000 -1.376451
vertex 0.250000 0.250000 -1.375672
endloop
endfacet
facet normal 0.288061 0.190380 -0.938497
outer loop
vertex 0.500000 0.250000 -1.376451
vertex 0.750000 0.250000 -1.299716
vertex 0.750000 0.000000 -1.350430
endloop
endfacet
facet normal 0.185733 0.083834 -0.979017
outer loop
vertex 0.500000 0.250000 -1.376451
vertex 0.750000 0.000000 -1.350430
vertex 0.500000 0.000000 -1.397858
endloop
endfacet
facet normal 0.017697 -0.036068 -0.999193
outer loop
vertex 0.500000 0.500000 -1.313168
vertex 0.750000 0.500000 -1.308740
vertex 0.750000 0.250000 -1.299716
endloop
endfacet
facet normal 0.285196 0.235199 -0.929164
outer loop
vertex 0.500000 0.500000 -1.313168
vertex 0.750000 0.250000 -1.299716
vertex 0.500000 0.250000 -1.376451
endloop
endfacet
facet normal 0.718885 -0.023360 -0.694737
outer loop
vertex 0.750000 0.500000 -1.308740
vertex 1.000000 0.500000 -1.050051
vertex 1.000000 0.250000 -1.041645
endloop
endfacet
facet normal 0.718023 -0.025108 -0.695566
outer loop
vertex 0.750000 0.500000 -1.308740
vertex 1.000000 0.250000 -1.041645
vertex 0.750000 0.250000 -1.299716
endloop
endfacet
facet normal -0.231108 0.463744 -0.855295
outer loop
vertex -0.500000 0.250000 -0.960958
vertex -0.250000 0.250000 -1.028510
vertex -0.250000 0.000000 -1.164061
endloop
endfacet
facet normal -0.599966 0.048776 -0.798537
outer loop
vertex -0.500000 0.250000 -0.960958
vertex -0.250000 0.000000 -1.164061
vertex -0.500000 0.000000 -0.976228
endloop
endfacet
facet normal -0.041881 0.113207 -0.992688
outer loop
vertex -0.500000 0.500000 -0.989453
vertex -0.250000 0.500000 -1.000000
vertex -0.250000 0.250000 -1.028510
endloop
endfacet
facet normal -0.259288 -0.109372 -0.959587
outer loop
vertex -0.500000 0.500000 -0.989453
vertex -0.250000 0.250000 -1.028510
vertex -0.500000 0.250000 -0.960958
endloop
endfacet
facet normal -0.220168 0.629594 -0.745076
outer loop
vertex -0.250000 0.500000 -1.000000
vertex -0.000000 0.500000 -1.073874
vertex -0.000000 0.250000 -1.285126
endloop
endfacet
facet normal -0.714022 0.079328 -0.695614
outer loop
vertex -0.250000 0.500000 -1.000000
vertex -0.000000 0.250000 -1.285126
vertex -0.250000 0.250000 -1.028510
endloop
endfacet
facet normal -0.274424 -0.174306 -0.945679
outer loop
vertex -0.500000 -0.750000 -0.749696
vertex -0.250000 -0.750000 -0.822242
vertex -0.250000 -1.000000 -0.776163
endloop
endfacet
facet normal 0.197298 0.296234 -0.934515
outer loop
vertex -0.500000 -0.750000 -0.749696
vertex -0.250000 -1.000000 -0.776163
vertex -0.500000 -1.000000 -0.828943
endloop
endfacet
facet normal -0.618748 -0.560736 -0.550205
outer loop
vertex -0.500000 -0.500000 -0.795883
vertex -0.250000 -0.500000 -1.077028
vertex -0.250000 -0.750000 -0.822242
endloop
endfacet
facet normal -0.274404 -0.174702 -0.945612
outer loop
vertex -0.500000 -0.500000 -0.795883
vertex -0.250000 -0.750000 -0.822242
vertex -0.500000 -0.750000 -0.749696
endloop
endfacet
facet normal -0.190073 -0.541742 -0.818772
outer loop
vertex -0.250000 -0.500000 -1.077028
vertex -0.000000 -0.500000 -1.135064
vertex -0.000000 -0.750000 -0.969651
endloop
endfacet
facet normal -0.381697 -0.659736 -0.647345
outer loop
vertex -0.250000 -0.500000 -1.077028
vertex -0.000000 -0.750000 -0.969651
vertex -0.250000 -0.750000 -0.822242
endloop
endfacet
facet normal -0.002496 -0.016859 -0.999855
outer loop
vertex 0.500000 -0.750000 -1.003591
vertex 0.750000 -0.750000 -1.004215
vertex 0.750000 -1.000000 -1.000000
endloop
endfacet
facet normal 0.000000 -0.014363 -0.999897
outer loop
vertex 0.500000 -0.750000 -1.003591
vertex 0.750000 -1.000000 -1.000000
vertex 0.500000 -1.000000 -1.000000
endloop
endfacet
facet normal -0.130658 -0.500728 -0.855687
outer loop
vertex 0.500000 -0.500000 -1.112336
vertex 0.750000 -0.500000 -1.150509
vertex 0.750000 -0.750000 -1.004215
endloop
endfacet
facet normal -0.002289 -0.398876 -0.917002
outer loop
vertex 0.500000 -0.500000 -1.112336
vertex 0.750000 -0.750000 -1.004215
vertex 0.500000 -0.750000 -1.003591
endloop
endfacet
facet normal 0.427791 -0.077334 -0.900563
outer loop
vertex 0.750000 -0.500000 -1.150509
vertex 1.000000 -0.500000 -1.031753
vertex 1.000000 -0.750000 -1.010285
endloop
endfacet
facet normal -0.020949 -0.504946 -0.862896
outer loop
vertex 0.750000 -0.500000 -1.150509
vertex 1.000000 -0.750000 -1.010285
vertex 0.750000 -0.750000 -1.004215
endloop
endfacet
endsolid Exported from Blender-2.82 (sub 7)
================================================
FILE: examples/case/system/collapseDict
================================================
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1906 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object collapseDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// If on, after collapsing check the quality of the mesh. If bad faces are
// generated then redo the collapsing with stricter filtering.
controlMeshQuality off;
collapseEdgesCoeffs
{
// Edges shorter than this absolute value will be merged
minimumEdgeLength 1e-8;
// The maximum angle between two edges that share a point attached to
// no other edges
maximumMergeAngle 30;
}
collapseFacesCoeffs
{
// The initial face length factor
initialFaceLengthFactor 0.5;
// If the face can't be collapsed to an edge, and it has a span less than
// the target face length multiplied by this coefficient, collapse it
// to a point.
maxCollapseFaceToPointSideLengthCoeff 0.3;
// Allow early collapse of edges to a point
allowEarlyCollapseToPoint on;
// Fraction to premultiply maxCollapseFaceToPointSideLengthCoeff by if
// allowEarlyCollapseToPoint is enabled
allowEarlyCollapseCoeff 0.2;
// Defining how close to the midpoint (M) of the projected
// vertices line a projected vertex (X) can be before making this
// an invalid edge collapse
//
// X---X-g----------------M----X-----------g----X--X
//
// Only allow a collapse if all projected vertices are outwith
// guardFraction (g) of the distance form the face centre to the
// furthest vertex in the considered direction
guardFraction 0.1;
}
//controlMeshQualityCoeffs
//{
// // Name of the dictionary that has the mesh quality coefficients used
// // by motionSmoother::checkMesh
// #include "meshQualityDict";
//
// // The amount that minimumEdgeLength will be reduced by for each
// // edge if that edge's collapse generates a poor quality face
// edgeReductionFactor 0.5;
//
// // The amount that initialFaceLengthFactor will be reduced by for each
// // face if its collapse generates a poor quality face
// faceReductionFactor $initialFaceLengthFactor;
//
// // Maximum number of smoothing iterations for the reductionFactors
// maximumSmoothingIterations 2;
//
// // Maximum number of outer iterations is mesh quality checking is enabled
// maximumIterations 10;
//
// // Maximum number of iterations deletion of a point can cause a bad face
// // to be constructed before it is forced to not be deleted
// maxPointErrorCount 5;
//}
// ************************************************************************* //
================================================
FILE: examples/case/system/controlDict
================================================
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1906 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application blockMesh;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0;
deltaT 0;
writeControl timeStep;
writeInterval 1;
purgeWrite 0;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
// ************************************************************************* //
================================================
FILE: examples/case/system/fvSchemes
================================================
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1906 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{}
gradSchemes
{}
divSchemes
{}
laplacianSchemes
{}
interpolationSchemes
{}
snGradSchemes
{}
// ************************************************************************* //
================================================
FILE: examples/case/system/fvSolution
================================================
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1906 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //
================================================
FILE: examples/chaining/flywheel.py
================================================
import os
import classy_blocks as cb
# A mesh for calculation of friction losses of a rotating rotor in a fluid.
# See flywheel.svg for explanation of dimensions and block numbers;
r_wheel = 8
t_rim = 1
w_rim = 3
w_wheel = 1
h_gap = 1
w_gap = 1
r_shaft = 1
# cell sizing
cell_size = 0.2
bl_thickness = 0.05
c2c_expansion = 1.25
# patches
fixed_patch = "fixed_wall"
rotating_patch = "rotating_wall"
mesh = cb.Mesh()
# put all shapes into this list for easier 'handling';
# indexes refer to block numbers in sketch
shapes = []
# block 0
shapes.append(
cb.Cylinder([0, 0, 0], [w_gap, 0, 0], [0, r_wheel - t_rim, 0]) # axis point 1 # axis point 2 # radius point 1
)
shapes.append(cb.Cylinder.chain(shapes[0], (w_rim - w_wheel) / 2))
shapes.append(cb.ExtrudedRing.expand(shapes[0], t_rim))
shapes.append(cb.ExtrudedRing.expand(shapes[2], h_gap))
shapes.append(cb.ExtrudedRing.chain(shapes[3], w_rim))
shapes.append(cb.ExtrudedRing.chain(shapes[4], w_gap))
shapes.append(cb.ExtrudedRing.contract(shapes[5], r_wheel - t_rim))
shapes.append(cb.ExtrudedRing.contract(shapes[6], r_shaft))
shapes.append(cb.ExtrudedRing.chain(shapes[7], (w_rim - w_wheel) / 2, start_face=True))
# Chopping:
# Cells on fixed wall are cell_size;
# rotating wall (wheel) is resolved, thus bl_thickness.
# Depending on geometry, two different scenarios are possible:
# a) use end_size and c2c_expansion or
# b) start_size and end_size
# In a), too large cells might be obtained far away from the wall, or
# in b), to high cell-to-cell expansion might be made.
def double_chop(function):
function(length_ratio=0.5, start_size=bl_thickness, c2c_expansion=c2c_expansion)
function(length_ratio=0.5, end_size=bl_thickness, c2c_expansion=1 / c2c_expansion)
# Axial
for i in (1, 2, 4, 6, 8):
double_chop(shapes[i].chop_axial)
# Radial
for i in (2, 4, 6, 7):
double_chop(shapes[i].chop_radial)
shapes[0].chop_radial(end_size=bl_thickness, c2c_expansion=1 / c2c_expansion)
# adjust this cell size to obtain roughly the same cell sizes
# in core and shell of the cylinder
shapes[2].chop_tangential(start_size=4 * cell_size)
# Patch names:
for i in (0, 2, 3):
shapes[i].set_start_patch(fixed_patch)
for i in (3, 4, 5):
shapes[i].set_outer_patch(fixed_patch)
for i in (5, 6, 7):
shapes[i].set_end_patch(fixed_patch)
for shape in shapes:
mesh.add(shape)
mesh.set_default_patch(rotating_patch, "wall")
mesh.modify_patch(fixed_patch, "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/helmholtz_nozzle.py
================================================
import os
import classy_blocks as cb
# A nozzle with a chamber that produces self-induced oscillations.
# See helmholtz_nozzle.svg for geometry explanation.
# geometry data (all dimensions in meters):
# inlet pipe
r_inlet = 10e-3
l_inlet = 50e-3
# nozzle
r_nozzle = 6e-3
l_nozzle = 20e-3
# chamber
l_chamber_inner = 100e-3
l_chamber_outer = 105e-3
r_chamber_outer = 20e-3
# outlet
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
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")
mesh.add(chamber_outer)
# translate outer points of outer chamber (and edges) to get
# that inverted cone at the end;
# this could also be done by a RevolvedRing
for face in chamber_outer.sketch_2.faces:
for i in (1, 2):
face.points[i].translate([l_chamber_outer - l_chamber_inner, 0, 0])
face.add_edge(1, cb.Origin([l_inlet + l_nozzle + l_chamber_outer, 0, 0]))
# 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.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/labyrinth.py
================================================
import os
from typing import List
import classy_blocks as cb
from classy_blocks.util import functions as f
mesh = cb.Mesh()
front_point = f.vector(20, -100, 0)
above_point = f.vector(0, 0, 100)
orienter = cb.ViewpointReorienter(front_point, above_point)
extrudes: List[cb.Extrude] = []
face = cb.Face([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]])
extrude = cb.Extrude(face, 1)
mesh.add(extrude)
for side in ("top", "right", "top", "top", "left", "top"):
face = extrude.get_face(side)
# 'left', 'bottom' and 'front' faces' normals point INTO
# the blocks so the default extrude direction won't work here.
normal = f.unit_vector(face.center - extrude.center)
extrude = cb.Extrude(face, normal)
# Any extrude that was not made from the 'top' face
# is now oriented differently from the first extrude.
# To keep things simple and intuitive, let's reorient
# the operations to keep them consistent - 'top' faces
# facing upwards.
orienter.reorient(extrude)
mesh.add(extrude)
mesh.set_default_patch("walls", "wall")
grader = cb.FixedCountGrader(mesh, 5)
grader.grade()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/orifice_plate.py
================================================
import os
import classy_blocks as cb
# see orifice_plate.svg for sketch
D = 0.1 # [m]
d_0 = 0.025
t = 0.005 # thickness of orifice plate
entry_length = 5 # *D
exit_length = 8 # *D
# chopping
cell_size = t # use much less in real life
# to save on simulation time
# use bigger cells in lenghty entry/exit sections
cell_dilution = 2
mesh = cb.Mesh()
r_0 = d_0 / 2
r_1 = r_0 + t / 4
r_2 = r_0 + t / 2
shapes = [None] * 7
shapes[0] = cb.Cylinder([0, 0, 0], [D * entry_length, 0, 0], [0, r_1, 0])
shapes[1] = cb.Frustum.chain(shapes[0], t / 4, r_0)
shapes[2] = cb.Cylinder.chain(shapes[1], t / 4)
shapes[3] = cb.Frustum.chain(shapes[2], t / 2, r_2)
shapes[4] = cb.Cylinder.chain(shapes[3], D * exit_length)
shapes[5] = cb.ExtrudedRing.expand(shapes[0], D / 2 - r_1)
shapes[6] = cb.ExtrudedRing.expand(shapes[4], D / 2 - r_2)
# chop to a sensible number of cells;
# dilute long inlet/outlet sections
shapes[0].chop_radial(start_size=cell_size)
shapes[0].chop_tangential(start_size=cell_size)
shapes[0].chop_axial(length_ratio=0.9, start_size=cell_size * cell_dilution, end_size=cell_size)
shapes[0].chop_axial(length_ratio=0.1, start_size=cell_size, end_size=t / 8)
shapes[6].chop_axial(length_ratio=0.1, start_size=t / 8, end_size=cell_size)
shapes[6].chop_axial(length_ratio=0.9, start_size=cell_size, end_size=cell_size * cell_dilution)
shapes[5].chop_radial(start_size=cell_size / 2, end_size=2 * cell_size)
shapes[6].chop_radial(start_size=cell_size / 2, end_size=2 * cell_size)
for i in (1, 2, 3):
shapes[i].chop_axial(start_size=t / 8)
for s in shapes:
if s is not None:
mesh.add(s)
# patches
for i in (0, 5):
shapes[i].set_start_patch("inlet")
for i in (4, 6):
shapes[i].set_end_patch("outlet")
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/tank.py
================================================
import os
import classy_blocks as cb
# a cylindrical tank with round end caps
diameter = 0.5
length = 0.5 # including end caps
mesh = cb.Mesh()
cylinder = cb.Cylinder([0, 0, 0], [length, 0, 0], [0, diameter / 2, 0])
wall_name = "tank_wall"
cylinder.set_outer_patch(wall_name)
start_cap = cb.Hemisphere.chain(cylinder, start_face=True)
start_cap.set_outer_patch(wall_name)
end_cap = cb.Hemisphere.chain(cylinder, start_face=False)
end_cap.set_outer_patch(wall_name)
mesh.add(cylinder)
mesh.add(start_cap)
mesh.add(end_cap)
grader = cb.SimpleGrader(mesh, 0.05)
grader.grade()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/test_tube.py
================================================
import os
import classy_blocks as cb
# a test tube as a reactor with a part of atmosphere above and below it
outer_diameter = 0.015 # main body,
body_length = 0.1
cap_diameter = 0.007 # connected to a round end cap
conical_length = 0.02 # with a frustum of this length
wall_thickness = 0.001
# there's some reacting stuff in the tube, reaching up to the top of
# the conical section
stuff_zone = "stuff"
# outside atmosphere extends upwards, away and below the 'body'
atm_height = 0.1
atm_radius = 0.1
# refer to other examples for a more proper-ish grading setup
h = 0.001
h_atm = 10 * h
mesh = cb.Mesh()
# the inside of test tube is modeled by 3 shapes
body = cb.Cylinder([0, 0, 0], [0, 0, -body_length], [outer_diameter / 2, 0, 0])
body.chop_axial(start_size=h)
body.chop_radial(start_size=h)
body.chop_tangential(start_size=h)
mesh.add(body)
cone = cb.Frustum.chain(body, conical_length, cap_diameter / 2)
cone.chop_axial(start_size=h)
cone.set_cell_zone(stuff_zone)
mesh.add(cone)
end_cap = cb.Hemisphere.chain(cone)
end_cap.chop_axial(start_size=h / 2)
end_cap.set_cell_zone(stuff_zone)
mesh.add(end_cap)
# atmosphere
atm_above = cb.Cylinder.chain(body, atm_height, start_face=True)
atm_above.chop_axial(start_size=h_atm)
atm_above.set_end_patch("atmosphere")
mesh.add(atm_above)
atm_wall = cb.ExtrudedRing.expand(atm_above, wall_thickness)
atm_wall.chop_radial(start_size=h_atm)
atm_wall.set_end_patch("atmosphere")
mesh.add(atm_wall)
atm_side_above = cb.ExtrudedRing.expand(atm_wall, atm_radius)
atm_side_above.chop_radial(start_size=h_atm)
atm_side_above.set_end_patch("atmosphere")
atm_side_above.set_outer_patch("atmosphere")
mesh.add(atm_side_above)
atm_side_below = cb.ExtrudedRing.chain(atm_side_above, body_length, start_face=True)
atm_side_below.chop_axial(start_size=h_atm)
atm_side_below.set_outer_patch("atmosphere")
atm_side_below.set_end_patch("atmosphere")
mesh.add(atm_side_below)
mesh.set_default_patch("tube_wall", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/chaining/venturi_tube.py
================================================
import os
import numpy as np
import classy_blocks as cb
from classy_blocks.util import functions as f
def calculate_fillet(r_pipe, r_fillet, a_cone):
# see venturi_tube.svg for explanation
a_cone = f.deg2rad(a_cone)
y_center = r_pipe - r_fillet
l_f = abs(r_fillet * np.sin(a_cone))
r_2 = y_center + r_fillet * np.cos(a_cone)
r_mid = y_center + r_fillet * np.cos(a_cone / 2)
return l_f, r_2, r_mid
def calculate_cone(r_start, r_end, a_cone):
return abs(r_end - r_start) / np.tan(f.deg2rad(a_cone))
# see venturi_tube.svg for sketch
# https://www.researchgate.net/figure/The-Critical-Dimensions-of-the-Classical-Venturi-Tube-Source-p-24-Principles-and_fig5_311949745
D = 0.1 # [m]
d = 0.03 # exaggerated to illustrate the awesomeness
entry_length = 5 # *D
entry_angle = 20 # degrees
exit_length = 8 # *D
exit_angle = 10 # degrees
fillet_radius = 1.5 * D # also exaggerated to display even more awesomeness
# chopping
cell_size = 0.08 * D
# to save on simulation time
# use bigger cells in lenghty entry/exit sections
cell_dilution = 5
mesh = cb.Mesh()
shapes = []
# entry tube
shapes.append(cb.Cylinder([0, 0, 0], [D * entry_length, 0, 0], [0, D / 2, 0]))
# Contraction: two fillets and a cone in between
# fillet from entry cylinder to entry cone
l_fillet_1, r_fillet_1, r_fillet_1_mid = calculate_fillet(D / 2, fillet_radius, entry_angle / 2)
# fillet from entry cone to middle cylinder
l_fillet_2, r_fillet_2, r_fillet_2_mid = calculate_fillet(d / 2, -fillet_radius, entry_angle / 2)
# length of cone connecting the fillets
l_cone = calculate_cone(r_fillet_1, r_fillet_2, entry_angle / 2) - l_fillet_1 - l_fillet_2
# print(l_fillet_1, l_cone, l_fillet_2)
# print(r_fillet_1, r_fillet_2)
shapes.append(cb.Frustum.chain(shapes[-1], l_fillet_1, r_fillet_1, radius_mid=r_fillet_1_mid))
shapes.append(cb.Frustum.chain(shapes[-1], l_cone, r_fillet_2))
shapes.append(cb.Frustum.chain(shapes[-1], l_fillet_2, d / 2, radius_mid=r_fillet_2_mid))
# the narrowest part
shapes.append(cb.Cylinder.chain(shapes[-1], d))
# expansion:
# same as contraction but at different angle
l_fillet_3, r_fillet_3, r_fillet_3_mid = calculate_fillet(d / 2, -fillet_radius, exit_angle / 2)
l_fillet_4, r_fillet_4, r_fillet_4_mid = calculate_fillet(D / 2, fillet_radius, exit_angle / 2)
l_cone = calculate_cone(r_fillet_3, r_fillet_4, exit_angle / 2) - l_fillet_3 - l_fillet_4
# print(l_fillet_3, l_cone, l_fillet_4)
# print(r_fillet_3, r_fillet_4)
shapes.append(cb.Frustum.chain(shapes[-1], l_fillet_3, r_fillet_3, radius_mid=r_fillet_3_mid))
shapes.append(cb.Frustum.chain(shapes[-1], l_cone, r_fillet_4))
shapes.append(cb.Frustum.chain(shapes[-1], l_fillet_4, D / 2, radius_mid=r_fillet_4_mid))
shapes.append(cb.Cylinder.chain(shapes[-1], D * exit_length))
# all cells sizes in longitudinal direction are fixed by the first block
shapes[0].chop_radial(start_size=cell_size)
shapes[0].chop_tangential(start_size=cell_size)
# use smaller cells in smaller diameters
for s in shapes[1:-1]:
s.chop_axial(start_size=cell_size * s.sketch_1.radius * 2 / D, end_size=cell_size * s.sketch_2.radius * 2 / D)
# dilute cells in first and last block
shapes[0].chop_axial(start_size=cell_size * cell_dilution, end_size=cell_size)
shapes[-1].chop_axial(end_size=cell_size * cell_dilution, start_size=cell_size)
# patches
shapes[0].set_start_patch("inlet")
shapes[-1].set_end_patch("outlet")
mesh.set_default_patch("walls", "wall")
for s in shapes:
mesh.add(s)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/complex/airfoil/airfoil.py
================================================
from typing import ClassVar
import numpy as np
import classy_blocks as cb
from classy_blocks.util import functions as f
# This rather lengthy tutorial does the following:
# - reads 2D airfoil points*
# - rotates the airfoil to a desired angle of attack
# - scales it to actual chord length
# - creates a small domain around the airfoil
# - maintains thickness of 1 in 3rd dimension**
# - optimizes its blocking for best results
# The example does not aim to produce production-ready
# airfoil meshes but serves as a demonstration of:
# - creation and manipulation of curves
# - usage of OnCurve edges
# - Sketch optimization (2D geometry)
# * A word on trailing edges
# NACA equations produce a blunt trailing edge if no correction is applied
# and this 'feature' is exploited here so that a blocking where
# thin boundary layer cells do not spread into the domain downstream.
# This blocking will not work with sharp trailing edges.
# Also, real-life geometry will not work with infinitely
# sharp trailing edges (or people around them won't).
# ** This is a default for 2D OpenFOAM cases
FILE_NAME = "naca2414.dat"
ANGLE_OF_ATTACK = 10 # in degrees
CHORD = 0.5 # desired chord (provided the one from points is 1)
OPTIMIZE = True # Set to False to skip optimization
CELL_SIZE = 0.025
BL_THICKNESS = 0.001 # thickness of boundary layer cells
C2C_EXPANSION = 1.1 # expansion ratio in boundary layer
mesh = cb.Mesh()
### Load airfoil curve
def get_curve(z: float) -> cb.SplineInterpolatedCurve:
"""Loads 2D points from a Selig file and
converts it to 3D by adding a provided z-coordinate."""
raw_data = np.loadtxt(FILE_NAME, skiprows=1) * CHORD
z_dimensions = np.ones((len(raw_data),)) * z
points = np.hstack((raw_data, z_dimensions[:, None]))
curve = cb.SplineInterpolatedCurve(points)
curve.rotate(f.deg2rad(-ANGLE_OF_ATTACK), [0, 0, 1])
return curve
foil_curve = get_curve(0)
top_foil_curve = get_curve(1)
### Select approximate point positions:
# refer to the airfoil.svg sketch for explanation
# and indexes
points = np.zeros((18, 3))
points[0] = [-CHORD / 2, 0, 0]
points[1] = [0, CHORD / 2, 0]
points[2] = [CHORD, CHORD / 2, 0]
points[3] = [1.5 * CHORD, CHORD / 2, 0]
points[4] = [1.5 * CHORD, CHORD / 4, 0]
points[5] = [1.5 * CHORD, -CHORD / 4, 0]
points[6] = [1.5 * CHORD, -CHORD / 2, 0]
points[7] = [CHORD, -CHORD / 2, 0]
points[8] = [0, -CHORD / 2, 0]
# points 9...15 with point 12 being set first
param_12 = foil_curve.get_closest_param(points[0])
curve_params = np.concatenate(
(np.linspace(0, param_12, num=3, endpoint=False), [param_12], np.linspace(param_12, 1, num=4)[1:])
)
for i, t in enumerate(curve_params):
points[i + 9] = foil_curve.get_point(t)
# create a sketch on the bottom
class AirfoilSketch(cb.MappedSketch):
quads: ClassVar = [
[12, 11, 1, 0], # 0
[11, 10, 2, 1], # 1
[10, 9, 16, 2], # 2
[9, 15, 17, 16], # 3
[15, 14, 7, 17], # 4
[14, 13, 8, 7], # 5
[13, 12, 0, 8], # 6
[2, 16, 4, 3], # 7
[16, 17, 5, 4], # 8
[17, 7, 6, 5], # 9
]
def __init__(self, points):
super().__init__(points, self.quads)
# determine initial positions for points 16 and 17
# with smoothing
smoother = cb.SketchSmoother(self)
smoother.smooth()
# Optimize:
optimizer = cb.SketchOptimizer(self)
pos = self.positions
# Points that slide along the airfoil curve
for i, point_index in enumerate((10, 11, 12, 13, 14)):
initial_param = curve_params[i]
optimizer.add_clamp(cb.CurveClamp(pos[point_index], foil_curve, initial_param))
# Points that move in their X-Y plane
for i in (16, 17):
optimizer.add_clamp(cb.PlaneClamp(pos[i], pos[i], [0, 0, 1]))
# Points that move along domain edges
def optimize_along_line(point_index, line_index_1, line_index_2):
clamp = cb.LineClamp(pos[point_index], pos[line_index_1], pos[line_index_2])
optimizer.add_clamp(clamp)
optimize_along_line(2, 1, 3)
optimize_along_line(7, 8, 6)
optimize_along_line(4, 3, 6)
optimize_along_line(5, 3, 6)
# point 0: on arc
clamp = cb.RadialClamp(pos[0], [0, 0, 0], [0, 0, 1])
optimizer.add_clamp(clamp)
optimizer.optimize(tolerance=1e-5, method="SLSQP", relax=True)
# edges were added in super().__init__() but now positions have changed and
# we have to adjust for that
self.add_edges()
def add_edges(self):
for i in (0, 1, 2, 4, 5, 6):
self.faces[i].add_edge(0, cb.OnCurve(foil_curve.copy()))
for i in (0, 6):
self.faces[i].add_edge(2, cb.Origin([0, 0, 0]))
### Create an extruded shape
base = AirfoilSketch(points)
shape = cb.ExtrudedShape(base, [0, 0, 1])
### Set cell size/grading;
# Keep in mind that not all blocks need exact specification as
# chopping will propagate automatically through blocking
shape.chop(2, count=1) # 1 cell in the 3rd dimension (2D domain)
# keep consistent first cell thickness by using edge grading
shape.operations[1].chop(1, start_size=BL_THICKNESS, c2c_expansion=C2C_EXPANSION, take="max", preserve="start_size")
# This is guesswork! Can be solved with a different blocking (that will product more even block sizes),
# a lot of math (check the cell size of block 3) or an automatic grader (TODO).
shape.operations[8].chop(1, start_size=BL_THICKNESS, end_size=CELL_SIZE, preserve="end_size")
### Set patches
shape.set_start_patch("topAndBottom")
shape.set_end_patch("topAndBottom")
for i in range(7):
shape.operations[i].set_patch("front", "airfoil")
mesh.modify_patch("airfoil", "wall")
mesh.modify_patch("topAndBottom", "empty")
mesh.set_default_patch("freestream", "patch")
mesh.add(shape)
# Chop remaining blocks with an automatic grader (see the comment at manual grading above)
grader = cb.SimpleGrader(mesh, CELL_SIZE)
grader.grade(take="max")
### Write the mesh
mesh.write("../../case/system/blockMeshDict", debug_path="debug.vtk")
================================================
FILE: examples/complex/cyclone/README
================================================
An advanced example with optimization, custom shapes, sketches and regions.
Work in progress, report bugs promptly!
Usage
1. Edit dimensions and meshing parameters in parameters.py
2. Read through comments in cyclone.py.
3. Run python cyclone.py
Comments
- To see initial blocking without optimization, comment out the optimizer.optimize(...) line in cyclone.py.
- To visualize blocks as they are constructed, call mesh.write() after the desired step (that is, added Region) and call sys.exit(), then open debug.vtk.
- To (hopefully) see blocking better, you can try the Shrink filter in paraview, set it to 0.99 then view it as Wireframe. Under Display tab, tick Render Lines As Tubes and set Line Witdh to 5 or so.
================================================
FILE: examples/complex/cyclone/__init__.py
================================================
================================================
FILE: examples/complex/cyclone/cyclone.py
================================================
#!/usr/bin/env python
import os
import numpy as np
import parameters as params
from geometry import geometry
from regions.body import ChainSketch, Cone, LowerBody, UpperBody
from regions.core import Core, Outlet
from regions.fillaround import FillAround
from regions.inlet import InletExtension, InletPipe
from regions.inner_ring import InnerRing
from regions.pipe import Pipe
from regions.region import Region
from regions.skirt import Skirt
import classy_blocks as cb
from classy_blocks.base.exceptions import UndefinedGradingsError
from classy_blocks.util import functions as f
mesh = cb.Mesh()
# A Region is an independent part of the mesh, constructed from
# various other entities but each Region has the same methods and properties.
def add_regions(regions: list[Region]) -> None:
for region in regions:
for element in region.elements:
mesh.add(element)
region.project()
region.set_patches()
# First (bad) guess at blocking: inlet is a semicylinder
# with top faces snapped to body, then the two faces of core
# are moved towards the center
inlet = InletPipe()
# Skirt contains 4 blocks, extruded from displaced inlet top faces
skirt = Skirt(inlet.inlet.shell)
# Skirt and FillAround form a complete outer ring
fillaround = FillAround(skirt.lofts[0], skirt.lofts[-1])
# Inner ring adds another layer of blocks inside the above ring.
inner_ring = InnerRing([*inlet.inner_lofts, *skirt.elements, *fillaround.elements])
optimize_regions = [inlet, skirt, fillaround, inner_ring]
add_regions(optimize_regions)
# This bad blocking needs to be improved before
# making further blocks. It is done on a semi-finished mesh:
mesh.assemble()
# Now coincident points have been merged into Vertices and each got its own index.
# write out the current blocking and get vertex numbers from paraview
try:
mesh.write("...", debug_path="pre-optimization.vtk")
except UndefinedGradingsError:
pass
# We'll redistribute (and fix) inner ring points evenly or optimization
# will find a better solution with a thin block in the
vindexes = [68, 69, 70, 84, 82, 80, 78, 76, 74, 71, 67, 66]
current_angles = [f.to_polar(mesh.vertices[i].position, axis="z")[1] for i in vindexes]
angle_offset = current_angles[0]
uniform_angles = np.linspace(2 * np.pi, 0, num=len(current_angles), endpoint=False) + angle_offset
for i, vindex in enumerate(vindexes):
position = mesh.vertices[vindex].position
polar = f.to_polar(position, axis="z")
polar[1] = uniform_angles[i]
mesh.vertices[vindex].move_to(f.to_cartesian(polar, axis="z"))
# correct points that created invalid cells
neighbours = [mesh.vertices[i].position for i in (30, 57, 84, 70)]
mesh.vertices[31].move_to(np.average(neighbours, axis=0))
neighbours = [mesh.vertices[i].position for i in (25, 67, 71, 33)]
mesh.vertices[22].move_to(np.average(neighbours, axis=0))
# Now, optimize the bad blocks in the inlet.
optimizer = cb.MeshOptimizer(mesh)
optimizer.config.relaxation_iterations = 5
optimizer.config.method = "SLSQP"
optimizer.config.abs_tol = 200
clamps = []
for region in optimize_regions:
for clamp in region.get_clamps(mesh):
optimizer.add_clamp(clamp)
optimizer.optimize()
# Now Block objects contain optimization results but those are not reflected in
# user-created Operations. Mesh.backport() will copy the data back.
mesh.backport()
# We'll add new stuff so we don't need those half-finished Blocks.
mesh.clear()
# The optimized inlet is short to aid optimization;
# it's time to extend it to specifications.
inlet_extension = InletExtension(inlet)
add_regions([inlet_extension])
# Upper body is an extension of inner and outer top rings
# (around outlet pipe)
upper_sketch = ChainSketch([skirt, fillaround, inner_ring])
upper = UpperBody(upper_sketch, geometry.l["upper"])
# Lower body begins where outlet pipe ends;
# it extends the above rings plus adds pipe thickness and core
lower_sketch = ChainSketch([upper])
lower = LowerBody(lower_sketch, geometry.l["lower"])
lower.elements[0].chop(2, start_size=params.BULK_SIZE)
pipe = Pipe(lower)
add_regions([upper, lower, pipe])
# Core is a 9-block-core cylinder, created from 12 points of pipe ring.
# Again, instead of finding those 12 points (which are difficult to find and sort)
# it is easier to re-assemble the mesh and get the points from debug.vtk in ParaView.
mesh.assemble()
vindexes = [173, 169, 170, 179, 180, 182, 184, 186, 188, 190, 177, 175]
vindexes.reverse()
points = [mesh.vertices[i].position for i in vindexes]
mesh.clear() # Again, we'll add new stuff right away
core = Core(points)
cone_sketch = ChainSketch([lower, pipe, core])
cone = Cone(cone_sketch)
outlet = Outlet(core.cylinder)
add_regions([core, cone, outlet])
# What's left is to mirror the inlet and upper rings to form a round inlet;
# Operation.mirror() is what we need
def mirror_region(region: Region):
mirrored = []
for element in region.elements:
mirror = element.copy().mirror([0, 0, 1], [0, 0, 0])
mesh.add(mirror)
mirrored.append(mirror)
return mirrored
fillaround_mirror = mirror_region(fillaround)
inner_ring_mirror = mirror_region(inner_ring)
mirror_region(skirt)
mirror_region(inlet)
mirror_region(inlet_extension)
mesh.set_default_patch("walls", "wall")
grader = cb.InflationGrader(mesh, params.BL_THICKNESS, params.BULK_SIZE, c2c_expansion=params.C2C_EXPANSION)
grader.grade()
mesh.add_geometry(geometry.surfaces)
mesh.settings.scale = params.MESH_SCALE
mesh.write(os.path.join("..", "..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/complex/cyclone/geometry.py
================================================
import dataclasses
from parameters import (
D_BODY,
D_CONE,
D_INLET,
D_OUTLET,
DIM_SCALE,
L_BODY,
L_CONE,
L_INLET,
L_OUTLET_IN,
L_OUTLET_OUT,
T_PIPE,
)
from classy_blocks.base.exceptions import GeometryConstraintError
from classy_blocks.cbtyping import NPPointType
from classy_blocks.util import functions as f
from classy_blocks.util.constants import vector_format as fvect
@dataclasses.dataclass
class Geometry:
"""Holds user-provided parameters and conversions to SI units;
simple relations and shortcuts for easier construction"""
def __post_init__(self):
# constraints check
if self.r["inlet"] >= self.r["body"] / 2:
raise GeometryConstraintError("Inlet must be smaller than body/2")
if self.z["skirt"] <= self.z["upper"]:
raise GeometryConstraintError("Outlet inside is too short")
@property
def r(self) -> dict[str, float]:
"""Radii as defined in parameters"""
return {
"inlet": DIM_SCALE * D_INLET / 2,
"outlet": DIM_SCALE * D_OUTLET / 2,
"body": DIM_SCALE * D_BODY / 2,
"pipe": DIM_SCALE * (D_OUTLET / 2 + T_PIPE),
"cone": DIM_SCALE * D_CONE / 2,
}
@property
def l(self) -> dict["str", "float"]: # noqa: E743
"""Lengths that matter"""
skirt = 0.1 * self.r["inlet"]
l_body = DIM_SCALE * L_BODY - skirt - self.r["inlet"]
l_outlet_in = DIM_SCALE * L_OUTLET_IN
upper = l_outlet_in - self.r["inlet"] - skirt
return {
"inlet": DIM_SCALE * L_INLET,
"outlet": DIM_SCALE * (L_OUTLET_IN + L_OUTLET_OUT),
"skirt": skirt,
"upper": upper,
"lower": l_body - upper,
"body": l_body,
"cone": DIM_SCALE * L_CONE,
"pipe": T_PIPE * DIM_SCALE, # pipe thickness
}
@property
def inlet(self) -> list[NPPointType]:
point_2 = f.vector(0, -self.r["body"] + self.r["inlet"], 0)
point_0 = point_2 + f.vector(-self.l["inlet"], 0, 0)
point_1 = point_2 + f.vector(-self.r["body"] * 1.1, 0, 0)
return [point_0, point_1, point_2]
@property
def z(self) -> dict[str, float]:
"""z-coordinates of cyclone parts"""
z_in_sk = self.r["inlet"] + self.l["skirt"]
return {
"skirt": -z_in_sk,
"upper": -z_in_sk - self.l["upper"],
"lower": -self.l["body"] - z_in_sk,
"cone": -self.l["body"] - self.l["cone"] - z_in_sk,
}
@property
def surfaces(self):
"""Returns definitions of searchable geometries for projections"""
delta_in = f.vector(-2 * self.l["inlet"], 0, 0)
p_body = f.vector(0, 0, -2 * self.z["cone"])
def cylinder(name, point_1, point_2, radius):
return {
name: [
"type searchableCylinder",
f"point1 {fvect(point_1)}",
f"point2 {fvect(point_2)}",
f"radius {radius}",
],
}
return {
**cylinder("inlet", self.inlet[0] - delta_in, self.inlet[2] + delta_in, self.r["inlet"]),
**cylinder("body", p_body, -p_body, self.r["body"]),
**cylinder("outlet", p_body, -p_body, self.r["outlet"]),
**cylinder("pipe", p_body, -p_body, self.r["pipe"]),
"cone": [
"type searchableCone",
f"point1 {fvect([0, 0, self.z['lower']])}",
f"radius1 {self.r['body']}",
"innerRadius1 0",
f"point2 {fvect([0, 0, self.z['cone']])}",
f"radius2 {self.r['cone']}",
"innerRadius2 0",
],
}
geometry = Geometry()
================================================
FILE: examples/complex/cyclone/parameters.py
================================================
### Geometry
# See docs/geometry.svg for a quick sketch
# Diameter and length of inlet pipe [mm]
D_INLET = 120
L_INLET = 500
# Body diameter and length
D_BODY = 300
L_BODY = 500
# Outlet pipe inner diameter and length;
# the 'in' part is inside body, out is extended away from the top surface.
# Keep in mind that L_OUTLET_IN must be greater than D_INLET
D_OUTLET = 140
L_OUTLET_IN = 140
L_OUTLET_OUT = 300
# outlet pipe wall thickness
T_PIPE = 10
# Length and end diameter of the conical section
L_CONE = 400
D_CONE = 120
DIM_SCALE = 1 # multiply all above dimensions with this
MESH_SCALE = 0.001 # goes into blockMeshDict.scale
# Mesh
# (use same dimensions as for geometry)
BULK_SIZE = DIM_SCALE * 10
BL_THICKNESS = DIM_SCALE * 0.5
C2C_EXPANSION = 1.2
================================================
FILE: examples/complex/cyclone/regions/__init__.py
================================================
================================================
FILE: examples/complex/cyclone/regions/body.py
================================================
from collections.abc import Sequence
import parameters as params
from geometry import geometry as geo
from regions.region import Region
import classy_blocks as cb
from classy_blocks.base.transforms import Scaling, Translation
from classy_blocks.construct.flat.sketch import Sketch
from classy_blocks.construct.operations.operation import Operation
from classy_blocks.construct.shapes.round import RoundSolidShape
from classy_blocks.util import functions as f
from classy_blocks.util.constants import TOL
class ChainSketch(Sketch):
"""Collects bottom-most faces of given regions and creates a sketch from them"""
@property
def grid(self):
return [self.faces]
@staticmethod
def _get_faces(ops: Sequence[Operation]) -> list[cb.Face]:
"""Skims faces from given operations and reorders them so
that they are ready for extruding or whatever"""
faces: list[cb.Face] = []
for operation in ops:
# TODO: copy edges and other data too
face = operation.get_closest_face([0, 0, 10 * geo.z["cone"]])
# skip faces, made from inlet core blocks
if face.center[2] > 0.99 * (geo.z["skirt"]):
continue
# reorient
if face.normal[2] > 0:
face.invert()
faces.append(face)
return faces
@staticmethod
def _add_arcs(faces: list[cb.Face]) -> None:
"""Adds arc edges between outermost points of outermost faces
to create round shape"""
# add arcs to outermost radius (body and cone)
max_radius = 0
for face in faces:
radii = [f.to_polar(point, axis="z")[0] for point in face.point_array]
max_radius = max(max_radius, max(radii))
for face in faces:
for i in range(4):
polar_1 = f.to_polar(face.point_array[i], axis="z")
polar_2 = f.to_polar(face.point_array[(i + 1) % 4], axis="z")
if abs(polar_1[0] - max_radius) < 2 * TOL and abs(polar_2[0] - max_radius) < 2 * TOL:
face.add_edge(i, cb.Origin([0, 0, polar_1[2]]))
def __init__(self, regions: list[Region]):
# gather faces
ops: Sequence[Operation] = []
for region in regions:
ops += region.elements
faces = self._get_faces(ops)
self._add_arcs(faces)
self._faces = faces
@property
def faces(self):
return self._faces
@property
def center(self):
return f.vector(0, 0, self.faces[0].center[2])
@property
def n_segments(self):
return 12
class BodyShape(RoundSolidShape):
@property
def shell(self):
return []
@property
def core(self):
return []
class UpperBody(Region):
def __init__(self, sketch: ChainSketch, length: float):
self.sketch = sketch
self.body = BodyShape(self.sketch, [Translation([0, 0, -length])])
def chop(self):
self.elements[0].chop(2, start_size=params.BULK_SIZE)
@property
def elements(self):
return self.body.operations
class LowerBody(UpperBody):
pass
class Cone(UpperBody):
def __init__(self, sketch: ChainSketch):
self.sketch = sketch
self.body = BodyShape(
self.sketch,
[
Translation([0, 0, -self.geo.l["cone"]]),
Scaling(self.geo.r["cone"] / self.geo.r["body"], f.vector(0, 0, self.geo.z["cone"])),
],
)
================================================
FILE: examples/complex/cyclone/regions/core.py
================================================
from collections.abc import Sequence
from typing import ClassVar
import numpy as np
import parameters as params
from regions.region import Region
import classy_blocks as cb
from classy_blocks.base.transforms import Transformation, Translation
from classy_blocks.cbtyping import NPVectorType, PointListType, PointType
from classy_blocks.construct.point import Point
from classy_blocks.construct.shapes.round import RoundSolidShape
class NineCoreDisk(cb.MappedSketch):
"""A disk that has 3x3 inside quads and 12 outer;
see docs/cylinder.svg for a sketch"""
quads: ClassVar = [
# core
[0, 1, 2, 3], # 0
# layer 1
[0, 15, 4, 5], # 1
[0, 5, 6, 1], # 2
[1, 6, 7, 8], # 3
[1, 8, 9, 2], # 4
[2, 9, 10, 11], # 5
[2, 11, 12, 3], # 6
[3, 12, 13, 14], # 7
[3, 14, 15, 0], # 8
# layer 2
[4, 16, 17, 5], # 9
[5, 17, 18, 6], # 10
[6, 18, 19, 7], # 11
[7, 19, 20, 8], # 12
[8, 20, 21, 9], # 13
[9, 21, 22, 10], # 14
[10, 22, 23, 11], # 15
[11, 23, 24, 12], # 16
[12, 24, 25, 13], # 17
[13, 25, 26, 14], # 18
[14, 26, 27, 15], # 19
[15, 27, 16, 4], # 20
]
def __init__(self, perimeter: PointListType, center_point: PointType):
center_point = np.asarray(center_point)
# inner points will be determined with smoothing;
# a good enough starting estimate is the center
# (anything in the same plane as other points)
outer_points = np.asarray(perimeter)
inner_points = np.ones((16, 3)) * np.average(outer_points, axis=0)
positions = np.concatenate((inner_points, outer_points))
self.center_point = Point(center_point)
super().__init__(positions, self.quads)
# smooth the inner_points (which are all invalid) into position
smoother = cb.SketchSmoother(self)
smoother.smooth()
@property
def core(self) -> list[cb.Face]:
return self.faces[:9]
@property
def shell(self) -> list[cb.Face]:
return self.faces[9:]
def add_edges(self):
for face in self.shell:
face.add_edge(1, cb.Origin(self.center_point.position))
@property
def parts(self):
return [*super().parts, self.center_point]
@property
def center(self):
return self.center_point.position
@property
def grid(self):
return [[self.faces[0]], self.faces[1:9], self.faces[9:]]
@property
def normal(self) -> NPVectorType:
return self.faces[0].normal
@property
def n_segments(self):
return 12
class DozenBlockCylinder(RoundSolidShape):
sketch_class = NineCoreDisk
def __init__(self, perimeter: PointListType, center_point: PointType, length: float):
sketch = NineCoreDisk(perimeter, center_point)
transforms: Sequence[Transformation] = [Translation(sketch.normal * length)]
super().__init__(sketch, transforms)
def chop_radial(self, **kwargs):
self.shell[0].chop(0, **kwargs)
class Core(Region):
def __init__(self, points: PointListType):
self.cylinder = DozenBlockCylinder(points, [0, 0, self.geo.z["upper"]], self.geo.l["lower"])
def chop(self):
self.cylinder.chop_radial(end_size=params.BL_THICKNESS, c2c_expansion=1 / params.C2C_EXPANSION)
self.cylinder.chop_tangential(start_size=params.BULK_SIZE * self.geo.r["outlet"] / self.geo.r["body"])
@property
def elements(self):
return self.cylinder.operations
class Outlet(Region):
def __init__(self, core_cylinder: DozenBlockCylinder):
self.operations: list[cb.Operation] = [
cb.Extrude(op.bottom_face.copy().translate([0, 0, self.geo.l["outlet"]]), [0, 0, -self.geo.l["outlet"]])
for op in core_cylinder.operations
]
def chop(self):
self.elements[0].chop(2, start_size=params.BULK_SIZE)
@property
def elements(self):
return self.operations
def set_patches(self):
for operation in self.elements:
operation.set_patch("bottom", "outlet")
================================================
FILE: examples/complex/cyclone/regions/fillaround.py
================================================
from regions.region import Region
import classy_blocks as cb
from classy_blocks.util import functions as f
class FillAround(Region):
"""A ring that leaves out lofts that interfere with loft_1 and loft_2,
then connects them to form a complete 'ring'."""
def __init__(self, loft_1: cb.Loft, loft_2: cb.Loft):
self.loft_1 = loft_1
self.loft_2 = loft_2
center = [0, 0, loft_1.center[2]]
inner_face = loft_1.get_closest_face(center)
outer_face = loft_1.get_closest_face(100 * loft_1.center)
bottom_face = loft_1.get_closest_face([0, 0, -100])
top_face = loft_1.get_closest_face([0, 0, 100])
z_bottom = min([p[2] for p in bottom_face.point_array])
z_top = max([p[2] for p in top_face.point_array])
r_inner = min([f.to_polar(p)[0] for p in inner_face.point_array])
r_outer = max([f.to_polar(p)[0] for p in outer_face.point_array])
# if one takes 11 segments, then after omitting first and last 3,
# 12 blocks are obtained together with skirt and other pieces
ring = cb.ExtrudedRing([0, 0, z_bottom], [0, 0, z_top], [0, -r_outer, z_bottom], r_inner, n_segments=11)
shell = ring.shell[1:-4]
# connect first and last lofts
connector_1 = cb.Connector(loft_1, shell[0])
connector_2 = cb.Connector(shell[-1], loft_2)
self._operations = [connector_1, *ring.shell[1:-4], connector_2]
@property
def elements(self):
return self._operations
@property
def connector_1(self):
return self._operations[0]
@property
def connector_2(self):
return self._operations[-1]
def project(self):
self.connector_1.project_side("left", "body", True, True)
self.connector_2.project_side("right", "body", True, True)
================================================
FILE: examples/complex/cyclone/regions/inlet.py
================================================
import numpy as np
from regions.region import Region
import classy_blocks as cb
from classy_blocks.construct.point import Point
from classy_blocks.util import functions as f
# Helps with optimization of this tricky part
cb.HalfDisk.core_ratio = 0.6
class InletPipe(Region):
line_clamps = (20, 18, 16, 13, 12)
plane_clamps = (0, 1, 8, 9, 5, 4, 11, 10)
free_clamps = (3, 2, 6, 7)
def __init__(self):
self.inlet = self.create_inlet()
def snap_point(self, point: Point) -> None:
"""Moves points on inlet's end face along x-axis
so that they touch cyclone body"""
# a.k.a. conform to that cylinder; those vertices will remain fixed
y_pos = point.position[1]
angle = np.arccos(y_pos / self.geo.r["body"])
x_pos = -self.geo.r["body"] * np.sin(angle)
point.translate([x_pos, 0, 0])
def scale_point(self, point: Point) -> None:
"""Move a point radially towards axis of cyclone
by a fraction of body thickness at this spot;
creates a cone from which shell will be built"""
vector = f.unit_vector(point.position)
vector[2] = 0
vector *= (self.geo.r["body"] - self.geo.r["pipe"]) * 0.3
point.translate(-vector)
def create_inlet(self):
inlet = cb.SemiCylinder(
self.geo.inlet[1], self.geo.inlet[2], self.geo.inlet[1] - f.vector(0, self.geo.r["inlet"], 0)
)
for op in inlet.operations:
op.top_face.remove_edges()
op.bottom_face.remove_edges()
for point in op.top_face.points:
# move points on inlet's end face so that they touch cyclone body,
# a.k.a. conform to that cylinder; those vertices will remain fixed
self.snap_point(point)
for op in inlet.core:
for point in op.top_face.points:
self.scale_point(point)
for op in inlet.shell:
for i in (0, 3):
self.scale_point(op.top_face.points[i])
return inlet
@property
def inner_lofts(self):
"""Lofts that will be used to create inner ring, that is, those that
have tops facing z-axis"""
return self.inlet.core
@property
def elements(self):
return self.inlet.operations
def project(self):
for operation in self.inlet.shell:
operation.project_side("right", "inlet", True, True)
class InletExtension(Region):
def __init__(self, inlet: InletPipe):
self.extension = cb.SemiCylinder(
self.geo.inlet[0], self.geo.inlet[1], self.geo.inlet[0] - f.vector(0, self.geo.r["inlet"], 0)
)
for i, operation in enumerate(self.extension.operations):
operation.top_face = inlet.elements[i].bottom_face
@property
def elements(self):
return self.extension.operations
def set_patches(self):
self.extension.set_start_patch("inlet")
================================================
FILE: examples/complex/cyclone/regions/inner_ring.py
================================================
import numpy as np
from regions.region import Region
import classy_blocks as cb
from classy_blocks.util import functions as f
class InnerRing(Region):
"""A ring, created by extruding innermost faces of given shapes"""
radial_clamps = (60, 61, 62, 63, 64, 65)
def _move_to_radius(self, point):
polar = f.to_polar(point, axis="z")
polar[0] = self.geo.r["pipe"]
return f.to_cartesian(polar, axis="z")
def _move_to_angle(self, point, angle):
polar = f.to_polar(point, axis="z")
polar[1] = angle
return f.to_cartesian(polar, axis="z")
def _reorient_face(self, face: cb.Face) -> None:
# find the point with lowest z and lowest angle and
# reorient face so that it starts with it
# ACHTUNG! Not the prettiest piece of code.
# TODO: Prettify
z_min = 1e12
angle_min = 1e12
i_point = 5 # a.k.a. invalid
for i, point in enumerate(face.point_array):
polar = f.to_polar(point, axis="z")
polar[1] += 10
if polar[2] < z_min and polar[1] < angle_min:
i_point = i
angle_min = polar[1]
z_min = polar[2]
face.reorient(face.point_array[i_point])
location = face.center
normal = face.normal
if np.dot(location, normal) > 0:
face.invert()
def __init__(self, lofts: list[cb.Loft]):
center_point = f.vector(0, 0, self.geo.z["skirt"])
outer_faces = [loft.get_closest_face(center_point) for loft in lofts]
for face in outer_faces:
self._reorient_face(face)
inner_faces = [face.copy() for face in outer_faces]
for face in inner_faces:
for point in face.points:
point.move_to(self._move_to_radius(point.position))
self.lofts = [cb.Loft(outer_faces[i], inner_faces[i]) for i in range(len(inner_faces))]
@property
def elements(self):
return self.lofts
def project(self):
for element in self.elements:
element.project_side("top", "pipe", True, True)
================================================
FILE: examples/complex/cyclone/regions/pipe.py
================================================
import numpy as np
from regions.region import Region
import classy_blocks as cb
from classy_blocks.cbtyping import NPPointType
from classy_blocks.util import functions as f
class Pipe(Region):
def __init__(self, outer: Region):
self.outer = outer
faces: list[cb.Face] = []
for operation in outer.elements:
face = operation.get_closest_face(self.center)
# filter faces that are from outer operations
for point in face.point_array:
if f.to_polar(point, axis="z")[0] > 1.01 * self.geo.r["pipe"]:
break
else:
faces.append(face)
for face in faces:
if np.dot(face.normal, face.center - self.center) > 0:
face.invert()
self.shell = cb.Shell(faces, self.geo.l["pipe"])
# snap all points on top faces to outlet cylinder
# and bottom faces to 'pipe' cylinder
for operation in self.shell.operations:
face = operation.top_face
for point in face.points:
polar = f.to_polar(point.position, axis="z")
polar[0] = self.geo.r["outlet"]
point.move_to(f.to_cartesian(polar, axis="z"))
operation.project_side("bottom", "pipe", edges=True, points=True)
@property
def center(self) -> NPPointType:
center_z = self.outer.elements[0].center[2]
return f.vector(0, 0, center_z)
@property
def elements(self):
return self.shell.operations
def project(self):
for operation in self.elements:
operation.project_side("top", "outlet", True, True)
================================================
FILE: examples/complex/cyclone/regions/region.py
================================================
import abc
from geometry import geometry
import classy_blocks as cb
from classy_blocks.construct.operations.operation import Operation
from classy_blocks.util import functions as f
class Region(abc.ABC):
"""A logical unit of the mesh that can be constructed independently"""
line_clamps: tuple[int, ...] = ()
radial_clamps: tuple[int, ...] = ()
plane_clamps: tuple[int, ...] = ()
free_clamps: tuple[int, ...] = ()
geo = geometry
@property
@abc.abstractmethod
def elements(self) -> list[Operation]:
"""Entities of any type to be added to the mesh"""
def get_line_clamps(self, mesh):
clamps: set[cb.ClampBase] = set()
for index in self.line_clamps:
vertex = mesh.vertices[index]
delta_x = f.vector(self.geo.r["inlet"] / 2, 0, 0)
clamp = cb.LineClamp(vertex.position, vertex.position, vertex.position + delta_x, (-100, 100))
clamps.add(clamp)
return clamps
def get_free_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
clamps: set[cb.ClampBase] = set()
for index in self.free_clamps:
vertex = mesh.vertices[index]
clamps.add(cb.FreeClamp(vertex.position))
return clamps
def get_plane_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
clamps: set[cb.ClampBase] = set()
for index in self.plane_clamps:
vertex = mesh.vertices[index]
clamp = cb.PlaneClamp(vertex.position, vertex.position, [0, 0, 1])
clamps.add(clamp)
return clamps
def get_radial_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
clamps: set[cb.ClampBase] = set()
for index in self.radial_clamps:
vertex = mesh.vertices[index]
clamp = cb.RadialClamp(vertex.position, [0, 0, 0], [0, 0, 1])
clamps.add(clamp)
return clamps
def get_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
"""Returns a list of clamps to be used for mesh optimization"""
clamps = self.get_line_clamps(mesh)
clamps.update(self.get_radial_clamps(mesh))
clamps.update(self.get_plane_clamps(mesh))
clamps.update(self.get_free_clamps(mesh))
return clamps
def project(self) -> None: # noqa: B027
"""Projections to geometry, if needed"""
def set_patches(self): # noqa: B027
"""Set pathes, if appropriate"""
================================================
FILE: examples/complex/cyclone/regions/skirt.py
================================================
from regions.region import Region
import classy_blocks as cb
class Skirt(Region):
"""A region that connects inlet pipe's top faces to a ring on the outside of cyclone"""
radial_clamps = (28, 23, 24, 30, 83, 81, 72, 66, 68, 69, 70, 84, 82, 80, 78, 76, 74, 71, 67)
plane_clamps = (22, 25, 27, 29, 31, 34, 59, 51, 55, 47, 43, 39, 33, 37, 41, 45, 49, 53, 57)
def __init__(self, inlet_shell: list[cb.Loft]):
self.inlet_shell = inlet_shell
# create 4 lofts, starting from inlet_shell's end faces, to a
# plane, normal to z-axis
z_coord = -self.geo.r["inlet"] - self.geo.l["skirt"]
top_faces = [loft.top_face for loft in self.inlet_shell]
bottom_faces = [face.copy() for face in top_faces]
for face in bottom_faces:
for point in face.points:
point.position[2] = z_coord
self.lofts = [cb.Loft(top_faces[i], bottom_faces[i]) for i in range(4)]
@property
def elements(self):
return self.lofts
def project(self):
for operation in self.elements:
operation.project_side("right", "body", True, True)
================================================
FILE: examples/complex/gear/gear.py
================================================
#!/usr/bin/env python
import os
import time
import numpy as np
import scipy.optimize
from involute_gear import InvoluteGear
from tooth import ToothSketch
import classy_blocks as cb
from classy_blocks.util import functions as f
time_start = time.time()
mesh = cb.Mesh()
# parameters
RADIUS_EXPANSION = 1.1
# create an interpolated curve that represents a gear tooth
fillet = 0.1 # Must be more than zero!
gear = InvoluteGear(fillet=fillet, arc_step_size=0.1, max_steps=1000, teeth=15)
tng_points = gear.generate_tooth_and_gap()
z_coords = np.zeros(len(tng_points[0]))
tng_points = np.stack((tng_points[0], tng_points[1], z_coords)).T
tng_points = np.flip(tng_points, axis=0)
# add start and end points exactly on the 2pi/teeth
start_point = f.to_polar(tng_points[0], axis="z")
start_point[1] = np.pi / gear.teeth
start_point = f.to_cartesian(start_point)
end_point = f.to_polar(tng_points[-1], axis="z")
end_point[1] = -np.pi / gear.teeth
end_point = f.to_cartesian(end_point)
tng_points = np.concatenate(([start_point], tng_points, [end_point]))
tooth_curve = cb.LinearInterpolatedCurve(tng_points)
gear_params = np.linspace(0, 1, num=8)
# fix points 1 and 3:
# 1 is on radius gear.root_radius + fillet/2
def frad(t, radius):
return f.norm(tooth_curve.get_point(t)) - radius
gear_params[1] = scipy.optimize.brentq(lambda t: frad(t, gear.root_radius + fillet / 2), 0, 0.25)
# 3 is on radius gear.outer_radius - fillet/2
gear_params[3] = scipy.optimize.brentq(lambda t: frad(t, gear.outer_radius - fillet / 2), 0.25, 0.5)
gear_params[6] = 1 - gear_params[1]
gear_params[4] = 1 - gear_params[3]
gear_params[2] = (gear_params[1] + gear_params[3]) / 2
gear_params[5] = (gear_params[4] + gear_params[6]) / 2
gear_points = np.array([tooth_curve.get_point(t) for t in gear_params])
outer_radius = f.norm(gear_points[3] * RADIUS_EXPANSION)
p11_polar = f.to_polar(gear_points[-1], axis="z")
p14_polar = f.to_polar(gear_points[0], axis="z")
angles = np.linspace(p11_polar[1], p14_polar[1], num=4)
tangential_points = np.array([f.to_cartesian([outer_radius, angle, 0]) for angle in angles])
radial_points_1 = np.linspace(gear_points[-1], tangential_points[0], axis=0, num=5)[1:-1]
radial_points_2 = np.linspace(tangential_points[-1], gear_points[0], axis=0, num=5)[1:-1]
outer_points = np.concatenate((gear_points, radial_points_1, tangential_points, radial_points_2))
inner_points = np.zeros((6, 3))
positions = np.concatenate((outer_points, inner_points))
# At this point, a smoother would reliably
# produce almost the best blocking if this was a convex sketch.
# Alas, this is a severely concave case so smoothing will produce
# degenerate quads which even optimizers won't be able to fix.
# It's best to manually position points, then optimize the sketch.
def mirror(target, source):
# once a position is obtained, the mirrored counterpart is also determined
positions[target] = [positions[source][0], -positions[source][1], 0]
# fix points 18 and 23 because optimization doesn't 'see' curved edges
# and produces high non-orthogonality
dir_0 = f.unit_vector(gear_points[0] - gear_points[1])
dir_2 = f.unit_vector(gear_points[2] - gear_points[1])
dir_18 = f.unit_vector(dir_0 + dir_2)
positions[18] = gear_points[1] + dir_18 * f.norm(gear_points[0] - gear_points[1]) / 2
mirror(23, 18)
positions[17] = positions[0] + f.unit_vector(positions[17] - positions[0]) * f.norm(positions[18] - positions[1])
mirror(8, 17)
# other points are somewhere between...
def midpoint(target, left, right):
positions[target] = (positions[left] + positions[right]) / 2
midpoint(19, 2, 16)
midpoint(20, 3, 13)
# and their mirrored counterparts
mirror(22, 19)
mirror(21, 20)
sketch = ToothSketch(positions, tooth_curve)
# Optimize the sketch:
optimizer = cb.SketchOptimizer(sketch)
# point 2 is on gear curve
optimizer.add_clamp(cb.CurveClamp(positions[2], tooth_curve))
# point 13 is movable radially
optimizer.add_clamp(cb.RadialClamp(positions[13], [0, 0, 0], [0, 0, 1]))
# 15-17 move along a line
for i in (15, 16, 17):
optimizer.add_clamp(cb.LineClamp(positions[i], gear_points[0], tangential_points[-1]))
# freely movable points (on sketch plane)
# TODO: easier clamp definition for sketch optimization
for i in (19, 20):
optimizer.add_clamp(cb.PlaneClamp(sketch.positions[i], sketch.positions[i], sketch.normal))
# Links!
symmetry_pairs = [
(2, 5),
(19, 22),
(20, 21),
(17, 8),
(16, 9),
(15, 10),
]
for pair in symmetry_pairs:
optimizer.add_link(cb.SymmetryLink(positions[pair[0]], positions[pair[1]], f.vector(0, 1, 0), f.vector(0, 0, 0)))
optimizer.optimize()
stack = cb.TransformedStack(
sketch,
[cb.Translation([0, 0, 4]), cb.Rotation(sketch.normal, 10 * np.pi / 180, [0, 0, 0])],
2,
[cb.Translation([0, 0, 2]), cb.Rotation(sketch.normal, 5 * np.pi / 180, [0, 0, 0])],
)
# TODO: this be mighty clumsy; unclumsify
bulk_size = 0.1
wall_size = 0.01
stack.shapes[0].chop(0, start_size=bulk_size)
stack.shapes[0].chop(1, start_size=wall_size, end_size=bulk_size / 2)
stack.shapes[0].operations[10].chop(1, start_size=bulk_size)
stack.chop(count=8)
# patches
for shape in stack.shapes:
for i in range(7):
shape.operations[i].set_patch("front", "gear")
for i in (9, 10, 11):
shape.operations[i].set_patch("front", "outer")
for operation in stack.shapes[0].operations:
operation.set_patch("bottom", "bottom")
for operation in stack.shapes[-1].operations:
operation.set_patch("top", "top")
mesh.add(stack)
for i, angle in enumerate(np.linspace(0, 2 * np.pi, num=gear.teeth, endpoint=False)[1:]):
print(f"Adding tooth {i + 2}")
mesh.add(stack.copy().rotate(angle, [0, 0, 1], [0, 0, 0]))
print("Writing mesh...")
mesh.write(os.path.join("..", "..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
time_end = time.time()
print(f"Elapsed time: {time_end - time_start}s")
================================================
FILE: examples/complex/gear/involute_gear.py
================================================
"""A copy of py_gear_gen (https://github.com/heartworm/py_gear_gen),
slightly modified to fit in classy_blocks for the gear pump example"""
import numpy as np
from classy_blocks.util import functions as f
class DimensionError(Exception):
pass
def rotation_matrix(theta):
return np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
def flip_matrix(h, v):
return [[-1 if h else 1, 0], [0, -1 if v else 1]]
def polar_to_cart(*coords):
if len(coords) == 1:
coords = coords[0]
r, ang = coords
return r * np.cos(ang), r * np.sin(ang)
def cart_to_polar(*coords):
if len(coords) == 1:
coords = coords[0]
x, y = coords
return np.sqrt(x * x + y * y), np.arctan2(y, x)
class InvoluteGear:
def __init__(
self,
module=1,
teeth=30,
pressure_angle_deg=20.0,
fillet=0.0,
backlash=0.0,
max_steps=100,
arc_step_size=0.1,
reduction_tolerance_deg=0.0,
dedendum_factor=1.157,
addendum_factor=1.0,
ring=False,
):
"""
Construct an involute gear, ready for generation using one of the generation methods.
:param module: The 'module' of the gear. (Diameter / Teeth)
:param teeth: How many teeth in the desired gear.
:param pressure_angle_deg: The pressure angle of the gear in DEGREES.
:param fillet: The radius of the fillet connecting a tooth to the root circle. NOT WORKING in ring gear.
:param backlash: The circumfrential play between teeth,
if meshed with another gear of the same backlash held stationary
:param max_steps: Maximum steps allowed to generate the involute profile. Higher is more accurate.
:param arc_step_size: The step size used for generating arcs.
:param ring: True if this is a ring (internal) gear, otherwise False.
"""
pressure_angle = f.deg2rad(pressure_angle_deg)
self.reduction_tolerance = f.deg2rad(reduction_tolerance_deg)
self.module = module
self.teeth = teeth
self.pressure_angle = pressure_angle
# Addendum is the height above the pitch circle that the tooth extends to
self.addendum = addendum_factor * module
# Dedendum is the depth below the pitch circle the root extends to. 1.157 is a std value allowing for clearance.
self.dedendum = dedendum_factor * module
# If the gear is a ring gear, then the clearance needs to be on the other side
if ring:
temp = self.addendum
self.addendum = self.dedendum
self.dedendum = temp
# The radius of the pitch circle
self.pitch_radius = (module * teeth) / 2
# The radius of the base circle, used to generate the involute curve
self.base_radius = np.cos(pressure_angle) * self.pitch_radius
# The radius of the gear's extremities
self.outer_radius = self.pitch_radius + self.addendum
# The radius of the gaps between the teeth
self.root_radius = self.pitch_radius - self.dedendum
# The radius of the fillet circle connecting the tooth to the root circle
self.fillet_radius = fillet if not ring else 0
# The angular width of a tooth and a gap. 360 degrees divided by the number of teeth
self.theta_tooth_and_gap = np.pi * 2 / teeth
# Converting the circumfrential backlash into an angle
angular_backlash = backlash / 2 / self.pitch_radius
# The angular width of the tooth at the pitch circle minus backlash, not taking the involute into account
self.theta_tooth = self.theta_tooth_and_gap / 2 + (-angular_backlash if not ring else angular_backlash)
# Where the involute profile intersects the pitch circle, found on iteration.
self.theta_pitch_intersect = None
# The angular width of the full tooth, at the root circle
self.theta_full_tooth = 0
self.max_steps = max_steps
self.arc_step_size = arc_step_size
"""
Reduces a line of many points to less points depending on the allowed angle tolerance
"""
def reduce_polyline(self, polyline):
vertices = [[], []]
last_vertex = [polyline[0][0], polyline[1][0]]
# Look through all vertices except start and end vertex
# Calculate by how much the lines before and after the vertex
# deviate from a straight path.
# If the deviation angle exceeds the specification, store it
for vertex_idx in range(1, len(polyline[0]) - 1):
next_slope = np.arctan2(
polyline[1][vertex_idx + 1] - polyline[1][vertex_idx + 0],
polyline[0][vertex_idx + 1] - polyline[0][vertex_idx + 0],
)
prev_slope = np.arctan2(
polyline[1][vertex_idx - 0] - last_vertex[1], polyline[0][vertex_idx - 0] - last_vertex[0]
)
deviation_angle = abs(prev_slope - next_slope)
if deviation_angle > self.reduction_tolerance:
vertices[0] += [polyline[0][vertex_idx]]
vertices[1] += [polyline[1][vertex_idx]]
last_vertex = [polyline[0][vertex_idx], polyline[1][vertex_idx]]
# Return vertices along with first and last point of the original polyline
return np.array(
[
np.concatenate([[polyline[0][0]], vertices[0], [polyline[0][-1]]]),
np.concatenate([[polyline[1][0]], vertices[1], [polyline[1][-1]]]),
]
)
def generate_half_tooth(self):
"""
Generate half an involute profile, ready to be mirrored in order to create one symmetrical involute tooth
:return: A numpy array, of the format [[x1, x2, ... , xn], [y1, y2, ... , yn]]
"""
# Theta is the angle around the circle, however PHI is simply a parameter for iteratively building the involute
phis = np.linspace(0, np.pi, self.max_steps)
points = []
reached_limit = False
self.theta_pitch_intersect = None
for phi in phis:
x = (self.base_radius * np.cos(phi)) + (phi * self.base_radius * np.sin(phi))
y = (self.base_radius * np.sin(phi)) - (phi * self.base_radius * np.cos(phi))
point = (x, y)
dist, theta = cart_to_polar(point)
if self.theta_pitch_intersect is None and dist >= self.pitch_radius:
self.theta_pitch_intersect = theta
self.theta_full_tooth = self.theta_pitch_intersect * 2 + self.theta_tooth
elif self.theta_pitch_intersect is not None and theta >= self.theta_full_tooth / 2:
reached_limit = True
break
if dist >= self.outer_radius:
points.append(polar_to_cart((self.outer_radius, theta)))
elif dist <= self.root_radius:
points.append(polar_to_cart((self.root_radius, theta)))
else:
points.append((x, y))
if not reached_limit:
raise Exception("Couldn't complete tooth profile.")
return np.transpose(points)
def generate_half_root(self):
"""
Generate half of the gap between teeth, for the first tooth
:return: A numpy array, of the format [[x1, x2, ... , xn], [y1, y2, ... , yn]]
"""
root_arc_length = (self.theta_tooth_and_gap - self.theta_full_tooth) * self.root_radius
points_root = []
for theta in np.arange(
self.theta_full_tooth,
self.theta_tooth_and_gap / 2 + self.theta_full_tooth / 2,
self.arc_step_size / self.root_radius,
):
# The current circumfrential position we are in the root arc, starting from 0
arc_position = (theta - self.theta_full_tooth) * self.root_radius
# If we are in the extemities of the root arc (defined by fillet_radius), then we are in a fillet
in_fillet = min((root_arc_length - arc_position), arc_position) < self.fillet_radius
r = self.root_radius
if in_fillet:
# Add a circular profile onto the normal root radius to form the fillet.
# High near the edges, small towards the centre
# The min() function handles the situation where the fillet size is massive and overlaps itself
circle_pos = min(arc_position, (root_arc_length - arc_position))
r = r + (
self.fillet_radius - np.sqrt(pow(self.fillet_radius, 2) - pow(self.fillet_radius - circle_pos, 2))
)
points_root.append(polar_to_cart((r, theta)))
return np.transpose(points_root)
def generate_roots(self):
"""
Generate both roots on either side of the first tooth
:return: A numpy array, of the format
[ [[x01, x02, ... , x0n], [y01, y02, ... , y0n]], [[x11, x12, ... , x1n], [y11, y12, ... , y1n]] ]
"""
self.half_root = self.generate_half_root()
self.half_root = np.dot(rotation_matrix(-self.theta_full_tooth / 2), self.half_root)
points_second_half = np.dot(flip_matrix(False, True), self.half_root)
points_second_half = np.flip(points_second_half, 1)
self.roots = [points_second_half, self.half_root]
# Generate a second set of point-reduced root
self.half_root_reduced = self.reduce_polyline(self.half_root)
points_second_half = np.dot(flip_matrix(False, True), self.half_root_reduced)
points_second_half = np.flip(points_second_half, 1)
self.roots_reduced = [points_second_half, self.half_root_reduced]
return self.roots_reduced
def generate_tooth(self):
"""
Generate only one involute tooth, without an accompanying tooth gap
:return: A numpy array, of the format [[x1, x2, ... , xn], [y1, y2, ... , yn]]
"""
self.half_tooth = self.generate_half_tooth()
self.half_tooth = np.dot(rotation_matrix(-self.theta_full_tooth / 2), self.half_tooth)
points_second_half = np.dot(flip_matrix(False, True), self.half_tooth)
points_second_half = np.flip(points_second_half, 1)
self.tooth = np.concatenate((self.half_tooth, points_second_half), axis=1)
# Generate a second set of point-reduced teeth
self.half_tooth_reduced = self.reduce_polyline(self.half_tooth)
points_second_half = np.dot(flip_matrix(False, True), self.half_tooth_reduced)
points_second_half = np.flip(points_second_half, 1)
self.tooth_reduced = np.concatenate((self.half_tooth_reduced, points_second_half), axis=1)
return self.tooth_reduced
def generate_tooth_and_gap(self):
"""
Generate only one tooth and one root profile, ready to be duplicated by rotating around the gear center
:return: A numpy array, of the format [[x1, x2, ... , xn], [y1, y2, ... , yn]]
"""
points_tooth = self.generate_tooth()
points_roots = self.generate_roots()
self.tooth_and_gap = np.concatenate((points_roots[0], points_tooth, points_roots[1]), axis=1)
return self.tooth_and_gap
def generate_gear(self):
"""
Generate the gear profile, and return a sequence of co-ordinates representing the outline of the gear
:return: A numpy array, of the format [[x1, x2, ... , xn], [y1, y2, ... , yn]]
"""
points_tooth_and_gap = self.generate_tooth_and_gap()
points_teeth = [
np.dot(rotation_matrix(self.theta_tooth_and_gap * n), points_tooth_and_gap) for n in range(self.teeth)
]
points_gear = np.concatenate(points_teeth, axis=1)
return points_gear
def get_point_list(self):
"""
Generate the gear profile, and return a sequence of co-ordinates representing the outline of the gear
:return: A numpy array, of the format [[x1, y2], [x2, y2], ... , [xn, yn]]
"""
gear = self.generate_gear()
return np.transpose(gear)
================================================
FILE: examples/complex/gear/tooth.py
================================================
from typing import ClassVar
import classy_blocks as cb
class ToothSketch(cb.MappedSketch):
quads: ClassVar = [
# layers on tooth wall
[0, 1, 18, 17], # 0
[1, 2, 19, 18], # 1
[2, 3, 20, 19], # 2
[3, 4, 21, 20], # 3
[4, 5, 22, 21], # 4
[5, 6, 23, 22], # 5
[6, 7, 8, 23], # 6
# surrounding blocks
[8, 9, 22, 23], # 7
[9, 10, 21, 22], # 8
[11, 12, 21, 10], # 9
[12, 13, 20, 21], # 10
[13, 14, 15, 20], # 11
[15, 16, 19, 20], # 12
[16, 17, 18, 19], # 13
]
# In x-direction, only one half needs to be chopped, the other half will be
# copied from teeth on the other side.
# In y-direction, block 10 should also be in the list
# except that it doesn't need boundary layers that will be created for blocks on the tooth.
# It will be chopped manually.
chops: ClassVar = [
[1, 2, 9, 10, 11],
[0],
]
def __init__(self, positions, curve: cb.LinearInterpolatedCurve):
self.curve = curve
super().__init__(positions, self.quads)
def add_edges(self) -> None:
for i in range(7):
# If all edges refer to the same curve, it will be
# transformed N-times, N being the number of entities
# where that curve is used. Therefore copy it
# so that each edge will have its own object to work with.
self.faces[i].add_edge(0, cb.OnCurve(self.curve.copy()))
for i in (9, 10, 11):
self.faces[i].add_edge(0, cb.Origin([0, 0, 0]))
================================================
FILE: examples/complex/heater/heater.py
================================================
import os
from typing import List
import numpy as np
import parameters as p
import classy_blocks as cb
from classy_blocks.construct.flat.sketch import Sketch
mesh = cb.Mesh()
# some shortcuts
xlv = p.xlv
ylv = p.ylv
zlv = p.zlv
def set_cell_zones(shape: cb.Shape):
solid_indexes = list(range(5))
fluid_indexes = list(range(5, 9))
for i in solid_indexes:
shape.operations[i].set_cell_zone("solid")
for i in fluid_indexes:
shape.operations[i].set_cell_zone("fluid")
# Cross-section of heater and fluid around it
cb.WrappedDisk.chops[0] = [1] # the solid part, chop the fluid zone manually
heater_xs = cb.WrappedDisk(p.heater_start_point, p.wrapping_corner_point, p.heater_diameter / 2, [1, 0, 0])
# The straight part of the heater, part 1: bottom
straight_1 = cb.ExtrudedShape(heater_xs, p.heater_length)
straight_1.chop(0, start_size=p.solid_cell_size)
straight_1.chop(1, start_size=p.solid_cell_size)
straight_1.chop(2, start_size=p.solid_cell_size)
straight_1.operations[5].chop(0, start_size=p.first_cell_size, c2c_expansion=p.c2c_expansion)
set_cell_zones(straight_1)
mesh.add(straight_1)
# The curved part of heater (and fluid around it); constructed from 4 revolves
heater_arch = cb.RevolvedStack(straight_1.sketch_2, np.pi, [0, 0, 1], [0, 0, 0], 4)
heater_arch.chop(start_size=p.solid_cell_size, take="min")
for shape in heater_arch.shapes:
set_cell_zones(shape)
mesh.add(heater_arch)
# The straight part of heater, part 2: after the arch
straight_2 = cb.ExtrudedShape(heater_arch.shapes[-1].sketch_2, p.heater_length)
set_cell_zones(straight_2)
mesh.add(straight_2)
# The arch creates a semi-cylindrical void; fill it with a semi-cylinder, of course
arch_fill = cb.SemiCylinder([0, 0, zlv[0]], [0, 0, zlv[1]], [xlv[1], ylv[4], zlv[0]])
mesh.add(arch_fill)
arch_fill.chop_radial(start_size=p.solid_cell_size)
# A custom sketch that takes the closest faces from given operations;
# They will definitely be wrongly oriented but we'll sort that out later
class NearestSketch(Sketch):
def __init__(self, operations: List[cb.Operation], far_point):
far_point = np.array(far_point)
self._faces = [op.get_closest_face(far_point) for op in operations]
@property
def faces(self):
return self._faces
@property
def grid(self):
return [self.faces]
@property
def center(self):
return np.average([face.center for face in self.faces], axis=0)
cylinder_xs = NearestSketch([arch_fill.operations[i] for i in (0, 1, 2, 5)], [-2 * p.heater_length, 0, 0])
pipe_fill = cb.ExtrudedShape(cylinder_xs, [-p.heater_length, 0, 0])
# reorient the operations in the shape
reorienter = cb.ViewpointReorienter([-2 * p.heater_length, 0, 0], [0, p.heater_length, 0])
for operation in pipe_fill.operations:
reorienter.reorient(operation)
mesh.add(pipe_fill)
# Domain: offset outermost faces of outermost operations
offset_shapes = [straight_1, *heater_arch.shapes, straight_2]
offset_ops = [shape.grid[2][2] for shape in offset_shapes]
offset_faces = [op.get_face("right") for op in offset_ops]
domain_shell = cb.Shell(offset_faces, ylv[1] - ylv[0])
domain_shell.operations[1].chop(2, start_size=2 * p.fluid_cell_size, end_size=10 * p.fluid_cell_size)
mesh.add(domain_shell)
# The offset faces create a domain that is not rectangular.
# Assemble the mesh and move vertices, then backport the changes so that
# they will be reflected in the offset shapes.
mesh.assemble()
# Vertex indexes are taken from debug.vtk file written right here.
# This is the quickest and simplest method and works as long as blocking
# doesn't change. If there was a parameter that controlled number of blocks
# (for instance, number of levels in the arch stack), then
# we'd have to obtain vertices programatically using GeometricFinder or similar.
for index in (106, 107):
mesh.vertices[index].position[0] = xlv[7]
mesh.vertices[index].position[1] = ylv[0]
for index in (110, 111):
mesh.vertices[index].position[0] = xlv[7]
mesh.vertices[index].position[1] = -ylv[0]
mesh.backport()
mesh.clear()
# Add blocks to fluid zone (those that haven't been added yet)
for operation in [*arch_fill.operations, *pipe_fill.operations, *domain_shell.operations]:
operation.set_cell_zone("fluid")
mesh.write(os.path.join("..", "..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/complex/heater/parameters.py
================================================
from classy_blocks.util import functions as f
# geometry
heater_diameter = 10
heater_length = 50
bend_radius = 3 * heater_diameter
domain_size = 50
# cell sizing
solid_cell_size = 1
fluid_cell_size = 0.5
first_cell_size = 0.05
c2c_expansion = 1.2
# mesh parameters (do not edit)
wrapping_height = (bend_radius + heater_diameter / 2) / 2
# coordinates, decomposed into grid, a.k.a. 'levels';
# see heater.svg for explanation
xlv = [
-heater_length,
0,
bend_radius - wrapping_height / 2,
bend_radius - heater_diameter / 2,
bend_radius,
bend_radius + heater_diameter / 2,
bend_radius + wrapping_height / 2,
domain_size,
]
ylv = [
-domain_size,
-bend_radius - wrapping_height / 2,
-bend_radius - heater_diameter / 2,
-bend_radius,
-bend_radius + wrapping_height / 2,
]
zlv = [-wrapping_height / 2, wrapping_height / 2]
heater_start_point = f.vector(xlv[0], ylv[3], 0)
wrapping_corner_point = heater_start_point + f.vector(0, wrapping_height / 2, -wrapping_height / 2)
================================================
FILE: examples/complex/karman.py
================================================
import os
import classy_blocks as cb
cylinder_diameter = 20e-3 # [m]
ring_thickness = 5e-3 # [m]
# domain size
domain_height = 0.05 # [m] (increase for "proper" simulation)
upstream_length = 0.03 # [m]
downstream_length = 0.05 # [m]
# size to roughly match cells outside ring
cell_size = 0.3 * ring_thickness
bl_thickness = 1e-4
c2c_expansion = 1.2 # cell-to-cell expansion ratio
# it's a 2-dimensional case
z = 0.01
mesh = cb.Mesh()
# a layer of cells on the cylinder
d = 2**0.5 / 2
outer_point = d * (cylinder_diameter / 2 + ring_thickness)
wall_ring = cb.ExtrudedRing(
[0, 0, 0],
[0, 0, z],
[outer_point, outer_point, 0],
cylinder_diameter / 2,
n_segments=4, # the default is 8 but here it makes no sense to have more than 4
)
wall_ring.chop_axial(count=1)
wall_ring.chop_tangential(start_size=cell_size)
wall_ring.chop_radial(start_size=bl_thickness, c2c_expansion=c2c_expansion)
wall_ring.set_inner_patch("cylinder")
mesh.add(wall_ring)
# boxes that fill up the whole domain
def make_box(p1, p2, size_axes, patches):
box = cb.Box([p1[0], p1[1], 0], [p2[0], p2[1], z])
for axis in size_axes:
box.chop(axis, start_size=cell_size)
for side, name in patches.items():
box.set_patch(side, name)
mesh.add(box)
# top 3 boxes
make_box(
[-upstream_length, outer_point], [-outer_point, domain_height / 2], [0, 1], {"back": "upper_wall", "left": "inlet"}
)
make_box([-outer_point, outer_point], [outer_point, domain_height / 2], [], {"back": "upper_wall"})
make_box(
[outer_point, outer_point],
[downstream_length, domain_height / 2],
[0, 1],
{"back": "upper_wall", "right": "outlet"},
)
# left and right of the cylinder
make_box([-upstream_length, -outer_point], [-outer_point, outer_point], [], {"left": "inlet"})
make_box([outer_point, -outer_point], [downstream_length, outer_point], [], {"right": "outlet"})
# bottom 3 boxes
make_box(
[-upstream_length, -domain_height / 2],
[-outer_point, -outer_point],
[0, 1],
{"front": "lower_wall", "left": "inlet"},
)
make_box([-outer_point, -domain_height / 2], [outer_point, -outer_point], [], {"front": "lower_wall"})
make_box(
[outer_point, -domain_height / 2],
[downstream_length, -outer_point],
[0, 1],
{"front": "lower_wall", "right": "outlet"},
)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/complex/plate/parameters.py
================================================
# plate properties
pl_thickness = 0.3
pl_length = 5
# domain
dm_upstream = 5
dm_height = 5
z = 1
# cell sizing
cell_size = 0.2
first_cell_thickness = 0.01
c2c_expansion = 1.1
bl_thickness = 1.5 # cumulative thickness of inflation layers
max_ar = 10
================================================
FILE: examples/complex/plate/plate.py
================================================
#!/usr/bin/env python
import os
import parameters as ps
import classy_blocks as cb
from classy_blocks.util import functions as f
# Example: flow over a flat plate of
points = [
[-ps.pl_thickness, 0, 0], # 0
[0, 0, 0], # 1 (set later)
[0, ps.pl_thickness, 0], # 2
[ps.pl_length, ps.pl_thickness, 0], # 3
[ps.pl_length, 0, 0], # 4
[-ps.bl_thickness - ps.pl_thickness, 0, 0], # 5
[0, 0, 0], # 6 (set later)
[0, ps.pl_thickness + ps.bl_thickness, 0], # 7
[ps.pl_length, ps.pl_thickness + ps.bl_thickness, 0], # 8
[-ps.dm_upstream, 0, 0], # 9
[0, 0, 0], # 10 (later)
[-ps.dm_upstream, ps.dm_height, 0], # 11
[0, 0, 0], # 12 (l8r)
[0, ps.dm_height, 0], # 13
[ps.pl_length, ps.dm_height, 0], # 14
]
points[1] = f.rotate(points[0], -f.deg2rad(45), [0, 0, 1], [0, 0, 0])
points[6] = f.rotate(points[5], -f.deg2rad(45), [0, 0, 1], [0, 0, 0])
points[10] = [points[9][0], points[6][1], 0]
points[12] = [points[6][0], points[11][1], 0]
mesh = cb.Mesh()
def make_extrude(indexes):
face = cb.Face([points[i] for i in indexes])
op = cb.Extrude(face, ps.z)
op.chop(2, count=1)
mesh.add(op)
return op
extrudes = [
make_extrude([0, 1, 6, 5]),
make_extrude([1, 2, 7, 6]),
make_extrude([2, 3, 8, 7]),
make_extrude([9, 5, 6, 10]),
make_extrude([10, 6, 12, 11]),
make_extrude([6, 7, 13, 12]),
make_extrude([7, 8, 14, 13]),
]
for index in (0, 1):
for corner in (0, 2):
extrudes[index].bottom_face.add_edge(corner, cb.Origin([0, 0, 0]))
extrudes[index].top_face.add_edge(corner, cb.Origin([0, 0, ps.z]))
for index in (0, 1):
extrudes[index].chop(0, start_size=ps.cell_size)
extrudes[2].chop(1, start_size=ps.first_cell_thickness, c2c_expansion=ps.c2c_expansion)
extrudes[2].chop(0, start_size=ps.cell_size, end_size=ps.cell_size * ps.max_ar)
extrudes[3].chop(0, start_size=ps.cell_size)
extrudes[5].chop(1, start_size=ps.cell_size)
mesh.write(os.path.join("..", "..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/modification/move_vertex.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
cylinder = cb.Cylinder([0, 0, 0], [1, 0, 0], [0, 1, 0])
cylinder.chop_axial(count=10)
cylinder.chop_radial(count=5)
cylinder.chop_tangential(count=8)
mesh.add(cylinder)
mesh.assemble()
finder = cb.GeometricFinder(mesh)
vertex = next(iter(finder.find_in_sphere([1, 0, 0])))
vertex.translate([0.4, 0, 0])
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/operation/box.py
================================================
import os
import classy_blocks as cb
box = cb.Box([-1, -2, -4], [4, 2, 1])
# direction of corners 0-1
box.chop(0, length_ratio=0.5, start_size=0.02, c2c_expansion=1.2)
box.chop(0, length_ratio=0.5, end_size=0.02, c2c_expansion=1 / 1.2)
# direction of corners 1-2
box.chop(1, length_ratio=0.5, start_size=0.02, c2c_expansion=1.2)
box.chop(1, length_ratio=0.5, end_size=0.02, c2c_expansion=1 / 1.2)
# extrude direction
box.chop(2, c2c_expansion=1, count=20)
mesh = cb.Mesh()
mesh.add(box)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/operation/channel.py
================================================
#!/usr/bin/env python
import os
import numpy as np
import classy_blocks as cb
# A channel with a 90-degred bend, square cross-section, low-Re
# Channel sizing
SCALE = 0.01
WIDTH = 8
HEIGHT = 6
LENGTH_1 = 30
INNER_RADIUS = 5
LENGTH_2 = 15
# Cell sizing
CELL_SIZE = 1
BL_THICKNESS = 0.1
C2C_EXPANSION = 1.2
### Construction
mesh = cb.Mesh()
left_block = cb.Box([0, 0, 0], [LENGTH_1, HEIGHT, WIDTH])
left_block.chop(0, start_size=CELL_SIZE)
left_block.chop(1, length_ratio=0.5, start_size=BL_THICKNESS, c2c_expansion=C2C_EXPANSION)
left_block.chop(1, length_ratio=0.5, end_size=BL_THICKNESS, c2c_expansion=1 / C2C_EXPANSION)
left_block.chop(2, length_ratio=0.5, start_size=BL_THICKNESS, c2c_expansion=C2C_EXPANSION)
left_block.chop(2, length_ratio=0.5, end_size=BL_THICKNESS, c2c_expansion=1 / C2C_EXPANSION)
left_block.set_patch("left", "inlet")
mesh.add(left_block)
revolve_face = left_block.get_face("right")
elbow = cb.Revolve(revolve_face, np.pi / 2, [0, -1, 0], [LENGTH_1, 0, HEIGHT + INNER_RADIUS])
elbow.chop(2, start_size=CELL_SIZE)
mesh.add(elbow)
top_face = elbow.get_face("top")
right_block = cb.Extrude(top_face, LENGTH_2)
right_block.chop(2, start_size=CELL_SIZE)
right_block.set_patch("top", "outlet")
mesh.add(right_block)
mesh.set_default_patch("walls", "wall")
mesh.settings.scale = SCALE
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/operation/connector.py
================================================
import os
import numpy as np
import classy_blocks as cb
box_1 = cb.Box([-1, -1, -1], [1, 1, 1])
box_2 = box_1.copy().rotate(np.pi / 4, [1, 1, 1], [0, 0, 0]).translate([4, 2, 0])
for i in range(3):
box_1.chop(i, count=10)
box_2.chop(i, count=10)
connector = cb.Connector(box_1, box_2)
connector.chop(2, count=10)
mesh = cb.Mesh()
mesh.add(box_1)
mesh.add(box_2)
mesh.add(connector)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/operation/extrude.py
================================================
import os
import classy_blocks as cb
base = cb.Face([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [cb.Arc([0.5, -0.2, 0]), None, None, None])
extrude = cb.Extrude(base, [0.5, 0.5, 3])
# direction of corners 0-1
extrude.chop(0, length_ratio=0.5, start_size=0.02, c2c_expansion=1.2)
extrude.chop(0, length_ratio=0.5, end_size=0.02, c2c_expansion=1 / 1.2)
# direction of corners 1-2
extrude.chop(1, length_ratio=0.5, start_size=0.02, c2c_expansion=1.2)
extrude.chop(1, length_ratio=0.5, end_size=0.02, c2c_expansion=1 / 1.2)
# extrude direction
extrude.chop(2, c2c_expansion=1, count=20)
extrude.set_patch("bottom", "wall")
extrude.set_patch("top", "wall")
mesh = cb.Mesh()
mesh.add(extrude)
mesh.set_default_patch("air", "patch")
mesh.modify_patch("wall", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/operation/loft.py
================================================
import os
import classy_blocks as cb
# Example geometry using Loft:
bottom_face = cb.Face(
# 4 points for face corners
[[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]],
# edges: arc between 0-1, line between 1-2, arc between 2-3, line between 3-0
[cb.Arc([0.5, -0.2, 0]), None, cb.Arc([0.5, 1.2, 0]), None],
)
top_face = cb.Face(
[[0, 0, 2], [1, 0, 2], [1, 1, 2], [0, 1, 2]], [None, cb.Arc([1.2, 0.5, 2]), None, cb.Arc([-0.2, 0.5, 2])]
)
loft = cb.Loft(bottom_face, top_face)
loft.add_side_edge(0, cb.PolyLine([[0.1, 0.1, 0.5], [0.15, 0.15, 1.0], [0.1, 0.1, 1.5]])) # corners 0 - 4
loft.add_side_edge(1, cb.Arc([0.9, 0.1, 1])) # 1 - 5
loft.add_side_edge(2, cb.Arc([0.9, 0.9, 1])) # 2 - 6
loft.add_side_edge(3, cb.Arc([0.1, 0.9, 1])) # 3 - 7
loft.chop(0, start_size=0.05, c2c_expansion=1.2)
loft.chop(1, count=20)
loft.chop(2, count=30)
mesh = cb.Mesh()
mesh.add(loft)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/operation/revolve.py
================================================
import os
import classy_blocks as cb
from classy_blocks.util import functions as f
base = cb.Face([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [cb.Arc([0.5, -0.2, 0]), None, None, None])
revolve = cb.Revolve(base, f.deg2rad(60), [0, -1, 0], [-2, 0, 0])
# a shortcut for setting count only
revolve.chop(0, count=10)
revolve.chop(1, count=10)
revolve.chop(2, count=30)
mesh = cb.Mesh()
mesh.add(revolve)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/operation/wedge.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
# a face with a single bump;
base = cb.Face(
# points
[[0, 0, 0], [1, 0, 0], [1, 0.2, 0], [0, 0.2, 0]],
# edges
[None, None, cb.Spline([[0.75, 0.15, 0], [0.50, 0.20, 0], [0.25, 0.25, 0]]), None],
)
# create a wedge, then copy it along x-axis,
# representing an annular seal with grooves
wedge = cb.Wedge(base)
wedge.set_outer_patch("static_wall")
wedge.set_inner_patch("rotating_walls")
wedge.chop(0, count=30)
wedges = [wedge.copy().translate([x, 0, 0]) for x in range(1, 6)]
wedges[0].set_patch("left", "inlet")
wedges[-1].set_patch("right", "outlet")
# this will be copied to all next blocks
wedges[0].chop(1, end_size=0.01, c2c_expansion=1 / 1.2)
# Once an entity is added to the mesh,
# its modifications will not be reflected there;
# adding is the last thing to do
for op in wedges:
mesh.add(op)
# change patch types and whatnot
mesh.modify_patch("static_wall", "wall")
mesh.modify_patch("rotating_walls", "wall")
mesh.modify_patch("wedge_front", "wedge")
mesh.modify_patch("wedge_back", "wedge")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"))
================================================
FILE: examples/optimization/diffuser_free.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
size = 0.1
# Create a rapidly expanding diffuser that will cause high non-orthogonality
# at the beginning of the contraction; then, move inner vertices so that
# this problem is avoided
small_pipe = cb.Cylinder([0, 0, 0], [2, 0, 0], [0, 1, 0])
small_pipe.chop_axial(start_size=size)
small_pipe.chop_radial(start_size=size)
small_pipe.chop_tangential(start_size=size)
mesh.add(small_pipe)
diffuser = cb.Frustum.chain(small_pipe, 0.5, 2)
diffuser.chop_axial(start_size=size)
mesh.add(diffuser)
big_pipe = cb.Cylinder.chain(diffuser, 5)
big_pipe.chop_axial(start_size=size)
mesh.add(big_pipe)
mesh.set_default_patch("walls", "wall")
# Internal edges in Cylinders are Splines by default;
# In this case their endpoints will be moved ('optimized') but not
# the points in between; this will create bad cells. Either re-define these edges after optimization
# or remove them altogether.
diffuser.remove_inner_edges()
small_pipe.remove_inner_edges()
big_pipe.remove_inner_edges()
# Assemble the mesh before making changes
mesh.assemble()
# Find inside vertices (start and stop surfaces of cylinders and frustum);
finder = cb.RoundSolidFinder(mesh, diffuser)
inner_vertices = finder.find_core(True)
inner_vertices.update(finder.find_core(False))
# Release those vertices so that optimization can find a better position for them
optimizer = cb.MeshOptimizer(mesh)
for vertex in inner_vertices:
clamp = cb.FreeClamp(vertex.position)
optimizer.add_clamp(clamp)
optimizer.optimize()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/optimization/diffuser_line.py
================================================
import os
import classy_blocks as cb
from classy_blocks.util import functions as f
mesh = cb.Mesh()
size = 0.1
# The setup is the same as the diffuser_free example
# except that here vertices are only allowed to move
# axially in a straight line.
# See diffuser_free for comments.
small_pipe = cb.Cylinder([0, 0, 0], [2, 0, 0], [0, 1, 0])
small_pipe.chop_axial(start_size=size)
small_pipe.chop_radial(start_size=size)
small_pipe.chop_tangential(start_size=size)
mesh.add(small_pipe)
diffuser = cb.Frustum.chain(small_pipe, 0.5, 2)
diffuser.chop_axial(start_size=size)
mesh.add(diffuser)
big_pipe = cb.Cylinder.chain(diffuser, 5)
big_pipe.chop_axial(start_size=size)
mesh.add(big_pipe)
mesh.set_default_patch("walls", "wall")
diffuser.remove_inner_edges()
small_pipe.remove_inner_edges()
big_pipe.remove_inner_edges()
mesh.assemble()
finder = cb.RoundSolidFinder(mesh, diffuser)
inner_vertices = finder.find_core(True)
inner_vertices.update(finder.find_core(False))
optimizer = cb.MeshOptimizer(mesh)
for vertex in inner_vertices:
clamp = cb.LineClamp(vertex.position, vertex.position, vertex.position + f.vector(1, 0, 0))
optimizer.add_clamp(clamp)
optimizer.optimize()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/optimization/duct.py
================================================
# An example where a Shape is optimized *before* it is added to mesh, using ShapeOptimizer
import os
import classy_blocks as cb
from classy_blocks.base.exceptions import ClampExistsError
mesh = cb.Mesh()
start_sketch = cb.SplineDisk([0, 0, 0], [2, 0, 0], [0, 1, 0], 0, 0)
end_sketch = cb.SplineDisk([0, 0, 0], [1, 0, 0], [0, 2, 0], 0, 0).translate([0, 0, 1])
shape = cb.LoftedShape(start_sketch, end_sketch)
optimizer = cb.ShapeOptimizer(shape.operations)
for operation in shape.operations[:4]:
# remove edges because inner splines will ruin the day
# TODO: make edges move with points too
operation.top_face.remove_edges()
operation.bottom_face.remove_edges()
for point in operation.point_array:
try:
optimizer.add_clamp(cb.FreeClamp(point))
except ClampExistsError:
pass
optimizer.optimize(tolerance=0.01)
mesh.add(shape)
grader = cb.SimpleGrader(mesh, 0.05)
grader.grade()
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/optimization/simple.py
================================================
import os
import classy_blocks as cb
from classy_blocks.optimize.clamps.free import FreeClamp
from classy_blocks.optimize.optimizer import MeshOptimizer
mesh = cb.Mesh()
# generate a cube, consisting of 2x2x2 smaller cubes
for x in (-1, 0):
for y in (-1, 0):
for z in (-1, 0):
box = cb.Box([x, y, z], [x + 1, y + 1, z + 1])
for axis in range(3):
box.chop(axis, count=10)
mesh.add(box)
mesh.set_default_patch("walls", "wall")
mesh.assemble()
# move the middle vertex to a sub-optimal position
finder = cb.GeometricFinder(mesh)
mid_vertex = next(iter(finder.find_in_sphere([0, 0, 0])))
mid_vertex.translate([0.6, 0.6, 0.6])
# find a better spot for the above point using automatic optimization
optimizer = MeshOptimizer(mesh)
# define which vertices can move during optimization, and in which DoF
mid_clamp = FreeClamp(mid_vertex.position)
optimizer.add_clamp(mid_clamp)
optimizer.optimize()
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/custom.py
================================================
import os
from typing import ClassVar
import numpy as np
import classy_blocks as cb
from classy_blocks.cbtyping import PointType
from classy_blocks.util import functions as f
# an example with a custom sketch, yielding a custom shape (square with rounded corners);
# see custom.svg for a sketch of blocking scheme
mesh = cb.Mesh()
class RoundSquare(cb.MappedSketch):
quads: ClassVar = [
[20, 0, 1, 12],
[12, 1, 2, 13],
[13, 2, 3, 21],
[21, 20, 12, 13],
[21, 3, 4, 14],
[14, 4, 5, 15],
[15, 5, 6, 22],
[22, 21, 14, 15],
[22, 6, 7, 16],
[16, 7, 8, 17],
[17, 8, 9, 23],
[23, 22, 16, 17],
[23, 9, 10, 18],
[18, 10, 11, 19],
[19, 11, 0, 20],
[20, 23, 18, 19],
[21, 22, 23, 20],
]
chops: ClassVar = [[0], [0, 1, 4, 5, 8, 12]]
def __init__(self, center: PointType, side: float, corner_round: float):
center = np.array(center)
points = [
center + f.vector(side / 2, 0, 0),
center + f.vector(side / 2, side / 2 - side * corner_round / 2, 0),
center + f.vector(side / 2 - side * corner_round / 2, side / 2, 0),
]
outer_points = []
angles = np.linspace(0, 2 * np.pi, num=4, endpoint=False)
for a in angles:
for i in range(3):
outer_points.append(f.rotate(points[i], a, [0, 0, 1], center))
inner_points = np.ones((12, 3)) * center
super().__init__(np.concatenate((outer_points, inner_points), axis=0), RoundSquare.quads)
def add_edges(self) -> None:
for i in (1, 5, 9, 13):
self.faces[i].add_edge(1, cb.Angle(np.pi / 2, [0, 0, 1]))
base = RoundSquare([0, 0, 0], 1, 0.5)
smoother = cb.SketchSmoother(base)
smoother.smooth()
shape = cb.ExtrudedShape(base, 1)
shape.chop(0, start_size=0.05)
shape.chop(1, start_size=0.05)
shape.chop(2, count=5)
mesh.add(shape)
mesh.assemble()
grader = cb.SimpleGrader(mesh, 0.03, take="max")
grader.grade()
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/cylinder.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
axis_point_1 = [0, 0, 0]
axis_point_2 = [0, 0, 1]
radius_point_1 = [1, 0, 0]
cylinder = cb.Cylinder(axis_point_1, axis_point_2, radius_point_1)
cylinder.set_start_patch("inlet")
cylinder.set_end_patch("outlet")
cylinder.set_outer_patch("walls")
# If curved core edges get in the way (when moving vertices, optimization, ...),
# remove them with this method:
cylinder.remove_inner_edges(start=False, end=True)
# Chop and grade
bl_thickness = 1e-3
core_size = 0.1
cylinder.chop_axial(count=30)
cylinder.chop_radial(start_size=core_size, end_size=bl_thickness)
cylinder.chop_tangential(start_size=core_size)
cylinder.set_start_patch("walls")
cylinder.set_end_patch("walls")
mesh.add(cylinder)
mesh.modify_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/elbow.py
================================================
import os
import numpy as np
import classy_blocks as cb
mesh = cb.Mesh()
radius_1 = 1
center_point_1 = [0.0, 0.0, 0.0]
radius_point_1 = [radius_1, 0.0, 0.0]
normal_1 = [0.0, 1.0, 0.0]
sweep_angle = -np.pi / 3
arc_center = [2.0, 0.0, 0.0]
rotation_axis = [0.0, 0.0, 1.0]
radius_2 = 0.4
boundary_size = 0.01
core_size = 0.08
elbow = cb.Elbow(center_point_1, radius_point_1, normal_1, sweep_angle, arc_center, rotation_axis, radius_2)
elbow.set_start_patch("inlet")
elbow.set_outer_patch("walls")
elbow.set_end_patch("outlet")
# counts and gradings
elbow.chop_tangential(start_size=core_size)
elbow.chop_radial(start_size=core_size, end_size=boundary_size)
elbow.chop_axial(start_size=2 * core_size)
mesh.add(elbow)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/extruded_ring.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
pipe_wall = cb.ExtrudedRing(
[0, 0, 0],
[2, 2, 0],
[-0.707, 0.707, 0],
0.8, # axis_point_1 # axis_point_2 # outer_radius # inner_radius
)
core_size = 0.1
bl_thickness = 0.005
pipe_wall.chop_axial(start_size=core_size)
pipe_wall.chop_tangential(start_size=core_size)
# chop radially twice to get boundary layer cells on both sides;
pipe_wall.chop_radial(length_ratio=0.5, start_size=bl_thickness, c2c_expansion=1.2)
pipe_wall.chop_radial(length_ratio=0.5, end_size=bl_thickness, c2c_expansion=1 / 1.2)
pipe_wall.set_start_patch("inlet")
pipe_wall.set_end_patch("outlet")
pipe_wall.set_inner_patch("inner_wall")
pipe_wall.set_outer_patch("outer_wall")
mesh.add(pipe_wall)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/frustum.py
================================================
import os
import numpy as np
import classy_blocks as cb
mesh = cb.Mesh()
axis_point_1 = [0.0, 0.0, 0.0]
axis_point_2 = [2.0, 0, 0.0]
radius_point_1 = [0.0, 0.0, 2.0]
radius_2 = 0.5
bl_thickness = 0.01
core_size = 0.1
# A note about radius_mid;
# it can be used to create shapes of revolution with curved sides;
# however, due to the way blockMesh face creation works, the result won't
# be totally 'round'.
# Also, in drastic cases, non-orthogonality at beginning/end face will be high
# because of sharp edges; in those cases it is better to use RevolvedRing combined with
# Cylinder/Frustum with non-flat start/end faces.
frustum = cb.Frustum(axis_point_1, axis_point_2, radius_point_1, radius_2, radius_mid=1.1)
cylinder = cb.Cylinder.chain(frustum, 6, start_face=True)
pos = cylinder.sketch_1.positions
pos[:9] += np.array([-0.3, 0, 0])
cylinder.sketch_1.update(pos)
cylinder.sketch_1.add_edges()
pos = frustum.sketch_1.positions
pos[:9] += np.array([-0.3, 0, 0])
frustum.sketch_1.update(pos)
frustum.sketch_1.add_edges()
cylinder.set_end_patch("inlet")
frustum.set_outer_patch("walls")
cylinder.set_outer_patch("walls")
frustum.set_end_patch("outlet")
cylinder.chop_axial(count=90)
frustum.chop_axial(count=30)
frustum.chop_radial(start_size=core_size, end_size=bl_thickness)
frustum.chop_tangential(start_size=core_size)
mesh.add(cylinder)
mesh.add(frustum)
mesh.modify_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/hemisphere.py
================================================
import os
import classy_blocks as cb
center = [0.0, 0.0, 0.0]
radius_point = [0.0, 0.0, 1.0]
normal = [0.0, 1.0, 0.0]
cell_size = 0.1
bl_thickness = 0.01
sphere = cb.Hemisphere(center, radius_point, normal)
sphere.chop_axial(start_size=cell_size)
sphere.chop_radial(start_size=cell_size, end_size=bl_thickness)
sphere.chop_tangential(start_size=cell_size)
sphere.set_start_patch("atmosphere") # the 'flat' part of the hemisphere
sphere.set_outer_patch("walls")
mesh = cb.Mesh()
mesh.add(sphere)
mesh.modify_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/one_core_cylinder.py
================================================
import os
import classy_blocks as cb
from classy_blocks.construct.flat.sketches.disk import OneCoreDisk
from classy_blocks.util import functions as f
# A simpler version of a Cylinder with only a single block in the middle;
# easier to block but slightly worse cell quality;
# currently there is no OneCoreCylinder shape so it has to be extruded;
# two lines are needed instead of one.
mesh = cb.Mesh()
axis_point_1 = f.vector(0.0, 0.0, 0.0)
axis_point_2 = f.vector(5.0, 5.0, 0.0)
radius_point_1 = f.vector(0.0, 0.0, 2.0)
one_core_disk = OneCoreDisk(axis_point_1, radius_point_1, axis_point_1 - axis_point_2)
cylinder = cb.ExtrudedShape(one_core_disk, f.norm(axis_point_2 - axis_point_1))
cylinder.chop(0, count=5)
cylinder.chop(1, count=10)
cylinder.chop(2, count=20)
mesh.add(cylinder)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/quarter_cylinder.py
================================================
import os
import classy_blocks as cb
from classy_blocks.construct.flat.sketches.disk import QuarterDisk
from classy_blocks.util import functions as f
mesh = cb.Mesh()
axis_point_1 = f.vector(0.0, 0.0, 0.0)
axis_point_2 = f.vector(5.0, 5.0, 0.0)
radius_point_1 = f.vector(0.0, 0.0, 2.0)
# make a disk with small core block - yields particularly bad cell sizes with normal chops
QuarterDisk.core_ratio = 0.4
quarter_disk = QuarterDisk(axis_point_1, radius_point_1, axis_point_1 - axis_point_2)
quarter_cylinder = cb.ExtrudedShape(quarter_disk, f.norm(axis_point_2 - axis_point_1))
mesh.add(quarter_cylinder)
# Use an automatic grader that will try to make cells in neighbouring blocks
# as similar in size as possible
grader = cb.SimpleGrader(mesh, 0.05)
grader.grade()
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/revolved_ring.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
# points that define ring cross-section;
# must be specified in the following order:
# p3---___
# / ---p2
# / \
# p0---------------p1
#
# 0---- -- ----- -- ----- -- ----- -- --->> axis
xs_points = [
[0.1, 0.2, 0],
[0.8, 0.1, 0],
[0.7, 0.5, 0],
[0.2, 0.5, 0],
]
xs_edges = [None, None, cb.Arc([0.3, 0.55, 0]), None] # these must be consistent with points
face = cb.Face(xs_points, xs_edges)
pipe_wall = cb.RevolvedRing([0, 0, 0], [1, 0, 0], face) # axis_point_1 # axis_point_2,
core_size = 0.05
pipe_wall.chop_axial(start_size=core_size)
pipe_wall.chop_tangential(start_size=core_size)
pipe_wall.chop_radial(count=10)
pipe_wall.set_start_patch("inlet")
pipe_wall.set_end_patch("outlet")
pipe_wall.set_inner_patch("inner_wall")
pipe_wall.set_outer_patch("outer_wall")
mesh.add(pipe_wall)
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/shell.py
================================================
import os
import classy_blocks as cb
mesh = cb.Mesh()
# Create a 7-block sphere by offsetting a box's faces.
box = cb.Box([-0.5, -0.5, -0.5], [0.5, 0.5, 0.5])
for i in range(3):
box.chop(i, count=10)
mesh.add(box)
# faces must point 'out' of the original block or
# newly created blocks will be inside-out;
offset_faces = [box.get_face(orient) for orient in ("bottom", "top", "left", "right", "front", "back")]
for i in (0, 2, 4):
offset_faces[i].invert()
shell = cb.Shell(offset_faces, 0.5)
shell.chop(count=10)
for operation in shell.operations:
operation.project_side("top", "sphere", edges=True, points=True)
mesh.add(shell)
mesh.add_geometry(
{
"sphere": [
"type searchableSphere",
"centre (0 0 0)",
"radius 1.5",
]
}
)
mesh.set_default_patch("walls", "wall")
mesh.write(os.path.join("..", "case", "system", "blockMeshDict"), debug_path="debug.vtk")
================================================
FILE: examples/shape/splined/combined_example.py
================================================
import os
import numpy as np
import classy_blocks as cb
center_point = np.asarray([0, 0, 0])
direction = np.asarray([1, 0, 0])
# Sketches can be completely circular. Here Arc are used to define the outer edges.
circular_sketch_1 = cb.SplineDisk(
center_point=center_point,
corner_1_point=np.asarray([0, 1, 0]),
corner_2_point=np.asarray([0, 0, 1]),
side_1=0,
side_2=0,
)
# Sketches can be elliptical. The outer edges are defined by splines.
# For high accuracy more spline points can be added using the key word n_outer_spline_points, in the initialization.
elliptical_sketch_1 = cb.SplineDisk(
center_point=center_point + direction * 1,
corner_1_point=np.asarray([0, 1, 0]) + direction * 1,
corner_2_point=np.asarray([0, 0, 1.2]) + direction * 1,
side_1=0,
side_2=0,
n_outer_spline_points=50,
)
elliptical_sketch_2 = cb.SplineDisk(
center_point=center_point + direction * 2,
corner_1_point=np.asarray([0, 1, 0])
gitextract_gjyxw34u/ ├── .editorconfig ├── .github/ │ ├── ISSUE_TEMPLATE.md │ └── workflows/ │ └── build_ci.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CITATION.cff ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs/ │ └── optimization/ │ └── quality-criteria.ods ├── examples/ │ ├── advanced/ │ │ ├── chop_preserve.py │ │ ├── collapsed.py │ │ ├── edge_grading.py │ │ ├── merged.py │ │ └── project.py │ ├── assembly/ │ │ ├── l_joint.py │ │ ├── n_joint.py │ │ └── t_joint.py │ ├── bug.py │ ├── case/ │ │ ├── Allrun.mesh │ │ ├── case.foam │ │ ├── constant/ │ │ │ └── geometry/ │ │ │ └── terrain.stl │ │ └── system/ │ │ ├── collapseDict │ │ ├── controlDict │ │ ├── fvSchemes │ │ └── fvSolution │ ├── chaining/ │ │ ├── flywheel.py │ │ ├── helmholtz_nozzle.py │ │ ├── labyrinth.py │ │ ├── orifice_plate.py │ │ ├── tank.py │ │ ├── test_tube.py │ │ └── venturi_tube.py │ ├── complex/ │ │ ├── airfoil/ │ │ │ └── airfoil.py │ │ ├── cyclone/ │ │ │ ├── README │ │ │ ├── __init__.py │ │ │ ├── cyclone.py │ │ │ ├── geometry.py │ │ │ ├── parameters.py │ │ │ └── regions/ │ │ │ ├── __init__.py │ │ │ ├── body.py │ │ │ ├── core.py │ │ │ ├── fillaround.py │ │ │ ├── inlet.py │ │ │ ├── inner_ring.py │ │ │ ├── pipe.py │ │ │ ├── region.py │ │ │ └── skirt.py │ │ ├── gear/ │ │ │ ├── gear.py │ │ │ ├── involute_gear.py │ │ │ └── tooth.py │ │ ├── heater/ │ │ │ ├── heater.py │ │ │ └── parameters.py │ │ ├── karman.py │ │ └── plate/ │ │ ├── parameters.py │ │ └── plate.py │ ├── modification/ │ │ └── move_vertex.py │ ├── operation/ │ │ ├── box.py │ │ ├── channel.py │ │ ├── connector.py │ │ ├── extrude.py │ │ ├── loft.py │ │ ├── revolve.py │ │ └── wedge.py │ ├── optimization/ │ │ ├── diffuser_free.py │ │ ├── diffuser_line.py │ │ ├── duct.py │ │ └── simple.py │ ├── shape/ │ │ ├── custom.py │ │ ├── cylinder.py │ │ ├── elbow.py │ │ ├── extruded_ring.py │ │ ├── frustum.py │ │ ├── hemisphere.py │ │ ├── one_core_cylinder.py │ │ ├── quarter_cylinder.py │ │ ├── revolved_ring.py │ │ ├── shell.py │ │ ├── splined/ │ │ │ ├── combined_example.py │ │ │ ├── spline_ring.py │ │ │ ├── spline_ring_whole_half_quarter.py │ │ │ └── spline_round.py │ │ ├── torus.py │ │ └── wrapped_cylinder.py │ ├── stack/ │ │ ├── cube.py │ │ └── fusilli.py │ └── transform/ │ └── mirror.py ├── pyproject.toml ├── src/ │ └── classy_blocks/ │ ├── __init__.py │ ├── assemble/ │ │ ├── __init__.py │ │ ├── assembler.py │ │ ├── depot.py │ │ ├── dump.py │ │ └── settings.py │ ├── base/ │ │ ├── __init__.py │ │ ├── element.py │ │ ├── exceptions.py │ │ └── transforms.py │ ├── cbtyping.py │ ├── construct/ │ │ ├── __init__.py │ │ ├── assemblies/ │ │ │ ├── assembly.py │ │ │ └── joints.py │ │ ├── curves/ │ │ │ ├── __init__.py │ │ │ ├── analytic.py │ │ │ ├── curve.py │ │ │ ├── discrete.py │ │ │ ├── interpolated.py │ │ │ └── interpolators.py │ │ ├── edges.py │ │ ├── flat/ │ │ │ ├── __init__.py │ │ │ ├── face.py │ │ │ ├── sketch.py │ │ │ └── sketches/ │ │ │ ├── __init__.py │ │ │ ├── annulus.py │ │ │ ├── disk.py │ │ │ ├── grid.py │ │ │ ├── mapped.py │ │ │ └── spline_round.py │ │ ├── operations/ │ │ │ ├── __init__.py │ │ │ ├── box.py │ │ │ ├── connector.py │ │ │ ├── extrude.py │ │ │ ├── loft.py │ │ │ ├── operation.py │ │ │ ├── revolve.py │ │ │ └── wedge.py │ │ ├── point.py │ │ ├── series.py │ │ ├── shape.py │ │ ├── shapes/ │ │ │ ├── __init__.py │ │ │ ├── cylinder.py │ │ │ ├── elbow.py │ │ │ ├── frustum.py │ │ │ ├── rings.py │ │ │ ├── round.py │ │ │ ├── shell.py │ │ │ └── sphere.py │ │ └── stack.py │ ├── grading/ │ │ ├── __init__.py │ │ ├── analyze/ │ │ │ ├── __init__.py │ │ │ ├── catalogue.py │ │ │ ├── probe.py │ │ │ └── row.py │ │ ├── define/ │ │ │ ├── __init__.py │ │ │ ├── chop.py │ │ │ ├── collector.py │ │ │ ├── grading.py │ │ │ └── relations.py │ │ └── graders/ │ │ ├── __init__.py │ │ ├── auto.py │ │ ├── fixed.py │ │ ├── inflation.py │ │ ├── manager.py │ │ └── simple.py │ ├── items/ │ │ ├── __init__.py │ │ ├── block.py │ │ ├── edges/ │ │ │ ├── __init__.py │ │ │ ├── arcs/ │ │ │ │ ├── __init__.py │ │ │ │ ├── angle.py │ │ │ │ ├── arc.py │ │ │ │ ├── arc_base.py │ │ │ │ └── origin.py │ │ │ ├── curve.py │ │ │ ├── edge.py │ │ │ ├── factory.py │ │ │ ├── line.py │ │ │ └── project.py │ │ ├── patch.py │ │ ├── side.py │ │ ├── vertex.py │ │ └── wires/ │ │ ├── __init__.py │ │ ├── axis.py │ │ ├── manager.py │ │ └── wire.py │ ├── lists/ │ │ ├── __init__.py │ │ ├── block_list.py │ │ ├── edge_list.py │ │ ├── face_list.py │ │ ├── patch_list.py │ │ └── vertex_list.py │ ├── lookup/ │ │ ├── __init__.py │ │ ├── cell_registry.py │ │ ├── connection_registry.py │ │ ├── face_registry.py │ │ └── point_registry.py │ ├── mesh.py │ ├── modify/ │ │ ├── __init__.py │ │ ├── find/ │ │ │ ├── __init__.py │ │ │ ├── finder.py │ │ │ ├── geometric.py │ │ │ └── shape.py │ │ └── reorient/ │ │ ├── __init__.py │ │ └── viewpoint.py │ ├── optimize/ │ │ ├── __init__.py │ │ ├── cell.py │ │ ├── clamps/ │ │ │ ├── __init__.py │ │ │ ├── clamp.py │ │ │ ├── curve.py │ │ │ ├── free.py │ │ │ └── surface.py │ │ ├── connection.py │ │ ├── grid.py │ │ ├── junction.py │ │ ├── links.py │ │ ├── optimizer.py │ │ ├── quality.py │ │ ├── record.py │ │ ├── report.py │ │ └── smoother.py │ ├── util/ │ │ ├── __init__.py │ │ ├── constants.py │ │ ├── frame.py │ │ ├── functions.py │ │ └── tools.py │ └── write/ │ ├── __init__.py │ ├── formats.py │ ├── vtk.py │ └── writer.py ├── tests/ │ ├── __init__.py │ ├── fixtures/ │ │ ├── __init__.py │ │ ├── block.py │ │ ├── data.py │ │ └── mesh.py │ ├── helpers/ │ │ ├── __init__.py │ │ └── collect_outputs.py │ ├── test_assemble.py │ ├── test_bugs/ │ │ ├── __init__.py │ │ └── test_grading.py │ ├── test_construct/ │ │ ├── __init__.py │ │ ├── test_assembly.py │ │ ├── test_chaining.py │ │ ├── test_curves/ │ │ │ ├── __init__.py │ │ │ ├── test_analytic.py │ │ │ ├── test_discrete.py │ │ │ ├── test_interpolated.py │ │ │ └── test_interpolators.py │ │ ├── test_edge_data.py │ │ ├── test_flat/ │ │ │ ├── __init__.py │ │ │ ├── test_annulus.py │ │ │ ├── test_disk.py │ │ │ ├── test_face.py │ │ │ └── test_sketch.py │ │ ├── test_operation/ │ │ │ ├── __init__.py │ │ │ ├── test_box.py │ │ │ ├── test_connector.py │ │ │ ├── test_extrude.py │ │ │ ├── test_operation.py │ │ │ └── test_wedge.py │ │ ├── test_point.py │ │ ├── test_shape.py │ │ ├── test_shell.py │ │ └── test_stack.py │ ├── test_grading/ │ │ ├── __init__.py │ │ ├── test_catalogue.py │ │ ├── test_collector.py │ │ ├── test_edge_grading.py │ │ ├── test_grading.py │ │ ├── test_inflation.py │ │ ├── test_layers.py │ │ ├── test_probe.py │ │ └── test_relations.py │ ├── test_items/ │ │ ├── __init__.py │ │ ├── test_axis.py │ │ ├── test_block.py │ │ ├── test_edge.py │ │ ├── test_patch.py │ │ ├── test_side.py │ │ ├── test_vertex.py │ │ └── test_wire.py │ ├── test_lists/ │ │ ├── __init__.py │ │ ├── test_edge_list.py │ │ ├── test_face_list.py │ │ └── test_patch_list.py │ ├── test_mesh.py │ ├── test_modify/ │ │ ├── __init__.py │ │ ├── test_finder.py │ │ └── test_reorient.py │ ├── test_optimize/ │ │ ├── __init__.py │ │ ├── optimize_fixtures.py │ │ ├── test_cell.py │ │ ├── test_clamps.py │ │ ├── test_grid.py │ │ ├── test_links.py │ │ ├── test_optimizer.py │ │ ├── test_quality.py │ │ └── test_smoother.py │ ├── test_propagation.py │ └── test_util/ │ ├── __init__.py │ ├── test_frame.py │ ├── test_functions.py │ ├── test_imports.py │ └── test_tools.py └── tox.ini
SYMBOL INDEX (2257 symbols across 184 files)
FILE: examples/chaining/flywheel.py
function double_chop (line 55) | def double_chop(function):
FILE: examples/chaining/venturi_tube.py
function calculate_fillet (line 9) | def calculate_fillet(r_pipe, r_fillet, a_cone):
function calculate_cone (line 21) | def calculate_cone(r_start, r_end, a_cone):
FILE: examples/complex/airfoil/airfoil.py
function get_curve (line 46) | def get_curve(z: float) -> cb.SplineInterpolatedCurve:
class AirfoilSketch (line 88) | class AirfoilSketch(cb.MappedSketch):
method __init__ (line 102) | def __init__(self, points):
method add_edges (line 143) | def add_edges(self):
FILE: examples/complex/cyclone/cyclone.py
function add_regions (line 25) | def add_regions(regions: list[Region]) -> None:
function mirror_region (line 139) | def mirror_region(region: Region):
FILE: examples/complex/cyclone/geometry.py
class Geometry (line 24) | class Geometry:
method __post_init__ (line 28) | def __post_init__(self):
method r (line 37) | def r(self) -> dict[str, float]:
method l (line 48) | def l(self) -> dict["str", "float"]: # noqa: E743
method inlet (line 67) | def inlet(self) -> list[NPPointType]:
method z (line 75) | def z(self) -> dict[str, float]:
method surfaces (line 86) | def surfaces(self):
FILE: examples/complex/cyclone/regions/body.py
class ChainSketch (line 16) | class ChainSketch(Sketch):
method grid (line 20) | def grid(self):
method _get_faces (line 24) | def _get_faces(ops: Sequence[Operation]) -> list[cb.Face]:
method _add_arcs (line 46) | def _add_arcs(faces: list[cb.Face]) -> None:
method __init__ (line 63) | def __init__(self, regions: list[Region]):
method faces (line 75) | def faces(self):
method center (line 79) | def center(self):
method n_segments (line 83) | def n_segments(self):
class BodyShape (line 87) | class BodyShape(RoundSolidShape):
method shell (line 89) | def shell(self):
method core (line 93) | def core(self):
class UpperBody (line 97) | class UpperBody(Region):
method __init__ (line 98) | def __init__(self, sketch: ChainSketch, length: float):
method chop (line 102) | def chop(self):
method elements (line 106) | def elements(self):
class LowerBody (line 110) | class LowerBody(UpperBody):
class Cone (line 114) | class Cone(UpperBody):
method __init__ (line 115) | def __init__(self, sketch: ChainSketch):
FILE: examples/complex/cyclone/regions/core.py
class NineCoreDisk (line 15) | class NineCoreDisk(cb.MappedSketch):
method __init__ (line 46) | def __init__(self, perimeter: PointListType, center_point: PointType):
method core (line 66) | def core(self) -> list[cb.Face]:
method shell (line 70) | def shell(self) -> list[cb.Face]:
method add_edges (line 73) | def add_edges(self):
method parts (line 78) | def parts(self):
method center (line 82) | def center(self):
method grid (line 86) | def grid(self):
method normal (line 90) | def normal(self) -> NPVectorType:
method n_segments (line 94) | def n_segments(self):
class DozenBlockCylinder (line 98) | class DozenBlockCylinder(RoundSolidShape):
method __init__ (line 101) | def __init__(self, perimeter: PointListType, center_point: PointType, ...
method chop_radial (line 106) | def chop_radial(self, **kwargs):
class Core (line 110) | class Core(Region):
method __init__ (line 111) | def __init__(self, points: PointListType):
method chop (line 114) | def chop(self):
method elements (line 119) | def elements(self):
class Outlet (line 123) | class Outlet(Region):
method __init__ (line 124) | def __init__(self, core_cylinder: DozenBlockCylinder):
method chop (line 130) | def chop(self):
method elements (line 134) | def elements(self):
method set_patches (line 137) | def set_patches(self):
FILE: examples/complex/cyclone/regions/fillaround.py
class FillAround (line 7) | class FillAround(Region):
method __init__ (line 11) | def __init__(self, loft_1: cb.Loft, loft_2: cb.Loft):
method elements (line 40) | def elements(self):
method connector_1 (line 44) | def connector_1(self):
method connector_2 (line 48) | def connector_2(self):
method project (line 51) | def project(self):
FILE: examples/complex/cyclone/regions/inlet.py
class InletPipe (line 12) | class InletPipe(Region):
method __init__ (line 17) | def __init__(self):
method snap_point (line 20) | def snap_point(self, point: Point) -> None:
method scale_point (line 29) | def scale_point(self, point: Point) -> None:
method create_inlet (line 38) | def create_inlet(self):
method inner_lofts (line 63) | def inner_lofts(self):
method elements (line 69) | def elements(self):
method project (line 72) | def project(self):
class InletExtension (line 77) | class InletExtension(Region):
method __init__ (line 78) | def __init__(self, inlet: InletPipe):
method elements (line 87) | def elements(self):
method set_patches (line 90) | def set_patches(self):
FILE: examples/complex/cyclone/regions/inner_ring.py
class InnerRing (line 8) | class InnerRing(Region):
method _move_to_radius (line 13) | def _move_to_radius(self, point):
method _move_to_angle (line 19) | def _move_to_angle(self, point, angle):
method _reorient_face (line 25) | def _reorient_face(self, face: cb.Face) -> None:
method __init__ (line 51) | def __init__(self, lofts: list[cb.Loft]):
method elements (line 67) | def elements(self):
method project (line 70) | def project(self):
FILE: examples/complex/cyclone/regions/pipe.py
class Pipe (line 9) | class Pipe(Region):
method __init__ (line 10) | def __init__(self, outer: Region):
method center (line 43) | def center(self) -> NPPointType:
method elements (line 48) | def elements(self):
method project (line 51) | def project(self):
FILE: examples/complex/cyclone/regions/region.py
class Region (line 10) | class Region(abc.ABC):
method elements (line 22) | def elements(self) -> list[Operation]:
method get_line_clamps (line 25) | def get_line_clamps(self, mesh):
method get_free_clamps (line 38) | def get_free_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
method get_plane_clamps (line 47) | def get_plane_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
method get_radial_clamps (line 57) | def get_radial_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
method get_clamps (line 67) | def get_clamps(self, mesh: cb.Mesh) -> set[cb.ClampBase]:
method project (line 76) | def project(self) -> None: # noqa: B027
method set_patches (line 79) | def set_patches(self): # noqa: B027
FILE: examples/complex/cyclone/regions/skirt.py
class Skirt (line 6) | class Skirt(Region):
method __init__ (line 12) | def __init__(self, inlet_shell: list[cb.Loft]):
method elements (line 29) | def elements(self):
method project (line 32) | def project(self):
FILE: examples/complex/gear/gear.py
function frad (line 46) | def frad(t, radius):
function mirror (line 84) | def mirror(target, source):
function midpoint (line 103) | def midpoint(target, left, right):
FILE: examples/complex/gear/involute_gear.py
class DimensionError (line 9) | class DimensionError(Exception):
function rotation_matrix (line 13) | def rotation_matrix(theta):
function flip_matrix (line 17) | def flip_matrix(h, v):
function polar_to_cart (line 21) | def polar_to_cart(*coords):
function cart_to_polar (line 28) | def cart_to_polar(*coords):
class InvoluteGear (line 35) | class InvoluteGear:
method __init__ (line 36) | def __init__(
method reduce_polyline (line 110) | def reduce_polyline(self, polyline):
method generate_half_tooth (line 142) | def generate_half_tooth(self):
method generate_half_root (line 178) | def generate_half_root(self):
method generate_roots (line 210) | def generate_roots(self):
method generate_tooth (line 230) | def generate_tooth(self):
method generate_tooth_and_gap (line 249) | def generate_tooth_and_gap(self):
method generate_gear (line 260) | def generate_gear(self):
method get_point_list (line 273) | def get_point_list(self):
FILE: examples/complex/gear/tooth.py
class ToothSketch (line 6) | class ToothSketch(cb.MappedSketch):
method __init__ (line 37) | def __init__(self, positions, curve: cb.LinearInterpolatedCurve):
method add_edges (line 41) | def add_edges(self) -> None:
FILE: examples/complex/heater/heater.py
function set_cell_zones (line 18) | def set_cell_zones(shape: cb.Shape):
class NearestSketch (line 66) | class NearestSketch(Sketch):
method __init__ (line 67) | def __init__(self, operations: List[cb.Operation], far_point):
method faces (line 72) | def faces(self):
method grid (line 76) | def grid(self):
method center (line 80) | def center(self):
FILE: examples/complex/karman.py
function make_box (line 44) | def make_box(p1, p2, size_axes, patches):
FILE: examples/complex/plate/plate.py
function make_extrude (line 38) | def make_extrude(indexes):
FILE: examples/shape/custom.py
class RoundSquare (line 15) | class RoundSquare(cb.MappedSketch):
method __init__ (line 38) | def __init__(self, center: PointType, side: float, corner_round: float):
method add_edges (line 56) | def add_edges(self) -> None:
FILE: examples/stack/cube.py
function move_side (line 39) | def move_side(point, normal, axis, value):
FILE: src/classy_blocks/assemble/assembler.py
class MeshAssembler (line 16) | class MeshAssembler:
method __init__ (line 17) | def __init__(self, depot: Depot, settings: Settings, merge_tol=constan...
method _create_blocks (line 25) | def _create_blocks(self, vertex_list: VertexList) -> BlockList:
method _create_edges (line 53) | def _create_edges(self, block_list: BlockList) -> EdgeList:
method _add_geometry (line 79) | def _add_geometry(self):
method _create_patches (line 84) | def _create_patches(self, block_list: BlockList) -> tuple[PatchList, F...
method _update_neighbours (line 104) | def _update_neighbours(self, block_list: BlockList) -> None:
method assemble (line 107) | def assemble(self) -> AssembledDump:
FILE: src/classy_blocks/assemble/depot.py
class Depot (line 11) | class Depot:
method __init__ (line 14) | def __init__(self) -> None:
method add_solid (line 18) | def add_solid(self, solid: AdditiveType) -> None:
method delete_solid (line 21) | def delete_solid(self, operation: Operation) -> None:
method operations (line 25) | def operations(self) -> list[Operation]:
FILE: src/classy_blocks/assemble/dump.py
class DumpBase (line 15) | class DumpBase(abc.ABC):
method is_assembled (line 18) | def is_assembled(self) -> bool:
method vertices (line 23) | def vertices(self) -> list[Vertex]:
method patches (line 28) | def patches(self) -> list[Patch]:
method blocks (line 33) | def blocks(self) -> list[Block]:
method edges (line 38) | def edges(self) -> list[Edge]:
class EmptyDump (line 42) | class EmptyDump(DumpBase):
method is_assembled (line 44) | def is_assembled(self):
method vertices (line 48) | def vertices(self):
method patches (line 52) | def patches(self):
method blocks (line 56) | def blocks(self):
method edges (line 60) | def edges(self):
class AssembledDump (line 64) | class AssembledDump(DumpBase):
method __init__ (line 65) | def __init__(
method is_assembled (line 80) | def is_assembled(self):
method vertices (line 85) | def vertices(self):
method patches (line 89) | def patches(self):
method blocks (line 93) | def blocks(self):
method edges (line 97) | def edges(self):
FILE: src/classy_blocks/assemble/settings.py
class Settings (line 8) | class Settings:
method add_geometry (line 26) | def add_geometry(self, geometry: GeometryType) -> None:
method modify_patch (line 29) | def modify_patch(self, name: str, kind: str, settings: Optional[list[s...
method slave_patches (line 36) | def slave_patches(self) -> set[str]:
FILE: src/classy_blocks/base/element.py
class ElementBase (line 12) | class ElementBase(abc.ABC):
method translate (line 16) | def translate(self: ElementBaseT, displacement: VectorType) -> Element...
method rotate (line 24) | def rotate(self: ElementBaseT, angle: float, axis: VectorType, origin:...
method scale (line 35) | def scale(self: ElementBaseT, ratio: float, origin: Optional[PointType...
method mirror (line 47) | def mirror(self: ElementBaseT, normal: VectorType, origin: Optional[Po...
method shear (line 58) | def shear(
method copy (line 66) | def copy(self: ElementBaseT) -> ElementBaseT:
method parts (line 72) | def parts(self: ElementBaseT) -> list[ElementBaseT]:
method center (line 81) | def center(self) -> NPPointType:
method geometry (line 85) | def geometry(self) -> Optional[dict]:
method transform (line 91) | def transform(self: ElementBaseT, transforms: Sequence[tr.Transformati...
FILE: src/classy_blocks/base/exceptions.py
class ShapeCreationError (line 5) | class ShapeCreationError(Exception):
method __init__ (line 9) | def __init__(self, msg: str, details: Optional[str] = None, *args) -> ...
class PointCreationError (line 20) | class PointCreationError(ShapeCreationError):
class ArrayCreationError (line 24) | class ArrayCreationError(ShapeCreationError):
class AnnulusCreationError (line 28) | class AnnulusCreationError(ShapeCreationError):
class EdgeCreationError (line 32) | class EdgeCreationError(ShapeCreationError):
class SideCreationError (line 36) | class SideCreationError(ShapeCreationError):
class FaceCreationError (line 40) | class FaceCreationError(ShapeCreationError):
class CylinderCreationError (line 44) | class CylinderCreationError(ShapeCreationError):
class ElbowCreationError (line 48) | class ElbowCreationError(ShapeCreationError):
class FrustumCreationError (line 52) | class FrustumCreationError(ShapeCreationError):
class ExtrudedRingCreationError (line 56) | class ExtrudedRingCreationError(ShapeCreationError):
class GeometryConstraintError (line 60) | class GeometryConstraintError(Exception):
class DegenerateGeometryError (line 64) | class DegenerateGeometryError(Exception):
class SharedPointError (line 69) | class SharedPointError(Exception):
class SharedPointNotFoundError (line 73) | class SharedPointNotFoundError(SharedPointError):
class PointNotCoincidentError (line 77) | class PointNotCoincidentError(SharedPointError):
class DisconnectedChopError (line 81) | class DisconnectedChopError(SharedPointError):
class VertexNotFoundError (line 86) | class VertexNotFoundError(Exception):
class EdgeNotFoundError (line 90) | class EdgeNotFoundError(Exception):
class CornerPairError (line 94) | class CornerPairError(Exception):
class PatchNotFoundError (line 98) | class PatchNotFoundError(Exception):
class UndefinedGradingsError (line 103) | class UndefinedGradingsError(Exception):
class InconsistentGradingsError (line 108) | class InconsistentGradingsError(Exception):
class NoInstructionError (line 112) | class NoInstructionError(Exception):
class BlockNotFoundError (line 116) | class BlockNotFoundError(Exception):
class NoClampError (line 121) | class NoClampError(Exception):
class ClampExistsError (line 125) | class ClampExistsError(Exception):
class NoCommonSidesError (line 129) | class NoCommonSidesError(Exception):
class NoJunctionError (line 133) | class NoJunctionError(Exception):
class InvalidLinkError (line 137) | class InvalidLinkError(Exception):
class OptimizationError (line 141) | class OptimizationError(Exception):
class MeshNotAssembledError (line 146) | class MeshNotAssembledError(Exception):
FILE: src/classy_blocks/base/transforms.py
class Transformation (line 11) | class Transformation:
class Translation (line 17) | class Translation(Transformation):
class Rotation (line 24) | class Rotation(Transformation):
class Scaling (line 33) | class Scaling(Transformation):
class Mirror (line 41) | class Mirror(Transformation):
class Shear (line 50) | class Shear(Transformation):
FILE: src/classy_blocks/cbtyping.py
class ChopArgs (line 43) | class ChopArgs(TypedDict, total=False):
FILE: src/classy_blocks/construct/assemblies/assembly.py
class Assembly (line 11) | class Assembly(ElementBase, abc.ABC):
method __init__ (line 12) | def __init__(self, shapes: Sequence[Shape]):
method parts (line 16) | def parts(self):
method center (line 20) | def center(self):
method operations (line 24) | def operations(self) -> list[Operation]:
FILE: src/classy_blocks/construct/assemblies/joints.py
class CuspSemiCylinder (line 14) | class CuspSemiCylinder(SemiCylinder):
method __init__ (line 19) | def __init__(
class CuspCylinder (line 48) | class CuspCylinder(Assembly):
method __init__ (line 49) | def __init__(
method shapes (line 66) | def shapes(self):
method chop_axial (line 69) | def chop_axial(self, **kwargs):
method chop_radial (line 72) | def chop_radial(self, **kwargs):
method chop_tangential (line 76) | def chop_tangential(self, **kwargs):
method set_outer_patch (line 80) | def set_outer_patch(self, patch_name: str) -> None:
method set_start_patch (line 84) | def set_start_patch(self, patch_name: str) -> None:
class JointBase (line 89) | class JointBase(Assembly, abc.ABC):
method __init__ (line 90) | def __init__(self, start_point: PointType, center_point: PointType, ra...
method _get_angles (line 113) | def _get_angles(self, count: int) -> FloatListType:
method center (line 117) | def center(self):
method chop_axial (line 121) | def chop_axial(self, **kwargs):
method chop_radial (line 125) | def chop_radial(self, **kwargs):
method chop_tangential (line 128) | def chop_tangential(self, **kwargs):
method set_outer_patch (line 132) | def set_outer_patch(self, patch_name: str) -> None:
method set_hole_patch (line 136) | def set_hole_patch(self, hole: int, patch_name: str) -> None:
class NJoint (line 140) | class NJoint(JointBase):
method _get_angles (line 141) | def _get_angles(self, count):
class TJoint (line 145) | class TJoint(JointBase):
method __init__ (line 146) | def __init__(self, start_point: PointType, center_point: PointType, ra...
method _get_angles (line 149) | def _get_angles(self, _):
class LJoint (line 153) | class LJoint(JointBase):
method __init__ (line 154) | def __init__(self, start_point: PointType, center_point: PointType, ra...
method _get_angles (line 157) | def _get_angles(self, _):
FILE: src/classy_blocks/construct/curves/analytic.py
class AnalyticCurve (line 11) | class AnalyticCurve(FunctionCurveBase):
method __init__ (line 16) | def __init__(self, function: ParamCurveFuncType, bounds: tuple[float, ...
method parts (line 21) | def parts(self):
method get_length (line 24) | def get_length(self, param_from: Optional[float] = None, param_to: Opt...
class LineCurve (line 31) | class LineCurve(AnalyticCurve):
method __init__ (line 37) | def __init__(self, point_1: PointType, point_2: PointType, bounds: tup...
method vector (line 44) | def vector(self) -> NPVectorType:
method parts (line 48) | def parts(self):
method center (line 52) | def center(self):
class CircleCurve (line 57) | class CircleCurve(AnalyticCurve):
method __init__ (line 62) | def __init__(
method normal (line 77) | def normal(self) -> NPVectorType:
method center (line 81) | def center(self):
method parts (line 85) | def parts(self):
FILE: src/classy_blocks/construct/curves/curve.py
class CurveBase (line 15) | class CurveBase(ElementBase):
method _check_param (line 20) | def _check_param(self, param: Union[int, float]) -> Union[int, float]:
method _get_params (line 27) | def _get_params(self, param_from: Optional[float] = None, param_to: Op...
method get_point (line 40) | def get_point(self, param: float) -> NPPointType:
method discretize (line 44) | def discretize(
method get_length (line 52) | def get_length(self, param_from: Optional[float] = None, param_to: Opt...
method length (line 57) | def length(self) -> float:
method get_closest_param (line 62) | def get_closest_param(self, point: PointType) -> float:
method get_closest_point (line 65) | def get_closest_point(self, point: PointType) -> NPPointType:
method get_param_at_length (line 69) | def get_param_at_length(self, length: float) -> float:
method _diff (line 73) | def _diff(self, param: float, order: int, delta: float = TOL) -> NPVec...
method get_tangent (line 86) | def get_tangent(self, param: float, delta: float = TOL) -> NPVectorType:
method get_normal (line 90) | def get_normal(self, param: float, delta: float = TOL) -> NPVectorType:
method get_binormal (line 95) | def get_binormal(self, param: float, delta: float = TOL) -> NPVectorType:
class PointCurveBase (line 101) | class PointCurveBase(CurveBase):
method _check_param (line 106) | def _check_param(self, param):
method center (line 110) | def center(self):
class FunctionCurveBase (line 115) | class FunctionCurveBase(PointCurveBase):
method discretize (line 120) | def discretize(
method get_closest_param (line 129) | def get_closest_param(self, point: PointType) -> float:
method get_point (line 153) | def get_point(self, param: float) -> NPPointType:
FILE: src/classy_blocks/construct/curves/discrete.py
class DiscreteCurve (line 12) | class DiscreteCurve(PointCurveBase):
method __init__ (line 22) | def __init__(self, points: PointListType):
method discretize (line 26) | def discretize(
method get_length (line 43) | def get_length(self, param_from: Optional[float] = None, param_to: Opt...
method get_closest_param (line 47) | def get_closest_param(self, point: PointType) -> float:
method center (line 60) | def center(self):
method get_point (line 64) | def get_point(self, param: float) -> NPPointType:
method parts (line 70) | def parts(self):
FILE: src/classy_blocks/construct/curves/interpolated.py
class InterpolatedCurveBase (line 13) | class InterpolatedCurveBase(FunctionCurveBase, abc.ABC):
method __init__ (line 28) | def __init__(self, points: PointListType, extrapolate: bool = False, e...
method segments (line 34) | def segments(self) -> int:
method parts (line 39) | def parts(self):
method get_length (line 47) | def get_length(self, param_from: Optional[float] = None, param_to: Opt...
class LinearInterpolatedCurve (line 64) | class LinearInterpolatedCurve(InterpolatedCurveBase):
class SplineInterpolatedCurve (line 68) | class SplineInterpolatedCurve(InterpolatedCurveBase):
FILE: src/classy_blocks/construct/curves/interpolators.py
class InterpolatorBase (line 10) | class InterpolatorBase(abc.ABC):
method _get_function (line 18) | def _get_function(self) -> ParamCurveFuncType:
method __init__ (line 21) | def __init__(self, points: Series, extrapolate: bool, equalize: bool =...
method __call__ (line 29) | def __call__(self, param: float) -> NPPointType:
method invalidate (line 36) | def invalidate(self) -> None:
method params (line 40) | def params(self) -> FloatListType:
class LinearInterpolator (line 53) | class LinearInterpolator(InterpolatorBase):
method _get_function (line 54) | def _get_function(self):
class SplineInterpolator (line 73) | class SplineInterpolator(InterpolatorBase):
method _get_function (line 74) | def _get_function(self):
FILE: src/classy_blocks/construct/edges.py
class EdgeData (line 12) | class EdgeData(ElementBase):
method parts (line 18) | def parts(self):
method center (line 22) | def center(self):
method representation (line 27) | def representation(self) -> EdgeKindType:
class Line (line 32) | class Line(EdgeData):
class Arc (line 38) | class Arc(EdgeData):
method __init__ (line 44) | def __init__(self, arc_point: PointType):
method parts (line 48) | def parts(self):
class Origin (line 52) | class Origin(EdgeData):
method __init__ (line 66) | def __init__(self, origin: PointType, flatness: float = 1):
method parts (line 71) | def parts(self):
class Angle (line 75) | class Angle(EdgeData):
method __init__ (line 88) | def __init__(self, angle: float, axis: VectorType):
method translate (line 92) | def translate(self, displacement):
method scale (line 95) | def scale(self, ratio, origin=None):
method parts (line 99) | def parts(self):
class Project (line 103) | class Project(EdgeData):
method __init__ (line 108) | def __init__(self, label: ProjectToType):
method convert_label (line 113) | def convert_label(label: ProjectToType) -> list[str]:
method check_length (line 122) | def check_length(self) -> None:
method add_label (line 127) | def add_label(self, label: ProjectToType) -> None:
class OnCurve (line 139) | class OnCurve(EdgeData):
method __init__ (line 144) | def __init__(self, curve: CurveBase, n_points: int = 10, representatio...
method parts (line 151) | def parts(self):
method center (line 155) | def center(self):
method representation (line 159) | def representation(self) -> EdgeKindType:
method discretize (line 162) | def discretize(self, param_from: float, param_to: float) -> NPPointLis...
class Spline (line 166) | class Spline(OnCurve):
method __init__ (line 171) | def __init__(self, points: PointListType):
method parts (line 176) | def parts(self):
method center (line 180) | def center(self):
method representation (line 184) | def representation(self) -> EdgeKindType:
class PolyLine (line 188) | class PolyLine(Spline):
method representation (line 195) | def representation(self) -> EdgeKindType:
FILE: src/classy_blocks/construct/flat/face.py
class Face (line 16) | class Face(ElementBase):
method __init__ (line 32) | def __init__(
method update (line 69) | def update(self, points: PointListType) -> None:
method add_edge (line 74) | def add_edge(self, corner: int, edge_data: Union[EdgeData, None]) -> N...
method remove_edges (line 85) | def remove_edges(self, corners: Optional[list[int]] = None) -> None:
method project_edge (line 95) | def project_edge(self, corner: int, label: ProjectToType) -> None:
method invert (line 105) | def invert(self) -> "Face":
method copy (line 113) | def copy(self) -> "Face":
method point_array (line 118) | def point_array(self) -> NPPointListType:
method center (line 123) | def center(self) -> NPPointType:
method normal (line 128) | def normal(self) -> NPVectorType:
method parts (line 143) | def parts(self):
method project (line 146) | def project(self, label: str, edges: bool = False, points: bool = Fals...
method shift (line 172) | def shift(self, count: int) -> "Face":
method reorient (line 182) | def reorient(self, start_near: PointType) -> "Face":
FILE: src/classy_blocks/construct/flat/sketch.py
class Sketch (line 12) | class Sketch(ElementBase):
method faces (line 21) | def faces(self) -> list[Face]:
method grid (line 26) | def grid(self) -> list[list[Face]]:
method copy (line 36) | def copy(self: SketchT) -> SketchT:
method center (line 42) | def center(self) -> NPPointType:
method normal (line 46) | def normal(self) -> NPVectorType:
method parts (line 51) | def parts(self):
FILE: src/classy_blocks/construct/flat/sketches/annulus.py
class Annulus (line 12) | class Annulus(Sketch):
method __init__ (line 18) | def __init__(
method faces (line 59) | def faces(self) -> list[Face]:
method grid (line 63) | def grid(self):
method center (line 67) | def center(self) -> NPPointType:
method n_segments (line 81) | def n_segments(self):
method outer_radius_point (line 86) | def outer_radius_point(self) -> NPPointType:
method outer_radius (line 91) | def outer_radius(self) -> float:
method radius (line 96) | def radius(self) -> float:
method radius_point (line 101) | def radius_point(self) -> NPPointType:
method inner_radius_point (line 106) | def inner_radius_point(self) -> NPPointType:
method inner_radius (line 111) | def inner_radius(self) -> float:
FILE: src/classy_blocks/construct/flat/sketches/disk.py
class FanPattern (line 22) | class FanPattern:
method __init__ (line 25) | def __init__(self, center_point: PointType, radius_point: PointType, n...
method get_outer_points (line 32) | def get_outer_points(self, angles) -> NPPointListType:
method get_inner_points (line 35) | def get_inner_points(self, angles, ratios: list[float]) -> NPPointList...
class DiskBase (line 47) | class DiskBase(MappedSketch, abc.ABC):
method __init__ (line 73) | def __init__(self, positions: PointListType, quads: list[IndexType]):
method origo (line 80) | def origo(self):
method diagonal_ratio (line 87) | def diagonal_ratio(self) -> float:
method circular_core_spline (line 90) | def circular_core_spline(
method add_core_spline_edges (line 130) | def add_core_spline_edges(self) -> None:
method add_edges (line 146) | def add_edges(self):
method center (line 153) | def center(self) -> NPPointType:
method radius_point (line 158) | def radius_point(self) -> NPPointType:
method radius_vector (line 163) | def radius_vector(self) -> NPVectorType:
method radius (line 171) | def radius(self) -> float:
method n_segments (line 176) | def n_segments(self):
method core (line 180) | def core(self) -> list[Face]:
method shell (line 184) | def shell(self) -> list[Face]:
method parts (line 188) | def parts(self):
class OneCoreDisk (line 192) | class OneCoreDisk(DiskBase):
method __init__ (line 201) | def __init__(self, center_point: PointType, radius_point: PointType, n...
method center (line 223) | def center(self):
method grid (line 227) | def grid(self):
method add_core_spline_edges (line 230) | def add_core_spline_edges(self):
class QuarterDisk (line 234) | class QuarterDisk(DiskBase):
method __init__ (line 242) | def __init__(self, center_point: PointType, radius_point: PointType, n...
method grid (line 260) | def grid(self):
class HalfDisk (line 264) | class HalfDisk(DiskBase):
method __init__ (line 272) | def __init__(self, center_point: PointType, radius_point: PointType, n...
method grid (line 293) | def grid(self):
class FourCoreDisk (line 297) | class FourCoreDisk(DiskBase):
method __init__ (line 303) | def __init__(self, center_point: PointType, radius_point: PointType, n...
method grid (line 330) | def grid(self):
class WrappedDisk (line 337) | class WrappedDisk(DiskBase):
method __init__ (line 346) | def __init__(self, center_point: PointType, corner_point: PointType, r...
method grid (line 378) | def grid(self):
method add_edges (line 381) | def add_edges(self):
method center (line 386) | def center(self):
class Oval (line 390) | class Oval(DiskBase):
method __init__ (line 396) | def __init__(self, center_point_1: PointType, center_point_2: PointTyp...
method center_1 (line 446) | def center_1(self) -> NPPointType:
method center_2 (line 450) | def center_2(self) -> NPPointType:
method center (line 454) | def center(self):
method add_edges (line 457) | def add_edges(self):
method grid (line 465) | def grid(self):
FILE: src/classy_blocks/construct/flat/sketches/grid.py
class Grid (line 10) | class Grid(Sketch):
method __init__ (line 21) | def __init__(self, point_1: PointType, point_2: PointType, count_1: in...
method faces (line 44) | def faces(self):
method center (line 48) | def center(self):
method grid (line 52) | def grid(self):
FILE: src/classy_blocks/construct/flat/sketches/mapped.py
class MappedSketch (line 13) | class MappedSketch(Sketch):
method __init__ (line 17) | def __init__(self, positions: PointListType, quads: list[IndexType]):
method update (line 27) | def update(self, positions: PointListType) -> None:
method add_edges (line 34) | def add_edges(self) -> None:
method faces (line 39) | def faces(self):
method grid (line 44) | def grid(self):
method center (line 49) | def center(self) -> NPPointType:
method positions (line 54) | def positions(self) -> NPPointListType:
method merge (line 63) | def merge(self, other: Union[list["MappedSketch"], "MappedSketch"]):
FILE: src/classy_blocks/construct/flat/sketches/spline_round.py
class SplineRound (line 12) | class SplineRound(DiskBase):
method __init__ (line 27) | def __init__(self, side_1: float, side_2: float, **kwargs):
method remove_core (line 34) | def remove_core(self):
method oval_core_spline (line 46) | def oval_core_spline(
method add_core_spline_edges (line 101) | def add_core_spline_edges(self) -> None:
method outer_spline (line 126) | def outer_spline(
method add_outer_spline_edges (line 185) | def add_outer_spline_edges(self, center: Optional[NPPointType] = None)...
method add_inner_spline_edges (line 205) | def add_inner_spline_edges(self, center: Optional[NPPointType] = None)...
method add_edges (line 224) | def add_edges(self) -> None:
method radius_1_point (line 240) | def radius_1_point(self) -> NPPointType:
method radius_1_vector (line 244) | def radius_1_vector(self) -> NPVectorType:
method radius_1 (line 248) | def radius_1(self) -> float:
method radius_2_point (line 252) | def radius_2_point(self) -> NPPointType:
method radius_2_vector (line 256) | def radius_2_vector(self) -> NPVectorType:
method radius_2 (line 260) | def radius_2(self) -> float:
method u_0 (line 264) | def u_0(self) -> NPVectorType:
method normal (line 269) | def normal(self) -> NPVectorType:
method u_1 (line 273) | def u_1(self) -> NPVectorType:
method u_1 (line 281) | def u_1(self, vec):
method u_2 (line 285) | def u_2(self) -> NPVectorType:
method u_2 (line 293) | def u_2(self, vec):
method scale (line 296) | def scale(self, ratio: float, origin: Optional[PointType] = None):
class QuarterSplineDisk (line 304) | class QuarterSplineDisk(SplineRound, QuarterDisk):
method __init__ (line 307) | def __init__(
method correct_disk (line 342) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
class HalfSplineDisk (line 368) | class HalfSplineDisk(SplineRound, HalfDisk):
method __init__ (line 371) | def __init__(
method correct_disk (line 406) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
class SplineDisk (line 443) | class SplineDisk(SplineRound, FourCoreDisk):
method __init__ (line 446) | def __init__(
method correct_disk (line 481) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
class QuarterSplineRing (line 542) | class QuarterSplineRing(QuarterSplineDisk):
method __init__ (line 550) | def __init__(
method correct_disk (line 589) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
method add_edges (line 610) | def add_edges(self) -> None:
method grid (line 641) | def grid(self):
method core (line 645) | def core(self):
class HalfSplineRing (line 649) | class HalfSplineRing(HalfSplineDisk, QuarterSplineRing):
method __init__ (line 657) | def __init__(
method correct_disk (line 695) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
method add_edges (line 722) | def add_edges(self) -> None:
method grid (line 753) | def grid(self):
method core (line 757) | def core(self):
class SplineRing (line 761) | class SplineRing(SplineDisk, QuarterSplineRing):
method __init__ (line 769) | def __init__(
method correct_disk (line 807) | def correct_disk(self, corner_1_point: NPPointType, corner_2_point: NP...
method grid (line 846) | def grid(self):
method core (line 850) | def core(self):
FILE: src/classy_blocks/construct/operations/box.py
class Box (line 8) | class Box(Loft):
method __init__ (line 23) | def __init__(self, start_point: PointType, diagonal_point: PointType):
FILE: src/classy_blocks/construct/operations/connector.py
class FacePair (line 9) | class FacePair:
method __init__ (line 10) | def __init__(self, face_1: Face, face_2: Face):
method distance (line 15) | def distance(self) -> float:
method alignment (line 20) | def alignment(self) -> float:
class Connector (line 27) | class Connector(Operation):
method __init__ (line 59) | def __init__(self, operation_1: Operation, operation_2: Operation):
FILE: src/classy_blocks/construct/operations/extrude.py
class Extrude (line 10) | class Extrude(Loft):
method __init__ (line 15) | def __init__(self, base: Face, amount: Union[float, VectorType]):
FILE: src/classy_blocks/construct/operations/operation.py
class Operation (line 31) | class Operation(ElementBase):
method __init__ (line 37) | def __init__(self, bottom_face: Face, top_face: Face):
method _project_update (line 51) | def _project_update(self, edge: EdgeData, label: ProjectToType):
method add_side_edge (line 59) | def add_side_edge(self, corner_idx: int, edge_data: EdgeData) -> None:
method chop (line 70) | def chop(self, axis: DirectionType, **kwargs: Unpack[ChopArgs]) -> None:
method chop_edge (line 115) | def chop_edge(self, corner_1: int, corner_2: int, **kwargs: Unpack[Cho...
method unchop (line 118) | def unchop(self, axis: Optional[DirectionType] = None) -> None:
method project_corner (line 127) | def project_corner(self, corner: int, label: ProjectToType) -> None:
method project_edge (line 138) | def project_edge(self, corner_1: int, corner_2: int, label: ProjectToT...
method project_side (line 157) | def project_side(self, side: OrientType, label: str, edges: bool = Fal...
method set_patch (line 199) | def set_patch(self, sides: Union[OrientType, list[OrientType]], name: ...
method set_cell_zone (line 228) | def set_cell_zone(self, cell_zone: str) -> None:
method parts (line 233) | def parts(self):
method points (line 237) | def points(self) -> list[Point]:
method point_array (line 242) | def point_array(self) -> NPPointType:
method center (line 247) | def center(self):
method get_patches_at_corner (line 250) | def get_patches_at_corner(self, corner: int) -> set:
method get_face (line 270) | def get_face(self, side: OrientType) -> Face:
method get_all_faces (line 276) | def get_all_faces(self) -> dict[OrientType, Face]:
method get_closest_side (line 280) | def get_closest_side(self, point: PointType) -> OrientType:
method get_closest_face (line 290) | def get_closest_face(self, point: PointType) -> Face:
method get_normal_face (line 294) | def get_normal_face(self, point: PointType) -> Face:
method patch_names (line 309) | def patch_names(self) -> dict[OrientType, str]:
method edges (line 326) | def edges(self) -> Frame[EdgeData]:
method get_index_from_side (line 342) | def get_index_from_side(side: OrientType) -> int:
method invert (line 349) | def invert(self) -> "Operation":
method mirror (line 354) | def mirror(self, normal: VectorType, origin: Optional[PointType] = None):
method transform (line 365) | def transform(self, transforms):
method from_series (line 377) | def from_series(cls, faces: list[Face]) -> "Operation":
FILE: src/classy_blocks/construct/operations/revolve.py
class Revolve (line 7) | class Revolve(Loft):
method __init__ (line 14) | def __init__(self, base: Face, angle: float, axis: VectorType, origin:...
FILE: src/classy_blocks/construct/operations/wedge.py
class Wedge (line 8) | class Wedge(Revolve):
method __init__ (line 31) | def __init__(self, face: Face, angle: Optional[float] = None):
method set_inner_patch (line 52) | def set_inner_patch(self, name: str) -> None:
method set_outer_patch (line 56) | def set_outer_patch(self, name: str) -> None:
FILE: src/classy_blocks/construct/point.py
class Point (line 14) | class Point(ElementBase):
method __init__ (line 18) | def __init__(self, position: PointType):
method move_to (line 25) | def move_to(self, position: PointType) -> None:
method translate (line 31) | def translate(self, displacement):
method rotate (line 36) | def rotate(self, angle, axis, origin: Optional[PointType] = None):
method scale (line 44) | def scale(self, ratio, origin: Optional[PointType] = None):
method mirror (line 52) | def mirror(self, normal: VectorType, origin: Optional[PointType] = None):
method shear (line 60) | def shear(self, normal: VectorType, origin: PointType, direction: Vect...
method project (line 75) | def project(self, label: ProjectToType) -> None:
method parts (line 83) | def parts(self):
method center (line 87) | def center(self):
method projected_to (line 91) | def projected_to(self) -> list[str]:
method __eq__ (line 94) | def __eq__(self, other):
method __repr__ (line 97) | def __repr__(self):
method __str__ (line 100) | def __str__(self):
class Vector (line 104) | class Vector(Point):
method components (line 108) | def components(self) -> NPVectorType:
method __repr__ (line 113) | def __repr__(self):
FILE: src/classy_blocks/construct/series.py
class Series (line 12) | class Series(ElementBase):
method __init__ (line 13) | def __init__(self, points: PointListType):
method translate (line 25) | def translate(self, displacement):
method rotate (line 30) | def rotate(self, angle, axis, origin: Optional[PointType] = None):
method scale (line 42) | def scale(self, ratio, origin: Optional[PointType] = None):
method mirror (line 50) | def mirror(self, normal: VectorType, origin: Optional[PointType] = None):
method shear (line 58) | def shear(self, normal: VectorType, origin: PointType, direction: Vect...
method center (line 75) | def center(self):
method parts (line 79) | def parts(self):
method __len__ (line 82) | def __len__(self):
method __getitem__ (line 85) | def __getitem__(self, i):
FILE: src/classy_blocks/construct/shape.py
class Shape (line 20) | class Shape(ElementBase, abc.ABC):
method operations (line 26) | def operations(self) -> list[Operation]:
method parts (line 30) | def parts(self):
method set_cell_zone (line 33) | def set_cell_zone(self, cell_zone: str) -> None:
method center (line 39) | def center(self) -> NPPointType:
method grid (line 45) | def grid(self) -> list[list[Operation]]:
class LoftedShape (line 50) | class LoftedShape(Shape, abc.ABC, Generic[SketchT]):
method __init__ (line 55) | def __init__(
method set_start_patch (line 87) | def set_start_patch(self, name: str) -> None:
method set_end_patch (line 92) | def set_end_patch(self, name: str) -> None:
method operations (line 98) | def operations(self):
method grid (line 102) | def grid(self):
method chop (line 106) | def chop(self, axis: DirectionType, **kwargs) -> None:
class ExtrudedShape (line 116) | class ExtrudedShape(LoftedShape):
method __init__ (line 121) | def __init__(self, sketch: Sketch, amount: Union[float, VectorType]):
class RevolvedShape (line 133) | class RevolvedShape(LoftedShape):
method __init__ (line 134) | def __init__(self, sketch: Sketch, angle: float, axis: VectorType, ori...
FILE: src/classy_blocks/construct/shapes/cylinder.py
class SemiCylinder (line 15) | class SemiCylinder(RoundSolidShape):
method __init__ (line 26) | def __init__(self, axis_point_1: PointType, axis_point_2: PointType, r...
method set_symmetry_patch (line 41) | def set_symmetry_patch(self, name: str) -> None:
class QuarterCylinder (line 48) | class QuarterCylinder(RoundSolidShape):
method __init__ (line 59) | def __init__(self, axis_point_1: PointType, axis_point_2: PointType, r...
method set_symmetry_patch (line 74) | def set_symmetry_patch(self, name: str) -> None:
class Cylinder (line 81) | class Cylinder(SemiCylinder):
method chain (line 85) | def chain(cls, source: RoundSolidShape, length: float, start_face: boo...
method fill (line 110) | def fill(cls, source: "ExtrudedRing") -> "Cylinder":
method set_symmetry_patch (line 120) | def set_symmetry_patch(self, _name: str) -> None:
FILE: src/classy_blocks/construct/shapes/elbow.py
class Elbow (line 11) | class Elbow(RoundSolidShape):
method __init__ (line 14) | def __init__(
method chain (line 37) | def chain(
FILE: src/classy_blocks/construct/shapes/frustum.py
class Frustum (line 14) | class Frustum(RoundSolidShape):
method __init__ (line 28) | def __init__(
method chain (line 59) | def chain(
FILE: src/classy_blocks/construct/shapes/rings.py
class ExtrudedRing (line 16) | class ExtrudedRing(RoundHollowShape):
method __init__ (line 19) | def __init__(
method chain (line 36) | def chain(cls, source: "ExtrudedRing", length: float, start_face: bool...
method expand (line 60) | def expand(cls, source: Union[RoundSolidShape, RoundHollowShape], thic...
method contract (line 73) | def contract(cls, source: "ExtrudedRing", inner_radius: float) -> "Ext...
class RevolvedRing (line 94) | class RevolvedRing(ExtrudedRing):
method __init__ (line 123) | def __init__(self, axis_point_1: PointType, axis_point_2: PointType, c...
method set_inner_patch (line 137) | def set_inner_patch(self, name: str) -> None:
method set_start_patch (line 142) | def set_start_patch(self, name: str) -> None:
method set_end_patch (line 147) | def set_end_patch(self, name: str) -> None:
method operations (line 154) | def operations(self) -> list[Operation]:
method chop_axial (line 157) | def chop_axial(self, **kwargs):
FILE: src/classy_blocks/construct/shapes/round.py
class RoundSolidShape (line 12) | class RoundSolidShape(LoftedShape):
method __init__ (line 21) | def __init__(
method chop_axial (line 40) | def chop_axial(self, **kwargs):
method chop_radial (line 44) | def chop_radial(self, **kwargs):
method chop_tangential (line 57) | def chop_tangential(self, **kwargs):
method core (line 62) | def core(self):
method shell (line 67) | def shell(self):
method set_outer_patch (line 71) | def set_outer_patch(self, name: str) -> None:
method remove_inner_edges (line 75) | def remove_inner_edges(self, start: bool = True, end: bool = True) -> ...
class RoundHollowShape (line 88) | class RoundHollowShape(RoundSolidShape):
method __init__ (line 89) | def __init__(
method shell (line 98) | def shell(self) -> list[Loft]:
method chop_tangential (line 102) | def chop_tangential(self, **kwargs) -> None:
method chop_radial (line 108) | def chop_radial(self, **kwargs):
method set_inner_patch (line 112) | def set_inner_patch(self, name: str) -> None:
FILE: src/classy_blocks/construct/shapes/shell.py
class SharedPoint (line 14) | class SharedPoint:
method __init__ (line 17) | def __init__(self, point: Point):
method add (line 23) | def add(self, face: Face, index: int) -> None:
method normal (line 38) | def normal(self) -> NPVectorType:
method is_shared (line 45) | def is_shared(self) -> bool:
method __eq__ (line 50) | def __eq__(self, other):
class SharedPointStore (line 54) | class SharedPointStore:
method __init__ (line 57) | def __init__(self) -> None:
method find_by_point (line 60) | def find_by_point(self, point: Point) -> SharedPoint:
method add_from_face (line 67) | def add_from_face(self, face: Face, index: int) -> SharedPoint:
class AwareFace (line 82) | class AwareFace:
method __init__ (line 85) | def __init__(self, face: Face, shared_points: list[SharedPoint]):
method get_offset_points (line 89) | def get_offset_points(self, amount: float) -> list[NPPointType]:
method get_offset_face (line 93) | def get_offset_face(self, amount: float) -> Face:
method is_solitary (line 97) | def is_solitary(self) -> bool:
class AwareFaceStore (line 103) | class AwareFaceStore:
method __init__ (line 107) | def __init__(self, faces: list[Face]):
method point_store (line 111) | def point_store(self):
method get_aware_face (line 120) | def get_aware_face(self, face) -> AwareFace:
method aware_faces (line 125) | def aware_faces(self) -> list[AwareFace]:
method get_offset_lofts (line 133) | def get_offset_lofts(self, amount: float) -> list[Loft]:
method is_disconnected (line 139) | def is_disconnected(self) -> bool:
class Shell (line 149) | class Shell(Shape):
method __init__ (line 161) | def __init__(self, faces: list[Face], amount: float):
method operations (line 169) | def operations(self):
method grid (line 173) | def grid(self):
method chop (line 176) | def chop(self, **kwargs) -> None:
method set_outer_patch (line 189) | def set_outer_patch(self, name: str) -> None:
FILE: src/classy_blocks/construct/shapes/sphere.py
function get_named_points (line 12) | def get_named_points(qdisk: QuarterDisk) -> dict[str, NPPointType]:
function eighth_sphere_lofts (line 38) | def eighth_sphere_lofts(
class EighthSphere (line 95) | class EighthSphere(Shape):
method __init__ (line 100) | def __init__(
method chop_axial (line 123) | def chop_axial(self, **kwargs):
method chop_radial (line 127) | def chop_radial(self, **kwargs):
method chop_tangential (line 131) | def chop_tangential(self, **kwargs):
method set_start_patch (line 140) | def set_start_patch(self, name: str) -> None:
method operations (line 151) | def operations(self):
method core (line 155) | def core(self):
method shell (line 159) | def shell(self):
method grid (line 163) | def grid(self):
method radius_point (line 167) | def radius_point(self) -> NPPointType:
method center_point (line 171) | def center_point(self) -> NPPointType:
method normal (line 175) | def normal(self) -> NPVectorType:
method radius (line 179) | def radius(self) -> float:
method geometry_label (line 184) | def geometry_label(self) -> str:
method center (line 189) | def center(self):
method geometry (line 193) | def geometry(self):
class QuarterSphere (line 204) | class QuarterSphere(EighthSphere):
class Hemisphere (line 208) | class Hemisphere(EighthSphere):
method chain (line 213) | def chain(cls, source, start_face=False):
method set_outer_patch (line 228) | def set_outer_patch(self, name):
FILE: src/classy_blocks/construct/stack.py
class Stack (line 15) | class Stack(ElementBase):
method __init__ (line 19) | def __init__(self) -> None:
method grid (line 23) | def grid(self):
method get_slice (line 28) | def get_slice(self, axis: DirectionType, index: int) -> list[Operation]:
method chop (line 54) | def chop(self, **kwargs) -> None:
method operations (line 61) | def operations(self) -> list[Operation]:
method parts (line 65) | def parts(self):
method center (line 69) | def center(self):
class TransformedStack (line 73) | class TransformedStack(Stack):
method __init__ (line 79) | def __init__(
class ExtrudedStack (line 104) | class ExtrudedStack(TransformedStack):
method __init__ (line 108) | def __init__(self, base: Sketch, amount: Union[float, VectorType], rep...
class RevolvedStack (line 117) | class RevolvedStack(TransformedStack):
method __init__ (line 121) | def __init__(self, base: Sketch, angle: float, axis: VectorType, origi...
FILE: src/classy_blocks/grading/analyze/catalogue.py
function get_block_from_axis (line 13) | def get_block_from_axis(block_list: BlockList, axis: Axis) -> Block:
class Instruction (line 21) | class Instruction:
method __init__ (line 24) | def __init__(self, block: Block):
method is_defined (line 29) | def is_defined(self):
method __hash__ (line 32) | def __hash__(self) -> int:
class RowCatalogue (line 36) | class RowCatalogue:
method __init__ (line 39) | def __init__(self, block_list: BlockList):
method _get_undefined_instructions (line 48) | def _get_undefined_instructions(self, direction: DirectionType) -> lis...
method _find_instruction (line 51) | def _find_instruction(self, block: Block):
method _add_block_to_row (line 59) | def _add_block_to_row(self, row: Row, instruction: Instruction, direct...
method _populate (line 75) | def _populate(self, direction: DirectionType) -> None:
method get_row_blocks (line 85) | def get_row_blocks(self, block: Block, direction: DirectionType) -> li...
FILE: src/classy_blocks/grading/analyze/probe.py
class WireInfo (line 17) | class WireInfo:
method length (line 25) | def length(self) -> float:
method size_after (line 29) | def size_after(self) -> Optional[float]:
method size_before (line 51) | def size_before(self) -> Optional[float]:
class WireCatalogue (line 73) | class WireCatalogue:
method __init__ (line 78) | def __init__(self, dump: AssembledDump, settings: Settings):
method _fetch (line 92) | def _fetch(self, index_1: int, index_2: int) -> Optional[WireInfo]:
method _populate (line 98) | def _populate(self) -> None:
method _get_wire_boundaries (line 114) | def _get_wire_boundaries(self, wire: Wire, block: Block) -> tuple[bool...
method get_info (line 141) | def get_info(self, wire: Wire) -> WireInfo:
class Probe (line 150) | class Probe:
method __init__ (line 153) | def __init__(self, dump: AssembledDump, settings: Settings):
method get_row_blocks (line 160) | def get_row_blocks(self, block: Block, direction: DirectionType) -> li...
method get_rows (line 163) | def get_rows(self, direction: DirectionType) -> list[Row]:
method get_wire_info (line 166) | def get_wire_info(self, wire: Wire) -> WireInfo:
FILE: src/classy_blocks/grading/analyze/row.py
class Entry (line 11) | class Entry:
method axis (line 21) | def axis(self) -> Axis:
method wires (line 25) | def wires(self) -> list[Wire]:
method neighbours (line 29) | def neighbours(self) -> set[Axis]:
method lengths (line 33) | def lengths(self) -> list[float]:
class Row (line 37) | class Row:
method __init__ (line 45) | def __init__(self) -> None:
method add_block (line 52) | def add_block(self, block: Block, heading: DirectionType) -> None:
method get_length (line 75) | def get_length(self, take: ChopTakeType = "avg"):
method get_axes (line 88) | def get_axes(self) -> list[Axis]:
method get_wires (line 91) | def get_wires(self) -> list[Wire]:
method set_count (line 99) | def set_count(self, count: int) -> None:
method blocks (line 108) | def blocks(self) -> list[Block]:
FILE: src/classy_blocks/grading/define/chop.py
class ChopRelation (line 10) | class ChopRelation:
method inputs (line 22) | def inputs(self) -> set[str]:
method from_function (line 27) | def from_function(cls, function: Callable):
method get_possible_combinations (line 42) | def get_possible_combinations() -> list["ChopRelation"]:
class ChopData (line 49) | class ChopData:
method get_specification (line 61) | def get_specification(self, invert: bool) -> GradingSpecType:
class Chop (line 69) | class Chop:
method defined_params (line 84) | def defined_params(self) -> int:
method __post_init__ (line 88) | def __post_init__(self):
method check (line 91) | def check(self):
method calculate (line 102) | def calculate(self, length: float) -> ChopData:
FILE: src/classy_blocks/grading/define/collector.py
class ChopCollector (line 6) | class ChopCollector:
method _prepare (line 7) | def _prepare(self) -> None:
method __init__ (line 13) | def __init__(self) -> None:
method chop_axis (line 16) | def chop_axis(self, direction: DirectionType, chop: Chop) -> None:
method chop_edge (line 19) | def chop_edge(self, corner_1: int, corner_2: int, chop: Chop) -> None:
method clear (line 29) | def clear(self) -> None:
method is_edge_chopped (line 33) | def is_edge_chopped(self) -> bool:
method __getitem__ (line 36) | def __getitem__(self, i: DirectionType):
FILE: src/classy_blocks/grading/define/grading.py
class GradingBase (line 51) | class GradingBase(abc.ABC):
method add_chop (line 59) | def add_chop(self, chop: Chop) -> None:
method clear (line 66) | def clear(self) -> None:
method chop_data (line 71) | def chop_data(self) -> list[ChopData]:
method get_specification (line 74) | def get_specification(self, inverted: bool) -> list[GradingSpecType]:
method specification (line 83) | def specification(self) -> list[GradingSpecType]:
method start_size (line 88) | def start_size(self) -> float:
method end_size (line 96) | def end_size(self) -> float:
method copy (line 103) | def copy(self, length: float, invert: bool = False) -> "Grading|Collap...
method count (line 141) | def count(self) -> int:
method is_defined (line 146) | def is_defined(self) -> bool:
method description (line 151) | def description(self) -> str:
class Grading (line 156) | class Grading(GradingBase):
method __init__ (line 157) | def __init__(self, length: float) -> None:
method chop_data (line 171) | def chop_data(self):
method add_chop (line 181) | def add_chop(self, chop: Chop):
method count (line 185) | def count(self):
method is_defined (line 189) | def is_defined(self):
method clear (line 192) | def clear(self) -> None:
method description (line 198) | def description(self):
method __eq__ (line 222) | def __eq__(self, other_grading):
method __repr__ (line 243) | def __repr__(self) -> str:
class CollapsedGrading (line 250) | class CollapsedGrading(GradingBase):
method __init__ (line 251) | def __init__(self) -> None:
method add_chop (line 257) | def add_chop(self, chop: Chop):
method chop_data (line 264) | def chop_data(self):
method count (line 268) | def count(self):
method is_defined (line 272) | def is_defined(self):
method clear (line 275) | def clear(self):
method description (line 279) | def description(self):
method __eq__ (line 282) | def __eq__(self, other):
method __repr__ (line 285) | def __repr__(self):
FILE: src/classy_blocks/grading/define/relations.py
function _validate_length (line 22) | def _validate_length(length) -> None:
function _validate_count (line 27) | def _validate_count(count: float, condition: str) -> None:
function _validate_start_end_size (line 53) | def _validate_start_end_size(size, name: str) -> None:
function _validate_c2c_expansion (line 58) | def _validate_c2c_expansion(c2c_expansion) -> None:
function _validate_total_expansion (line 63) | def _validate_total_expansion(expansion) -> None:
function get_start_size__count__c2c_expansion (line 69) | def get_start_size__count__c2c_expansion(length, count, c2c_expansion):
function get_start_size__end_size__total_expansion (line 80) | def get_start_size__end_size__total_expansion(length, end_size, total_ex...
function get_end_size__start_size__total_expansion (line 89) | def get_end_size__start_size__total_expansion(length, start_size, total_...
function get_count__start_size__c2c_expansion (line 97) | def get_count__start_size__c2c_expansion(length, start_size, c2c_expansi...
function get_count__end_size__c2c_expansion (line 111) | def get_count__end_size__c2c_expansion(length, end_size, c2c_expansion):
function get_count__total_expansion__c2c_expansion (line 128) | def get_count__total_expansion__c2c_expansion(length, total_expansion, c...
function get_count__total_expansion__start_size (line 143) | def get_count__total_expansion__start_size(length, total_expansion, star...
function get_c2c_expansion__count__start_size (line 166) | def get_c2c_expansion__count__start_size(length, count, start_size):
function get_c2c_expansion__count__end_size (line 195) | def get_c2c_expansion__count__end_size(length, count, end_size):
function get_c2c_expansion__count__total_expansion (line 220) | def get_c2c_expansion__count__total_expansion(length, count, total_expan...
function get_total_expansion__count__c2c_expansion (line 232) | def get_total_expansion__count__c2c_expansion(length, count, c2c_expansi...
function get_total_expansion__start_size__end_size (line 240) | def get_total_expansion__start_size__end_size(length, start_size, end_si...
function get_calculation_functions (line 249) | def get_calculation_functions() -> dict[str, Callable]:
FILE: src/classy_blocks/grading/graders/auto.py
class AutoGraderMixin (line 9) | class AutoGraderMixin(abc.ABC):
method _get_row_length (line 12) | def _get_row_length(self, row: Row) -> float:
FILE: src/classy_blocks/grading/graders/fixed.py
class FixedAxisGrader (line 11) | class FixedAxisGrader(AxisGrader):
method __init__ (line 12) | def __init__(self, block: Block, direction: DirectionType, count: int):
method get_chops (line 16) | def get_chops(self):
class FixedCountGrader (line 20) | class FixedCountGrader(GradingManager, AutoGraderMixin):
method __init__ (line 21) | def __init__(self, mesh: Mesh, count: int = 5):
method _grade_row (line 29) | def _grade_row(self, row: Row):
FILE: src/classy_blocks/grading/graders/inflation.py
function sum_length (line 19) | def sum_length(first_cell_size: float, count: int, c2c_expansion: float)...
class InflationParams (line 31) | class InflationParams:
method bl_thickness (line 42) | def bl_thickness(self) -> float:
method inflation_count (line 46) | def inflation_count(self) -> int:
method inflation_end_size (line 51) | def inflation_end_size(self) -> float:
method buffer_start_size (line 59) | def buffer_start_size(self) -> float:
method buffer_count (line 64) | def buffer_count(self) -> int:
method buffer_thickness (line 70) | def buffer_thickness(self) -> float:
class Layer (line 74) | class Layer(abc.ABC):
method _construct (line 86) | def _construct(
method __init__ (line 110) | def __init__(
method get_chop (line 117) | def get_chop(self):
method invert (line 127) | def invert(self) -> "Layer":
method copy (line 134) | def copy(self) -> "Layer":
method __repr__ (line 137) | def __repr__(self):
class InflationLayer (line 149) | class InflationLayer(Layer):
method __init__ (line 150) | def __init__(self, params: InflationParams, remaining_length: float):
class BufferLayer (line 156) | class BufferLayer(Layer):
method __init__ (line 157) | def __init__(self, params: InflationParams, remaining_length: float):
class BulkLayer (line 163) | class BulkLayer(Layer):
method __init__ (line 164) | def __init__(self, params: InflationParams, remaining_length: float):
method get_chop (line 169) | def get_chop(self):
class LayerStack (line 173) | class LayerStack:
method _normalize_ratios (line 176) | def _normalize_ratios(self):
method _construct (line 183) | def _construct(self) -> list[Layer]:
method __init__ (line 206) | def __init__(self, params: InflationParams, total_length: float):
method invert (line 213) | def invert(self) -> "LayerStack":
method mirror (line 221) | def mirror(self) -> "LayerStack":
method count (line 233) | def count(self) -> int:
method remaining_length (line 237) | def remaining_length(self) -> float:
class InflationAxisGrader (line 241) | class InflationAxisGrader(AxisGrader):
method __init__ (line 242) | def __init__(self, block: Block, direction: DirectionType, params: Inf...
method get_stack (line 247) | def get_stack(self) -> LayerStack:
method get_chops (line 250) | def get_chops(self) -> list[Chop]:
class InvertedInflationAxisGrader (line 255) | class InvertedInflationAxisGrader(InflationAxisGrader):
method get_stack (line 256) | def get_stack(self):
class DoubleInflationAxisGrader (line 263) | class DoubleInflationAxisGrader(InflationAxisGrader):
method get_stack (line 264) | def get_stack(self) -> LayerStack:
class BulkAxisGrader (line 271) | class BulkAxisGrader(FixedAxisGrader):
method __init__ (line 272) | def __init__(self, block: Block, direction: DirectionType, params: Inf...
class InflationGrader (line 276) | class InflationGrader(GradingManager, AutoGraderMixin):
method __init__ (line 307) | def __init__(
method _get_grader (line 328) | def _get_grader(self, row: Row) -> Union[type[InflationAxisGrader], ty...
method _grade_row (line 355) | def _grade_row(self, row: Row):
FILE: src/classy_blocks/grading/graders/manager.py
class WireGrader (line 17) | class WireGrader:
method __init__ (line 18) | def __init__(self, wire: Wire):
method copy (line 22) | def copy(from_wire: Wire, to_wire: Wire) -> None:
method assign (line 30) | def assign(self, grading: GradingBase) -> None:
method copy_to_coincidents (line 44) | def copy_to_coincidents(self, override: bool = False) -> None:
method re_chop (line 57) | def re_chop(self, chops: list[Chop]) -> None:
class AxisGrader (line 97) | class AxisGrader:
method __init__ (line 98) | def __init__(self, block: Block, direction: DirectionType):
method axis (line 103) | def axis(self) -> Axis:
method get_chops (line 106) | def get_chops(self) -> list[Chop]:
method grade (line 110) | def grade(self) -> int:
class RowGrader (line 146) | class RowGrader:
method __init__ (line 147) | def __init__(self, row: Row):
method grade (line 150) | def grade(self) -> None:
class GradingDistributor (line 159) | class GradingDistributor:
method __init__ (line 160) | def __init__(self, row: Row):
method undefined_axes (line 182) | def undefined_axes(self) -> set[Axis]:
method is_done (line 186) | def is_done(self) -> bool:
method _list_ungraded (line 189) | def _list_ungraded(self) -> str:
method _complete_axis (line 199) | def _complete_axis(self, axis: Axis) -> bool:
method _propagate_wires (line 216) | def _propagate_wires(self, axis: Axis) -> set[Axis]:
method distribute (line 231) | def distribute(self) -> None:
class GradingManager (line 257) | class GradingManager:
method __init__ (line 261) | def __init__(self, dump: AssembledDump, settings: Settings):
method _grade_row (line 264) | def _grade_row(self, row: Row) -> None:
method _grade_edges (line 268) | def _grade_edges(self, row: Row) -> None:
method _check_consistency (line 283) | def _check_consistency(self, row: Row) -> None:
method grade (line 306) | def grade(self):
FILE: src/classy_blocks/grading/graders/simple.py
class SimpleGrader (line 10) | class SimpleGrader(GradingManager, AutoGraderMixin):
method __init__ (line 11) | def __init__(self, mesh: Mesh, cell_size: float, take: ChopTakeType = ...
method _get_row_count (line 20) | def _get_row_count(self, row: Row):
method _grade_row (line 23) | def _grade_row(self, row: Row):
FILE: src/classy_blocks/items/block.py
class Block (line 13) | class Block:
method __init__ (line 16) | def __init__(self, index: int, vertices: list[Vertex]):
method add_edge (line 44) | def add_edge(self, corner_1: int, corner_2: int, edge: Edge):
method set_chops (line 53) | def set_chops(self, collector: ChopCollector) -> None:
method get_axis_wires (line 56) | def get_axis_wires(self, direction: DirectionType) -> list[Wire]:
method get_axis_direction (line 60) | def get_axis_direction(self, axis: Axis) -> DirectionType:
method add_neighbour (line 68) | def add_neighbour(self, candidate: "Block") -> None:
method update_wires (line 84) | def update_wires(self) -> None:
method wire_list (line 90) | def wire_list(self) -> list[Wire]:
method edge_list (line 96) | def edge_list(self) -> list[Edge]:
method is_graded (line 107) | def is_graded(self) -> bool:
method indexes (line 112) | def indexes(self) -> IndexType:
method get_side_vertices (line 115) | def get_side_vertices(self, orient: OrientType) -> list[Vertex]:
method __hash__ (line 118) | def __hash__(self) -> int:
method __repr__ (line 121) | def __repr__(self) -> str:
FILE: src/classy_blocks/items/edges/arcs/angle.py
function arc_from_theta (line 13) | def arc_from_theta(edge_point_1: PointType, edge_point_2: PointType, ang...
class AngleEdge (line 45) | class AngleEdge(ArcEdgeBase):
method third_point (line 51) | def third_point(self):
method description (line 57) | def description(self):
FILE: src/classy_blocks/items/edges/arcs/arc.py
class ArcEdge (line 8) | class ArcEdge(ArcEdgeBase):
method third_point (line 14) | def third_point(self):
FILE: src/classy_blocks/items/edges/arcs/arc_base.py
class ArcEdgeBase (line 14) | class ArcEdgeBase(Edge, abc.ABC):
method third_point (line 19) | def third_point(self) -> Point:
method length (line 23) | def length(self) -> float:
method description (line 30) | def description(self):
method is_valid (line 35) | def is_valid(self):
FILE: src/classy_blocks/items/edges/arcs/origin.py
function arc_from_origin (line 16) | def arc_from_origin(
class OriginEdge (line 81) | class OriginEdge(ArcEdgeBase):
method third_point (line 90) | def third_point(self):
method description (line 107) | def description(self):
FILE: src/classy_blocks/items/edges/curve.py
class CurveEdgeBase (line 13) | class CurveEdgeBase(Edge, abc.ABC):
method point_array (line 21) | def point_array(self) -> NPPointListType:
method param_start (line 25) | def param_start(self) -> float:
method param_end (line 29) | def param_end(self) -> float:
method description (line 33) | def description(self):
class SplineEdge (line 40) | class SplineEdge(CurveEdgeBase):
method point_array (line 46) | def point_array(self) -> NPPointListType:
method length (line 50) | def length(self):
class PolyLineEdge (line 57) | class PolyLineEdge(SplineEdge):
class OnCurveEdge (line 64) | class OnCurveEdge(CurveEdgeBase):
method length (line 70) | def length(self):
method param_start (line 74) | def param_start(self) -> float:
method param_end (line 79) | def param_end(self) -> float:
method point_array (line 84) | def point_array(self) -> NPPointListType:
method representation (line 88) | def representation(self) -> EdgeKindType:
FILE: src/classy_blocks/items/edges/edge.py
class Edge (line 15) | class Edge(ElementBase):
method __post_init__ (line 22) | def __post_init__(self):
method kind (line 30) | def kind(self) -> EdgeKindType:
method representation (line 35) | def representation(self) -> EdgeKindType:
method is_valid (line 40) | def is_valid(self) -> bool:
method length (line 57) | def length(self) -> float:
method description (line 63) | def description(self) -> str:
method center (line 71) | def center(self):
method parts (line 76) | def parts(self):
FILE: src/classy_blocks/items/edges/factory.py
class EdgeFactory (line 12) | class EdgeFactory:
method __init__ (line 16) | def __init__(self):
method register_kind (line 19) | def register_kind(self, kind: EdgeKindType, creator: type[Edge]) -> None:
method create (line 23) | def create(self, vertex_1, vertex_2, data: EdgeData) -> Edge:
FILE: src/classy_blocks/items/edges/line.py
class LineEdge (line 8) | class LineEdge(Edge):
method length (line 14) | def length(self):
method description (line 19) | def description(self):
method is_valid (line 24) | def is_valid(self):
FILE: src/classy_blocks/items/edges/project.py
class ProjectEdge (line 8) | class ProjectEdge(Edge):
method length (line 14) | def length(self):
method description (line 19) | def description(self):
FILE: src/classy_blocks/items/patch.py
class Patch (line 6) | class Patch:
method __init__ (line 9) | def __init__(self, name: str):
method add_side (line 19) | def add_side(self, side: Side) -> None:
FILE: src/classy_blocks/items/side.py
class Side (line 7) | class Side:
method __init__ (line 11) | def __init__(self, orient: OrientType, vertices: list[Vertex]):
method __eq__ (line 20) | def __eq__(self, other):
method __hash__ (line 23) | def __hash__(self):
FILE: src/classy_blocks/items/vertex.py
class Vertex (line 8) | class Vertex(Point):
method __init__ (line 12) | def __init__(self, position: PointType, index: int):
method __eq__ (line 18) | def __eq__(self, other):
method __hash__ (line 25) | def __hash__(self):
method __repr__ (line 28) | def __repr__(self):
method from_point (line 32) | def from_point(cls, point: Point, index: int):
FILE: src/classy_blocks/items/wires/axis.py
class Axis (line 7) | class Axis:
method __init__ (line 11) | def __init__(self, direction: DirectionType, wires: list[Wire]):
method add_neighbour (line 18) | def add_neighbour(self, other: "Axis") -> None:
method add_inline (line 26) | def add_inline(self, other: "Axis") -> None:
method is_aligned (line 35) | def is_aligned(self, other: "Axis") -> bool:
method is_inline (line 46) | def is_inline(self, other: "Axis") -> bool:
method lengths (line 72) | def lengths(self) -> list[float]:
method start_vertices (line 76) | def start_vertices(self) -> set[Vertex]:
method end_vertices (line 80) | def end_vertices(self) -> set[Vertex]:
method count (line 84) | def count(self) -> int:
method is_simple (line 88) | def is_simple(self) -> bool:
method is_graded (line 92) | def is_graded(self): # TODO: change to is_chopped
method __str__ (line 95) | def __str__(self):
method __hash__ (line 98) | def __hash__(self):
FILE: src/classy_blocks/items/wires/manager.py
class WireManager (line 5) | class WireManager:
method __init__ (line 6) | def __init__(self, wires: list[Wire]):
method __getitem__ (line 9) | def __getitem__(self, index) -> Wire:
method __iter__ (line 12) | def __iter__(self):
method format_single (line 15) | def format_single(self) -> str:
method format_all (line 19) | def format_all(self) -> str:
method length (line 24) | def length(self) -> float:
method is_simple (line 30) | def is_simple(self) -> bool:
method count (line 42) | def count(self):
FILE: src/classy_blocks/items/wires/wire.py
function get_length (line 13) | def get_length(wire: "Wire") -> float:
class WireJoint (line 18) | class WireJoint:
method __hash__ (line 25) | def __hash__(self):
class Wire (line 29) | class Wire:
method __init__ (line 33) | def __init__(self, vertices: list[Vertex], direction: DirectionType, c...
method length (line 56) | def length(self) -> float:
method update (line 59) | def update(self) -> None:
method is_coincident (line 63) | def is_coincident(self, candidate: "Wire") -> bool:
method is_aligned (line 68) | def is_aligned(self, candidate: "Wire") -> bool:
method add_edge (line 76) | def add_edge(self, edge: Edge) -> None:
method add_coincident (line 79) | def add_coincident(self, candidate: "Wire") -> None:
method add_inline (line 84) | def add_inline(self, candidate: "Wire") -> None:
method is_graded (line 103) | def is_graded(self) -> bool:
method is_collapsed (line 107) | def is_collapsed(self):
method __repr__ (line 110) | def __repr__(self):
FILE: src/classy_blocks/lists/block_list.py
class BlockList (line 5) | class BlockList:
method __init__ (line 8) | def __init__(self) -> None:
method add (line 11) | def add(self, block: Block) -> None:
method update_neighbours (line 15) | def update_neighbours(self, registry: HexPointRegistry) -> None:
method __hash__ (line 23) | def __hash__(self):
FILE: src/classy_blocks/lists/edge_list.py
function get_location (line 11) | def get_location(vertex_1, vertex_2):
class EdgeList (line 18) | class EdgeList:
method __init__ (line 21) | def __init__(self) -> None:
method find (line 24) | def find(self, vertex_1: Vertex, vertex_2: Vertex) -> Edge:
method add (line 32) | def add(self, vertex_1: Vertex, vertex_2: Vertex, data: EdgeData) -> E...
method add_from_operation (line 48) | def add_from_operation(self, vertices: list[Vertex], operation: Operat...
FILE: src/classy_blocks/lists/face_list.py
class ProjectedFace (line 12) | class ProjectedFace:
method __eq__ (line 18) | def __eq__(self, other):
class FaceList (line 22) | class FaceList:
method __init__ (line 25) | def __init__(self) -> None:
method find_existing (line 28) | def find_existing(self, side: Side) -> bool:
method add (line 36) | def add(self, vertices: list[Vertex], operation: Operation) -> None:
method add_face (line 49) | def add_face(self, vertices: list[Vertex], orient: OrientType, face: F...
method add_side (line 54) | def add_side(self, side: Side, label: str) -> None:
FILE: src/classy_blocks/lists/patch_list.py
class PatchList (line 12) | class PatchList:
method __init__ (line 15) | def __init__(self) -> None:
method add (line 20) | def add(self, vertices: list[Vertex], operation: Operation) -> None:
method get (line 25) | def get(self, name: str) -> Patch:
method find (line 32) | def find(self, vertices: set[Vertex]) -> Patch:
method add_side (line 41) | def add_side(self, patch_name: str, orient: OrientType, vertices: list...
method modify (line 45) | def modify(self, name: str, kind: str, settings: Optional[list[str]] =...
method merge (line 53) | def merge(self, master: str, slave: str) -> None:
FILE: src/classy_blocks/lists/vertex_list.py
class DuplicatedEntry (line 9) | class DuplicatedEntry:
method __init__ (line 13) | def __init__(self, vertex: Vertex, patches: set[str]):
method point (line 18) | def point(self) -> NPPointType:
class VertexList (line 23) | class VertexList:
method __init__ (line 26) | def __init__(self, vertices: list[Vertex]) -> None:
method find_duplicated (line 33) | def find_duplicated(self, position: NPPointType, slave_patches: set[st...
method add_duplicated (line 43) | def add_duplicated(self, point: Point, slave_patches: set[str]) -> Ver...
FILE: src/classy_blocks/lookup/cell_registry.py
class CellRegistry (line 5) | class CellRegistry:
method __init__ (line 7) | def __init__(self, addressing: list[IndexType]):
method get_near_cells (line 20) | def get_near_cells(self, point_index: int) -> set[int]:
FILE: src/classy_blocks/lookup/connection_registry.py
function get_key (line 9) | def get_key(index_1: int, index_2: int):
class Connection (line 13) | class Connection:
method __init__ (line 16) | def __init__(self, index_1: int, index_2: int):
method get_other_index (line 19) | def get_other_index(self, index):
method __repr__ (line 25) | def __repr__(self):
method __hash__ (line 28) | def __hash__(self):
class ConnectionRegistryBase (line 32) | class ConnectionRegistryBase:
method __init__ (line 35) | def __init__(self, points: NPPointListType, addressing: list[IndexType]):
method get_connected_indexes (line 56) | def get_connected_indexes(self, index: int) -> set[int]:
class QuadConnectionRegistry (line 60) | class QuadConnectionRegistry(ConnectionRegistryBase):
class HexConnectionRegistry (line 64) | class HexConnectionRegistry(ConnectionRegistryBase):
FILE: src/classy_blocks/lookup/face_registry.py
class FaceRegistryBase (line 8) | class FaceRegistryBase(abc.ABC):
method get_key_from_side (line 11) | def get_key_from_side(self, cell: int, side: OrientType) -> tuple:
method __init__ (line 18) | def __init__(self, addressing: list[IndexType]):
method get_cells (line 40) | def get_cells(self, cell: int, side: OrientType) -> set[int]:
class QuadFaceRegistry (line 44) | class QuadFaceRegistry(FaceRegistryBase):
class HexFaceRegistry (line 48) | class HexFaceRegistry(FaceRegistryBase):
FILE: src/classy_blocks/lookup/point_registry.py
class PointRegistryBase (line 16) | class PointRegistryBase:
method __init__ (line 21) | def __init__(self, flattened_points: NPPointListType, merge_tol: float...
method _compile_unique (line 38) | def _compile_unique(self) -> NPPointListType:
method _query_unique (line 53) | def _query_unique(self, positions) -> list[int]:
method _query_repeated (line 62) | def _query_repeated(self, positions) -> list[int]:
method find_point_index (line 70) | def find_point_index(self, position: PointType) -> int:
method find_point_cells (line 78) | def find_point_cells(self, position: PointType) -> list[int]:
method find_cell_points (line 84) | def find_cell_points(self, cell: int) -> NPPointListType:
method find_cell_indexes (line 90) | def find_cell_indexes(self, cell: int) -> list[int]:
method find_cell_neighbours (line 94) | def find_cell_neighbours(self, cell: int) -> list[int]:
method flatten (line 106) | def flatten(points, length) -> NPPointListType:
method from_addresses (line 110) | def from_addresses(
method cell_count (line 120) | def cell_count(self) -> int:
method point_count (line 124) | def point_count(self) -> int:
class QuadPointRegistry (line 128) | class QuadPointRegistry(PointRegistryBase):
method from_sketch (line 134) | def from_sketch(cls: type[PointRegistryType], sketch: Sketch, merge_to...
class HexPointRegistry (line 140) | class HexPointRegistry(PointRegistryBase):
method from_operations (line 146) | def from_operations(
FILE: src/classy_blocks/mesh.py
class Mesh (line 23) | class Mesh:
method __init__ (line 26) | def __init__(self) -> None:
method add (line 34) | def add(self, solid: AdditiveType) -> None:
method merge_patches (line 41) | def merge_patches(self, master: str, slave: str) -> None:
method set_default_patch (line 47) | def set_default_patch(self, name: str, kind: str) -> None:
method modify_patch (line 52) | def modify_patch(self, name: str, kind: str, settings: Optional[list[s...
method add_geometry (line 58) | def add_geometry(self, geometry: GeometryType) -> None:
method delete (line 65) | def delete(self, operation: Operation) -> None:
method assemble (line 70) | def assemble(self, merge_tol: float = TOL) -> AssembledDump:
method clear (line 83) | def clear(self) -> None:
method backport (line 88) | def backport(self) -> None:
method grade (line 112) | def grade(self) -> None:
method write (line 124) | def write(self, output_path: str, debug_path: Optional[str] = None, me...
method is_assembled (line 143) | def is_assembled(self) -> bool:
method vertices (line 148) | def vertices(self) -> list[Vertex]:
method patches (line 152) | def patches(self) -> list[Patch]:
method operations (line 156) | def operations(self) -> list[Operation]:
method blocks (line 161) | def blocks(self) -> list[Block]:
FILE: src/classy_blocks/modify/find/finder.py
class FinderBase (line 12) | class FinderBase:
method __init__ (line 15) | def __init__(self, mesh: Mesh):
method _find_by_position (line 18) | def _find_by_position(self, position: PointType, radius: Optional[floa...
FILE: src/classy_blocks/modify/find/geometric.py
class GeometricFinder (line 9) | class GeometricFinder(FinderBase):
method find_in_sphere (line 12) | def find_in_sphere(self, position: PointType, radius: Optional[float] ...
method find_in_box_corners (line 18) | def find_in_box_corners(self, corner_point: PointType, diagonal_point:...
method find_in_box_center (line 24) | def find_in_box_center(self, center_point: PointType, size_x: float, s...
method find_on_plane (line 30) | def find_on_plane(self, point: PointType, normal: VectorType):
FILE: src/classy_blocks/modify/find/shape.py
class RoundSolidFinder (line 10) | class RoundSolidFinder(FinderBase):
method __init__ (line 14) | def __init__(self, mesh: Mesh, shape: RoundSolidShape):
method _get_sketch (line 18) | def _get_sketch(self, end_face: bool) -> Disk:
method _find_from_points (line 24) | def _find_from_points(self, points: list[Point]) -> set[Vertex]:
method _find_from_faces (line 32) | def _find_from_faces(self, faces: list[Face]) -> set[Vertex]:
method find_core (line 40) | def find_core(self, end_face: bool = False) -> set[Vertex]:
method find_shell (line 46) | def find_shell(self, end_face: bool = False) -> set[Vertex]:
FILE: src/classy_blocks/modify/reorient/viewpoint.py
class Triangle (line 11) | class Triangle:
method __init__ (line 14) | def __init__(self, points: list[NPPointType]):
method normal (line 18) | def normal(self) -> NPVectorType:
method center (line 25) | def center(self) -> NPPointType:
method flip (line 28) | def flip(self):
method orient (line 32) | def orient(self, hull_center: NPPointType) -> None:
class Quadrangle (line 39) | class Quadrangle:
method __init__ (line 42) | def __init__(self, triangles: list[Triangle]):
method get_unique_points (line 57) | def get_unique_points(list_1: list[NPPointType], list_2: list[NPPointT...
method get_common_points (line 76) | def get_common_points(list_1: list[NPPointType], list_2: list[NPPointT...
method get_common_point (line 87) | def get_common_point(self, quad_1: "Quadrangle", quad_2: "Quadrangle")...
class ViewpointReorienter (line 98) | class ViewpointReorienter:
method __init__ (line 110) | def __init__(self, observer: PointType, ceiling: PointType):
method _make_triangles (line 114) | def _make_triangles(self, points: NPPointListType) -> list[Triangle]:
method _get_normals (line 130) | def _get_normals(self, center: NPPointType) -> dict[OrientType, NPVect...
method _get_aligned (line 150) | def _get_aligned(self, triangles: list[Triangle], vector: NPVectorType...
method reorient (line 153) | def reorient(self, operation: Operation):
FILE: src/classy_blocks/optimize/cell.py
class CellBase (line 10) | class CellBase(abc.ABC):
method __init__ (line 15) | def __init__(self, index: int, grid_points: NPPointListType, indexes: ...
method get_common_indexes (line 23) | def get_common_indexes(self, candidate: "CellBase") -> set[int]:
method get_corner (line 30) | def get_corner(self, index: int) -> int:
method get_common_side (line 35) | def get_common_side(self, candidate: "CellBase") -> OrientType:
method boundary (line 51) | def boundary(self) -> set[int]:
method __str__ (line 63) | def __str__(self):
method __repr__ (line 66) | def __repr__(self):
class QuadCell (line 70) | class QuadCell(CellBase):
class HexCell (line 77) | class HexCell(CellBase):
FILE: src/classy_blocks/optimize/clamps/clamp.py
class ClampBase (line 12) | class ClampBase(abc.ABC):
method __init__ (line 15) | def __init__(
method initial_guess (line 31) | def initial_guess(self) -> list[float]:
method get_params (line 34) | def get_params(self) -> list[float]:
method update_params (line 44) | def update_params(self, params: list[float]):
FILE: src/classy_blocks/optimize/clamps/curve.py
class CurveClamp (line 11) | class CurveClamp(ClampBase):
method __init__ (line 20) | def __init__(
method initial_guess (line 36) | def initial_guess(self):
class LineClamp (line 40) | class LineClamp(ClampBase):
method __init__ (line 48) | def __init__(
method initial_guess (line 64) | def initial_guess(self) -> list[float]:
class RadialClamp (line 70) | class RadialClamp(ClampBase):
method __init__ (line 78) | def __init__(
method initial_guess (line 100) | def initial_guess(self):
FILE: src/classy_blocks/optimize/clamps/free.py
class FreeClamp (line 7) | class FreeClamp(ClampBase):
method __init__ (line 8) | def __init__(self, position: PointType):
method get_params_from_vertex (line 11) | def get_params_from_vertex(self):
method initial_guess (line 17) | def initial_guess(self):
FILE: src/classy_blocks/optimize/clamps/surface.py
class PlaneClamp (line 9) | class PlaneClamp(ClampBase):
method __init__ (line 15) | def __init__(self, position: PointType, point: PointType, normal: Vect...
method initial_guess (line 31) | def initial_guess(self):
class ParametricSurfaceClamp (line 35) | class ParametricSurfaceClamp(ClampBase):
method initial_guess (line 44) | def initial_guess(self):
FILE: src/classy_blocks/optimize/connection.py
class CellConnection (line 5) | class CellConnection:
FILE: src/classy_blocks/optimize/grid.py
class GridBase (line 31) | class GridBase:
method __init__ (line 38) | def __init__(self, points: NPPointListType, addressing: list[IndexType]):
method _bind_junction_neighbours (line 51) | def _bind_junction_neighbours(self) -> None:
method _bind_cell_neighbours (line 59) | def _bind_cell_neighbours(self) -> None:
method _bind_junction_cells (line 71) | def _bind_junction_cells(self) -> None:
method get_junction_from_clamp (line 79) | def get_junction_from_clamp(self, clamp: ClampBase) -> Junction:
method add_clamp (line 86) | def add_clamp(self, clamp: ClampBase) -> None:
method add_link (line 94) | def add_link(self, link: LinkBase) -> None:
method clamps (line 117) | def clamps(self) -> list[ClampBase]:
method quality (line 127) | def quality(self) -> float:
method update (line 133) | def update(self, index: int, position: NPPointType) -> float:
class QuadGrid (line 157) | class QuadGrid(GridBase):
method from_sketch (line 163) | def from_sketch(cls, sketch: Sketch, merge_tol: float = TOL) -> "QuadG...
class HexGrid (line 174) | class HexGrid(GridBase):
method from_elements (line 180) | def from_elements(
method from_dump (line 198) | def from_dump(cls, dump: AssembledDump) -> "HexGrid":
FILE: src/classy_blocks/optimize/junction.py
class LinkTie (line 15) | class LinkTie:
class Junction (line 20) | class Junction:
method __init__ (line 24) | def __init__(self, points: NPPointListType, index: int):
method point (line 36) | def point(self) -> NPPointType:
method add_clamp (line 39) | def add_clamp(self, clamp: ClampBase) -> None:
method add_link (line 45) | def add_link(self, link: LinkBase, follower_index: int) -> None:
method is_boundary (line 49) | def is_boundary(self) -> bool:
method quality (line 58) | def quality(self) -> float:
FILE: src/classy_blocks/optimize/links.py
class LinkBase (line 10) | class LinkBase(abc.ABC):
method __init__ (line 15) | def __init__(self, leader: PointType, follower: PointType):
method update (line 19) | def update(self) -> None:
method transform (line 24) | def transform(self) -> NPPointType:
method __str__ (line 28) | def __str__(self):
class TranslationLink (line 32) | class TranslationLink(LinkBase):
method __init__ (line 36) | def __init__(self, leader: PointType, follower: PointType):
method transform (line 40) | def transform(self) -> NPPointType:
class RotationLink (line 44) | class RotationLink(LinkBase):
method __init__ (line 52) | def __init__(self, leader: PointType, follower: PointType, axis: Vecto...
method transform (line 64) | def transform(self) -> NPPointType:
method _get_height (line 76) | def _get_height(self, point: NPPointType) -> NPVectorType:
method _get_radius (line 80) | def _get_radius(self, point: NPPointType) -> NPVectorType:
class SymmetryLink (line 85) | class SymmetryLink(LinkBase):
method __init__ (line 88) | def __init__(self, leader: PointType, follower: PointType, normal: Vec...
method _get_follower (line 94) | def _get_follower(self) -> NPPointType:
method transform (line 97) | def transform(self) -> NPPointType:
FILE: src/classy_blocks/optimize/optimizer.py
class OptimizerConfig (line 31) | class OptimizerConfig:
class OptimizerBase (line 60) | class OptimizerBase(abc.ABC):
method __init__ (line 65) | def __init__(self, grid: GridBase, report: bool = True):
method add_clamp (line 76) | def add_clamp(self, clamp: ClampBase) -> None:
method add_link (line 80) | def add_link(self, link: LinkBase) -> None:
method _get_sensitivity (line 83) | def _get_sensitivity(self, clamp: ClampBase):
method _optimize_clamp (line 102) | def _optimize_clamp(self, clamp: ClampBase, relaxation_factor: float) ...
method _optimize_iteration (line 152) | def _optimize_iteration(self, iteration_no: int) -> IterationRecord:
method relaxation_factor (line 166) | def relaxation_factor(self, iteration_no: int) -> float:
method optimize (line 187) | def optimize(
method _backport (line 235) | def _backport(self) -> None:
class MeshOptimizer (line 239) | class MeshOptimizer(OptimizerBase):
method __init__ (line 240) | def __init__(self, mesh: Mesh, report: bool = True, merge_tol: float =...
method _backport (line 247) | def _backport(self):
class ShapeOptimizer (line 253) | class ShapeOptimizer(OptimizerBase):
method __init__ (line 254) | def __init__(self, operations: list[Operation], report: bool = True, m...
method _backport (line 260) | def _backport(self) -> None:
class SketchOptimizer (line 269) | class SketchOptimizer(OptimizerBase):
method __init__ (line 270) | def __init__(self, sketch: Sketch, report: bool = True, merge_tol: flo...
method _backport (line 277) | def _backport(self):
method auto_optimize (line 289) | def auto_optimize(
FILE: src/classy_blocks/optimize/quality.py
function scale_quality (line 12) | def scale_quality(base: float, exponent: float, factor: float, value: fl...
function scale_aspect (line 17) | def scale_aspect(ratio: float) -> float:
function take (line 22) | def take(points: NPPointListType, indexes: NPIndexType):
function get_center_point (line 35) | def get_center_point(points: NPPointListType) -> NPPointType:
function get_quad_normal (line 40) | def get_quad_normal(points: NPPointListType) -> tuple[NPVectorType, NPVe...
function scale_angle (line 65) | def scale_angle(angle: float) -> float:
function get_quad_non_ortho (line 78) | def get_quad_non_ortho(points: NPPointListType, center: NPPointType, nor...
function get_quad_inner_angle (line 98) | def get_quad_inner_angle(points: NPPointListType, normal: NPVectorType, ...
function get_quad_quality (line 114) | def get_quad_quality(grid_points: NPPointListType, cell_indexes: NPIndex...
function get_hex_quality (line 132) | def get_hex_quality(grid_points: NPPointListType, cell_indexes: NPIndexT...
FILE: src/classy_blocks/optimize/record.py
class OptimizationRecord (line 10) | class OptimizationRecord:
method abs_improvement (line 18) | def abs_improvement(self) -> float:
method rel_improvement (line 22) | def rel_improvement(self) -> float:
class IterationRecord (line 27) | class IterationRecord:
method abs_improvement (line 34) | def abs_improvement(self) -> float:
method rel_improvement (line 38) | def rel_improvement(self) -> float:
class ClampRecord (line 43) | class ClampRecord:
method improvement (line 52) | def improvement(self) -> float:
FILE: src/classy_blocks/optimize/report.py
class OptimizationReporterBase (line 7) | class OptimizationReporterBase(abc.ABC):
method iteration_start (line 9) | def iteration_start(self, iteration_no: int, relaxation: float) -> None:
method clamp_start (line 13) | def clamp_start(self, crecord: ClampRecord) -> None:
method clamp_end (line 17) | def clamp_end(self, crecord: ClampRecord) -> None:
method iteration_end (line 21) | def iteration_end(self, srecord: IterationRecord) -> None:
method optimization_end (line 25) | def optimization_end(self, orecord: OptimizationRecord) -> None:
class SilentReporter (line 29) | class SilentReporter(OptimizationReporterBase):
method iteration_start (line 30) | def iteration_start(self, iteration_no: int, relaxation: float) -> None:
method clamp_start (line 33) | def clamp_start(self, crecord: ClampRecord) -> None:
method clamp_end (line 36) | def clamp_end(self, crecord: ClampRecord) -> None:
method iteration_end (line 39) | def iteration_end(self, srecord: IterationRecord) -> None:
method optimization_end (line 42) | def optimization_end(self, orecord: OptimizationRecord) -> None:
class TextReporter (line 46) | class TextReporter(OptimizationReporterBase):
method iteration_start (line 47) | def iteration_start(self, iteration_no: int, relaxation: float) -> None:
method clamp_start (line 56) | def clamp_start(self, crecord: ClampRecord) -> None:
method clamp_end (line 60) | def clamp_end(self, crecord: ClampRecord) -> None:
method iteration_end (line 69) | def iteration_end(self, srecord: IterationRecord) -> None:
method optimization_end (line 74) | def optimization_end(self, orecord: OptimizationRecord) -> None:
FILE: src/classy_blocks/optimize/smoother.py
class SmootherBase (line 15) | class SmootherBase(abc.ABC):
method __init__ (line 16) | def __init__(self, grid: GridBase):
method fix_indexes (line 26) | def fix_indexes(self, indexes: Iterable[int]) -> None:
method fix_points (line 29) | def fix_points(self, points: PointListType):
method smooth (line 35) | def smooth(self, iterations: int = 5) -> None:
method backport (line 47) | def backport(self) -> None:
class MeshSmoother (line 51) | class MeshSmoother(SmootherBase):
method __init__ (line 52) | def __init__(self, mesh: Mesh, merge_tol: float = TOL):
method backport (line 57) | def backport(self):
class SketchSmoother (line 62) | class SketchSmoother(SmootherBase):
method __init__ (line 63) | def __init__(self, sketch: MappedSketch):
method backport (line 70) | def backport(self):
FILE: src/classy_blocks/util/constants.py
function vector_format (line 55) | def vector_format(vector) -> str:
FILE: src/classy_blocks/util/frame.py
class Frame (line 9) | class Frame(Generic[BeamT]):
method __init__ (line 27) | def __init__(self) -> None:
method add_beam (line 35) | def add_beam(self, corner_1: int, corner_2: int, beam: Optional[BeamT]...
method get_axis_beams (line 46) | def get_axis_beams(self, axis: DirectionType) -> list[BeamT]:
method get_all_beams (line 58) | def get_all_beams(self) -> list[tuple[int, int, BeamT]]:
method __getitem__ (line 75) | def __getitem__(self, index):
FILE: src/classy_blocks/util/functions.py
function vector (line 15) | def vector(x: float, y: float, z: float) -> NPVectorType:
function deg2rad (line 21) | def deg2rad(deg: float) -> float:
function rad2deg (line 26) | def rad2deg(rad: float) -> float:
function norm (line 31) | def norm(matrix: Union[PointType, PointListType]) -> float:
function unit_vector (line 40) | def unit_vector(vect: VectorType) -> NPVectorType:
function angle_between (line 46) | def angle_between(vect_1: VectorType, vect_2: VectorType) -> float:
function _rotation_matrix (line 65) | def _rotation_matrix(axis: NPVectorType, angle: float):
function rotation_matrix (line 81) | def rotation_matrix(axis: VectorType, angle: float):
function _rotate (line 91) | def _rotate(point: NPPointType, angle: float, axis: NPVectorType, origin...
function rotate (line 100) | def rotate(point: PointType, angle: float, axis: VectorType, origin: Poi...
function scale (line 109) | def scale(point: PointType, ratio: float, origin: Optional[PointType]) -...
function to_polar (line 118) | def to_polar(point: PointType, axis: Literal["x", "z"] = "z") -> NPVecto...
function to_cartesian (line 136) | def to_cartesian(point: PointType, direction: Literal[1, -1] = 1, axis: ...
function lin_map (line 161) | def lin_map(x: float, x_min: float, x_max: float, out_min: float, out_ma...
function arc_length_3point (line 173) | def arc_length_3point(p_start: NPPointType, p_btw: NPPointType, p_end: N...
function divide_arc (line 217) | def divide_arc(center: NPPointType, point_1: NPPointType, point_2: NPPoi...
function arc_mid (line 233) | def arc_mid(center: NPPointType, point_1: NPPointType, point_2: NPPointT...
function mirror (line 238) | def mirror(points: Union[PointType, PointListType], normal: VectorType, ...
function point_to_plane_distance (line 274) | def point_to_plane_distance(origin: PointType, normal: VectorType, point...
function is_point_on_plane (line 286) | def is_point_on_plane(origin: PointType, normal: VectorType, point: Poin...
function point_to_line_distance (line 291) | def point_to_line_distance(origin: PointType, direction: VectorType, poi...
function polyline_length (line 300) | def polyline_length(points: NPPointListType) -> float:
function flatten_2d_list (line 311) | def flatten_2d_list(twodim: list[list]) -> list:
FILE: src/classy_blocks/util/tools.py
function report (line 12) | def report(text, end=None):
class EdgeLocation (line 21) | class EdgeLocation:
method start_corner (line 30) | def start_corner(self) -> int:
FILE: src/classy_blocks/write/formats.py
function indent (line 9) | def indent(text: str, levels: int) -> str:
function format_vertex (line 14) | def format_vertex(vertex: Vertex) -> str:
function format_block (line 25) | def format_block(block: Block) -> str:
function format_edge (line 56) | def format_edge(edge: Edge) -> str:
function format_side (line 60) | def format_side(side: Side) -> str:
function format_patch (line 64) | def format_patch(patch: Patch) -> str:
function format_face (line 92) | def format_face(face: ProjectedFace) -> str:
FILE: src/classy_blocks/write/vtk.py
function mesh_to_vtk (line 7) | def mesh_to_vtk(path: str, vertices: list[Vertex], blocks: list[Block]) ...
function sketch_to_vtk (line 102) | def sketch_to_vtk(sketch: Sketch, filename: str) -> None:
FILE: src/classy_blocks/write/writer.py
function format_geometry (line 13) | def format_geometry(geometry: GeometryType) -> str:
function format_list (line 33) | def format_list(name: str, items: list, formatter: Callable) -> str:
function format_settings (line 44) | def format_settings(settings: Settings):
class MeshWriter (line 74) | class MeshWriter:
method __init__ (line 75) | def __init__(self, dump: AssembledDump, settings: Settings):
method write (line 79) | def write(self, output_path: str):
FILE: tests/fixtures/block.py
class BlockTestCase (line 13) | class BlockTestCase(DataTestCase):
method make_vertices (line 16) | def make_vertices(self, index: int) -> list[Vertex]:
method make_block (line 24) | def make_block(self, index: int) -> Block:
method make_loft (line 48) | def make_loft(self, index: int) -> Loft:
FILE: tests/fixtures/data.py
class TestOperationData (line 62) | class TestOperationData:
method points (line 82) | def points(self):
method indexes (line 87) | def indexes(self):
class DataTestCase (line 134) | class DataTestCase(unittest.TestCase):
method get_single_data (line 138) | def get_single_data(index: int) -> TestOperationData:
method get_all_data (line 143) | def get_all_data() -> list[TestOperationData]:
FILE: tests/fixtures/mesh.py
class MeshTestCase (line 9) | class MeshTestCase(DataTestCase):
method make_box (line 12) | def make_box(self, index):
method setUp (line 22) | def setUp(self):
FILE: tests/helpers/collect_outputs.py
function collect_dict (line 18) | def collect_dict(path):
FILE: tests/test_assemble.py
class RegistryTests (line 14) | class RegistryTests(unittest.TestCase):
method get_shape (line 15) | def get_shape(self) -> Cylinder:
method get_hex_point_registry (line 18) | def get_hex_point_registry(self) -> HexPointRegistry:
method test_find_point_index (line 33) | def test_find_point_index(self, point, index):
method test_connection (line 39) | def test_connection(self):
method test_junction (line 52) | def test_junction(self, point_index, neighbour_count):
method test_face_registry (line 71) | def test_face_registry(self, cell, side, indexes):
method test_cell_registry (line 89) | def test_cell_registry(self, point, cells) -> None:
FILE: tests/test_bugs/test_grading.py
class GradingBugTests (line 11) | class GradingBugTests(unittest.TestCase):
method test_invert_grading (line 12) | def test_invert_grading(self):
FILE: tests/test_construct/test_assembly.py
class AssemblyTests (line 12) | class AssemblyTests(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method fanout (line 18) | def fanout(self, count: int) -> NPPointListType:
method get_joint_points (line 23) | def get_joint_points(self, joint: JointBase) -> NPPointListType:
method test_t_joint (line 32) | def test_t_joint(self):
method test_l_joint (line 40) | def test_l_joint(self):
method test_n_joint (line 49) | def test_n_joint(self, branches):
method test_operations (line 57) | def test_operations(self):
method test_center (line 62) | def test_center(self):
method test_chop (line 67) | def test_chop(self):
method test_set_patches (line 82) | def test_set_patches(self):
FILE: tests/test_construct/test_chaining.py
class ElbowChainingTests (line 21) | class ElbowChainingTests(unittest.TestCase):
method setUp (line 24) | def setUp(self):
method check_success (line 37) | def check_success(self, chained_shape, end_center):
method test_to_elbow_end (line 50) | def test_to_elbow_end(self):
method test_chain_on_invalid_start_face (line 63) | def test_chain_on_invalid_start_face(self):
method test_to_elbow_start (line 70) | def test_to_elbow_start(self):
method test_to_cylinder_start (line 75) | def test_to_cylinder_start(self):
method test_to_cylinder_end (line 80) | def test_to_cylinder_end(self):
method test_to_cylinder_negative (line 85) | def test_to_cylinder_negative(self):
method test_chain_frustum_invalid_length (line 90) | def test_chain_frustum_invalid_length(self):
method test_to_frustum_start (line 94) | def test_to_frustum_start(self):
method test_to_frustum_end (line 98) | def test_to_frustum_end(self):
method test_to_sphere_end (line 102) | def test_to_sphere_end(self):
method test_to_sphere_start (line 106) | def test_to_sphere_start(self):
class RingChainingTests (line 111) | class RingChainingTests(unittest.TestCase):
method setUp (line 114) | def setUp(self):
method check_success (line 125) | def check_success(self, chained_shape, end_center):
method test_chain_invalid_length (line 138) | def test_chain_invalid_length(self):
method test_chain_end (line 142) | def test_chain_end(self):
method test_chain_start (line 147) | def test_chain_start(self):
class ExpandContractTests (line 153) | class ExpandContractTests(unittest.TestCase):
method setUp (line 156) | def setUp(self):
method check_success (line 159) | def check_success(self, shape_1, shape_2, n_blocks, n_vertices):
method test_expand_cylinder (line 167) | def test_expand_cylinder(self):
method test_expand_ring (line 174) | def test_expand_ring(self):
method test_contract_ring_invalid_radius (line 181) | def test_contract_ring_invalid_radius(self):
method test_contract_ring_zero_radius (line 186) | def test_contract_ring_zero_radius(self):
method test_contract_ring (line 191) | def test_contract_ring(self):
method test_fill_assert (line 197) | def test_fill_assert(self):
method test_fill (line 202) | def test_fill(self):
FILE: tests/test_construct/test_curves/test_analytic.py
class AnalyticCurveTests (line 13) | class AnalyticCurveTests(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_arc_length_halfcircle (line 25) | def test_arc_length_halfcircle(self):
method test_arc_length_quartercircle (line 29) | def test_arc_length_quartercircle(self):
method test_length_property (line 32) | def test_length_property(self):
method test_closest_param (line 42) | def test_closest_param(self, position, param):
method test_discretize (line 45) | def test_discretize(self):
method test_transform (line 53) | def test_transform(self):
method test_tangent (line 65) | def test_tangent(self, param, tangent):
method test_normal (line 75) | def test_normal(self, param, normal):
method test_binormal (line 85) | def test_binormal(self, param):
class LineCurveTests (line 89) | class LineCurveTests(unittest.TestCase):
method setUp (line 90) | def setUp(self):
method curve (line 97) | def curve(self) -> LineCurve:
method test_init (line 100) | def test_init(self):
method test_values_within_bounds (line 110) | def test_values_within_bounds(self, param, value):
method test_values_outside_bounds (line 119) | def test_values_outside_bounds(self, param):
method test_translate (line 123) | def test_translate(self):
method test_rotate (line 129) | def test_rotate(self):
method test_scale (line 135) | def test_scale(self):
method test_scale_nocenter (line 141) | def test_scale_nocenter(self):
method test_center (line 147) | def test_center(self):
method test_get_param_at_length (line 150) | def test_get_param_at_length(self):
class CircleCurveTests (line 154) | class CircleCurveTests(unittest.TestCase):
method setUp (line 155) | def setUp(self):
method curve (line 163) | def curve(self) -> CircleCurve:
method test_circle_points (line 167) | def test_circle_points(self, param, point):
method test_translate (line 170) | def test_translate(self):
method test_rotate (line 176) | def test_rotate(self):
method test_scale (line 182) | def test_scale(self):
FILE: tests/test_construct/test_curves/test_discrete.py
class DiscreteCurveTests (line 10) | class DiscreteCurveTests(unittest.TestCase):
method setUp (line 11) | def setUp(self):
method curve (line 21) | def curve(self) -> DiscreteCurve:
method test_single_point (line 24) | def test_single_point(self):
method test_wrong_shape (line 29) | def test_wrong_shape(self):
method test_discretize_wrong_params (line 35) | def test_discretize_wrong_params(self, param_from, param_to):
method test_discretize (line 40) | def test_discretize(self):
method test_discretize_partial (line 44) | def test_discretize_partial(self):
method test_discretize_inverted (line 48) | def test_discretize_inverted(self):
method test_length (line 55) | def test_length(self):
method test_get_length (line 65) | def test_get_length(self, param_from, param_to):
method test_get_closest_param (line 79) | def test_get_closest_param(self, point, index):
method test_translate (line 82) | def test_translate(self):
method test_center (line 89) | def test_center(self):
method test_scale (line 92) | def test_scale(self):
FILE: tests/test_construct/test_curves/test_interpolated.py
class LinearInterpolatedCurveTests (line 9) | class LinearInterpolatedCurveTests(unittest.TestCase):
method setUp (line 10) | def setUp(self):
method curve (line 21) | def curve(self) -> LinearInterpolatedCurve:
method test_discretize (line 24) | def test_discretize(self):
method test_get_length (line 37) | def test_get_length(self, param_from, param_to):
method test_length (line 41) | def test_length(self):
method test_get_point (line 44) | def test_get_point(self):
method test_get_closest_param (line 58) | def test_get_closest_param(self, point, param):
method test_transform (line 61) | def test_transform(self):
method test_param_at_length (line 68) | def test_param_at_length(self):
method test_shear (line 71) | def test_shear(self):
class SplineInterpolatedCurveTests (line 87) | class SplineInterpolatedCurveTests(unittest.TestCase):
method setUp (line 88) | def setUp(self):
method curve (line 101) | def curve(self) -> SplineInterpolatedCurve:
method test_length (line 104) | def test_length(self):
method test_through_points (line 118) | def test_through_points(self, param):
method test_transform (line 123) | def test_transform(self):
method test_center_warning (line 130) | def test_center_warning(self):
method test_interpolation_values_line (line 145) | def test_interpolation_values_line(self, param):
method test_get_param_at (line 156) | def test_get_param_at(self):
FILE: tests/test_construct/test_curves/test_interpolators.py
class LinearInterpolatorTests (line 10) | class LinearInterpolatorTests(unittest.TestCase):
method setUp (line 11) | def setUp(self):
method test_points (line 31) | def test_points(self, param, result):
method test_extrapolate_exception (line 36) | def test_extrapolate_exception(self):
FILE: tests/test_construct/test_edge_data.py
class EdgeDataTests (line 12) | class EdgeDataTests(unittest.TestCase):
method test_line_create (line 15) | def test_line_create(self):
method test_arc_transform (line 19) | def test_arc_transform(self):
method test_origin_transform (line 26) | def test_origin_transform(self):
method test_angle_scale (line 33) | def test_angle_scale(self):
method test_angle_translate (line 41) | def test_angle_translate(self):
method test_angle_rotate (line 48) | def test_angle_rotate(self):
method test_spline_transform (line 55) | def test_spline_transform(self):
method test_project_create_single (line 64) | def test_project_create_single(self):
method test_project_create_double (line 70) | def test_project_create_double(self):
method test_project_create_multiple (line 76) | def test_project_create_multiple(self):
method test_add_same (line 81) | def test_add_same(self):
method test_add_different_single (line 88) | def test_add_different_single(self):
method test_add_different_list (line 95) | def test_add_different_list(self):
method test_add_too_many (line 102) | def test_add_too_many(self):
method test_default_transform (line 109) | def test_default_transform(self):
method test_default_repr (line 117) | def test_default_repr(self):
class CurveEdgeTests (line 121) | class CurveEdgeTests(unittest.TestCase):
method points (line 123) | def points(self):
method curve (line 134) | def curve(self) -> DiscreteCurve:
method test_on_curve_translate (line 137) | def test_on_curve_translate(self):
method test_on_curve_rotate (line 143) | def test_on_curve_rotate(self):
method test_on_curve_rotate_nocenter (line 151) | def test_on_curve_rotate_nocenter(self):
method test_spline_repr (line 161) | def test_spline_repr(self):
method test_polyline_repr (line 166) | def test_polyline_repr(self):
method test_spline_center (line 171) | def test_spline_center(self):
FILE: tests/test_construct/test_flat/test_annulus.py
class AnnulusTests (line 10) | class AnnulusTests(unittest.TestCase):
method test_invalid_inner_radius (line 13) | def test_invalid_inner_radius(self):
method test_coplanar_assert (line 17) | def test_coplanar_assert(self):
method test_center (line 24) | def test_center(self, n_segments):
FILE: tests/test_construct/test_flat/test_disk.py
class QuarterDiskTests (line 16) | class QuarterDiskTests(unittest.TestCase):
method qdisk (line 18) | def qdisk(self):
method assert_coincident (line 21) | def assert_coincident(self, qdisk: QuarterDisk):
method test_quarter_translate (line 36) | def test_quarter_translate(self):
method test_quarter_rotate (line 42) | def test_quarter_rotate(self):
method test_quarter_scale_origin (line 48) | def test_quarter_scale_origin(self):
method test_quarter_scale_origin_default (line 55) | def test_quarter_scale_origin_default(self):
method test_quarter_combined (line 62) | def test_quarter_combined(self):
method test_face (line 71) | def test_face(self, i_face):
method test_points_keys (line 81) | def test_points_keys(self):
method test_point_position (line 98) | def test_point_position(self, key, position):
class DisksTests (line 106) | class DisksTests(unittest.TestCase):
method test_one_core_disk (line 107) | def test_one_core_disk(self):
method test_one_core_disk_origo (line 113) | def test_one_core_disk_origo(self):
method test_one_core__disk_edges (line 118) | def test_one_core__disk_edges(self):
method test_half_disk (line 128) | def test_half_disk(self):
method test_wrapped_disk (line 134) | def test_wrapped_disk(self):
method test_wrapped_disk_edges (line 141) | def test_wrapped_disk_edges(self):
class OvalTests (line 152) | class OvalTests(unittest.TestCase):
method oval (line 154) | def oval(self) -> Oval:
method test_construct (line 161) | def test_construct(self):
method test_planar (line 164) | def test_planar(self):
method test_centers (line 169) | def test_centers(self):
method test_grid (line 174) | def test_grid(self):
class ChopTests (line 181) | class ChopTests(unittest.TestCase):
method setUp (line 182) | def setUp(self):
method test_one_core_disk (line 185) | def test_one_core_disk(self):
FILE: tests/test_construct/test_flat/test_face.py
class FaceTests (line 13) | class FaceTests(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_face_too_few_points (line 17) | def test_face_too_few_points(self):
method test_face_invalid_points (line 22) | def test_face_invalid_points(self):
method test_face_center (line 27) | def test_face_center(self):
method test_reverse (line 31) | def test_reverse(self):
method test_translate_face (line 40) | def test_translate_face(self):
method test_rotate_face_center (line 66) | def test_rotate_face_center(self):
method test_rotate_face_custom_origin (line 84) | def test_rotate_face_custom_origin(self):
method test_rotate_default_origin (line 102) | def test_rotate_default_origin(self):
method test_scale_face_center (line 114) | def test_scale_face_center(self):
method test_scale_face_custom_origin (line 123) | def test_scale_face_custom_origin(self):
method test_scale_face_edges (line 131) | def test_scale_face_edges(self):
method test_add_edge (line 138) | def test_add_edge(self):
method test_replace_edge (line 148) | def test_replace_edge(self):
method test_reorient_indexes (line 155) | def test_reorient_indexes(self):
method test_reorient_normal (line 165) | def test_reorient_normal(self):
method test_update (line 174) | def test_update(self):
method test_wrong_edge_count (line 182) | def test_wrong_edge_count(self):
method test_check_coplanar_raise (line 186) | def test_check_coplanar_raise(self):
method test_remove_edge (line 193) | def test_remove_edge(self):
method test_remove_edges (line 203) | def test_remove_edges(self):
method test_shear (line 214) | def test_shear(self):
FILE: tests/test_construct/test_flat/test_sketch.py
class MappedSketchTests (line 9) | class MappedSketchTests(unittest.TestCase):
method positions (line 11) | def positions(self):
method quads (line 25) | def quads(self):
method sketch (line 34) | def sketch(self):
method test_faces (line 37) | def test_faces(self):
method test_grid (line 40) | def test_grid(self):
method test_update (line 43) | def test_update(self):
method test_merge (line 52) | def test_merge(self):
class GridSketchTests (line 68) | class GridSketchTests(unittest.TestCase):
method test_construct (line 69) | def test_construct(self):
method test_center (line 74) | def test_center(self):
FILE: tests/test_construct/test_operation/test_box.py
class BoxTests (line 9) | class BoxTests(unittest.TestCase):
method test_create_box (line 24) | def test_create_box(self, diagonal_point):
FILE: tests/test_construct/test_operation/test_connector.py
class ConnectorTests (line 9) | class ConnectorTests(unittest.TestCase):
method setUp (line 10) | def setUp(self):
method test_create_normal (line 18) | def test_create_normal(self):
method test_create_inverted (line 21) | def test_create_inverted(self):
method test_direction (line 24) | def test_direction(self):
method test_direction_inverted (line 32) | def test_direction_inverted(self):
FILE: tests/test_construct/test_operation/test_extrude.py
class ExtrudeTests (line 11) | class ExtrudeTests(unittest.TestCase):
method setUp (line 12) | def setUp(self):
method face (line 19) | def face(self) -> Face:
method extrude (line 23) | def extrude(self) -> Extrude:
method test_extrude_box (line 26) | def test_extrude_box(self):
method test_extrude_slanted (line 35) | def test_extrude_slanted(self):
method test_extrude_edges (line 46) | def test_extrude_edges(self):
method test_extrude_amount (line 59) | def test_extrude_amount(self):
FILE: tests/test_construct/test_operation/test_operation.py
class OperationTests (line 16) | class OperationTests(BlockTestCase):
method setUp (line 19) | def setUp(self):
method test_add_side_edge_invalid_corner_index (line 22) | def test_add_side_edge_invalid_corner_index(self):
method test_set_patch_single (line 27) | def test_set_patch_single(self):
method test_set_patch_multiple (line 33) | def test_set_patch_multiple(self):
method test_edges (line 50) | def test_edges(self, corner_1, corner_2, edge_data_class):
method test_faces (line 60) | def test_faces(self, side):
method test_patch_from_corner_empty (line 64) | def test_patch_from_corner_empty(self):
method test_patch_from_corner_single (line 68) | def test_patch_from_corner_single(self):
method test_patch_from_corner_multiple (line 75) | def test_patch_from_corner_multiple(self):
method test_chop (line 84) | def test_chop(self):
method test_unchop_single (line 90) | def test_unchop_single(self):
method test_unchop_all (line 97) | def test_unchop_all(self):
method test_set_cell_zone (line 106) | def test_set_cell_zone(self):
method test_center (line 112) | def test_center(self):
method test_set_patch_name (line 117) | def test_set_patch_name(self, side):
method test_get_closest_side (line 133) | def test_get_closest_side(self, point, orient):
method test_get_closest_face (line 146) | def test_get_closest_face(self, point):
method test_get_normal_face (line 161) | def test_get_normal_face(self, point, orient):
method test_from_series_error (line 166) | def test_from_series_error(self):
method test_from_series_2 (line 171) | def test_from_series_2(self):
method test_from_series_3 (line 177) | def test_from_series_3(self):
method test_from_series_4 (line 186) | def test_from_series_4(self):
class OperationProjectionTests (line 201) | class OperationProjectionTests(BlockTestCase):
method setUp (line 204) | def setUp(self):
method count_edges (line 207) | def count_edges(self, kind: str) -> int:
method test_project_side_top (line 218) | def test_project_side_top(self):
method test_project_side_bottom (line 224) | def test_project_side_bottom(self):
method test_project_sides (line 231) | def test_project_sides(self, side):
method test_no_projected_edges (line 238) | def test_no_projected_edges(self):
method test_project_sides_edges (line 244) | def test_project_sides_edges(self, side):
method test_project_sides_points (line 251) | def test_project_sides_points(self, side):
method test_project_side (line 263) | def test_project_side(self):
method test_project_side_edges (line 269) | def test_project_side_edges(self):
method test_project_two_sides_bottom (line 277) | def test_project_two_sides_bottom(self):
method test_project_two_sides_top (line 287) | def test_project_two_sides_top(self):
method test_project_corner_top (line 297) | def test_project_corner_top(self):
method test_project_corner_bottom (line 303) | def test_project_corner_bottom(self):
method test_project_edge (line 337) | def test_project_edge(self, corner_1, corner_2):
method test_project_edge_twice (line 356) | def test_project_edge_twice(self):
method test_project_edge_multiple (line 372) | def test_project_edge_multiple(self, first, second, result):
class OperationTransformTests (line 380) | class OperationTransformTests(unittest.TestCase):
method setUp (line 384) | def setUp(self):
method test_construct (line 404) | def test_construct(self):
method test_translate (line 408) | def test_translate(self):
method test_rotate (line 423) | def test_rotate(self):
method test_rotate_default_origin (line 438) | def test_rotate_default_origin(self):
method test_mirror_bottom (line 452) | def test_mirror_bottom(self):
method test_mirror_top (line 462) | def test_mirror_top(self):
method test_index_from_side (line 473) | def test_index_from_side(self):
method test_mirror (line 477) | def test_mirror(self):
method test_mirror_transform (line 483) | def test_mirror_transform(self):
method test_mirror_transform_no_origin (line 489) | def test_mirror_transform_no_origin(self):
FILE: tests/test_construct/test_operation/test_wedge.py
class WedgeTests (line 7) | class WedgeTests(unittest.TestCase):
method setUp (line 8) | def setUp(self):
method base (line 12) | def base(self) -> Face:
method wedge (line 16) | def wedge(self) -> Wedge:
method test_wedge_construction_mirror (line 19) | def test_wedge_construction_mirror(self):
method test_wedge_construction_revolve (line 26) | def test_wedge_construction_revolve(self):
method test_inner_patch (line 33) | def test_inner_patch(self):
method test_outer_patch (line 39) | def test_outer_patch(self):
method test_chop (line 45) | def test_chop(self):
FILE: tests/test_construct/test_point.py
class PointTests (line 11) | class PointTests(unittest.TestCase):
method point (line 15) | def point(self) -> Point:
method test_invalid_creation_parameters (line 25) | def test_invalid_creation_parameters(self, position):
method test_default_rotate_origin (line 29) | def test_default_rotate_origin(self):
method test_default_scale_origin (line 33) | def test_default_scale_origin(self):
method test_center (line 37) | def test_center(self):
method test_points_equal (line 41) | def test_points_equal(self):
method test_points_not_equal (line 48) | def test_points_not_equal(self):
method test_project_double (line 55) | def test_project_double(self):
method test_project_twice (line 63) | def test_project_twice(self):
method test_project_twice_mixed (line 72) | def test_project_twice_mixed(self):
method test_mirror_default_origin (line 80) | def test_mirror_default_origin(self):
FILE: tests/test_construct/test_shape.py
class ShapeTests (line 19) | class ShapeTests(unittest.TestCase):
method setUp (line 22) | def setUp(self):
method test_translate (line 25) | def test_translate(self):
method test_translate_sketches (line 31) | def test_translate_sketches(self):
method test_cylinder_center (line 37) | def test_cylinder_center(self):
method test_set_start_patch (line 41) | def test_set_start_patch(self):
method test_set_end_patch (line 48) | def test_set_end_patch(self):
method test_outer_patch (line 55) | def test_outer_patch(self):
method test_inner_patch_extruded (line 62) | def test_inner_patch_extruded(self):
method test_inner_patch_revolved (line 70) | def test_inner_patch_revolved(self):
method test_start_patch_revolved (line 80) | def test_start_patch_revolved(self):
method test_end_patch_revolved (line 90) | def test_end_patch_revolved(self):
class ElbowTests (line 101) | class ElbowTests(unittest.TestCase):
method setUp (line 104) | def setUp(self):
method radius_1 (line 117) | def radius_1(self) -> float:
method elbow (line 122) | def elbow(self) -> Elbow:
method test_radius_1 (line 134) | def test_radius_1(self):
method test_radius_2 (line 138) | def test_radius_2(self):
method test_radius_mid_nonuniform (line 142) | def test_radius_mid_nonuniform(self):
method test_radius_mid_uniform (line 147) | def test_radius_mid_uniform(self):
method test_sketch_positions (line 153) | def test_sketch_positions(self):
class RevolvedRingTests (line 163) | class RevolvedRingTests(unittest.TestCase):
method setUp (line 166) | def setUp(self):
method test_set_inner_patch (line 174) | def test_set_inner_patch(self):
method test_set_outer_patch (line 181) | def test_set_outer_patch(self):
method test_chop_ring_tangential (line 188) | def test_chop_ring_tangential(self):
method test_transform (line 196) | def test_transform(self):
class ExtrudedRingTests (line 203) | class ExtrudedRingTests(unittest.TestCase):
method test_transform (line 204) | def test_transform(self):
class SphereTests (line 211) | class SphereTests(unittest.TestCase):
method test_sphere_radii (line 212) | def test_sphere_radii(self):
method test_start_patch (line 222) | def test_start_patch(self):
method test_outer_patch (line 234) | def test_outer_patch(self):
method test_core (line 241) | def test_core(self):
method test_center (line 246) | def test_center(self):
method test_geometry (line 251) | def test_geometry(self):
class FrustumTests (line 259) | class FrustumTests(unittest.TestCase):
method test_non_perpendicular_axis_radius (line 260) | def test_non_perpendicular_axis_radius(self):
method test_curved_side (line 264) | def test_curved_side(self):
class CylinderTests (line 275) | class CylinderTests(unittest.TestCase):
method setUp (line 276) | def setUp(self):
method test_non_perpendicular_axis_radius (line 282) | def test_non_perpendicular_axis_radius(self):
method test_edges (line 286) | def test_edges(self):
method test_core (line 292) | def test_core(self):
method test_chop_radial_start_size (line 296) | def test_chop_radial_start_size(self):
method test_chop_radial_end_size (line 302) | def test_chop_radial_end_size(self):
method test_mirror (line 308) | def test_mirror(self):
method _test_mirror_transform (line 316) | def _test_mirror_transform(self):
method test_remove_inner_edges (line 324) | def test_remove_inner_edges(self):
method test_symmetry_patches (line 334) | def test_symmetry_patches(self):
class LoftedShapeTests (line 339) | class LoftedShapeTests(unittest.TestCase):
method sketch (line 341) | def sketch(self):
method test_end_sketch_exception (line 344) | def test_end_sketch_exception(self):
method test_test_mid_sketch_exception (line 351) | def test_test_mid_sketch_exception(self):
method test_grid (line 359) | def test_grid(self):
method test_chop_0 (line 365) | def test_chop_0(self):
method test_chop_2 (line 373) | def test_chop_2(self):
method test_extruded_shape_scalar (line 379) | def test_extruded_shape_scalar(self):
method test_extruded_shape_vector (line 384) | def test_extruded_shape_vector(self):
method test_revolved_shape (line 389) | def test_revolved_shape(self):
FILE: tests/test_construct/test_shell.py
class ShellTestsBase (line 14) | class ShellTestsBase(DataTestCase):
method setUp (line 15) | def setUp(self):
method get_face (line 25) | def get_face(self, orient) -> Face:
method get_point (line 28) | def get_point(self, orient, index):
class SharedPointTests (line 32) | class SharedPointTests(ShellTestsBase):
method get_shared_point (line 33) | def get_shared_point(self, orient: OrientType, index: int):
method test_equal (line 41) | def test_equal(self):
method test_add (line 52) | def test_add(self):
method test_duplicated (line 61) | def test_duplicated(self):
method test_noncoincident (line 73) | def test_noncoincident(self):
method test_normal_single (line 80) | def test_normal_single(self):
method test_normal_multiple (line 88) | def test_normal_multiple(self):
method test_is_single (line 97) | def test_is_single(self):
method test_is_shared (line 102) | def test_is_shared(self):
class SharedpointStoreTests (line 109) | class SharedpointStoreTests(ShellTestsBase):
method setUp (line 110) | def setUp(self):
method test_sps_find_by_point_success (line 115) | def test_sps_find_by_point_success(self):
method test_sps_find_by_point_failure (line 124) | def test_sps_find_by_point_failure(self):
method test_sps_add_from_face_new (line 134) | def test_sps_add_from_face_new(self):
method test_sps_add_from_face_duplicate (line 139) | def test_sps_add_from_face_duplicate(self):
class AwareFaceTests (line 147) | class AwareFaceTests(SharedPointTests):
method get_aware_face (line 148) | def get_aware_face(self, orient):
method test_get_offset_points (line 159) | def test_get_offset_points(self):
method test_get_offset_face (line 170) | def test_get_offset_face(self):
method test_is_solitary (line 178) | def test_is_solitary(self):
method test_is_not_solitary (line 183) | def test_is_not_solitary(self):
class AwareFaceStoreTests (line 190) | class AwareFaceStoreTests(SharedPointTests):
method get_aws (line 191) | def get_aws(self, orients: list[OrientType]) -> AwareFaceStore:
method test_get_point_store_single (line 196) | def test_get_point_store_single(self):
method test_get_point_store_double_separate (line 201) | def test_get_point_store_double_separate(self):
method test_get_point_store_double_joined (line 206) | def test_get_point_store_double_joined(self):
method test_get_point_store_cube (line 211) | def test_get_point_store_cube(self):
method test_get_aware_faces (line 224) | def test_get_aware_faces(self, orients):
class ShellTests (line 230) | class ShellTests(ShellTestsBase):
method get_shell_faces (line 231) | def get_shell_faces(self, orients: list[OrientType]):
method get_shell (line 245) | def get_shell(self, orients: list[OrientType]):
method test_operations_count (line 255) | def test_operations_count(self, orients):
method test_chop (line 258) | def test_chop(self):
method test_set_outer_patch (line 264) | def test_set_outer_patch(self) -> None:
method test_chop_disconnected (line 272) | def test_chop_disconnected(self):
method test_grid (line 278) | def test_grid(self):
FILE: tests/test_construct/test_stack.py
class StackTests (line 9) | class StackTests(unittest.TestCase):
method round_base (line 11) | def round_base(self) -> cb.OneCoreDisk:
method square_base (line 15) | def square_base(self) -> cb.Grid:
method test_construct_extruded_vector (line 18) | def test_construct_extruded_vector(self):
method test_construct_extruded_amount (line 24) | def test_construct_extruded_amount(self):
method test_construct_revolved (line 30) | def test_construct_revolved(self):
method test_construct_transformed (line 33) | def test_construct_transformed(self):
method test_chop (line 41) | def test_chop(self):
method test_center (line 49) | def test_center(self):
method test_stack_transform (line 54) | def test_stack_transform(self):
method test_grid_square_axis0 (line 61) | def test_grid_square_axis0(self):
method test_grid_square_axis1 (line 66) | def test_grid_square_axis1(self):
method test_grid_square_axis2 (line 71) | def test_grid_square_axis2(self):
method test_grid_round_axis0 (line 76) | def test_grid_round_axis0(self):
method test_grid_round_axis1 (line 81) | def test_grid_round_axis1(self):
method test_grid_round_axis2 (line 86) | def test_grid_round_axis2(self):
method test_get_slice_square (line 109) | def test_get_slice_square(self, axis, index, count):
FILE: tests/test_grading/test_catalogue.py
class InstructionTests (line 8) | class InstructionTests(BlockTestCase):
method setUp (line 9) | def setUp(self):
method test_not_defined (line 12) | def test_not_defined(self):
method test_defined (line 16) | def test_defined(self):
method test_hash (line 20) | def test_hash(self):
class RowCatalogueTests (line 24) | class RowCatalogueTests(BlockTestCase):
method setUp (line 25) | def setUp(self):
method test_row_blocks_exception (line 33) | def test_row_blocks_exception(self):
method test_find_instruction_exception (line 38) | def test_find_instruction_exception(self):
FILE: tests/test_grading/test_collector.py
class CollectorTests (line 6) | class CollectorTests(unittest.TestCase):
method test_chop_edge_single (line 7) | def test_chop_edge_single(self):
method test_chop_edge_multiple (line 18) | def test_chop_edge_multiple(self):
method test_is_not_edge_chopped (line 30) | def test_is_not_edge_chopped(self):
method test_is_edge_chopped (line 37) | def test_is_edge_chopped(self):
FILE: tests/test_grading/test_edge_grading.py
class EdgeGradingExampleTests (line 17) | class EdgeGradingExampleTests(unittest.TestCase):
method setUp (line 18) | def setUp(self):
method test_axis_simple_grading (line 51) | def test_axis_simple_grading(self):
method test_axis_edge_grading (line 58) | def test_axis_edge_grading(self):
method test_block_grading_simple (line 63) | def test_block_grading_simple(self):
method test_block_grading_edge (line 69) | def test_block_grading_edge(self):
class EdgeGradingTests (line 76) | class EdgeGradingTests(unittest.TestCase):
method setUp (line 79) | def setUp(self):
method prepare (line 82) | def prepare(self):
method test_inconsistent_wires (line 86) | def test_inconsistent_wires(self):
method test_curved_block (line 104) | def test_curved_block(self):
method test_no_preserve (line 118) | def test_no_preserve(self):
method test_propagated_count (line 132) | def test_propagated_count(self):
class BoxEdgeChopTests (line 155) | class BoxEdgeChopTests(unittest.TestCase):
method setUp (line 158) | def setUp(self):
method finalize (line 164) | def finalize(self):
method get_grading (line 168) | def get_grading(self, direction: DirectionType, i_wire: int) -> list[G...
method test_edge_chop_solo_fail (line 173) | def test_edge_chop_solo_fail(self):
method test_edge_chop_solo_success (line 180) | def test_edge_chop_solo_success(self):
method test_edge_chop_multiple (line 192) | def test_edge_chop_multiple(self):
method test_clear (line 207) | def test_clear(self):
FILE: tests/test_grading/test_grading.py
class GradingTests (line 12) | class GradingTests(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method test_calculator_functions (line 16) | def test_calculator_functions(self):
method test_calculate (line 59) | def test_calculate(self, keys, count, total_expansion):
method add_chop (line 65) | def add_chop(self, length_ratio, count, total_expansion):
method test_output_empty (line 70) | def test_output_empty(self):
method test_output_single (line 74) | def test_output_single(self):
method test_output_multi (line 78) | def test_output_multi(self):
method test_copy_invert_simple (line 87) | def test_copy_invert_simple(self):
method test_add_division_zero_length (line 95) | def test_add_division_zero_length(self):
method test_insuficient_data (line 103) | def test_insuficient_data(self):
method test_over_defined (line 113) | def test_over_defined(self):
method test_wrong_combination (line 117) | def test_wrong_combination(self):
method test_add_division_1 (line 125) | def test_add_division_1(self):
method test_add_division_2 (line 136) | def test_add_division_2(self):
method test_add_division_3 (line 141) | def test_add_division_3(self):
method test_add_division_inverted (line 147) | def test_add_division_inverted(self):
method test_add_wrong_ratio (line 155) | def test_add_wrong_ratio(self, ratio):
method test_is_defined (line 160) | def test_is_defined(self):
method test_is_not_defined (line 165) | def test_is_not_defined(self):
method test_warn_ratio (line 168) | def test_warn_ratio(self):
method test_invert_empty (line 176) | def test_invert_empty(self):
method test_equal (line 181) | def test_equal(self):
method test_not_equal_divisionsn (line 192) | def test_not_equal_divisionsn(self):
method test_not_equal (line 205) | def test_not_equal(self):
method test_copy_preserve_none (line 215) | def test_copy_preserve_none(self):
method test_copy_preserve_start (line 224) | def test_copy_preserve_start(self):
method test_copy_preserve_end (line 235) | def test_copy_preserve_end(self):
method test_start_size_exception (line 246) | def test_start_size_exception(self):
method test_end_size_exception (line 252) | def test_end_size_exception(self):
method test_grading_description_undefined (line 258) | def test_grading_description_undefined(self):
method test_grading_description_define (line 263) | def test_grading_description_define(self):
class CollapsedGradingTests (line 270) | class CollapsedGradingTests(unittest.TestCase):
method test_add_chop_count (line 271) | def test_add_chop_count(self):
method test_add_chop_nocount (line 277) | def test_add_chop_nocount(self):
method test_count_multi (line 284) | def test_count_multi(self):
method test_clear (line 292) | def test_clear(self):
method test_description (line 301) | def test_description(self):
FILE: tests/test_grading/test_inflation.py
class InflationGraderTests (line 10) | class InflationGraderTests(unittest.TestCase):
method get_grader (line 11) | def get_grader(self, mesh: Mesh) -> InflationGrader:
method test_flipped_blocks (line 14) | def test_flipped_blocks(self):
FILE: tests/test_grading/test_layers.py
class ParamsTests (line 13) | class ParamsTests(unittest.TestCase):
method setUp (line 14) | def setUp(self):
method test_bl_thickness (line 17) | def test_bl_thickness(self):
method test_inflation_count (line 20) | def test_inflation_count(self):
method test_inflation_end_size (line 23) | def test_inflation_end_size(self):
method test_buffer_start_size (line 26) | def test_buffer_start_size(self):
method test_buffer_count (line 29) | def test_buffer_count(self):
method test_sum_length_simple (line 32) | def test_sum_length_simple(self):
method test_sum_length_graded (line 35) | def test_sum_length_graded(self):
method test_buffer_thickness (line 38) | def test_buffer_thickness(self):
class LayerStackTests (line 42) | class LayerStackTests(ParamsTests):
method test_inflation_layer_count (line 43) | def test_inflation_layer_count(self):
method test_inflation_layer_size (line 48) | def test_inflation_layer_size(self):
method test_inflation_layer_size_truncated (line 53) | def test_inflation_layer_size_truncated(self):
method test_inflation_count_zero (line 58) | def test_inflation_count_zero(self):
method test_buffer_count (line 63) | def test_buffer_count(self):
method test_buffer_length_truncated (line 68) | def test_buffer_length_truncated(self):
method test_buffer_length (line 74) | def test_buffer_length(self):
method test_bulk_layer (line 79) | def test_bulk_layer(self):
method test_stack_inflation_short (line 84) | def test_stack_inflation_short(self):
method test_stack_inflation_exact (line 90) | def test_stack_inflation_exact(self):
method test_stack_buffer (line 96) | def test_stack_buffer(self):
method test_stack_bulk (line 101) | def test_stack_bulk(self):
method test_length_ratios (line 106) | def test_length_ratios(self):
FILE: tests/test_grading/test_probe.py
class ProbeTests (line 18) | class ProbeTests(unittest.TestCase):
method get_stack (line 19) | def get_stack(self) -> ExtrudedStack:
method get_flipped_stack (line 24) | def get_flipped_stack(self) -> ExtrudedStack:
method get_cylinder (line 32) | def get_cylinder(self) -> Cylinder:
method get_frustum (line 35) | def get_frustum(self) -> Frustum:
method get_box (line 38) | def get_box(self) -> Box:
method setUp (line 41) | def setUp(self):
method test_block_from_axis_fail (line 44) | def test_block_from_axis_fail(self):
method test_get_row_length (line 57) | def test_get_row_length(self, take, length):
method test_get_blocks_on_layer (line 67) | def test_get_blocks_on_layer(self, block, axis):
method test_block_from_axis (line 77) | def test_block_from_axis(self, index):
method test_get_layers (line 87) | def test_get_layers(self, axis):
method test_get_blocks_cylinder (line 107) | def test_get_blocks_cylinder(self, axis, row, blocks):
method test_get_blocks_inverted (line 128) | def test_get_blocks_inverted(self, axis, row, blocks):
method test_flipped_simple (line 141) | def test_flipped_simple(self):
method test_flipped_shape (line 163) | def test_flipped_shape(self, flip_indexes, check_row, check_index):
method test_wire_boundaries_explicit (line 192) | def test_wire_boundaries_explicit(self, wire_start, wire_end, starts_a...
method test_wire_boundaries_default (line 222) | def test_wire_boundaries_default(self, wire_start, wire_end, starts_at...
method test_wire_boundaries_cylinder (line 238) | def test_wire_boundaries_cylinder(self):
FILE: tests/test_grading/test_relations.py
class TestGradingRelations (line 15) | class TestGradingRelations(unittest.TestCase):
method assertAlmostEqual (line 18) | def assertAlmostEqual(self, *args, **kwargs): # noqa: N802
method test_get_start_size__count__c2c_expansion_valid (line 31) | def test_get_start_size__count__c2c_expansion_valid(self, args, result):
method test_get_start_size__count__c2c_expansion_zerolen (line 34) | def test_get_start_size__count__c2c_expansion_zerolen(self):
method test_get_start_size__count__c2c_expansion_contracting (line 38) | def test_get_start_size__count__c2c_expansion_contracting(self):
method test_get_start_size__end_size__total_expansion_valid (line 42) | def test_get_start_size__end_size__total_expansion_valid(self):
method test_get_start_size__end_size__total_expansion_zerolen (line 45) | def test_get_start_size__end_size__total_expansion_zerolen(self):
method test_get_start_size__end_size__total_expansion_zeroexp (line 49) | def test_get_start_size__end_size__total_expansion_zeroexp(self):
method test_get_end_size__start_size__total_expansion_valid (line 53) | def test_get_end_size__start_size__total_expansion_valid(self):
method test_get_end_size__start_size__total_expansion_neglen (line 56) | def test_get_end_size__start_size__total_expansion_neglen(self):
method test_get_count__start__size__c2c_expansion_valid (line 69) | def test_get_count__start__size__c2c_expansion_valid(self, args, result):
method test_get_count__start__size__c2c_expansion_invalid (line 79) | def test_get_count__start__size__c2c_expansion_invalid(self, args):
method test_get_count__end_size__c2c_expansion_valid (line 96) | def test_get_count__end_size__c2c_expansion_valid(self, args, result):
method test_get_count__end_size__c2c_expansion_invalid (line 99) | def test_get_count__end_size__c2c_expansion_invalid(self):
method test_get_count__total_expansion__c2c_expansion_valid (line 103) | def test_get_count__total_expansion__c2c_expansion_valid(self):
method test_get_count__total_expansion__c2c_expansion_border (line 106) | def test_get_count__total_expansion__c2c_expansion_border(self):
method test_get_count__total_expansion__c2c_expansion_invalid (line 115) | def test_get_count__total_expansion__c2c_expansion_invalid(self, args):
method test_get_count__total_expansion__start_size_valid (line 128) | def test_get_count__total_expansion__start_size_valid(self, args, resu...
method test_get_c2c_expansion__count__start_size_valid (line 142) | def test_get_c2c_expansion__count__start_size_valid(self, args, result):
method test_get_c2c_expansion__count__start_size_invalid (line 154) | def test_get_c2c_expansion__count__start_size_invalid(self, args):
method test_get_c2c_expansion__count__end_size_valid (line 166) | def test_get_c2c_expansion__count__end_size_valid(self, args, result):
method test_get_c2c_expansion__count__end_size_invalid (line 176) | def test_get_c2c_expansion__count__end_size_invalid(self, args):
method test_get_c2c_expansion__count__total_expansion_valid (line 187) | def test_get_c2c_expansion__count__total_expansion_valid(self, args, r...
method test_get_c2c_expansion__count__total_expansion_invalid (line 190) | def test_get_c2c_expansion__count__total_expansion_invalid(self):
method test_get_total_expansion__count__c2c_expansion_valid (line 195) | def test_get_total_expansion__count__c2c_expansion_valid(self, args, r...
method test_get_total_expansion__count__c2c_expansion_invalid (line 198) | def test_get_total_expansion__count__c2c_expansion_invalid(self):
method test_get_total_expansion__start_size__end_size_valid (line 210) | def test_get_total_expansion__start_size__end_size_valid(self, args, r...
method test_get_total_expansion__start_size__end_size_invalid (line 213) | def test_get_total_expansion__start_size__end_size_invalid(self):
method test_validate_count_valid (line 229) | def test_validate_count_valid(self, count, condition):
method test_validate_count_invalid_type (line 232) | def test_validate_count_invalid_type(self):
method test_validate_count_invalid_operator (line 236) | def test_validate_count_invalid_operator(self):
method test_validate_count_unknown_operator (line 240) | def test_validate_count_unknown_operator(self):
class ChopRelationTests (line 245) | class ChopRelationTests(unittest.TestCase):
method test_from_function_invalid (line 246) | def test_from_function_invalid(self):
FILE: tests/test_items/test_axis.py
class AxisTests (line 7) | class AxisTests(BlockTestCase):
method add_blocks (line 10) | def add_blocks(self) -> tuple[Block, Block]:
method test_length_avg (line 19) | def test_length_avg(self):
method test_is_aligned_exception (line 27) | def test_is_aligned_exception(self):
method test_is_aligned (line 38) | def test_is_aligned(self, axis):
method test_is_not_aligned (line 47) | def test_is_not_aligned(self):
method test_sequential_before (line 61) | def test_sequential_before(self):
method test_sequential_after (line 70) | def test_sequential_after(self):
method test_is_inline (line 78) | def test_is_inline(self):
method test_is_not_inline (line 83) | def test_is_not_inline(self):
FILE: tests/test_items/test_block.py
function _mkcollector (line 15) | def _mkcollector(axis: DirectionType, chops: list[Chop]) -> ChopCollector:
class BlockTests (line 23) | class BlockTests(BlockTestCase):
method test_add_neighbour_1_wires (line 34) | def test_add_neighbour_1_wires(self, this_corners, nei_corners):
method test_add_neighbour_1_axes (line 47) | def test_add_neighbour_1_axes(self):
method test_add_neighbour_2_wires (line 59) | def test_add_neighbour_2_wires(self):
method test_add_neighbour_2_axes (line 69) | def test_add_neighbour_2_axes(self):
method test_add_neighbour_3 (line 80) | def test_add_neighbour_3(self):
method test_add_neighbour_twice (line 91) | def test_add_neighbour_twice(self):
method test_add_self (line 103) | def test_add_self(self):
method test_add_neighbour_inverted (line 113) | def test_add_neighbour_inverted(self):
method test_add_foreign (line 132) | def test_add_foreign(self):
method test_axis_direction (line 150) | def test_axis_direction(self):
method test_repr (line 157) | def test_repr(self):
class WireframeTests (line 161) | class WireframeTests(BlockTestCase):
method setUp (line 164) | def setUp(self):
method test_wires_count (line 168) | def test_wires_count(self):
method test_wire_indexes (line 173) | def test_wire_indexes(self):
method test_axis_count (line 193) | def test_axis_count(self):
method test_find_wire_fail (line 199) | def test_find_wire_fail(self, corner_1, corner_2):
method test_find_wire_success (line 205) | def test_find_wire_success(self, corner_1, corner_2):
method test_get_axis_wires_length (line 210) | def test_get_axis_wires_length(self, axis):
method test_edge_list_empty (line 215) | def test_edge_list_empty(self, block_index, edge_count):
method test_index_exception (line 220) | def test_index_exception(self):
FILE: tests/test_items/test_edge.py
class EdgeTransformTests (line 20) | class EdgeTransformTests(unittest.TestCase):
method setUp (line 23) | def setUp(self):
method test_arc_edge_translate (line 27) | def test_arc_edge_translate(self):
method test_angle_edge_rotate_1 (line 33) | def test_angle_edge_rotate_1(self):
method test_angle_edge_rotate_2 (line 42) | def test_angle_edge_rotate_2(self):
method test_spline_edge_translate (line 51) | def test_spline_edge_translate(self):
method test_default_origin (line 75) | def test_default_origin(self):
class EdgeFactoryTests (line 83) | class EdgeFactoryTests(unittest.TestCase):
method setUp (line 86) | def setUp(self):
method test_arc (line 90) | def test_arc(self):
method test_default_origin (line 98) | def test_default_origin(self):
method test_flat_origin (line 107) | def test_flat_origin(self):
method test_angle (line 115) | def test_angle(self):
method test_spline (line 124) | def test_spline(self):
method test_polyline (line 131) | def test_polyline(self):
method test_project_edge_single (line 138) | def test_project_edge_single(self):
method test_project_edge_multi (line 145) | def test_project_edge_multi(self):
class EdgeValidityTests (line 153) | class EdgeValidityTests(unittest.TestCase):
method get_edge (line 156) | def get_edge(self, data: edges.EdgeData) -> Edge:
method test_degenerate (line 160) | def test_degenerate(self):
method test_line_edge (line 165) | def test_line_edge(self):
method test_valid_arc (line 171) | def test_valid_arc(self):
method test_invalid_edge_creation_points (line 175) | def test_invalid_edge_creation_points(self):
method test_invalid_arc (line 189) | def test_invalid_arc(self):
method test_invalid_origin (line 193) | def test_invalid_origin(self):
method test_valid_origin (line 199) | def test_valid_origin(self):
method test_invalid_angle (line 203) | def test_invalid_angle(self):
method test_valid_angle (line 209) | def test_valid_angle(self):
method test_valid_spline (line 213) | def test_valid_spline(self):
method test_valid_polyline (line 217) | def test_valid_polyline(self):
method test_valid_project (line 221) | def test_valid_project(self):
class EdgeLengthTests (line 226) | class EdgeLengthTests(unittest.TestCase):
method get_edge (line 229) | def get_edge(self, data: edges.EdgeData) -> Edge:
method test_degenerate_arc (line 233) | def test_degenerate_arc(self):
method test_arc_edge (line 237) | def test_arc_edge(self):
method test_origin_edge (line 241) | def test_origin_edge(self):
method test_spline_edge (line 245) | def test_spline_edge(self):
method test_poly_edge (line 249) | def test_poly_edge(self):
method test_project_edge (line 253) | def test_project_edge(self):
method test_flattened_edge (line 257) | def test_flattened_edge(self):
class AlternativeArcTests (line 264) | class AlternativeArcTests(unittest.TestCase):
method test_arc_mid (line 269) | def test_arc_mid(self):
method test_arc_from_theta (line 276) | def test_arc_from_theta(self):
method test_arc_from_origin (line 286) | def test_arc_from_origin(self):
method test_arc_from_origin_warn (line 293) | def test_arc_from_origin_warn(self):
class EdgeDescriptionTests (line 306) | class EdgeDescriptionTests(unittest.TestCase):
method get_edge (line 309) | def get_edge(self, data: edges.EdgeData) -> Edge:
method test_line_description (line 313) | def test_line_description(self):
method test_arc_description (line 317) | def test_arc_description(self):
method test_angle_description (line 323) | def test_angle_description(self):
method test_origin_description (line 328) | def test_origin_description(self):
method test_spline_description (line 333) | def test_spline_description(self):
method test_project_description_single (line 339) | def test_project_description_single(self):
method test_project_description_double (line 343) | def test_project_description_double(self):
class OnCurveEdgeTests (line 350) | class OnCurveEdgeTests(unittest.TestCase):
method setUp (line 351) | def setUp(self):
method edge (line 366) | def edge(self) -> OnCurveEdge:
method test_length (line 369) | def test_length(self):
method test_param_start (line 372) | def test_param_start(self):
method test_param_end (line 375) | def test_param_end(self):
method test_point_array (line 378) | def test_point_array(self):
method test_representation (line 381) | def test_representation(self):
FILE: tests/test_items/test_patch.py
class PatchTests (line 7) | class PatchTests(BlockTestCase):
method setUp (line 8) | def setUp(self):
method patch (line 12) | def patch(self) -> Patch:
method get_side (line 16) | def get_side(self, index: int, orient: OrientType) -> Side:
method test_add_side (line 20) | def test_add_side(self):
method test_add_equal_sides (line 27) | def test_add_equal_sides(self):
FILE: tests/test_items/test_side.py
class SideTests (line 7) | class SideTests(BlockTestCase):
method test_create_invalid_num_of_vertices (line 8) | def test_create_invalid_num_of_vertices(self):
method test_create_success (line 13) | def test_create_success(self):
method test_equal (line 20) | def test_equal(self):
FILE: tests/test_items/test_vertex.py
class VertexTests (line 11) | class VertexTests(DataTestCase):
method test_assert_3d (line 14) | def test_assert_3d(self):
method test_translate_int (line 19) | def test_translate_int(self):
method test_translate_float (line 25) | def test_translate_float(self):
method test_rotate (line 32) | def test_rotate(self):
method test_scale (line 40) | def test_scale(self):
method test_inequal (line 46) | def test_inequal(self):
method test_description_plain (line 53) | def test_description_plain(self):
method test_project_single (line 59) | def test_project_single(self):
method test_project_multiple (line 68) | def test_project_multiple(self):
method test_multitransform (line 77) | def test_multitransform(self):
FILE: tests/test_items/test_wire.py
class WireTests (line 9) | class WireTests(DataTestCase):
method setUp (line 12) | def setUp(self) -> None:
method wire (line 22) | def wire(self) -> Wire:
method test_coincident_aligned (line 26) | def test_coincident_aligned(self):
method test_coincident_inverted (line 33) | def test_coincident_inverted(self):
method test_not_coincident (line 43) | def test_not_coincident(self):
method test_is_aligned_exception (line 54) | def test_is_aligned_exception(self):
method test_is_aligned (line 68) | def test_is_aligned(self):
method test_is_inverted (line 75) | def test_is_inverted(self):
method test_add_inline_duplicate (line 84) | def test_add_inline_duplicate(self):
FILE: tests/test_lists/test_edge_list.py
class EdgeListTests (line 12) | class EdgeListTests(DataTestCase):
method setUp (line 13) | def setUp(self):
method get_vertices (line 18) | def get_vertices(self, index: int) -> list[Vertex]:
method test_find_existing (line 26) | def test_find_existing(self):
method test_find_existing_invertex (line 33) | def test_find_existing_invertex(self):
method test_find_nonexisting (line 40) | def test_find_nonexisting(self):
method test_add_new (line 48) | def test_add_new(self):
method test_add_existing (line 55) | def test_add_existing(self):
method test_add_invalid (line 63) | def test_add_invalid(self):
method test_vertex_order (line 70) | def test_vertex_order(self):
method test_add_from_operations (line 86) | def test_add_from_operations(self):
FILE: tests/test_lists/test_face_list.py
class ProjectedFaceTests (line 9) | class ProjectedFaceTests(BlockTestCase):
method side_1 (line 11) | def side_1(self) -> Side:
method side_2 (line 15) | def side_2(self) -> Side:
method test_equal (line 18) | def test_equal(self):
method test_not_equal (line 24) | def test_not_equal(self):
class FaceListTests (line 36) | class FaceListTests(BlockTestCase):
method setUp (line 37) | def setUp(self):
method get_side (line 44) | def get_side(self, block: int, orient: OrientType) -> Side:
method test_find_existing_success (line 47) | def test_find_existing_success(self):
method test_find_existing_fail (line 54) | def test_find_existing_fail(self):
method test_capture_sides (line 70) | def test_capture_sides(self, orient):
FILE: tests/test_lists/test_patch_list.py
class PatchListTests (line 5) | class PatchListTests(BlockTestCase):
method setUp (line 6) | def setUp(self):
method test_get_new (line 13) | def test_get_new(self):
method test_get_existing (line 20) | def test_get_existing(self):
method test_modify_type (line 26) | def test_modify_type(self):
method test_add (line 31) | def test_add(self):
FILE: tests/test_mesh.py
class MeshTests (line 10) | class MeshTests(BlockTestCase):
method setUp (line 11) | def setUp(self):
method test_is_not_assembled (line 14) | def test_is_not_assembled(self):
method test_is_assembled (line 18) | def test_is_assembled(self):
method test_assemble (line 26) | def test_assemble(self):
method test_merged_multi (line 35) | def test_merged_multi(self):
method test_cell_zone_operation (line 78) | def test_cell_zone_operation(self):
method test_cell_zone_shape (line 89) | def test_cell_zone_shape(self):
method test_chop_shape_axial (line 100) | def test_chop_shape_axial(self):
method test_chop_cylinder_tangential (line 114) | def test_chop_cylinder_tangential(self):
method test_set_default_patch (line 128) | def test_set_default_patch(self):
method test_modify_patch (line 133) | def test_modify_patch(self):
method test_operations (line 138) | def test_operations(self):
method test_with_geometry (line 150) | def test_with_geometry(self):
method test_backport (line 161) | def test_backport(self):
method test_backport_empty (line 171) | def test_backport_empty(self):
method test_delete (line 177) | def test_delete(self):
method test_assemble_noncoincident (line 194) | def test_assemble_noncoincident(self):
FILE: tests/test_modify/test_finder.py
class GeometricFinderTests (line 10) | class GeometricFinderTests(BlockTestCase):
method setUp (line 11) | def setUp(self):
method test_by_position_close (line 22) | def test_by_position_close(self):
method test_by_position_close_count (line 28) | def test_by_position_close_count(self):
method test_by_position_far (line 34) | def test_by_position_far(self):
method test_by_position_all (line 40) | def test_by_position_all(self):
method test_on_plane_bottom (line 46) | def test_on_plane_bottom(self):
method test_on_plane_top (line 51) | def test_on_plane_top(self):
class RoundSolidShapeFinderTests (line 57) | class RoundSolidShapeFinderTests(BlockTestCase):
method setUp (line 58) | def setUp(self):
method test_core_count (line 69) | def test_core_count(self, end_face):
method test_shell_count (line 76) | def test_shell_count(self, end_face):
FILE: tests/test_modify/test_reorient.py
class TriangleTests (line 12) | class TriangleTests(unittest.TestCase):
method setUp (line 13) | def setUp(self):
method test_normal (line 16) | def test_normal(self):
method test_center (line 19) | def test_center(self):
method test_flip (line 22) | def test_flip(self):
method test_orient_no_change (line 27) | def test_orient_no_change(self):
method test_orient_change (line 32) | def test_orient_change(self):
class QuadrangleTests (line 38) | class QuadrangleTests(unittest.TestCase):
method setUp (line 39) | def setUp(self):
method test_get_common_points (line 48) | def test_get_common_points(self):
method test_get_unique_points (line 56) | def test_get_unique_points(self):
method test_point_count (line 64) | def test_point_count(self):
class ViewpointReorienterTests (line 70) | class ViewpointReorienterTests(BlockTestCase):
method setUp (line 71) | def setUp(self):
method loft (line 75) | def loft(self) -> Loft:
method test_sort_regular (line 118) | def test_sort_regular(self, axis, angle):
method test_translated_face (line 135) | def test_translated_face(self):
method test_rotated_face (line 145) | def test_rotated_face(self):
method test_moved_point (line 158) | def test_moved_point(self):
FILE: tests/test_optimize/optimize_fixtures.py
class SketchTestsBase (line 13) | class SketchTestsBase(unittest.TestCase):
method positions (line 15) | def positions(self):
method quads (line 31) | def quads(self):
method grid (line 40) | def grid(self):
class BoxTestsBase (line 44) | class BoxTestsBase(unittest.TestCase):
method setUp (line 45) | def setUp(self):
method get_vertex (line 63) | def get_vertex(self, position):
FILE: tests/test_optimize/test_cell.py
class CellTests (line 9) | class CellTests(MeshTestCase):
method setUp (line 10) | def setUp(self):
method mesh_points (line 14) | def mesh_points(self):
method get_cell (line 17) | def get_cell(self, index: int) -> HexCell:
method test_common_vertices (line 28) | def test_common_vertices(self, index_1, index_2, count):
method test_get_corner (line 35) | def test_get_corner(self, block, vertex, corner):
method test_get_common_side (line 41) | def test_get_common_side(self, index_1, index_2, orient):
method test_no_common_sides (line 47) | def test_no_common_sides(self):
FILE: tests/test_optimize/test_clamps.py
class ClampTestsBase (line 13) | class ClampTestsBase(unittest.TestCase):
method setUp (line 14) | def setUp(self):
class FreeClampTests (line 18) | class FreeClampTests(ClampTestsBase):
method test_free_init (line 19) | def test_free_init(self):
method test_free_update (line 25) | def test_free_update(self):
class CurveClampTests (line 33) | class CurveClampTests(ClampTestsBase):
method setUp (line 34) | def setUp(self):
method test_line_init (line 42) | def test_line_init(self):
method test_line_init_far (line 48) | def test_line_init_far(self):
method test_line_value (line 54) | def test_line_value(self):
method test_line_bounds_lower (line 61) | def test_line_bounds_lower(self):
method test_line_bounds_upper (line 67) | def test_line_bounds_upper(self):
method test_analytic_init (line 73) | def test_analytic_init(self):
method test_analytic_init_noncoincident (line 78) | def test_analytic_init_noncoincident(self):
method test_analytic_bounds_lower (line 84) | def test_analytic_bounds_lower(self):
method test_analytic_bounds_upper (line 90) | def test_analytic_bounds_upper(self):
method test_radial_init (line 97) | def test_radial_init(self):
method test_radial_rotate (line 103) | def test_radial_rotate(self):
class SurfaceClampTests (line 112) | class SurfaceClampTests(ClampTestsBase):
method setUp (line 113) | def setUp(self):
method test_plane_clamp (line 125) | def test_plane_clamp(self):
method test_plane_move_u (line 130) | def test_plane_move_u(self):
method test_plane_move_v (line 137) | def test_plane_move_v(self):
method test_plane_move_uv (line 144) | def test_plane_move_uv(self):
method test_parametric_init (line 151) | def test_parametric_init(self):
method test_parametric_initial_unbounded (line 156) | def test_parametric_initial_unbounded(self):
method test_parametric_initial_bounded (line 161) | def test_parametric_initial_bounded(self):
method test_parametric_move (line 166) | def test_parametric_move(self):
method test_parametric_bounds_upper (line 173) | def test_parametric_bounds_upper(self):
FILE: tests/test_optimize/test_grid.py
class HexGridTests (line 14) | class HexGridTests(MeshTestCase):
method get_grid (line 15) | def get_grid(self, mesh: Mesh) -> HexGrid:
method setUp (line 21) | def setUp(self):
method test_cells_quantity (line 25) | def test_cells_quantity(self):
method test_junctions_quantity (line 28) | def test_junctions_quantity(self):
method test_junction_boundary (line 31) | def test_junction_boundary(self):
method test_junction_internal (line 36) | def test_junction_internal(self):
method test_junction_cells (line 55) | def test_junction_cells(self, index, count):
method test_cell_neighbours (line 60) | def test_cell_neighbours(self, parent, orient, neighbour):
method test_neighbours (line 64) | def test_neighbours(self, junction, count):
class QuadGridTests (line 68) | class QuadGridTests(SketchTestsBase):
method test_from_sketch (line 69) | def test_from_sketch(self):
method test_neighbour_cells (line 85) | def test_neighbour_cells(self, i_cell, n_neighbours):
method test_positions (line 96) | def test_positions(self):
method test_find_neighbours (line 112) | def test_find_neighbours(self, i_junction, expected_neighbours):
method test_fixed_points (line 121) | def test_fixed_points(self):
FILE: tests/test_optimize/test_links.py
class TranslationLinkTests (line 10) | class TranslationLinkTests(unittest.TestCase):
method test_translate (line 11) | def test_translate(self):
class RotationLinkTests (line 20) | class RotationLinkTests(unittest.TestCase):
method setUp (line 21) | def setUp(self):
method test_radius (line 33) | def test_radius(self, origin):
method test_rotate (line 41) | def test_rotate(self):
method test_rotate_negative (line 48) | def test_rotate_negative(self):
method test_rotate_arbitrary (line 90) | def test_rotate_arbitrary(self, axis, origin, angle):
method test_coincident (line 99) | def test_coincident(self):
class SymmetryLinkTests (line 104) | class SymmetryLinkTests(unittest.TestCase):
method test_move (line 105) | def test_move(self):
method test_move_displaced_origin (line 113) | def test_move_displaced_origin(self):
FILE: tests/test_optimize/test_optimizer.py
class MeshOptimizerTests (line 17) | class MeshOptimizerTests(BoxTestsBase):
method test_relaxation (line 24) | def test_relaxation(self, relaxation, iteration, result):
method test_add_junction_existing (line 29) | def test_add_junction_existing(self):
method test_optimize (line 36) | def test_optimize(self):
method test_optimize_linked (line 50) | def test_optimize_linked(self):
class SketchOptimizerTests (line 68) | class SketchOptimizerTests(SketchTestsBase):
method test_optimize_manual (line 69) | def test_optimize_manual(self):
method test_optimize_auto (line 80) | def test_optimize_auto(self):
method test_bad_algo (line 88) | def test_bad_algo(self):
method test_algo_options (line 98) | def test_algo_options(self):
class ComplexSketchTests (line 116) | class ComplexSketchTests(unittest.TestCase):
method setUp (line 122) | def setUp(self):
method test_optimize (line 165) | def test_optimize(self):
FILE: tests/test_optimize/test_quality.py
class QualityTests (line 9) | class QualityTests(unittest.TestCase):
method test_quad_inner_angle (line 17) | def test_quad_inner_angle(self, point_2, angle):
method test_quad_quality (line 26) | def test_quad_quality(self):
FILE: tests/test_optimize/test_smoother.py
class HexSmootherTests (line 10) | class HexSmootherTests(BoxTestsBase):
method test_smooth_mesh (line 11) | def test_smooth_mesh(self):
method test_fix_index (line 20) | def test_fix_index(self):
method test_fix_point (line 30) | def test_fix_point(self):
class QuadSmootherTests (line 41) | class QuadSmootherTests(SketchTestsBase):
method test_smooth_disk (line 42) | def test_smooth_disk(self):
method test_smooth (line 54) | def test_smooth(self):
FILE: tests/test_propagation.py
class PropagationTests (line 7) | class PropagationTests(BlockTestCase):
method setUp (line 8) | def setUp(self):
method test_propagate_normal (line 11) | def test_propagate_normal(self):
method test_propagate_upsidedown (line 32) | def test_propagate_upsidedown(self):
FILE: tests/test_util/test_frame.py
class FrameTests (line 6) | class FrameTests(unittest.TestCase):
method test_add_beam_invalid (line 7) | def test_add_beam_invalid(self):
FILE: tests/test_util/test_functions.py
class TestFunctions (line 9) | class TestFunctions(unittest.TestCase):
method assert_np_equal (line 10) | def assert_np_equal(self, a, b, msg=None):
method assert_np_almost_equal (line 13) | def assert_np_almost_equal(self, a, b, msg=None):
method test_deg2rad (line 16) | def test_deg2rad(self):
method test_rad2deg (line 21) | def test_rad2deg(self):
method test_unit_vector (line 26) | def test_unit_vector(self):
method test_norm_vector (line 33) | def test_norm_vector(self):
method test_angle_between (line 37) | def test_angle_between(self):
method test_arbitrary_rotation_point (line 49) | def test_arbitrary_rotation_point(self):
method test_arbitrary_rotation_axis (line 57) | def test_arbitrary_rotation_axis(self):
method test_to_polar_z_axis (line 65) | def test_to_polar_z_axis(self):
method test_to_polar_x_axis (line 72) | def test_to_polar_x_axis(self):
method test_to_polar_invalid_axis (line 79) | def test_to_polar_invalid_axis(self):
method test_lin_map (line 83) | def test_lin_map(self):
method test_lin_map_limit (line 87) | def test_lin_map_limit(self):
method test_to_cartesian_point (line 92) | def test_to_cartesian_point(self):
method test_polar2cartesian_x_axis (line 105) | def test_polar2cartesian_x_axis(self):
method test_polar2cartesian_z_axis (line 111) | def test_polar2cartesian_z_axis(self):
method test_to_cartesian_asserts (line 117) | def test_to_cartesian_asserts(self):
method test_arc_length_3point_half (line 127) | def test_arc_length_3point_half(self):
method test_arc_length_3point_quarter (line 133) | def test_arc_length_3point_quarter(self):
method test_arc_length_3point_3quarter (line 140) | def test_arc_length_3point_3quarter(self):
method test_arc_length_3point_full (line 147) | def test_arc_length_3point_full(self):
method test_arc_length_3point_zero (line 155) | def test_arc_length_3point_zero(self):
method test_mirror_yz (line 163) | def test_mirror_yz(self):
method test_mirror_yz_origin (line 169) | def test_mirror_yz_origin(self):
method test_mirror_xz (line 175) | def test_mirror_xz(self):
method test_mirror_xz_origin (line 181) | def test_mirror_xz_origin(self):
method test_mirror_xy (line 187) | def test_mirror_xy(self):
method test_mirror_xy_origin (line 193) | def test_mirror_xy_origin(self):
method test_mirror_arbitrary (line 199) | def test_mirror_arbitrary(self):
method test_mirror_arbitrary_inverted (line 205) | def test_mirror_arbitrary_inverted(self):
method test_mirror_arbitrary_origin (line 211) | def test_mirror_arbitrary_origin(self):
method test_mirror_array (line 217) | def test_mirror_array(self):
method test_is_point_on_plane_true (line 232) | def test_is_point_on_plane_true(self, origin, normal, point):
method test_is_point_on_plane_false (line 244) | def test_is_point_on_plane_false(self, origin, normal, point):
method test_point_to_line_distance (line 247) | def test_point_to_line_distance(self):
method test_polyline_1dim (line 254) | def test_polyline_1dim(self):
method test_polyline_2dim (line 259) | def test_polyline_2dim(self):
method test_polyline_3dim (line 264) | def test_polyline_3dim(self):
method test_polyline_singlepoint (line 276) | def test_polyline_singlepoint(self):
method test_point_to_plane_distance (line 292) | def test_point_to_plane_distance(self, point, normal, origin, distance):
FILE: tests/test_util/test_imports.py
class ImportsTests (line 6) | class ImportsTests(unittest.TestCase):
method test_import_transforms (line 9) | def test_import_transforms(self):
method test_import_curves (line 16) | def test_import_curves(self):
method test_import_edges (line 25) | def test_import_edges(self):
method test_import_flat (line 34) | def test_import_flat(self):
method test_import_operations (line 37) | def test_import_operations(self):
method test_import_sketches (line 45) | def test_import_sketches(self):
method test_import_stacks (line 54) | def test_import_stacks(self):
method test_import_shapes (line 59) | def test_import_shapes(self):
method test_import_mesh (line 73) | def test_import_mesh(self):
method test_import_finders (line 76) | def test_import_finders(self):
method test_import_clamps (line 80) | def test_import_clamps(self):
method test_import_links (line 87) | def test_import_links(self):
method test_import_optimizer (line 93) | def test_import_optimizer(self):
method test_import_assemblies (line 100) | def test_import_assemblies(self):
FILE: tests/test_util/test_tools.py
class ToolsTests (line 9) | class ToolsTests(unittest.TestCase):
method test_wrong_edge_location (line 18) | def test_wrong_edge_location(self, corner_1, corner_2):
Condensed preview — 294 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (904K chars).
[
{
"path": ".editorconfig",
"chars": 292,
"preview": "# http://editorconfig.org\n\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\ninsert_"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 324,
"preview": "* classy_blocks version:\n* Python version:\n* Operating System:\n\n### Description\n\nDescribe what you were trying to get do"
},
{
"path": ".github/workflows/build_ci.yml",
"chars": 1155,
"preview": "name: Test and analyze\n\non: [ push ]\n\njobs:\n pytests:\n strategy:\n matrix:\n python-ve"
},
{
"path": ".gitignore",
"chars": 2270,
"preview": "# Why not include workspace and its settings/tasks/cfgs in git so others can benefit?\n#.vscode\n#*.code-workspace\nvenv_*/"
},
{
"path": ".pre-commit-config.yaml",
"chars": 531,
"preview": "# See https://pre-commit.com for more information\n# See https://pre-commit.com/hooks.html for more hooks\nrepos:\n- repo"
},
{
"path": "CHANGELOG.md",
"chars": 14509,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "CITATION.cff",
"chars": 546,
"preview": "cff-version: 1.2.0\nmessage: \"If you use this software, please cite it as below.\"\ntitle: classy_blocks\nabstract: \"A Pytho"
},
{
"path": "CONTRIBUTING.md",
"chars": 4258,
"preview": "# Contributing\n\nContributions are welcome, and they are greatly appreciated! Every\nlittle bit helps, and credit will alw"
},
{
"path": "LICENSE",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2022, Nejc Jurkovic\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "README.md",
"chars": 19773,
"preview": "\n\nPython classes for easier creation of OpenFOAM's block"
},
{
"path": "examples/advanced/chop_preserve.py",
"chars": 984,
"preview": "\"\"\"demonstrates the 'preserve' keyword to .chop() method\"\"\"\n\nimport os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\nst"
},
{
"path": "examples/advanced/collapsed.py",
"chars": 652,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\nbottom_face = cb.Face([[0, 0, 0], [1, 0, 0], [0.5, 1, 0], [0.5,"
},
{
"path": "examples/advanced/edge_grading.py",
"chars": 1466,
"preview": "\"\"\"A simple cylinder but with custom grading of selected edges\"\"\"\n\nimport os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh"
},
{
"path": "examples/advanced/merged.py",
"chars": 1152,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n# two boxes, connected with a geometrically identical\n# but dif"
},
{
"path": "examples/advanced/project.py",
"chars": 1977,
"preview": "import os\n\nimport classy_blocks as cb\n\ngeometry = {\n \"terrain\": [\n \"type triSurfaceMesh\",\n \"name terrai"
},
{
"path": "examples/assembly/l_joint.py",
"chars": 740,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.assemblies.joints import LJoint\nfrom classy_blocks.ut"
},
{
"path": "examples/assembly/n_joint.py",
"chars": 781,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.assemblies.joints import NJoint\nfrom classy_blocks.ut"
},
{
"path": "examples/assembly/t_joint.py",
"chars": 778,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.assemblies.joints import TJoint\nfrom classy_blocks.ut"
},
{
"path": "examples/bug.py",
"chars": 606,
"preview": "import numpy as np\n\nimport classy_blocks as cb\n\nbox = cb.Box([0, 0, 0], [1, 1, 1])\n\nbase_face = box.bottom_face\nneighbou"
},
{
"path": "examples/case/Allrun.mesh",
"chars": 282,
"preview": "#!/bin/bash\ncd \"${0%/*}\" || exit\nsource $WM_PROJECT_DIR/bin/tools/RunFunctions\nsource $WM_PROJECT_DIR/bin/tools/CleanFun"
},
{
"path": "examples/case/case.foam",
"chars": 0,
"preview": ""
},
{
"path": "examples/case/constant/geometry/terrain.stl",
"chars": 23768,
"preview": "solid terrain\r\nfacet normal -0.024250 -0.041091 -0.998861\r\nouter loop\r\nvertex 0.750000 -0.750000 -1.004215\r\nvertex 1.000"
},
{
"path": "examples/case/system/collapseDict",
"chars": 3311,
"preview": "/*--------------------------------*- C++ -*----------------------------------*\\\n| ========= | "
},
{
"path": "examples/case/system/controlDict",
"chars": 1209,
"preview": "/*--------------------------------*- C++ -*----------------------------------*\\\n| ========= | "
},
{
"path": "examples/case/system/fvSchemes",
"chars": 970,
"preview": "/*--------------------------------*- C++ -*----------------------------------*\\\n| ========= | "
},
{
"path": "examples/case/system/fvSolution",
"chars": 860,
"preview": "/*--------------------------------*- C++ -*----------------------------------*\\\n| ========= | "
},
{
"path": "examples/chaining/flywheel.py",
"chars": 2549,
"preview": "import os\n\nimport classy_blocks as cb\n\n# A mesh for calculation of friction losses of a rotating rotor in a fluid.\n# See"
},
{
"path": "examples/chaining/helmholtz_nozzle.py",
"chars": 3078,
"preview": "import os\n\nimport classy_blocks as cb\n\n# A nozzle with a chamber that produces self-induced oscillations.\n# See helmholt"
},
{
"path": "examples/chaining/labyrinth.py",
"chars": 1211,
"preview": "import os\nfrom typing import List\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as f\n\nmesh = cb.M"
},
{
"path": "examples/chaining/orifice_plate.py",
"chars": 1873,
"preview": "import os\n\nimport classy_blocks as cb\n\n# see orifice_plate.svg for sketch\n\nD = 0.1 # [m]\nd_0 = 0.025\nt = 0.005 # thick"
},
{
"path": "examples/chaining/tank.py",
"chars": 676,
"preview": "import os\n\nimport classy_blocks as cb\n\n# a cylindrical tank with round end caps\ndiameter = 0.5\nlength = 0.5 # including"
},
{
"path": "examples/chaining/test_tube.py",
"chars": 2055,
"preview": "import os\n\nimport classy_blocks as cb\n\n# a test tube as a reactor with a part of atmosphere above and below it\nouter_dia"
},
{
"path": "examples/chaining/venturi_tube.py",
"chars": 3581,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as f\n\n\ndef calculate_"
},
{
"path": "examples/complex/airfoil/airfoil.py",
"chars": 6139,
"preview": "from typing import ClassVar\n\nimport numpy as np\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as "
},
{
"path": "examples/complex/cyclone/README",
"chars": 719,
"preview": "An advanced example with optimization, custom shapes, sketches and regions.\nWork in progress, report bugs promptly!\n\nUsa"
},
{
"path": "examples/complex/cyclone/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "examples/complex/cyclone/cyclone.py",
"chars": 5594,
"preview": "#!/usr/bin/env python\nimport os\n\nimport numpy as np\nimport parameters as params\nfrom geometry import geometry\nfrom regio"
},
{
"path": "examples/complex/cyclone/geometry.py",
"chars": 3827,
"preview": "import dataclasses\n\nfrom parameters import (\n D_BODY,\n D_CONE,\n D_INLET,\n D_OUTLET,\n DIM_SCALE,\n L_BOD"
},
{
"path": "examples/complex/cyclone/parameters.py",
"chars": 760,
"preview": "### Geometry\n# See docs/geometry.svg for a quick sketch\n\n# Diameter and length of inlet pipe [mm]\nD_INLET = 120\nL_INLET "
},
{
"path": "examples/complex/cyclone/regions/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "examples/complex/cyclone/regions/body.py",
"chars": 3516,
"preview": "from collections.abc import Sequence\n\nimport parameters as params\nfrom geometry import geometry as geo\nfrom regions.regi"
},
{
"path": "examples/complex/cyclone/regions/core.py",
"chars": 4193,
"preview": "from collections.abc import Sequence\nfrom typing import ClassVar\n\nimport numpy as np\nimport parameters as params\nfrom re"
},
{
"path": "examples/complex/cyclone/regions/fillaround.py",
"chars": 1827,
"preview": "from regions.region import Region\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as f\n\n\nclass Fill"
},
{
"path": "examples/complex/cyclone/regions/inlet.py",
"chars": 2964,
"preview": "import numpy as np\nfrom regions.region import Region\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.point impo"
},
{
"path": "examples/complex/cyclone/regions/inner_ring.py",
"chars": 2133,
"preview": "import numpy as np\nfrom regions.region import Region\n\nimport classy_blocks as cb\nfrom classy_blocks.util import function"
},
{
"path": "examples/complex/cyclone/regions/pipe.py",
"chars": 1669,
"preview": "import numpy as np\nfrom regions.region import Region\n\nimport classy_blocks as cb\nfrom classy_blocks.cbtyping import NPPo"
},
{
"path": "examples/complex/cyclone/regions/region.py",
"chars": 2437,
"preview": "import abc\n\nfrom geometry import geometry\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.operations.operation "
},
{
"path": "examples/complex/cyclone/regions/skirt.py",
"chars": 1145,
"preview": "from regions.region import Region\n\nimport classy_blocks as cb\n\n\nclass Skirt(Region):\n \"\"\"A region that connects inlet"
},
{
"path": "examples/complex/gear/gear.py",
"chars": 5919,
"preview": "#!/usr/bin/env python\nimport os\nimport time\n\nimport numpy as np\nimport scipy.optimize\nfrom involute_gear import Involute"
},
{
"path": "examples/complex/gear/involute_gear.py",
"chars": 12129,
"preview": "\"\"\"A copy of py_gear_gen (https://github.com/heartworm/py_gear_gen),\nslightly modified to fit in classy_blocks for the g"
},
{
"path": "examples/complex/gear/tooth.py",
"chars": 1613,
"preview": "from typing import ClassVar\n\nimport classy_blocks as cb\n\n\nclass ToothSketch(cb.MappedSketch):\n quads: ClassVar = [\n "
},
{
"path": "examples/complex/heater/heater.py",
"chars": 4391,
"preview": "import os\nfrom typing import List\n\nimport numpy as np\nimport parameters as p\n\nimport classy_blocks as cb\nfrom classy_blo"
},
{
"path": "examples/complex/heater/parameters.py",
"chars": 1022,
"preview": "from classy_blocks.util import functions as f\n\n# geometry\nheater_diameter = 10\nheater_length = 50\nbend_radius = 3 * heat"
},
{
"path": "examples/complex/karman.py",
"chars": 2413,
"preview": "import os\n\nimport classy_blocks as cb\n\ncylinder_diameter = 20e-3 # [m]\nring_thickness = 5e-3 # [m]\n\n# domain size\ndoma"
},
{
"path": "examples/complex/plate/parameters.py",
"chars": 252,
"preview": "# plate properties\npl_thickness = 0.3\npl_length = 5\n\n# domain\ndm_upstream = 5\ndm_height = 5\nz = 1\n\n# cell sizing\ncell_si"
},
{
"path": "examples/complex/plate/plate.py",
"chars": 2068,
"preview": "#!/usr/bin/env python\nimport os\n\nimport parameters as ps\n\nimport classy_blocks as cb\nfrom classy_blocks.util import func"
},
{
"path": "examples/modification/move_vertex.py",
"chars": 493,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\ncylinder = cb.Cylinder([0, 0, 0], [1, 0, 0], [0, 1, 0])\ncylinde"
},
{
"path": "examples/operation/box.py",
"chars": 600,
"preview": "import os\n\nimport classy_blocks as cb\n\nbox = cb.Box([-1, -2, -4], [4, 2, 1])\n\n# direction of corners 0-1\nbox.chop(0, len"
},
{
"path": "examples/operation/channel.py",
"chars": 1380,
"preview": "#!/usr/bin/env python\nimport os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\n# A channel with a 90-degred bend, squa"
},
{
"path": "examples/operation/connector.py",
"chars": 527,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\nbox_1 = cb.Box([-1, -1, -1], [1, 1, 1])\nbox_2 = box_1.copy()."
},
{
"path": "examples/operation/extrude.py",
"chars": 837,
"preview": "import os\n\nimport classy_blocks as cb\n\nbase = cb.Face([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [cb.Arc([0.5, -0.2, "
},
{
"path": "examples/operation/loft.py",
"chars": 1001,
"preview": "import os\n\nimport classy_blocks as cb\n\n# Example geometry using Loft:\nbottom_face = cb.Face(\n # 4 points for face cor"
},
{
"path": "examples/operation/revolve.py",
"chars": 515,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as f\n\nbase = cb.Face([[0, 0, 0], [1, 0, 0"
},
{
"path": "examples/operation/wedge.py",
"chars": 1154,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n# a face with a single bump;\nbase = cb.Face(\n # points\n ["
},
{
"path": "examples/optimization/diffuser_free.py",
"chars": 1639,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\nsize = 0.1\n\n# Create a rapidly expanding diffuser that will cau"
},
{
"path": "examples/optimization/diffuser_line.py",
"chars": 1285,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.util import functions as f\n\nmesh = cb.Mesh()\n\nsize = 0.1\n\n# The"
},
{
"path": "examples/optimization/duct.py",
"chars": 1077,
"preview": "# An example where a Shape is optimized *before* it is added to mesh, using ShapeOptimizer\nimport os\n\nimport classy_bloc"
},
{
"path": "examples/optimization/simple.py",
"chars": 1056,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.optimize.clamps.free import FreeClamp\nfrom classy_blocks.optimi"
},
{
"path": "examples/shape/custom.py",
"chars": 2177,
"preview": "import os\nfrom typing import ClassVar\n\nimport numpy as np\n\nimport classy_blocks as cb\nfrom classy_blocks.cbtyping import"
},
{
"path": "examples/shape/cylinder.py",
"chars": 880,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\naxis_point_1 = [0, 0, 0]\naxis_point_2 = [0, 0, 1]\nradius_point_"
},
{
"path": "examples/shape/elbow.py",
"chars": 813,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\nradius_1 = 1\ncenter_point_1 = [0.0, 0.0, 0."
},
{
"path": "examples/shape/extruded_ring.py",
"chars": 843,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\npipe_wall = cb.ExtrudedRing(\n [0, 0, 0],\n [2, 2, 0],\n "
},
{
"path": "examples/shape/frustum.py",
"chars": 1501,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\naxis_point_1 = [0.0, 0.0, 0.0]\naxis_point_2"
},
{
"path": "examples/shape/hemisphere.py",
"chars": 629,
"preview": "import os\n\nimport classy_blocks as cb\n\ncenter = [0.0, 0.0, 0.0]\nradius_point = [0.0, 0.0, 1.0]\nnormal = [0.0, 1.0, 0.0]\n"
},
{
"path": "examples/shape/one_core_cylinder.py",
"chars": 925,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.flat.sketches.disk import OneCoreDisk\nfrom classy_blo"
},
{
"path": "examples/shape/quarter_cylinder.py",
"chars": 906,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.flat.sketches.disk import QuarterDisk\nfrom classy_blo"
},
{
"path": "examples/shape/revolved_ring.py",
"chars": 1005,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n# points that define ring cross-section;\n# must be specified in"
},
{
"path": "examples/shape/shell.py",
"chars": 936,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n\n# Create a 7-block sphere by offsetting a box's faces.\nbox = c"
},
{
"path": "examples/shape/splined/combined_example.py",
"chars": 3725,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\ncenter_point = np.asarray([0, 0, 0])\ndirection = np.asarray(["
},
{
"path": "examples/shape/splined/spline_ring.py",
"chars": 377,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n\nsketch = cb.SplineRing([0, 0, 0], [1, 0, 0], [0, 1.2, 0], 0.2,"
},
{
"path": "examples/shape/splined/spline_ring_whole_half_quarter.py",
"chars": 829,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\nquarter_ring_sketch = cb.QuarterSplineRing([0, 0, 0], [1.0, 0, "
},
{
"path": "examples/shape/splined/spline_round.py",
"chars": 764,
"preview": "import os\nimport random\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.flat.sketches.spline_round import Splin"
},
{
"path": "examples/shape/torus.py",
"chars": 856,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\n# A torus; a simple demonstration of copyin"
},
{
"path": "examples/shape/wrapped_cylinder.py",
"chars": 844,
"preview": "import os\n\nimport classy_blocks as cb\nfrom classy_blocks.construct.flat.sketches.disk import WrappedDisk\n\n# A simpler ve"
},
{
"path": "examples/stack/cube.py",
"chars": 2527,
"preview": "# a mesh for studying flow over a cube\nimport os\n\nimport classy_blocks as cb\n\n# cube side;\n# it sits in the coordinate s"
},
{
"path": "examples/stack/fusilli.py",
"chars": 911,
"preview": "import os\n\nimport numpy as np\n\nimport classy_blocks as cb\nfrom classy_blocks.base.transforms import Rotation, Translatio"
},
{
"path": "examples/transform/mirror.py",
"chars": 924,
"preview": "import os\n\nimport classy_blocks as cb\n\nmesh = cb.Mesh()\n\naxis_point_1 = [0.0, 0.0, 0.0]\naxis_point_2 = [2.0, 0.0, 0.0]\nr"
},
{
"path": "pyproject.toml",
"chars": 1209,
"preview": "[project]\nname = \"classy_blocks\"\nversion = \"1.10.0\"\ndescription = \"Python classes for easier creation of openFoam's bloc"
},
{
"path": "src/classy_blocks/__init__.py",
"chars": 4222,
"preview": "from .base.transforms import Mirror, Rotation, Scaling, Shear, Translation\nfrom .construct.assemblies.assembly import As"
},
{
"path": "src/classy_blocks/assemble/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/assemble/assembler.py",
"chars": 4841,
"preview": "from classy_blocks.assemble.depot import Depot\nfrom classy_blocks.assemble.dump import AssembledDump\nfrom classy_blocks."
},
{
"path": "src/classy_blocks/assemble/depot.py",
"chars": 1016,
"preview": "from typing import Union\n\nfrom classy_blocks.construct.assemblies.assembly import Assembly\nfrom classy_blocks.construct."
},
{
"path": "src/classy_blocks/assemble/dump.py",
"chars": 2372,
"preview": "import abc\n\nfrom classy_blocks.base.exceptions import MeshNotAssembledError\nfrom classy_blocks.items.block import Block\n"
},
{
"path": "src/classy_blocks/assemble/settings.py",
"chars": 1236,
"preview": "from dataclasses import dataclass, field\nfrom typing import Optional\n\nfrom classy_blocks.cbtyping import GeometryType\n\n\n"
},
{
"path": "src/classy_blocks/base/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/base/element.py",
"chars": 4547,
"preview": "import abc\nimport copy\nfrom collections.abc import Sequence\nfrom typing import Optional, TypeVar\n\nfrom classy_blocks.bas"
},
{
"path": "src/classy_blocks/base/exceptions.py",
"chars": 3336,
"preview": "from typing import Optional\n\n\n### Construction\nclass ShapeCreationError(Exception):\n \"\"\"Base class for shape creation"
},
{
"path": "src/classy_blocks/base/transforms.py",
"chars": 1248,
"preview": "\"\"\"Dataclasses for packing combinations of transforms of <anything>\ninto an easily digestable function/method arguments\""
},
{
"path": "src/classy_blocks/cbtyping.py",
"chars": 2015,
"preview": "from collections.abc import Sequence\nfrom typing import Any, Callable, Literal, Optional, TypedDict, Union\n\nfrom nptypin"
},
{
"path": "src/classy_blocks/construct/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/assemblies/assembly.py",
"chars": 726,
"preview": "import abc\nfrom collections.abc import Sequence\n\nimport numpy as np\n\nfrom classy_blocks.base.element import ElementBase\n"
},
{
"path": "src/classy_blocks/construct/assemblies/joints.py",
"chars": 5626,
"preview": "import abc\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import FloatListType, PointType\nfrom classy_blocks.construct"
},
{
"path": "src/classy_blocks/construct/curves/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/curves/analytic.py",
"chars": 2950,
"preview": "from typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import NPVectorType, ParamCurveFuncType, Po"
},
{
"path": "src/classy_blocks/construct/curves/curve.py",
"chars": 6051,
"preview": "import abc\nimport warnings\nfrom typing import Optional, Union\n\nimport numpy as np\nimport scipy.optimize\n\nfrom classy_blo"
},
{
"path": "src/classy_blocks/construct/curves/discrete.py",
"chars": 2630,
"preview": "import warnings\nfrom typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import NPPointListType, NPP"
},
{
"path": "src/classy_blocks/construct/curves/interpolated.py",
"chars": 2615,
"preview": "import abc\nfrom typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import PointListType\nfrom classy"
},
{
"path": "src/classy_blocks/construct/curves/interpolators.py",
"chars": 2543,
"preview": "import abc\n\nimport numpy as np\nimport scipy.interpolate\n\nfrom classy_blocks.cbtyping import FloatListType, NPPointType, "
},
{
"path": "src/classy_blocks/construct/edges.py",
"chars": 5710,
"preview": "import warnings\n\nfrom classy_blocks.base.element import ElementBase\nfrom classy_blocks.base.exceptions import EdgeCreati"
},
{
"path": "src/classy_blocks/construct/flat/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/flat/face.py",
"chars": 7145,
"preview": "import collections\nimport copy\nfrom typing import Optional, Union\n\nimport numpy as np\n\nfrom classy_blocks.base.element i"
},
{
"path": "src/classy_blocks/construct/flat/sketch.py",
"chars": 1601,
"preview": "import abc\nimport copy\nfrom typing import ClassVar, TypeVar\n\nfrom classy_blocks.base.element import ElementBase\nfrom cla"
},
{
"path": "src/classy_blocks/construct/flat/sketches/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/flat/sketches/annulus.py",
"chars": 3933,
"preview": "import numpy as np\n\nfrom classy_blocks.base.exceptions import AnnulusCreationError\nfrom classy_blocks.cbtyping import NP"
},
{
"path": "src/classy_blocks/construct/flat/sketches/disk.py",
"chars": 14703,
"preview": "import abc\nfrom typing import ClassVar, Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import (\n IndexType"
},
{
"path": "src/classy_blocks/construct/flat/sketches/grid.py",
"chars": 1756,
"preview": "import numpy as np\n\nfrom classy_blocks.cbtyping import PointType\nfrom classy_blocks.construct.flat.face import Face\nfrom"
},
{
"path": "src/classy_blocks/construct/flat/sketches/mapped.py",
"chars": 4031,
"preview": "import warnings\nfrom typing import Union\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import IndexType, NPPointListT"
},
{
"path": "src/classy_blocks/construct/flat/sketches/spline_round.py",
"chars": 31767,
"preview": "from typing import ClassVar, Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import NPPointListType, NPPointTy"
},
{
"path": "src/classy_blocks/construct/operations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/operations/box.py",
"chars": 1743,
"preview": "import numpy as np\n\nfrom classy_blocks.cbtyping import PointType\nfrom classy_blocks.construct.flat.face import Face\nfrom"
},
{
"path": "src/classy_blocks/construct/operations/connector.py",
"chars": 3146,
"preview": "import numpy as np\n\nfrom classy_blocks.construct.flat.face import Face\nfrom classy_blocks.construct.operations.operation"
},
{
"path": "src/classy_blocks/construct/operations/extrude.py",
"chars": 728,
"preview": "from typing import Union\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import VectorType\nfrom classy_blocks.construct"
},
{
"path": "src/classy_blocks/construct/operations/loft.py",
"chars": 266,
"preview": "from classy_blocks.construct.operations.operation import Operation\n\n# since any possible block shape can be created with"
},
{
"path": "src/classy_blocks/construct/operations/operation.py",
"chars": 16120,
"preview": "import warnings\nfrom typing import Optional, Union, get_args\n\nimport numpy as np\nfrom typing_extensions import Unpack\n\nf"
},
{
"path": "src/classy_blocks/construct/operations/revolve.py",
"chars": 953,
"preview": "from classy_blocks.cbtyping import VectorType\nfrom classy_blocks.construct import edges\nfrom classy_blocks.construct.fla"
},
{
"path": "src/classy_blocks/construct/operations/wedge.py",
"chars": 2098,
"preview": "from typing import Optional\n\nfrom classy_blocks.construct.flat.face import Face\nfrom classy_blocks.construct.operations."
},
{
"path": "src/classy_blocks/construct/point.py",
"chars": 3771,
"preview": "from typing import Optional, TypeVar\n\nimport numpy as np\n\nfrom classy_blocks.base.element import ElementBase\nfrom classy"
},
{
"path": "src/classy_blocks/construct/series.py",
"chars": 2690,
"preview": "from typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.base.element import ElementBase\nfrom classy_blocks.b"
},
{
"path": "src/classy_blocks/construct/shape.py",
"chars": 5059,
"preview": "\"\"\"Abstract base classes for different Shape types\"\"\"\n\nimport abc\nfrom typing import Generic, Optional, TypeVar, Union\n\n"
},
{
"path": "src/classy_blocks/construct/shapes/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/construct/shapes/cylinder.py",
"chars": 4847,
"preview": "from typing import ClassVar, Union\n\nimport numpy as np\n\nfrom classy_blocks.base import transforms as tr\nfrom classy_bloc"
},
{
"path": "src/classy_blocks/construct/shapes/elbow.py",
"chars": 2114,
"preview": "import numpy as np\n\nfrom classy_blocks.base import transforms as tr\nfrom classy_blocks.base.exceptions import ElbowCreat"
},
{
"path": "src/classy_blocks/construct/shapes/frustum.py",
"chars": 2993,
"preview": "from typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.base import transforms as tr\nfrom classy_blocks.base"
},
{
"path": "src/classy_blocks/construct/shapes/rings.py",
"chars": 5995,
"preview": "from typing import Union\n\nimport numpy as np\n\nfrom classy_blocks.base import transforms as tr\nfrom classy_blocks.base.ex"
},
{
"path": "src/classy_blocks/construct/shapes/round.py",
"chars": 4469,
"preview": "from collections.abc import Sequence\nfrom typing import Optional\n\nfrom classy_blocks.base import transforms as tr\nfrom c"
},
{
"path": "src/classy_blocks/construct/shapes/shell.py",
"chars": 6311,
"preview": "import functools\n\nimport numpy as np\n\nfrom classy_blocks.base.exceptions import DisconnectedChopError, PointNotCoinciden"
},
{
"path": "src/classy_blocks/construct/shapes/sphere.py",
"chars": 6998,
"preview": "import numpy as np\n\nfrom classy_blocks.cbtyping import NPPointType, NPVectorType, PointType, VectorType\nfrom classy_bloc"
},
{
"path": "src/classy_blocks/construct/stack.py",
"chars": 4564,
"preview": "from collections.abc import Sequence\nfrom typing import Optional, Union\n\nimport numpy as np\n\nfrom classy_blocks.base imp"
},
{
"path": "src/classy_blocks/grading/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/grading/analyze/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/grading/analyze/catalogue.py",
"chars": 3173,
"preview": "import functools\nfrom typing import get_args\n\nfrom classy_blocks.base.exceptions import BlockNotFoundError, NoInstructio"
},
{
"path": "src/classy_blocks/grading/analyze/probe.py",
"chars": 5859,
"preview": "import dataclasses\nfrom typing import Optional\n\nfrom classy_blocks.assemble.dump import AssembledDump\nfrom classy_blocks"
},
{
"path": "src/classy_blocks/grading/analyze/row.py",
"chars": 3254,
"preview": "import dataclasses\n\nfrom classy_blocks.base.exceptions import InconsistentGradingsError\nfrom classy_blocks.cbtyping impo"
},
{
"path": "src/classy_blocks/grading/define/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/grading/define/chop.py",
"chars": 4909,
"preview": "import dataclasses\nfrom functools import lru_cache\nfrom typing import Callable, Optional, Union\n\nfrom classy_blocks.cbty"
},
{
"path": "src/classy_blocks/grading/define/collector.py",
"chars": 1147,
"preview": "from classy_blocks.cbtyping import DirectionType\nfrom classy_blocks.grading.define.chop import Chop\nfrom classy_blocks.u"
},
{
"path": "src/classy_blocks/grading/define/grading.py",
"chars": 8793,
"preview": "\"\"\"In theory, combination of three of these 6 values can be specified:\n - Total length\n - Number of cells\n - Total expan"
},
{
"path": "src/classy_blocks/grading/define/relations.py",
"chars": 9078,
"preview": "import inspect\nimport sys\nfrom typing import Callable\n\nimport numpy as np\nimport scipy.optimize\n\nfrom classy_blocks.util"
},
{
"path": "src/classy_blocks/grading/graders/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/grading/graders/auto.py",
"chars": 512,
"preview": "import abc\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import ChopTakeType\nfrom classy_blocks.grading.analyze.row i"
},
{
"path": "src/classy_blocks/grading/graders/fixed.py",
"chars": 1186,
"preview": "from classy_blocks.assemble.dump import AssembledDump\nfrom classy_blocks.cbtyping import DirectionType\nfrom classy_block"
},
{
"path": "src/classy_blocks/grading/graders/inflation.py",
"chars": 12099,
"preview": "import abc\nimport copy\nimport dataclasses\nfrom typing import Union\n\nfrom classy_blocks.assemble.dump import AssembledDum"
},
{
"path": "src/classy_blocks/grading/graders/manager.py",
"chars": 11653,
"preview": "from typing import get_args\n\nfrom classy_blocks.assemble.dump import AssembledDump\nfrom classy_blocks.assemble.settings "
},
{
"path": "src/classy_blocks/grading/graders/simple.py",
"chars": 1078,
"preview": "from classy_blocks.assemble.dump import AssembledDump\nfrom classy_blocks.cbtyping import ChopTakeType\nfrom classy_blocks"
},
{
"path": "src/classy_blocks/items/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/items/block.py",
"chars": 4189,
"preview": "from typing import get_args\n\nfrom classy_blocks.cbtyping import DirectionType, IndexType, OrientType\nfrom classy_blocks."
},
{
"path": "src/classy_blocks/items/edges/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/items/edges/arcs/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/items/edges/arcs/angle.py",
"chars": 2351,
"preview": "import dataclasses\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import PointType, VectorType\nfrom classy_blocks.cons"
},
{
"path": "src/classy_blocks/items/edges/arcs/arc.py",
"chars": 319,
"preview": "import dataclasses\n\nfrom classy_blocks.construct import edges\nfrom classy_blocks.items.edges.arcs.arc_base import ArcEdg"
},
{
"path": "src/classy_blocks/items/edges/arcs/arc_base.py",
"chars": 1722,
"preview": "import abc\nimport dataclasses\n\nimport numpy as np\n\nfrom classy_blocks.construct.point import Point\nfrom classy_blocks.it"
},
{
"path": "src/classy_blocks/items/edges/arcs/origin.py",
"chars": 3793,
"preview": "import dataclasses\nimport warnings\nfrom typing import ClassVar\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import N"
},
{
"path": "src/classy_blocks/items/edges/curve.py",
"chars": 2379,
"preview": "import abc\nimport dataclasses\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import EdgeKindType, NPPointListType\nfrom"
},
{
"path": "src/classy_blocks/items/edges/edge.py",
"chars": 2543,
"preview": "import abc\nimport dataclasses\nimport warnings\n\nfrom classy_blocks.base.element import ElementBase\nfrom classy_blocks.bas"
},
{
"path": "src/classy_blocks/items/edges/factory.py",
"chars": 1463,
"preview": "from classy_blocks.cbtyping import EdgeKindType\nfrom classy_blocks.construct.edges import EdgeData\nfrom classy_blocks.it"
},
{
"path": "src/classy_blocks/items/edges/line.py",
"chars": 525,
"preview": "import dataclasses\n\nfrom classy_blocks.construct import edges\nfrom classy_blocks.items.edges.edge import Edge\n\n\n@datacla"
},
{
"path": "src/classy_blocks/items/edges/project.py",
"chars": 494,
"preview": "import dataclasses\n\nfrom classy_blocks.construct import edges\nfrom classy_blocks.items.edges.edge import Edge\n\n\n@datacla"
},
{
"path": "src/classy_blocks/items/patch.py",
"chars": 647,
"preview": "import warnings\n\nfrom classy_blocks.items.side import Side\n\n\nclass Patch:\n \"\"\"Definition of a patch, including type, "
},
{
"path": "src/classy_blocks/items/side.py",
"chars": 914,
"preview": "from classy_blocks.base.exceptions import SideCreationError\nfrom classy_blocks.cbtyping import OrientType\nfrom classy_bl"
},
{
"path": "src/classy_blocks/items/vertex.py",
"chars": 1183,
"preview": "\"\"\"Defines a numbered vertex in 3D space and all operations\nthat can be applied to it.\"\"\"\n\nfrom classy_blocks.cbtyping i"
},
{
"path": "src/classy_blocks/items/wires/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/items/wires/axis.py",
"chars": 3329,
"preview": "from classy_blocks.cbtyping import DirectionType\nfrom classy_blocks.items.vertex import Vertex\nfrom classy_blocks.items."
},
{
"path": "src/classy_blocks/items/wires/manager.py",
"chars": 1263,
"preview": "\nfrom classy_blocks.items.wires.wire import Wire\n\n\nclass WireManager:\n def __init__(self, wires: list[Wire]):\n "
},
{
"path": "src/classy_blocks/items/wires/wire.py",
"chars": 3963,
"preview": "import dataclasses\nimport functools\n\nfrom classy_blocks.cbtyping import DirectionType\nfrom classy_blocks.construct.edges"
},
{
"path": "src/classy_blocks/lists/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/lists/block_list.py",
"chars": 742,
"preview": "from classy_blocks.items.block import Block\nfrom classy_blocks.lookup.point_registry import HexPointRegistry\n\n\nclass Blo"
},
{
"path": "src/classy_blocks/lists/edge_list.py",
"chars": 2084,
"preview": "from classy_blocks.base.exceptions import EdgeNotFoundError\nfrom classy_blocks.construct.edges import EdgeData\nfrom clas"
},
{
"path": "src/classy_blocks/lists/face_list.py",
"chars": 1902,
"preview": "import dataclasses\n\nfrom classy_blocks.cbtyping import OrientType\nfrom classy_blocks.construct.flat.face import Face\nfro"
},
{
"path": "src/classy_blocks/lists/patch_list.py",
"chars": 2073,
"preview": "from collections import OrderedDict\nfrom typing import Optional\n\nfrom classy_blocks.base.exceptions import PatchNotFound"
},
{
"path": "src/classy_blocks/lists/vertex_list.py",
"chars": 2525,
"preview": "from classy_blocks.base.exceptions import VertexNotFoundError\nfrom classy_blocks.cbtyping import NPPointType\nfrom classy"
},
{
"path": "src/classy_blocks/lookup/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/lookup/cell_registry.py",
"chars": 753,
"preview": "from classy_blocks.cbtyping import IndexType\nfrom classy_blocks.util import functions as f\n\n\nclass CellRegistry:\n # W"
},
{
"path": "src/classy_blocks/lookup/connection_registry.py",
"chars": 2052,
"preview": "from typing import ClassVar\n\nfrom classy_blocks.cbtyping import IndexType, NPPointListType\nfrom classy_blocks.util.const"
},
{
"path": "src/classy_blocks/lookup/face_registry.py",
"chars": 1684,
"preview": "import abc\nfrom typing import ClassVar\n\nfrom classy_blocks.cbtyping import IndexType, OrientType\nfrom classy_blocks.opti"
},
{
"path": "src/classy_blocks/lookup/point_registry.py",
"chars": 5668,
"preview": "from typing import TypeVar\n\nimport numpy as np\nimport scipy.spatial\n\nfrom classy_blocks.base.exceptions import VertexNot"
},
{
"path": "src/classy_blocks/mesh.py",
"chars": 6888,
"preview": "from typing import Optional, Union\n\nfrom classy_blocks.assemble.assembler import MeshAssembler\nfrom classy_blocks.assemb"
},
{
"path": "src/classy_blocks/modify/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/modify/find/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/modify/find/finder.py",
"chars": 1007,
"preview": "from typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import PointType\nfrom classy_blocks.items.v"
},
{
"path": "src/classy_blocks/modify/find/geometric.py",
"chars": 1753,
"preview": "from typing import Optional\n\nfrom classy_blocks.cbtyping import PointType, VectorType\nfrom classy_blocks.items.vertex im"
},
{
"path": "src/classy_blocks/modify/find/shape.py",
"chars": 1901,
"preview": "from classy_blocks.construct.flat.face import Face\nfrom classy_blocks.construct.flat.sketches.disk import Disk\nfrom clas"
},
{
"path": "src/classy_blocks/modify/reorient/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/modify/reorient/viewpoint.py",
"chars": 7243,
"preview": "import numpy as np\nfrom scipy.spatial import ConvexHull\n\nfrom classy_blocks.base.exceptions import DegenerateGeometryErr"
},
{
"path": "src/classy_blocks/optimize/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/optimize/cell.py",
"chars": 3315,
"preview": "import abc\nfrom typing import ClassVar, Optional\n\nfrom classy_blocks.base.exceptions import NoCommonSidesError\nfrom clas"
},
{
"path": "src/classy_blocks/optimize/clamps/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "src/classy_blocks/optimize/clamps/clamp.py",
"chars": 1428,
"preview": "import abc\nfrom typing import Callable, Optional\n\nimport numpy as np\nimport scipy.optimize\n\nfrom classy_blocks.cbtyping "
},
{
"path": "src/classy_blocks/optimize/clamps/curve.py",
"chars": 3341,
"preview": "from typing import Optional\n\nimport numpy as np\n\nfrom classy_blocks.cbtyping import PointType, VectorType\nfrom classy_bl"
},
{
"path": "src/classy_blocks/optimize/clamps/free.py",
"chars": 503,
"preview": "import numpy as np\n\nfrom classy_blocks.cbtyping import PointType\nfrom classy_blocks.optimize.clamps.clamp import ClampBa"
},
{
"path": "src/classy_blocks/optimize/clamps/surface.py",
"chars": 1595,
"preview": "import numpy as np\n\nfrom classy_blocks.cbtyping import NPPointType, PointType, VectorType\nfrom classy_blocks.optimize.cl"
}
]
// ... and 94 more files (download for full content)
About this extraction
This page contains the full source code of the damogranlabs/classy_blocks GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 294 files (829.0 KB), approximately 233.3k tokens, and a symbol index with 2257 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.