├── .gitignore
├── src
└── openmc_cad_adapter
│ ├── __init__.py
│ ├── cubit_util.py
│ ├── geom_util.py
│ ├── gqs.py
│ ├── surfaces.py
│ └── to_cubit_journal.py
├── test
├── __init__.py
├── pincell_cell1.jou
├── xcylinder.jou
├── ycylinder.jou
├── tallies.xml
├── cylinder.jou
├── gold
│ ├── pincell_cell1.jou
│ ├── z_torus.jou
│ ├── ellipsoid.jou
│ ├── cylinder.jou
│ ├── xcylinder.jou
│ ├── ycylinder.jou
│ ├── x_torus.jou
│ ├── y_torus.jou
│ ├── z_cone.jou
│ ├── x_cone.jou
│ ├── y_cone.jou
│ ├── pincell_cell2.jou
│ ├── pincell_cell3.jou
│ ├── nested_spheres.jou
│ ├── pincell_cell4.jou
│ ├── pincell.jou
│ ├── plane.jou
│ └── lattice-hexagonal.jou
├── plots.xml
├── pincell_cell2.jou
├── pincell_cell3.jou
├── conftest.py
├── settings.xml
├── materials.xml
├── local_tests.py
├── test_utilities.py
├── pincell_cell4.jou
├── geometry.xml
├── pincell.jou
├── test_examples.py
├── test_quadric.py
├── test_local.py
├── assembly.jou
└── lattice-hexagonal.jou
├── .github
├── environment.yml
└── workflows
│ └── ci.yml
├── LICENSE
├── README.md
└── pyproject.toml
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | __pycache__
3 | *.egg-info
4 |
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | from .to_cubit_journal import to_cubit_journal
3 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | from .conftest import test_config, run_in_tmpdir
3 | from .test_utilities import *
--------------------------------------------------------------------------------
/.github/environment.yml:
--------------------------------------------------------------------------------
1 | name: test-env
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python>=3.8
6 | - numpy
7 | - pytest
8 | - openmc==0.15.0
--------------------------------------------------------------------------------
/test/pincell_cell1.jou:
--------------------------------------------------------------------------------
1 | #CELL 1
2 | cylinder height 500 radius 0.39218
3 | #{ id1 = Id("body") }
4 | body { id1 } name "Cell_1"
5 | group "Material_1" add body { id1 }
6 |
--------------------------------------------------------------------------------
/test/xcylinder.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 1
4 | cylinder height 500 radius 1.0
5 | #{ id1 = Id("body") }
6 | rotate body { id1 } about y angle 90
7 | body { id1 } move 0 10.0 5.0
8 | body { id1 } name "Cell_1"
9 |
--------------------------------------------------------------------------------
/test/ycylinder.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 2
4 | cylinder height 500 radius 1.0
5 | #{ id1 = Id("body") }
6 | rotate body { id1 } about x angle 90
7 | body { id1 } move 10.0 0 5.0
8 | body { id1 } name "Cell_2"
9 |
--------------------------------------------------------------------------------
/test/tallies.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 101
5 |
6 |
7 | 1
8 | total
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/cylinder.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 3
4 | cylinder height 500 radius 6.0
5 | #{ id1 = Id("body") }
6 | body { id1 } rotate 0.0 about Z
7 | body { id1 } rotate 45.0 about Y
8 | body { id1 } rotate 35.264389682754654 about X
9 | body { id1 } move 5.0 5.0 5.0
10 | body { id1 } name "Cell_3"
11 |
--------------------------------------------------------------------------------
/test/gold/pincell_cell1.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | cylinder height 500 radius 0.39218
9 | #{ id1 = Id("body") }
10 | body { id1 } name "Cell_1"
11 | group "mat:UO2 fuel at 2.4% wt enrichme" add body { id1 }
12 | graphics flush
13 | set default autosize on
14 | zoom reset
15 | set echo on
16 | set info on
17 | set warning on
18 | set journal on
19 |
--------------------------------------------------------------------------------
/test/plots.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 400 400
5 | 0 0 0
6 | 6 6
7 |
8 |
9 | 400 400
10 | 0 0 0
11 | 8 8
12 |
13 |
14 |
--------------------------------------------------------------------------------
/test/pincell_cell2.jou:
--------------------------------------------------------------------------------
1 | #CELL 2
2 | cylinder height 500 radius 0.39218
3 | #{ id2 = Id("body") }
4 | brick x 500 y 500 z 500
5 | #{ id3 = Id("body") }
6 | subtract body { id2 } from body { id3 }
7 | cylinder height 500 radius 0.40005
8 | #{ id4 = Id("body") }
9 | #{ id5 = Id("body") }
10 | intersect body { id3 } { id4 }
11 | #{ id6 = Id("body") }
12 | #{id7 = ( id5 == id6 ) ? id4 : id6}
13 | body { id7 } name "Cell_2"
14 | group "Material_2" add body { id7 }
15 |
--------------------------------------------------------------------------------
/test/gold/z_torus.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | torus major radius 5.0 minor radius 2.0
9 | #{ id1 = Id("body") }
10 | body { id1 } move 50.0 50.0 50.0
11 | body { id1 } name "Cell_1"
12 | group "mat:void" add body { id1 }
13 | graphics flush
14 | set default autosize on
15 | zoom reset
16 | set echo on
17 | set info on
18 | set warning on
19 | set journal on
20 |
--------------------------------------------------------------------------------
/test/pincell_cell3.jou:
--------------------------------------------------------------------------------
1 | #CELL 3
2 | cylinder height 500 radius 0.40005
3 | #{ id8 = Id("body") }
4 | brick x 500 y 500 z 500
5 | #{ id9 = Id("body") }
6 | subtract body { id8 } from body { id9 }
7 | cylinder height 500 radius 0.4572
8 | #{ id10 = Id("body") }
9 | #{ id11 = Id("body") }
10 | intersect body { id9 } { id10 }
11 | #{ id12 = Id("body") }
12 | #{id13 = ( id11 == id12 ) ? id10 : id12}
13 | body { id13 } name "Cell_3"
14 | group "Material_3" add body { id13 }
15 |
--------------------------------------------------------------------------------
/test/gold/ellipsoid.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | sphere radius 1
9 | #{ id1 = Id("body") }
10 | body { id1 } scale x 1.0 y 0.7071067811865476 z 0.5773502691896257
11 | body { None } name "Cell_1"
12 | group "mat:void" add body { None }
13 | graphics flush
14 | set default autosize on
15 | zoom reset
16 | set echo on
17 | set info on
18 | set warning on
19 | set journal on
20 |
--------------------------------------------------------------------------------
/test/gold/cylinder.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | cylinder height 500 radius 6.0
9 | #{ id1 = Id("body") }
10 | body { id1 } rotate 90.0 about Y
11 | body { id1 } rotate 45.0 about Z
12 | body { id1 } name "Cell_1"
13 | group "mat:void" add body { id1 }
14 | graphics flush
15 | set default autosize on
16 | zoom reset
17 | set echo on
18 | set info on
19 | set warning on
20 | set journal on
21 |
--------------------------------------------------------------------------------
/test/gold/xcylinder.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | cylinder height 500 radius 1.0
9 | #{ id1 = Id("body") }
10 | rotate body { id1 } about y angle 90
11 | body { id1 } move 0 10.0 5.0
12 | body { id1 } name "Cell_1"
13 | group "mat:void" add body { id1 }
14 | graphics flush
15 | set default autosize on
16 | zoom reset
17 | set echo on
18 | set info on
19 | set warning on
20 | set journal on
21 |
--------------------------------------------------------------------------------
/test/gold/ycylinder.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | cylinder height 500 radius 1.0
9 | #{ id1 = Id("body") }
10 | rotate body { id1 } about x angle 90
11 | body { id1 } move 10.0 0 5.0
12 | body { id1 } name "Cell_1"
13 | group "mat:void" add body { id1 }
14 | graphics flush
15 | set default autosize on
16 | zoom reset
17 | set echo on
18 | set info on
19 | set warning on
20 | set journal on
21 |
--------------------------------------------------------------------------------
/test/gold/x_torus.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | torus major radius 5.0 minor radius 2.0
9 | #{ id1 = Id("body") }
10 | rotate body { id1 } about y angle 90
11 | body { id1 } move 10.0 10.0 10.0
12 | body { id1 } name "Cell_1"
13 | group "mat:void" add body { id1 }
14 | graphics flush
15 | set default autosize on
16 | zoom reset
17 | set echo on
18 | set info on
19 | set warning on
20 | set journal on
21 |
--------------------------------------------------------------------------------
/test/gold/y_torus.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | torus major radius 5.0 minor radius 2.0
9 | #{ id1 = Id("body") }
10 | rotate body { id1 } about x angle 90
11 | body { id1 } move -10.0 -10.0 -10.0
12 | body { id1 } name "Cell_1"
13 | group "mat:void" add body { id1 }
14 | graphics flush
15 | set default autosize on
16 | zoom reset
17 | set echo on
18 | set info on
19 | set warning on
20 | set journal on
21 |
--------------------------------------------------------------------------------
/test/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | test_config = {'update': False}
4 |
5 |
6 | def pytest_addoption(parser):
7 | parser.addoption('--update', action='store_true')
8 |
9 |
10 | def pytest_configure(config):
11 | opts = ['update']
12 | for opt in opts:
13 | if config.getoption(opt) is not None:
14 | test_config[opt] = config.getoption(opt)
15 |
16 |
17 | @pytest.fixture
18 | def run_in_tmpdir(tmpdir):
19 | orig = tmpdir.chdir()
20 | try:
21 | yield
22 | finally:
23 | orig.chdir()
24 |
--------------------------------------------------------------------------------
/test/gold/z_cone.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | create frustum height 500 radius 250.0 top 0
9 | #{ id1 = Id("body") }
10 | body { id1 } move 0 0 -250.0
11 | body { id1 } copy reflect z
12 | #{ id2 = Id("body") }
13 | unite body { id1 } { id2 }
14 | body { id1 } move 50.0 10.0 2.0
15 | body { id1 } name "Cell_1"
16 | group "mat:void" add body { id1 }
17 | graphics flush
18 | set default autosize on
19 | zoom reset
20 | set echo on
21 | set info on
22 | set warning on
23 | set journal on
24 |
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/cubit_util.py:
--------------------------------------------------------------------------------
1 | _CUBIT_ID = 1
2 |
3 |
4 | def reset_cubit_ids():
5 | global _CUBIT_ID
6 | _CUBIT_ID = 1
7 |
8 |
9 | def lastid():
10 | global _CUBIT_ID
11 | id_out = _CUBIT_ID
12 | _CUBIT_ID += 1
13 | return id_out
14 |
15 |
16 | def new_variable():
17 | idn = lastid()
18 | return f"id{idn}"
19 |
20 |
21 | def emit_get_last_id(type="body", cmds=None):
22 | idn = lastid()
23 | ids = f"id{idn}"
24 | if cmds is not None:
25 | cmds.append(f'#{{ {ids} = Id("{type}") }}')
26 | else:
27 | print('Warning: cmds is None')
28 | return ids
29 |
--------------------------------------------------------------------------------
/test/gold/x_cone.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | create frustum height 500 radius 1118.033988749895 top 0
9 | #{ id1 = Id("body") }
10 | body { id1 } move 0 0 -250.0
11 | body { id1 } copy reflect z
12 | #{ id2 = Id("body") }
13 | unite body { id1 } { id2 }
14 | rotate body { id1 } about y angle 90
15 | body { id1 } move 30.0 3.0 5.0
16 | body { id1 } name "Cell_1"
17 | group "mat:void" add body { id1 }
18 | graphics flush
19 | set default autosize on
20 | zoom reset
21 | set echo on
22 | set info on
23 | set warning on
24 | set journal on
25 |
--------------------------------------------------------------------------------
/test/gold/y_cone.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | create frustum height 500 radius 707.1067811865476 top 0
9 | #{ id1 = Id("body") }
10 | body { id1 } move 0 0 -250.0
11 | body { id1 } copy reflect z
12 | #{ id2 = Id("body") }
13 | unite body { id1 } { id2 }
14 | rotate body { id1 } about x angle 90
15 | body { id1 } move 40.0 20.0 7.0
16 | body { id1 } name "Cell_1"
17 | group "mat:void" add body { id1 }
18 | graphics flush
19 | set default autosize on
20 | zoom reset
21 | set echo on
22 | set info on
23 | set warning on
24 | set journal on
25 |
--------------------------------------------------------------------------------
/test/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | eigenvalue
4 | 10000
5 | 20
6 | 10
7 |
8 | 0.0005
9 | std_dev
10 |
11 |
12 |
13 | -1 -1 -1 1 1 1
14 |
15 |
16 | true
17 |
18 |
19 |
20 | true
21 | 100
22 |
23 |
24 |
--------------------------------------------------------------------------------
/test/gold/pincell_cell2.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 2
8 | cylinder height 500 radius 0.39218
9 | #{ id2 = Id("body") }
10 | brick x 500 y 500 z 500
11 | #{ id3 = Id("body") }
12 | subtract body { id2 } from body { id3 }
13 | cylinder height 500 radius 0.40005
14 | #{ id4 = Id("body") }
15 | #{ id5 = Id("body") }
16 | intersect body { id3 } { id4 }
17 | #{ id6 = Id("body") }
18 | #{id7 = ( id5 == id6 ) ? id4 : id6}
19 | body { id7 } name "Cell_2"
20 | group "mat:Helium for gap" add body { id7 }
21 | graphics flush
22 | set default autosize on
23 | zoom reset
24 | set echo on
25 | set info on
26 | set warning on
27 | set journal on
28 |
--------------------------------------------------------------------------------
/test/gold/pincell_cell3.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 3
8 | cylinder height 500 radius 0.40005
9 | #{ id8 = Id("body") }
10 | brick x 500 y 500 z 500
11 | #{ id9 = Id("body") }
12 | subtract body { id8 } from body { id9 }
13 | cylinder height 500 radius 0.4572
14 | #{ id10 = Id("body") }
15 | #{ id11 = Id("body") }
16 | intersect body { id9 } { id10 }
17 | #{ id12 = Id("body") }
18 | #{id13 = ( id11 == id12 ) ? id10 : id12}
19 | body { id13 } name "Cell_3"
20 | group "mat:Zircaloy 4" add body { id13 }
21 | graphics flush
22 | set default autosize on
23 | zoom reset
24 | set echo on
25 | set info on
26 | set warning on
27 | set journal on
28 |
--------------------------------------------------------------------------------
/test/materials.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/test/local_tests.py:
--------------------------------------------------------------------------------
1 | import functools
2 |
3 | import openmc
4 |
5 | from openmc_cad_adapter import to_cubit_journal
6 |
7 | from .test_utilities import diff_gold_file
8 |
9 |
10 | def openmc_reset(func):
11 | @functools.wraps(func)
12 | def wrapper(*args, **kwargs):
13 | openmc.reset_auto_ids()
14 | func(*args, **kwargs)
15 | return wrapper
16 |
17 |
18 | @openmc_reset
19 | def test_xcylinder(request):
20 | x_cyl = openmc.XCylinder(r=1.0, y0=10.0, z0=5.0)
21 | g = openmc.Geometry([openmc.Cell(region=-x_cyl)])
22 | to_cubit_journal(g, world=(500, 500, 500), filename='xcylinder.jou')
23 | diff_gold_file('xcylinder.jou')
24 |
25 |
26 | @openmc_reset
27 | def test_ycylinder(request):
28 | y_cyl = openmc.YCylinder(r=1.0, x0=10.0, z0=5.0)
29 | g = openmc.Geometry([openmc.Cell(region=-y_cyl)])
30 | to_cubit_journal(g, world=(500, 500, 500), filename='ycylinder.jou')
31 | diff_gold_file('ycylinder.jou')
32 |
33 |
34 |
--------------------------------------------------------------------------------
/test/test_utilities.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 | import difflib
4 | import filecmp
5 |
6 | from test import test_config
7 |
8 | def diff_files(test_output, gold_file):
9 |
10 | if test_config['update']:
11 | os.makedirs(os.path.dirname(gold_file), exist_ok=True)
12 | shutil.copy(test_output, gold_file)
13 |
14 | if not filecmp.cmp(test_output, gold_file):
15 | print(''.join(difflib.unified_diff(open(gold_file, 'r').readlines(),
16 | open(test_output, 'r').readlines())))
17 | raise RuntimeError(f'{gold_file} and {test_output} are different')
18 |
19 |
20 | def diff_gold_file(gold_file, request=None):
21 | if request is not None:
22 | gold_file = request.path.parent / gold_file
23 | b = request.path.parent / 'gold' / gold_file.name
24 | else:
25 | b = os.path.join(os.path.dirname(__file__), 'gold', os.path.basename(gold_file))
26 | diff_files(gold_file, b)
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | CI:
12 | runs-on: ubuntu-latest
13 | defaults:
14 | run:
15 | shell: bash -leo pipefail {0}
16 |
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v2
20 |
21 | - uses: mamba-org/setup-micromamba@v1
22 | with:
23 | environment-file: .github/environment.yml
24 | init-shell: bash
25 |
26 | - name: Clone OpenMC
27 | run: |
28 | git clone https://github.com/openmc-dev/openmc --branch v0.15.0 $HOME/openmc
29 |
30 | - name: Install
31 | run: |
32 | python -m pip install .
33 |
34 | - name: Test examples
35 | run: |
36 | micromamba activate test-env
37 | OPENMC_EXAMPLES_DIR=$HOME/openmc/examples pytest -v ./test
38 |
39 | - name: Setup tmate session
40 | if: ${{ failure() }}
41 | uses: mxschmitt/action-tmate@v3
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022 UChicago Argonne, LLC
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 |
--------------------------------------------------------------------------------
/test/gold/nested_spheres.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 3
8 | sphere radius 20.0
9 | #{ id1 = Id("body") }
10 | brick x 500 y 500 z 500
11 | #{ id2 = Id("body") }
12 | subtract body { id1 } from body { id2 }
13 | sphere radius 30.0
14 | #{ id3 = Id("body") }
15 | #{ id4 = Id("body") }
16 | intersect body { id2 } { id3 }
17 | #{ id5 = Id("body") }
18 | #{id6 = ( id4 == id5 ) ? id3 : id5}
19 | body { id6 } name "Cell_3"
20 | group "mat:void" add body { id6 }
21 | #CELL 2
22 | sphere radius 10.0
23 | #{ id7 = Id("body") }
24 | brick x 500 y 500 z 500
25 | #{ id8 = Id("body") }
26 | subtract body { id7 } from body { id8 }
27 | sphere radius 20.0
28 | #{ id9 = Id("body") }
29 | #{ id10 = Id("body") }
30 | intersect body { id8 } { id9 }
31 | #{ id11 = Id("body") }
32 | #{id12 = ( id10 == id11 ) ? id9 : id11}
33 | body { id12 } name "Cell_2"
34 | group "mat:void" add body { id12 }
35 | #CELL 1
36 | sphere radius 10.0
37 | #{ id13 = Id("body") }
38 | body { id13 } name "Cell_1"
39 | group "mat:void" add body { id13 }
40 | graphics flush
41 | set default autosize on
42 | zoom reset
43 | set echo on
44 | set info on
45 | set warning on
46 | set journal on
47 |
--------------------------------------------------------------------------------
/test/pincell_cell4.jou:
--------------------------------------------------------------------------------
1 | #CELL 4
2 | cylinder height 500 radius 0.4572
3 | #{ id14 = Id("body") }
4 | brick x 500 y 500 z 500
5 | #{ id15 = Id("body") }
6 | subtract body { id14 } from body { id15 }
7 | brick x 500 y 500 z 500
8 | #{ id16 = Id("body") }
9 | section body { id16 } with xplane offset -0.62992
10 | #{ id17 = Id("body") }
11 | intersect body { id15 } { id16 }
12 | #{ id18 = Id("body") }
13 | #{id19 = ( id17 == id18 ) ? id16 : id18}
14 | brick x 500 y 500 z 500
15 | #{ id20 = Id("body") }
16 | section body { id20 } with xplane offset 0.62992 reverse
17 | #{ id21 = Id("body") }
18 | intersect body { id19 } { id20 }
19 | #{ id22 = Id("body") }
20 | #{id23 = ( id21 == id22 ) ? id20 : id22}
21 | brick x 500 y 500 z 500
22 | #{ id24 = Id("body") }
23 | section body { id24 } with yplane offset -0.62992
24 | #{ id25 = Id("body") }
25 | intersect body { id23 } { id24 }
26 | #{ id26 = Id("body") }
27 | #{id27 = ( id25 == id26 ) ? id24 : id26}
28 | brick x 500 y 500 z 500
29 | #{ id28 = Id("body") }
30 | section body { id28 } with yplane offset 0.62992 reverse
31 | #{ id29 = Id("body") }
32 | intersect body { id27 } { id28 }
33 | #{ id30 = Id("body") }
34 | #{id31 = ( id29 == id30 ) ? id28 : id30}
35 | body { id31 } name "Cell_4"
36 | group "Material_4" add body { id31 }
37 |
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/geom_util.py:
--------------------------------------------------------------------------------
1 | import math
2 | import numpy as np
3 |
4 | def vector_to_euler_xyz(v):
5 | v = np.asarray(v)
6 | v /= np.linalg.norm(v)
7 |
8 | x, y, z = v
9 |
10 | xy_norm = math.sqrt(x**2 + y**2)
11 |
12 | theta = np.arctan2(z, xy_norm)
13 | # if z component is zero, vector is in the xy plane
14 | if z == 0:
15 | theta = np.pi / 2
16 | phi = np.arctan2(y, x)
17 |
18 | # Ensure angles are within [0, 2*pi] range
19 | phi %= (2 * math.pi)
20 | theta %= (2 * math.pi)
21 |
22 | oe = 180 / math.pi
23 | return phi * oe, theta * oe, 0.0
24 |
25 |
26 | def rotate(id, x, y, z, cmds):
27 | if nonzero(x, y, z):
28 | phi, theta, psi = vector_to_euler_xyz((x, y, z))
29 | cmds.append(f"body {{ {id} }} rotate {theta} about Y")
30 | cmds.append(f"body {{ {id} }} rotate {phi} about Z")
31 | # cmds.append(f"body {{ {id} }} rotate {phi} about Z")
32 | # cmds.append(f"body {{ {id} }} rotate {theta} about Y")
33 | # cmds.append(f"body {{ {id} }} rotate {psi} about X")
34 |
35 |
36 | def nonzero(*args):
37 | return any(arg != 0 for arg in args)
38 |
39 |
40 | def move( id, x, y, z, cmds):
41 | if nonzero( x, y, z ):
42 | cmds.append(f"body {{ {id} }} move {x} {y} {z}")
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Conversion of OpenMC Geometry Components to CAD
2 |
3 | [](https://opensource.org/licenses/MIT)
4 |
5 |
6 | This project converts OpenMC models from XML files to a Cubit journal file for import as CAD geometry.
7 |
8 | ## Installation
9 |
10 | To install this tool run:
11 |
12 | ```shell
13 | python -m pip install git+https://github.com/openmc-dev/openmc_cad_adapter.git
14 | ```
15 |
16 | This will make the `openmc_to_cad` script available for use. To convert an OpenMC model, run:
17 |
18 | ```shell
19 | openmc_to_cad /path/to/openmc/model.xml
20 | ```
21 |
22 | ## Disclaimer
23 |
24 | There has been no methodical V&V on this converter; use at your own risk!
25 |
26 |
27 | ## Dependencies
28 |
29 | - [NumPy](https://numpy.org/)
30 | - [OpenMC](https://docs.openmc.org/en/stable/) (>= v0.14.0)
31 |
32 | ## Limitations
33 |
34 | There are several known and many unknown limitations of this tool. It is in a
35 | preliminary state and subject to considerable redesign, including the addition
36 | of a backend for other CAD engines.
37 |
38 | Specific Limitations:
39 |
40 | - general Cones are not handled
41 | - Torii are required to have a single minor radius, OpenMC allows for different minor radii orthogonal to the toroidal axis
--------------------------------------------------------------------------------
/test/geometry.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 |
10 | 1.0 2.0
11 | 3
12 | 0.0 0.0 0.0
13 |
14 | 3
15 | 4 4
16 | 4 3 4
17 | 4 4
18 | 4 4 4
19 | 4 4
20 | 4 4 4
21 | 4 4
22 | 4
23 | 3
24 | 1 1
25 | 1 3 1
26 | 1 1
27 | 1 1 1
28 | 1 1
29 | 1 1 1
30 | 1 1
31 | 1
32 | 3
33 | 4 4
34 | 4 3 4
35 | 4 4
36 | 4 4 4
37 | 4 4
38 | 4 4 4
39 | 4 4
40 | 4
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["flit_core >=3.2,<4"]
3 | build-backend = "flit_core.buildapi"
4 |
5 | [project]
6 | name = "openmc_cad_adapter"
7 | version = "0.1.0"
8 | description = "Tool to convert OpenMC Geometry input file to CAD"
9 | readme = "README.md"
10 | authors = [
11 | { name = "Kevin Tew", email = "kevin@coreform.com" },
12 | { name = "Patrick Shriwise", email = "pshriwise@gmail.com"}
13 | ]
14 | license = { file = "LICENSE" }
15 | requires-python = ">=3.7"
16 |
17 | dependencies = [
18 | "numpy"
19 | ]
20 |
21 | classifiers = [
22 | "Development Status :: 3 - Alpha",
23 | "Intended Audience :: Developers",
24 | "Intended Audience :: End Users/Desktop",
25 | "Intended Audience :: Science/Research",
26 | "License :: OSI Approved :: MIT License",
27 | "Natural Language :: English",
28 | "Operating System :: OS Independent",
29 | "Programming Language :: Python :: 3 :: Only",
30 | "Programming Language :: Python :: 3.7",
31 | "Programming Language :: Python :: 3.8",
32 | "Programming Language :: Python :: 3.9",
33 | "Programming Language :: Python :: 3.10",
34 | "Topic :: Scientific/Engineering :: Physics",
35 | ]
36 |
37 | [project.urls]
38 | "Bug Tracker" = "https://github.com/openmc-dev/openmc_cad_adapter/issues"
39 | Discussions = "https://openmc.discourse.org"
40 | "Source Code" = "https://github.com/openmc-dev/openmc_cad_adapter"
41 |
42 | [project.scripts]
43 | openmc_to_cad = "openmc_cad_adapter.to_cubit_journal:openmc_to_cad"
44 |
--------------------------------------------------------------------------------
/test/gold/pincell_cell4.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 4
8 | cylinder height 500 radius 0.4572
9 | #{ id14 = Id("body") }
10 | brick x 500 y 500 z 500
11 | #{ id15 = Id("body") }
12 | subtract body { id14 } from body { id15 }
13 | brick x 500 y 500 z 500
14 | #{ id16 = Id("body") }
15 | section body { id16 } with xplane offset -0.62992
16 | #{ id17 = Id("body") }
17 | intersect body { id15 } { id16 }
18 | #{ id18 = Id("body") }
19 | #{id19 = ( id17 == id18 ) ? id16 : id18}
20 | brick x 500 y 500 z 500
21 | #{ id20 = Id("body") }
22 | section body { id20 } with xplane offset 0.62992 reverse
23 | #{ id21 = Id("body") }
24 | intersect body { id19 } { id20 }
25 | #{ id22 = Id("body") }
26 | #{id23 = ( id21 == id22 ) ? id20 : id22}
27 | brick x 500 y 500 z 500
28 | #{ id24 = Id("body") }
29 | section body { id24 } with yplane offset -0.62992
30 | #{ id25 = Id("body") }
31 | intersect body { id23 } { id24 }
32 | #{ id26 = Id("body") }
33 | #{id27 = ( id25 == id26 ) ? id24 : id26}
34 | brick x 500 y 500 z 500
35 | #{ id28 = Id("body") }
36 | section body { id28 } with yplane offset 0.62992 reverse
37 | #{ id29 = Id("body") }
38 | intersect body { id27 } { id28 }
39 | #{ id30 = Id("body") }
40 | #{id31 = ( id29 == id30 ) ? id28 : id30}
41 | body { id31 } name "Cell_4"
42 | group "mat:Borated water" add body { id31 }
43 | graphics flush
44 | set default autosize on
45 | zoom reset
46 | set echo on
47 | set info on
48 | set warning on
49 | set journal on
50 |
--------------------------------------------------------------------------------
/test/pincell.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 1
4 | cylinder height 500 radius 0.39218
5 | #{ id1 = Id("body") }
6 | body { id1 } name "Cell_1"
7 | group "Material_1" add body { id1 }
8 | #CELL 2
9 | cylinder height 500 radius 0.39218
10 | #{ id2 = Id("body") }
11 | brick x 500 y 500 z 500
12 | #{ id3 = Id("body") }
13 | subtract body { id2 } from body { id3 }
14 | cylinder height 500 radius 0.40005
15 | #{ id4 = Id("body") }
16 | #{ id5 = Id("body") }
17 | intersect body { id3 } { id4 }
18 | #{ id6 = Id("body") }
19 | #{id7 = ( id5 == id6 ) ? id4 : id6}
20 | body { id7 } name "Cell_2"
21 | group "Material_2" add body { id7 }
22 | #CELL 3
23 | cylinder height 500 radius 0.40005
24 | #{ id8 = Id("body") }
25 | brick x 500 y 500 z 500
26 | #{ id9 = Id("body") }
27 | subtract body { id8 } from body { id9 }
28 | cylinder height 500 radius 0.4572
29 | #{ id10 = Id("body") }
30 | #{ id11 = Id("body") }
31 | intersect body { id9 } { id10 }
32 | #{ id12 = Id("body") }
33 | #{id13 = ( id11 == id12 ) ? id10 : id12}
34 | body { id13 } name "Cell_3"
35 | group "Material_3" add body { id13 }
36 | #CELL 4
37 | cylinder height 500 radius 0.4572
38 | #{ id14 = Id("body") }
39 | brick x 500 y 500 z 500
40 | #{ id15 = Id("body") }
41 | subtract body { id14 } from body { id15 }
42 | brick x 500 y 500 z 500
43 | #{ id16 = Id("body") }
44 | section body { id16 } with xplane offset -0.62992
45 | #{ id17 = Id("body") }
46 | intersect body { id15 } { id16 }
47 | #{ id18 = Id("body") }
48 | #{id19 = ( id17 == id18 ) ? id16 : id18}
49 | brick x 500 y 500 z 500
50 | #{ id20 = Id("body") }
51 | section body { id20 } with xplane offset 0.62992 reverse
52 | #{ id21 = Id("body") }
53 | intersect body { id19 } { id20 }
54 | #{ id22 = Id("body") }
55 | #{id23 = ( id21 == id22 ) ? id20 : id22}
56 | brick x 500 y 500 z 500
57 | #{ id24 = Id("body") }
58 | section body { id24 } with yplane offset -0.62992
59 | #{ id25 = Id("body") }
60 | intersect body { id23 } { id24 }
61 | #{ id26 = Id("body") }
62 | #{id27 = ( id25 == id26 ) ? id24 : id26}
63 | brick x 500 y 500 z 500
64 | #{ id28 = Id("body") }
65 | section body { id28 } with yplane offset 0.62992 reverse
66 | #{ id29 = Id("body") }
67 | intersect body { id27 } { id28 }
68 | #{ id30 = Id("body") }
69 | #{id31 = ( id29 == id30 ) ? id28 : id30}
70 | body { id31 } name "Cell_4"
71 | group "Material_4" add body { id31 }
72 |
--------------------------------------------------------------------------------
/test/gold/pincell.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | cylinder height 500 radius 0.39218
9 | #{ id1 = Id("body") }
10 | body { id1 } name "Cell_1"
11 | group "mat:UO2 fuel at 2.4% wt enrichme" add body { id1 }
12 | #CELL 2
13 | cylinder height 500 radius 0.39218
14 | #{ id2 = Id("body") }
15 | brick x 500 y 500 z 500
16 | #{ id3 = Id("body") }
17 | subtract body { id2 } from body { id3 }
18 | cylinder height 500 radius 0.40005
19 | #{ id4 = Id("body") }
20 | #{ id5 = Id("body") }
21 | intersect body { id3 } { id4 }
22 | #{ id6 = Id("body") }
23 | #{id7 = ( id5 == id6 ) ? id4 : id6}
24 | body { id7 } name "Cell_2"
25 | group "mat:Helium for gap" add body { id7 }
26 | #CELL 3
27 | cylinder height 500 radius 0.40005
28 | #{ id8 = Id("body") }
29 | brick x 500 y 500 z 500
30 | #{ id9 = Id("body") }
31 | subtract body { id8 } from body { id9 }
32 | cylinder height 500 radius 0.4572
33 | #{ id10 = Id("body") }
34 | #{ id11 = Id("body") }
35 | intersect body { id9 } { id10 }
36 | #{ id12 = Id("body") }
37 | #{id13 = ( id11 == id12 ) ? id10 : id12}
38 | body { id13 } name "Cell_3"
39 | group "mat:Zircaloy 4" add body { id13 }
40 | #CELL 4
41 | cylinder height 500 radius 0.4572
42 | #{ id14 = Id("body") }
43 | brick x 500 y 500 z 500
44 | #{ id15 = Id("body") }
45 | subtract body { id14 } from body { id15 }
46 | brick x 500 y 500 z 500
47 | #{ id16 = Id("body") }
48 | section body { id16 } with xplane offset -0.62992
49 | #{ id17 = Id("body") }
50 | intersect body { id15 } { id16 }
51 | #{ id18 = Id("body") }
52 | #{id19 = ( id17 == id18 ) ? id16 : id18}
53 | brick x 500 y 500 z 500
54 | #{ id20 = Id("body") }
55 | section body { id20 } with xplane offset 0.62992 reverse
56 | #{ id21 = Id("body") }
57 | intersect body { id19 } { id20 }
58 | #{ id22 = Id("body") }
59 | #{id23 = ( id21 == id22 ) ? id20 : id22}
60 | brick x 500 y 500 z 500
61 | #{ id24 = Id("body") }
62 | section body { id24 } with yplane offset -0.62992
63 | #{ id25 = Id("body") }
64 | intersect body { id23 } { id24 }
65 | #{ id26 = Id("body") }
66 | #{id27 = ( id25 == id26 ) ? id24 : id26}
67 | brick x 500 y 500 z 500
68 | #{ id28 = Id("body") }
69 | section body { id28 } with yplane offset 0.62992 reverse
70 | #{ id29 = Id("body") }
71 | intersect body { id27 } { id28 }
72 | #{ id30 = Id("body") }
73 | #{id31 = ( id29 == id30 ) ? id28 : id30}
74 | body { id31 } name "Cell_4"
75 | group "mat:Borated water" add body { id31 }
76 | graphics flush
77 | set default autosize on
78 | zoom reset
79 | set echo on
80 | set info on
81 | set warning on
82 | set journal on
83 |
--------------------------------------------------------------------------------
/test/test_examples.py:
--------------------------------------------------------------------------------
1 | import os
2 | import difflib
3 | import filecmp
4 | from pathlib import Path
5 |
6 | import subprocess
7 |
8 | import pytest
9 |
10 | from openmc_cad_adapter import to_cubit_journal
11 | import openmc
12 |
13 | from test import diff_files
14 |
15 |
16 | examples = ["pincell/build_xml.py",
17 | "lattice/hexagonal/build_xml.py",
18 | "assembly/assembly.py"]
19 |
20 |
21 | if 'OPENMC_EXAMPLES_DIR' not in os.environ:
22 | raise EnvironmentError('Variable OPENMC_EXAMPLES_DIR is required')
23 |
24 |
25 | OPENMC_EXAMPLES_DIR = Path(os.environ['OPENMC_EXAMPLES_DIR']).resolve()
26 |
27 |
28 | def example_name(example):
29 | return '-'.join(example.split('/')[:-1])
30 |
31 |
32 | def generate_example_xml(example):
33 | if 'assembly' in example:
34 | subprocess.Popen(['python', str(OPENMC_EXAMPLES_DIR / example), '--generate']).wait()
35 | else:
36 | exec(open(OPENMC_EXAMPLES_DIR / example).read())
37 |
38 |
39 | @pytest.mark.parametrize("example", examples, ids=example_name)
40 | def test_examples(example, request, run_in_tmpdir):
41 |
42 | openmc.reset_auto_ids()
43 | generate_example_xml(example)
44 |
45 | openmc.reset_auto_ids()
46 | model = openmc.Model.from_xml()
47 |
48 | world = [500, 500, 500]
49 | output = example_name(example) + '.jou'
50 | to_cubit_journal(model.geometry, world=world, filename=output)
51 |
52 | gold_file = request.path.parent / Path('gold') / Path(output)
53 | diff_files(output, gold_file)
54 |
55 |
56 | def test_cell_by_cell_conversion(request, run_in_tmpdir):
57 | openmc.reset_auto_ids()
58 | exec(open(OPENMC_EXAMPLES_DIR / "pincell/build_xml.py").read())
59 |
60 | openmc.reset_auto_ids()
61 | model = openmc.Model.from_xml()
62 |
63 | cell_ids = list(model.geometry.get_all_cells().keys())
64 |
65 | world = [500, 500, 500]
66 | output = 'pincell'
67 | to_cubit_journal(model.geometry, world=world, cells=cell_ids, filename=output)
68 |
69 | for cell_id in cell_ids:
70 | output = f'pincell_cell{cell_id}.jou'
71 | gold_file = request.path.parent / Path('gold') / Path(output)
72 | diff_files(output, gold_file)
73 |
74 |
75 | @pytest.mark.parametrize("example", examples, ids=example_name)
76 | def test_examples_cli(example, request, run_in_tmpdir):
77 |
78 | openmc.reset_auto_ids()
79 | generate_example_xml(example)
80 |
81 | openmc.reset_auto_ids()
82 | world = [500, 500, 500]
83 | output = example_name(example) + '.jou'
84 | cmd = ['openmc_to_cad', '.', '-o', output, '--world'] + [str(w) for w in world]
85 | pipe = subprocess.Popen(cmd)
86 | pipe.wait()
87 | if pipe.returncode != 0:
88 | raise RuntimeError(f'Command {" ".join(cmd)} failed')
89 |
90 | gold_file = request.path.parent / Path('gold') / Path(output)
91 | diff_files(output, gold_file)
--------------------------------------------------------------------------------
/test/gold/plane.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | brick x 1000 y 1000 z 1000
9 | #{ id1 = Id("body") }
10 | body { id1 } move 0.0 0.0 -500
11 | Rotate body { id1 } about 0 0 0 direction -0.7071067811865476 0.7071067811865476 0.0 Angle 90.0
12 | body { id1 } move -2.4999999999999996 -2.4999999999999996 -0.0
13 | brick x 500 y 500 z 500
14 | #{ id2 = Id("body") }
15 | subtract body { id1 } from body { id2 }
16 | brick x 1000 y 1000 z 1000
17 | #{ id3 = Id("body") }
18 | body { id3 } move 0.0 0.0 -500
19 | Rotate body { id3 } about 0 0 0 direction -0.7071067811865476 0.7071067811865476 0.0 Angle 90.0
20 | body { id3 } move 2.4999999999999996 2.4999999999999996 0.0
21 | brick x 500 y 500 z 500
22 | #{ id4 = Id("body") }
23 | intersect body { id3 } { id4 }
24 | #{ id5 = Id("body") }
25 | intersect body { id2 } { id4 }
26 | #{ id6 = Id("body") }
27 | #{id7 = ( id5 == id6 ) ? id4 : id6}
28 | brick x 1000 y 1000 z 1000
29 | #{ id8 = Id("body") }
30 | body { id8 } move 0.0 0.0 -500
31 | Rotate body { id8 } about 0 0 0 direction -1.0 0.0 0.0 Angle 45.00000000000001
32 | body { id8 } move -0.0 -2.4999999999999996 -2.4999999999999996
33 | brick x 500 y 500 z 500
34 | #{ id9 = Id("body") }
35 | subtract body { id8 } from body { id9 }
36 | #{ id10 = Id("body") }
37 | intersect body { id7 } { id9 }
38 | #{ id11 = Id("body") }
39 | #{id12 = ( id10 == id11 ) ? id9 : id11}
40 | brick x 1000 y 1000 z 1000
41 | #{ id13 = Id("body") }
42 | body { id13 } move 0.0 0.0 -500
43 | Rotate body { id13 } about 0 0 0 direction -1.0 0.0 0.0 Angle 45.00000000000001
44 | body { id13 } move 0.0 2.4999999999999996 2.4999999999999996
45 | brick x 500 y 500 z 500
46 | #{ id14 = Id("body") }
47 | intersect body { id13 } { id14 }
48 | #{ id15 = Id("body") }
49 | intersect body { id12 } { id14 }
50 | #{ id16 = Id("body") }
51 | #{id17 = ( id15 == id16 ) ? id14 : id16}
52 | brick x 1000 y 1000 z 1000
53 | #{ id18 = Id("body") }
54 | body { id18 } move 0.0 0.0 -500
55 | Rotate body { id18 } about 0 0 0 direction 0.0 1.0 0.0 Angle 45.00000000000001
56 | body { id18 } move -2.4999999999999996 -0.0 -2.4999999999999996
57 | brick x 500 y 500 z 500
58 | #{ id19 = Id("body") }
59 | subtract body { id18 } from body { id19 }
60 | #{ id20 = Id("body") }
61 | intersect body { id17 } { id19 }
62 | #{ id21 = Id("body") }
63 | #{id22 = ( id20 == id21 ) ? id19 : id21}
64 | brick x 1000 y 1000 z 1000
65 | #{ id23 = Id("body") }
66 | body { id23 } move 0.0 0.0 -500
67 | Rotate body { id23 } about 0 0 0 direction 0.0 1.0 0.0 Angle 45.00000000000001
68 | body { id23 } move 2.4999999999999996 0.0 2.4999999999999996
69 | brick x 500 y 500 z 500
70 | #{ id24 = Id("body") }
71 | intersect body { id23 } { id24 }
72 | #{ id25 = Id("body") }
73 | intersect body { id22 } { id24 }
74 | #{ id26 = Id("body") }
75 | #{id27 = ( id25 == id26 ) ? id24 : id26}
76 | body { id27 } name "Cell_1"
77 | group "mat:void" add body { id27 }
78 | graphics flush
79 | set default autosize on
80 | zoom reset
81 | set echo on
82 | set info on
83 | set warning on
84 | set journal on
85 |
--------------------------------------------------------------------------------
/test/test_quadric.py:
--------------------------------------------------------------------------------
1 |
2 | import pytest
3 |
4 | import openmc
5 |
6 | from openmc_cad_adapter import to_cubit_journal
7 | from openmc_cad_adapter.gqs import *
8 |
9 |
10 | def test_ellipsoid_classification():
11 | # ELLIPSOID
12 | testEllip = openmc.Quadric(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
13 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testEllip)
14 | assert quadric_type == ELLIPSOID
15 |
16 |
17 | def test_one_sheet_hyperboloid_classification():
18 | # ONE_SHEET_HYPERBOLOID
19 | testOneSheet = openmc.Quadric(1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
20 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testOneSheet)
21 | assert quadric_type == ONE_SHEET_HYPERBOLOID
22 |
23 |
24 | def test_two_sheet_hyperboloid_classification():
25 | # TWO_SHEET_HYPERBOLOID
26 | testTwoSheet = openmc.Quadric(-1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
27 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testTwoSheet)
28 | assert quadric_type == TWO_SHEET_HYPERBOLOID
29 |
30 |
31 | def test_elliptic_cone_classification():
32 | # ELLIPTIC_CONE
33 | testEllCone = openmc.Quadric(1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
34 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testEllCone)
35 | assert quadric_type == ELLIPTIC_CONE
36 |
37 |
38 | def test_elliptic_paraboloid_classification():
39 | # ELLIPTIC_PARABOLOID
40 | testEllPara = openmc.Quadric(1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0)
41 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testEllPara)
42 | assert quadric_type == ELLIPTIC_PARABOLOID
43 |
44 |
45 | def test_hyperbolic_paraboloid_classification():
46 | # HYPERBOLIC_PARABOLOID
47 | testHypPara = openmc.Quadric(1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0)
48 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testHypPara)
49 | assert quadric_type == HYPERBOLIC_PARABOLOID
50 |
51 |
52 | def test_elliptic_cyl_classification():
53 | # ELLIPTIC_CYL
54 | testEllCyl = openmc.Quadric(1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
55 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testEllCyl)
56 | assert quadric_type == ELLIPTIC_CYLINDER
57 |
58 |
59 | def test_hyperbolic_cyl_classification():
60 | # HYPERBOLIC_CYL
61 | testHypCyl = openmc.Quadric(1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)
62 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testHypCyl)
63 | assert quadric_type == HYPERBOLIC_CYLINDER
64 |
65 |
66 | def test_parabolic_cyl_classification():
67 | # PARABOLIC_CYL
68 | testParaCyl = openmc.Quadric(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0)
69 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testParaCyl)
70 | assert quadric_type == PARABOLIC_CYLINDER
71 |
72 |
73 | # Transformation Tests
74 | def test_ellipsoid_classification():
75 | # ELLIPSOID
76 | testRotEllip = openmc.Quadric(103, 125, 66, -48, -12, -60, 0, 0, 0, -294)
77 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testRotEllip)
78 | assert quadric_type == ELLIPSOID
79 |
80 |
81 | def test_elliptic_cone_classification():
82 | # ELLIPTIC_CONE
83 | testRotCone = openmc.Quadric(3, 3, -1, 2, 0, 0, 0, 0, 0, 0)
84 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testRotCone)
85 | assert quadric_type == ELLIPTIC_CONE
86 |
87 |
88 | def test_elliptic_paraboloid_classification():
89 | # ELLIPTIC_PARABOLOID
90 | testRotEllParab = openmc.Quadric(1, 3, 1, 2, 2, 2, -2, 4, 2, 12)
91 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testRotEllParab)
92 | assert quadric_type == ELLIPTIC_PARABOLOID
93 |
94 |
95 | def test_elliptic_cylinder_classification():
96 | # ELLIPTIC_CYLINDER
97 | testRotEllCyl = openmc.Quadric(5, 2, 5, -4, -4, -2, 6, -12, 18, -3)
98 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testRotEllCyl)
99 | assert quadric_type == ELLIPTIC_CYLINDER
100 |
101 |
102 | def test_parabolic_cylinder_classification():
103 | # PARABOLIC CYLINDER
104 | testRotParaCyl = openmc.Quadric(9, 36, 4, -36, -24, 12, -16, -24, -48, 56)
105 | quadric_type, A, B, C, K, _, _ = characterize_general_quadratic(testRotParaCyl)
106 | assert quadric_type == PARABOLIC_CYLINDER
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/gqs.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from numpy.linalg import matrix_rank
3 |
4 | UNKNOWN_QUADRIC = -1
5 | ELLIPSOID = 1
6 | ONE_SHEET_HYPERBOLOID = 2
7 | TWO_SHEET_HYPERBOLOID = 3
8 | ELLIPTIC_CONE = 4
9 | ELLIPTIC_PARABOLOID = 5
10 | HYPERBOLIC_PARABOLOID = 6
11 | ELLIPTIC_CYLINDER = 7
12 | HYPERBOLIC_CYLINDER = 8
13 | PARABOLIC_CYLINDER = 9
14 |
15 |
16 | def characterize_general_quadratic( surface ): #s surface
17 | gq_tol = 1e-6
18 | equivalence_tol = 1e-8
19 | a = surface.coefficients['a']
20 | b = surface.coefficients['b']
21 | c = surface.coefficients['c']
22 | d = surface.coefficients['d']
23 | e = surface.coefficients['e']
24 | f = surface.coefficients['f']
25 | g = surface.coefficients['g']
26 | h = surface.coefficients['h']
27 | j = surface.coefficients['j']
28 | k = surface.coefficients['k']
29 | #coefficient matrix
30 | Aa = np.asarray([[a, d/2, f/2],
31 | [d/2, b, e/2],
32 | [f/2, e/2, c]])
33 | #hessian matrix
34 | Ac = np.asarray([[a, d/2, f/2, g/2],
35 | [d/2, b, e/2, h/2],
36 | [f/2, e/2, c, j/2],
37 | [g/2, h/2, j/2, k]])
38 | rank_Aa = matrix_rank( Aa )
39 | rank_Ac = matrix_rank( Ac )
40 |
41 | det_Ac = np.linalg.det(Ac)
42 | if np.abs( det_Ac ) < gq_tol:
43 | delta = 0
44 | else:
45 | delta = -1 if det_Ac < 0 else 1
46 |
47 | eigenvalues, eigenvectors = np.linalg.eig(Aa)
48 | signs = np.array([0, 0, 0])
49 | for i in range(0, 3):
50 | if eigenvalues[i] > -1 * gq_tol:
51 | signs[i] = 1
52 | else:
53 | signs[i] = -1
54 |
55 | S = 1 if np.abs( signs.sum() ) == 3 else -1
56 |
57 | B = np.array([[ -g/2], [-h/2], [-j/2 ]])
58 |
59 | Aai = np.linalg.pinv( Aa )
60 |
61 | C = np.dot(Aai, B)
62 |
63 | dx = C[0]
64 | dy = C[1]
65 | dz = C[2]
66 |
67 | #Update the constant using the resulting translation
68 | K_ = k + (g/2)*dx + (h/2)*dy + (j/2)*dz
69 | K_ = K_[0]
70 |
71 | if rank_Aa == 2 and rank_Ac == 3 and S == 1:
72 | delta = -1 if K_ * signs[0] < 0 else 1
73 |
74 | D = -1 if K_ * signs[0] else 1
75 |
76 |
77 | def find_type( rAa, rAc, delta, S, D ):
78 | quadric_type = UNKNOWN_QUADRIC
79 | if 3 == rAa and 4 == rAc and -1 == delta and 1 == S:
80 | quadric_type = ELLIPSOID
81 | elif 3 == rAa and 4 == rAc and 1 == delta and -1 == S:
82 | quadric_type = ONE_SHEET_HYPERBOLOID
83 | elif 3 == rAa and 4 == rAc and -1 == delta and -1 == S:
84 | quadric_type = TWO_SHEET_HYPERBOLOID
85 | elif 3 == rAa and 3 == rAc and 0 == delta and -1 == S:
86 | quadric_type = ELLIPTIC_CONE
87 | elif 2 == rAa and 4 == rAc and -1 == delta and 1 == S:
88 | quadric_type = ELLIPTIC_PARABOLOID
89 | elif 2 == rAa and 4 == rAc and 1 == delta and -1 == S:
90 | quadric_type = HYPERBOLIC_PARABOLOID
91 | elif 2 == rAa and 3 == rAc and -1 == delta and 1 == S:
92 | quadric_type = ELLIPTIC_CYLINDER
93 | elif 2 == rAa and 3 == rAc and 0 == delta and -1 == S:
94 | quadric_type = HYPERBOLIC_CYLINDER
95 | elif 1 == rAa and 3 == rAc and 0 == delta and 1 == S:
96 | quadric_type = PARABOLIC_CYLINDER
97 | else:
98 | quadric_type = UNKNOWN_QUADRIC
99 |
100 | # special case, replace delta with D
101 | if 2 == rAa and 3 == rAc and 1 == S and D != 0 :
102 | quadric_type = find_type( rAa, rAc, D, S, 0 )
103 |
104 |
105 | if quadric_type == UNKNOWN_QUADRIC:
106 | msg = f'UNKNOWN QUADRIC: rAa={rAa}, rAc={rAc}, delta={delta}, S={S}, D={D}'
107 | raise ValueError(msg)
108 |
109 | return quadric_type
110 |
111 | gq_type = find_type(rank_Aa, rank_Ac, delta, S, D)
112 |
113 | #set the translation
114 | translation = C
115 |
116 | rotation_matrix = eigenvectors
117 |
118 | for i in range( 0, 3 ):
119 | if abs(eigenvalues[i]) < gq_tol:
120 | eigenvalues[i] = 0
121 |
122 | A_ = eigenvalues[0]
123 | B_ = eigenvalues[1]
124 | C_ = eigenvalues[2];
125 | D_ = 0; E_ = 0; F_ = 0;
126 | G_ = 0; H_ = 0; J_ = 0;
127 |
128 | # alter type and coefficients for special cases
129 | # where coefficients are near-zero
130 | if gq_type == ONE_SHEET_HYPERBOLOID:
131 | if abs(K_) < equivalence_tol:
132 | K_ = 0
133 | gq_type = ELLIPTIC_CONE
134 | if gq_type == TWO_SHEET_HYPERBOLOID:
135 | if abs(K_) < equivalence_tol:
136 | K_ = 0
137 | gq_type = ELLIPTIC_CONE
138 | if gq_type == ELLIPSOID:
139 | if abs(A_) < equivalence_tol:
140 | A_ = 0
141 | gq_type = ELLIPTIC_CYLINDER
142 | elif abs( B_) < equivalence_tol:
143 | B_ = 0
144 | gq_type = ELLIPTIC_CYLINDER
145 | elif abs( C_) < equivalence_tol:
146 | C_ = 0
147 | gq_type = ELLIPTIC_CYLINDER
148 |
149 | return (gq_type, A_, B_, C_, K_, translation, rotation_matrix)
150 |
151 |
152 | __all__ = ["characterize_general_quadratic",
153 | "ELLIPSOID",
154 | "ONE_SHEET_HYPERBOLOID",
155 | "TWO_SHEET_HYPERBOLOID",
156 | "ELLIPTIC_CONE",
157 | "ELLIPTIC_PARABOLOID",
158 | "HYPERBOLIC_PARABOLOID",
159 | "ELLIPTIC_CYLINDER",
160 | "HYPERBOLIC_CYLINDER",
161 | "PARABOLIC_CYLINDER"]
162 |
--------------------------------------------------------------------------------
/test/test_local.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | import pytest
4 |
5 | import openmc
6 |
7 | from openmc_cad_adapter import to_cubit_journal
8 |
9 | from .test_utilities import diff_gold_file
10 | from test import run_in_tmpdir
11 |
12 |
13 | def reset_openmc_ids(func):
14 | """
15 | Decorator to reset the auto-generated IDs in OpenMC before running a test
16 | """
17 | @wraps(func)
18 | def wrapper(*args, **kwargs):
19 | openmc.reset_auto_ids()
20 | func(*args, **kwargs)
21 | return wrapper
22 |
23 |
24 | @reset_openmc_ids
25 | def test_planes(request, run_in_tmpdir):
26 | plane1 = openmc.Plane(a=1.0, b=1.0, c=0.0, d=-5.0)
27 | plane2 = openmc.Plane(a=1.0, b=1.0, c=0.0, d=5.0)
28 | plane3 = openmc.Plane(a=0.0, b=1.0, c=1.0, d=-5.0)
29 | plane4 = openmc.Plane(a=0.0, b=1.0, c=1.0, d=5.0)
30 | plane5 = openmc.Plane(a=1.0, b=0.0, c=1.0, d=-5.0)
31 | plane6 = openmc.Plane(a=1.0, b=0.0, c=1.0, d=5.0)
32 | g = openmc.Geometry([openmc.Cell(region=+plane1 & -plane2 & +plane3 & -plane4 & +plane5 & -plane6)])
33 | to_cubit_journal(g, world=(500, 500, 500), filename='plane.jou')
34 | diff_gold_file('plane.jou')
35 |
36 |
37 | @reset_openmc_ids
38 | def test_nested_spheres(request, run_in_tmpdir):
39 | inner_sphere = openmc.Sphere(r=10.0)
40 | middle_sphere = openmc.Sphere(r=20.0)
41 | outer_sphere = openmc.Sphere(r=30.0)
42 |
43 | inner_cell = openmc.Cell(region=-inner_sphere)
44 | middle_cell = openmc.Cell(region=+inner_sphere & -middle_sphere)
45 | outer_cell = openmc.Cell(region=+middle_sphere & -outer_sphere)
46 |
47 | g = openmc.Geometry([outer_cell, middle_cell, inner_cell])
48 | to_cubit_journal(g, world=(500, 500, 500), filename='nested_spheres.jou')
49 | diff_gold_file('nested_spheres.jou')
50 |
51 |
52 | # Test the XCylinder and YCylinder classes, the ZCylinder surface is tested
53 | # extensively in the OpenMC example tests
54 | @reset_openmc_ids
55 | def test_xcylinder(request, run_in_tmpdir):
56 | x_cyl = openmc.XCylinder(r=1.0, y0=10.0, z0=5.0)
57 | g = openmc.Geometry([openmc.Cell(region=-x_cyl)])
58 | to_cubit_journal(g, world=(500, 500, 500), filename='xcylinder.jou')
59 | diff_gold_file('xcylinder.jou')
60 |
61 |
62 | @reset_openmc_ids
63 | def test_ycylinder(request, run_in_tmpdir):
64 | y_cyl = openmc.YCylinder(r=1.0, x0=10.0, z0=5.0)
65 | g = openmc.Geometry([openmc.Cell(region=-y_cyl)])
66 | to_cubit_journal(g, world=(500, 500, 500), filename='ycylinder.jou')
67 | diff_gold_file('ycylinder.jou')
68 |
69 |
70 | @reset_openmc_ids
71 | def test_cylinder(request, run_in_tmpdir):
72 | cyl = openmc.Cylinder(x0=0.0, y0=0.0, z0=0.0, r=6.0, dx=0.7071, dy=0.7071, dz=0.0)
73 | g = openmc.Geometry([openmc.Cell(region=-cyl)])
74 | to_cubit_journal(g, world=(500, 500, 500), filename='cylinder.jou')
75 | diff_gold_file('cylinder.jou')
76 |
77 |
78 | @reset_openmc_ids
79 | def test_x_cone(request, run_in_tmpdir):
80 | x_cone = openmc.XCone(x0=30.0, y0=3.0, z0=5.0, r2=5.0)
81 | g = openmc.Geometry([openmc.Cell(region=-x_cone)])
82 | to_cubit_journal(g, world=(500, 500, 500), filename='x_cone.jou')
83 | diff_gold_file('x_cone.jou')
84 |
85 |
86 | @reset_openmc_ids
87 | def test_y_cone(request, run_in_tmpdir):
88 | y_cone = openmc.YCone(x0=40.0, y0=20.0, z0=7.0, r2=2.0)
89 | g = openmc.Geometry([openmc.Cell(region=-y_cone)])
90 | to_cubit_journal(g, world=(500, 500, 500), filename='y_cone.jou')
91 | diff_gold_file('y_cone.jou')
92 |
93 |
94 | @reset_openmc_ids
95 | def test_z_cone(request, run_in_tmpdir):
96 | z_cone = openmc.ZCone(x0=50.0, y0=10.0, z0=2.0, r2=0.25)
97 | g = openmc.Geometry([openmc.Cell(region=-z_cone)])
98 | to_cubit_journal(g, world=(500, 500, 500), filename='z_cone.jou')
99 | diff_gold_file('z_cone.jou')
100 |
101 |
102 | @reset_openmc_ids
103 | def test_x_torus(request, run_in_tmpdir):
104 | x_torus = openmc.XTorus(x0=10.0, y0=10.0, z0=10.0, a=5.0, b=2.0, c=2.0)
105 | g = openmc.Geometry([openmc.Cell(region=-x_torus)])
106 | to_cubit_journal(g, world=(500, 500, 500), filename='x_torus.jou')
107 | diff_gold_file('x_torus.jou')
108 |
109 |
110 | @reset_openmc_ids
111 | def test_y_torus(request, run_in_tmpdir):
112 | y_torus = openmc.YTorus(x0=-10.0, y0=-10.0, z0=-10.0, a=5.0, b=2.0, c=2.0)
113 | g = openmc.Geometry([openmc.Cell(region=-y_torus)])
114 | to_cubit_journal(g, world=(500, 500, 500), filename='y_torus.jou')
115 | diff_gold_file('y_torus.jou')
116 |
117 |
118 | @reset_openmc_ids
119 | def test_z_torus(request, run_in_tmpdir):
120 | z_torus = openmc.ZTorus(x0=50.0, y0=50.0, z0=50.0, a=5.0, b=2.0, c=2.0)
121 | g = openmc.Geometry([openmc.Cell(region=-z_torus)])
122 | to_cubit_journal(g, world=(500, 500, 500), filename='z_torus.jou')
123 | diff_gold_file('z_torus.jou')
124 |
125 |
126 | @reset_openmc_ids
127 | def test_torus_diff_radii(request, run_in_tmpdir):
128 | with pytest.raises(ValueError):
129 | z_torus = openmc.ZTorus(x0=50.0, y0=50.0, z0=50.0, a=5.0, b=2.0, c=3.0)
130 | g = openmc.Geometry([openmc.Cell(region=-z_torus)])
131 | to_cubit_journal(g, world=(500, 500, 500), filename='a_torus.jou')
132 |
133 |
134 | @reset_openmc_ids
135 | def test_general_cone(request, run_in_tmpdir):
136 | with pytest.raises(NotImplementedError):
137 | cone = openmc.Cone(x0=0.0, y0=0.0, z0=0.0, r2=6.0, dx=1, dy=1, dz=1)
138 | g = openmc.Geometry([openmc.Cell(region=-cone)])
139 | to_cubit_journal(g, world=(500, 500, 500), filename='cone.jou')
140 |
141 | @reset_openmc_ids
142 | def test_gq_ellipsoid(request, run_in_tmpdir):
143 | ellipsoid = openmc.Quadric(1, 2, 3, k=-1)
144 | g = openmc.Geometry([openmc.Cell(region=-ellipsoid)])
145 | to_cubit_journal(g, world=(500, 500, 500), filename='ellipsoid.jou')
146 | diff_gold_file('ellipsoid.jou')
147 |
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/surfaces.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 | import sys
3 | import math
4 | import warnings
5 |
6 | import numpy as np
7 | import openmc
8 |
9 | from .cubit_util import emit_get_last_id, lastid
10 | from .geom_util import move, rotate
11 |
12 | def indent(indent_size):
13 | return ' ' * (2*indent_size)
14 |
15 |
16 | class CADSurface(ABC):
17 |
18 | def to_cubit_surface(self, ent_type, node, extents, inner_world=None, hex=False):
19 | ids, cmds = self.to_cubit_surface_inner(ent_type, node, extents, inner_world, hex)
20 | # TODO: Add boundary condition to the correct surface(s)
21 | # cmds += self.boundary_condition(ids)
22 | return ids, cmds
23 |
24 | @abstractmethod
25 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
26 | raise NotImplementedError
27 |
28 | def boundary_condition(self, cad_surface_ids):
29 | if self.boundary_type == 'transmission':
30 | return []
31 | cmds = []
32 | cmds.append(f'group \"boundary:{self.boundary_type}\" add surface {cad_surface_ids[2:]}')
33 | return cmds
34 |
35 | @classmethod
36 | def from_openmc_surface(cls, surface):
37 | with warnings.catch_warnings() as w:
38 | warnings.simplefilter("ignore")
39 | return cls.from_openmc_surface_inner(surface)
40 |
41 | @classmethod
42 | @abstractmethod
43 | def from_openmc_surface_inner(cls, surface):
44 | raise NotImplementedError
45 |
46 |
47 | class CADPlane(CADSurface, openmc.Plane):
48 |
49 | @staticmethod
50 | def lreverse(node):
51 | return "" if node.side == '-' else "reverse"
52 |
53 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
54 | cmds = []
55 |
56 | n = np.array([self.coefficients[k] for k in ('a', 'b', 'c')])
57 | distance = self.coefficients['d'] / np.linalg.norm(n)
58 |
59 | # Create cutter block larger than the world and rotate/translate it so
60 | # the +z plane of the block is coincident with this general plane
61 | max_extent = np.max(extents)
62 | cmds.append(f"brick x {2*max_extent} y {2*max_extent} z {2*max_extent}" )
63 | ids = emit_get_last_id( ent_type, cmds)
64 | cmds.append(f"body {{ { ids } }} move 0.0 0.0 {-max_extent}")
65 |
66 | nhat = n / np.linalg.norm(n)
67 | rhat = np.array([0.0, 0.0, 1.0])
68 | angle = math.degrees(math.acos(np.dot(nhat, rhat)))
69 |
70 | if not math.isclose(angle, 0.0, abs_tol=1e-6):
71 | rot_axis = np.cross(rhat, nhat)
72 | rot_axis /= np.linalg.norm(rot_axis)
73 | axis = f"{rot_axis[0]} {rot_axis[1]} {rot_axis[2]}"
74 | cmds.append(f"Rotate body {{ {ids} }} about 0 0 0 direction {axis} Angle {angle}")
75 |
76 | tvec = distance*nhat
77 | cmds.append(f"body {{ { ids } }} move {tvec[0]} {tvec[1]} {tvec[2]}")
78 |
79 | cmds.append(f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
80 | wid = emit_get_last_id( ent_type, cmds)
81 | # if positive half space we subtract the cutter block from the world
82 | if node.side != '-':
83 | cmds.append(f"subtract body {{ { ids } }} from body {{ { wid } }}")
84 | # if negative half space we intersect the cutter block with the world
85 | else:
86 | cmds.append(f"intersect body {{ { ids } }} {{ { wid } }}")
87 |
88 | return wid, cmds
89 |
90 | @classmethod
91 | def from_openmc_surface_inner(cls, plane):
92 | return cls(a=plane.a, b=plane.b, c=plane.c, d=plane.d, boundary_type=plane.boundary_type, albedo=plane.albedo, name=plane.name, surface_id=plane.id)
93 |
94 |
95 | class CADXPlane(CADSurface, openmc.XPlane):
96 |
97 | @staticmethod
98 | def reverse(node):
99 | return "reverse" if node.side == '-' else ""
100 |
101 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
102 | cad_cmds = []
103 | cad_cmds.append(f"brick x {extents[0]} y {extents[1]} z {extents[2]}")
104 | ids = emit_get_last_id( ent_type, cad_cmds)
105 | cad_cmds.append(f"section body {{ {ids} }} with xplane offset {self.coefficients['x0']} {self.reverse(node)}")
106 | return ids, cad_cmds
107 |
108 | @classmethod
109 | def from_openmc_surface_inner(cls, plane):
110 | return cls(x0=plane.x0, boundary_type=plane.boundary_type, albedo=plane.albedo, name=plane.name, surface_id=plane.id)
111 |
112 |
113 | class CADYPlane(CADSurface, openmc.YPlane):
114 |
115 | @staticmethod
116 | def reverse(node):
117 | return "reverse" if node.side == '-' else ""
118 |
119 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
120 | cad_cmds = []
121 | cad_cmds.append(f"brick x {extents[0]} y {extents[1]} z {extents[2]}")
122 | ids = emit_get_last_id( ent_type, cad_cmds)
123 | cad_cmds.append(f"section body {{ {ids} }} with yplane offset {self.coefficients['y0']} {self.reverse(node)}")
124 | return ids, cad_cmds
125 |
126 | @classmethod
127 | def from_openmc_surface_inner(cls, plane):
128 | return cls(y0=plane.y0, boundary_type=plane.boundary_type, albedo=plane.albedo, name=plane.name, surface_id=plane.id)
129 |
130 |
131 | class CADZPlane(CADSurface, openmc.ZPlane):
132 |
133 | @staticmethod
134 | def reverse(node):
135 | return "reverse" if node.side == '-' else ""
136 |
137 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
138 | cad_cmds = []
139 | cad_cmds.append(f"brick x {extents[0]} y {extents[1]} z {extents[2]}")
140 | ids = emit_get_last_id( ent_type, cad_cmds)
141 | cad_cmds.append(f"section body {{ {ids} }} with zplane offset {self.coefficients['z0']} {self.reverse(node)}")
142 | return ids, cad_cmds
143 |
144 | @classmethod
145 | def from_openmc_surface_inner(cls, plane):
146 | return cls(z0=plane.z0, boundary_type=plane.boundary_type, albedo=plane.albedo, name=plane.name, surface_id=plane.id)
147 |
148 | class CADCylinder(CADSurface, openmc.Cylinder):
149 |
150 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
151 | print('XCADCylinder to cubit surface')
152 | cad_cmds = []
153 | h = inner_world[2] if inner_world else extents[2]
154 | cad_cmds.append(f"cylinder height {h} radius {self.r}")
155 | ids = emit_get_last_id(cmds=cad_cmds)
156 | if node.side != '-':
157 | wid = 0
158 | if inner_world:
159 | if hex:
160 | cad_cmds.append(f"create prism height {inner_world[2]} sides 6 radius { ( inner_world[0] / 2 ) }")
161 | wid = emit_get_last_id(ent_type, cad_cmds)
162 | cad_cmds.append(f"rotate body {{ {wid} }} about z angle 30")
163 | else:
164 | cad_cmds.append(f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}")
165 | wid = emit_get_last_id(ent_type, cad_cmds)
166 | else:
167 | cad_cmds.append( f"brick x {w[0]} y {w[1]} z {w[2]}" )
168 | wid = emit_get_last_id(ent_type, cad_cmds)
169 | cad_cmds.append( f"subtract body {{ { ids } }} from body {{ { wid } }}" )
170 | rotate( wid, self.dx, self.dy, self.dz, cad_cmds)
171 | move( wid, self.x0, self.y0, self.z0, cad_cmds)
172 | return wid, cad_cmds
173 | rotate( ids, self.dx, self.dy, self.dz, cad_cmds)
174 | move( ids, self.x0, self.y0, self.z0, cad_cmds)
175 | return ids, cad_cmds
176 |
177 | @classmethod
178 | def from_openmc_surface_inner(cls, cyl):
179 | return cls(r=cyl.r, x0=cyl.x0, y0=cyl.y0, z0=cyl.z0, dx=cyl.dx, dy=cyl.dy, dz=cyl.dz,
180 | boundary_type=cyl.boundary_type, albedo=cyl.albedo, name=cyl.name, surface_id=cyl.id)
181 |
182 | class CADXCylinder(CADSurface, openmc.XCylinder):
183 |
184 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
185 | cad_cmds = []
186 | h = inner_world[0] if inner_world else extents[0]
187 | cad_cmds.append( f"cylinder height {h} radius {self.r}")
188 | ids = emit_get_last_id( ent_type , cad_cmds)
189 | cad_cmds.append(f"rotate body {{ {ids} }} about y angle 90")
190 | if node.side != '-':
191 | wid = 0
192 | if inner_world:
193 | if hex:
194 | cad_cmds.append(f"create prism height {inner_world[2]} sides 6 radius { ( inner_world[0] / 2 ) }")
195 | wid = emit_get_last_id(ent_type, cad_cmds)
196 | cad_cmds.append(f"rotate body {{ {wid} }} about z angle 30")
197 | cad_cmds.append(f"rotate body {{ {wid} }} about y angle 90")
198 | else:
199 | cad_cmds.append(f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}")
200 | wid = emit_get_last_id(ent_type, cad_cmds)
201 | else:
202 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
203 | wid = emit_get_last_id( ent_type , cad_cmds)
204 | cad_cmds.append(f"subtract body {{ { ids } }} from body {{ { wid } }}")
205 | move(wid, 0, self.y0, self.z0, cad_cmds)
206 | return wid, cad_cmds
207 | move(ids, 0, self.y0, self.z0, cad_cmds)
208 | return ids, cad_cmds
209 |
210 | @classmethod
211 | def from_openmc_surface_inner(cls, cyl):
212 | return cls(r=cyl.r, y0=cyl.y0, z0=cyl.z0, boundary_type=cyl.boundary_type, albedo=cyl.albedo, name=cyl.name, surface_id=cyl.id)
213 |
214 |
215 | class CADYCylinder(CADSurface, openmc.YCylinder):
216 |
217 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
218 | cad_cmds = []
219 | h = inner_world[1] if inner_world else extents[1]
220 | cad_cmds.append( f"cylinder height {h} radius {self.r}")
221 | ids = emit_get_last_id( ent_type , cad_cmds)
222 | cad_cmds.append(f"rotate body {{ {ids} }} about x angle 90")
223 | if node.side != '-':
224 | wid = 0
225 | if inner_world:
226 | if hex:
227 | cad_cmds.append(f"create prism height {inner_world[2]} sides 6 radius { ( inner_world[0] / 2 ) }")
228 | wid = emit_get_last_id(ent_type, cad_cmds)
229 | cad_cmds.append(f"rotate body {{ {wid} }} about z angle 30")
230 | cad_cmds.append(f"rotate body {{ {wid} }} about x angle 90")
231 | else:
232 | cad_cmds.append(f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}")
233 | wid = emit_get_last_id(ent_type, cad_cmds)
234 | else:
235 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
236 | wid = emit_get_last_id( ent_type , cad_cmds)
237 | cad_cmds.append(f"subtract body {{ { ids } }} from body {{ { wid } }}")
238 | move(wid, self.x0, 0, self.z0, cad_cmds)
239 | return wid, cad_cmds
240 | move(ids, self.x0, 0, self.z0, cad_cmds)
241 | return ids, cad_cmds
242 |
243 | @classmethod
244 | def from_openmc_surface_inner(cls, cyl):
245 | return cls(r=cyl.r, x0=cyl.x0, z0=cyl.z0, boundary_type=cyl.boundary_type, albedo=cyl.albedo, name=cyl.name, surface_id=cyl.id)
246 |
247 |
248 | class CADZCylinder(CADSurface, openmc.ZCylinder):
249 |
250 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
251 | cad_cmds = []
252 | h = inner_world[2] if inner_world else extents[2]
253 | cad_cmds.append( f"cylinder height {h} radius {self.r}")
254 | ids = emit_get_last_id( ent_type , cad_cmds)
255 | if node.side != '-':
256 | wid = 0
257 | if inner_world:
258 | if hex:
259 | cad_cmds.append(f"create prism height {inner_world[2]} sides 6 radius { ( inner_world[0] / 2 ) }")
260 | wid = emit_get_last_id(ent_type, cad_cmds)
261 | cad_cmds.append(f"rotate body {{ {wid} }} about z angle 30")
262 | else:
263 | cad_cmds.append(f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}")
264 | wid = emit_get_last_id(ent_type, cad_cmds)
265 | else:
266 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
267 | wid = emit_get_last_id( ent_type , cad_cmds)
268 | cad_cmds.append(f"subtract body {{ { ids } }} from body {{ { wid } }}")
269 | move(wid, self.x0, self.y0, 0, cad_cmds)
270 | return wid, cad_cmds
271 | move(ids, self.x0, self.y0, 0, cad_cmds)
272 | return ids, cad_cmds
273 |
274 | @classmethod
275 | def from_openmc_surface_inner(cls, cyl):
276 | return cls(r=cyl.r, x0=cyl.x0, y0=cyl.y0, boundary_type=cyl.boundary_type, albedo=cyl.albedo, name=cyl.name, surface_id=cyl.id)
277 |
278 |
279 | class CADSphere(CADSurface, openmc.Sphere):
280 |
281 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
282 | cad_cmds = []
283 | cad_cmds.append( f"sphere radius {self.r}")
284 | ids = emit_get_last_id(ent_type, cad_cmds)
285 | move(ids, self.x0, self.y0, self.z0, cad_cmds)
286 | if node.side != '-':
287 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
288 | wid = emit_get_last_id( ent_type , cad_cmds)
289 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
290 | ids = wid
291 | return ids, cad_cmds
292 |
293 | @classmethod
294 | def from_openmc_surface_inner(cls, sphere):
295 | return cls(r=sphere.r, x0=sphere.x0, y0=sphere.y0, z0=sphere.z0, boundary_type=sphere.boundary_type, albedo=sphere.albedo, name=sphere.name, surface_id=sphere.id)
296 |
297 | class CADCone(CADSurface):
298 |
299 | def to_cubit_surface(self, ent_type, node, extents, inner_world=None, hex=False):
300 | raise NotImplementedError('General Cones are not yet supported')
301 |
302 | @classmethod
303 | def from_openmc_surface(cls, surface):
304 | raise NotImplementedError('General Cones are not yet supported')
305 |
306 | class CADXCone(CADSurface, openmc.XCone):
307 |
308 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
309 | cad_cmds = []
310 | cad_cmds.append( f"create frustum height {extents[0]} radius {math.sqrt(self.coefficients['r2'])*extents[0]} top 0")
311 | ids = emit_get_last_id(ent_type, cad_cmds)
312 | cad_cmds.append(f"body {{ {ids} }} move 0 0 -{extents[0]/2.0}")
313 | cad_cmds.append(f"body {{ {ids} }} copy reflect z")
314 | ids2 = emit_get_last_id(ent_type, cad_cmds)
315 | cad_cmds.append(f"unite body {{ {ids} }} {{ {ids2} }}")
316 | cad_cmds.append( f"rotate body {{ {ids} }} about y angle 90")
317 | x0, y0, z0 = self.coefficients['x0'], self.coefficients['y0'], self.coefficients['z0']
318 | cad_cmds.append(f"body {{ {ids} }} move {x0} {y0} {z0}")
319 |
320 | if node.side != '-':
321 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
322 | wid = emit_get_last_id(ent_type , cad_cmds)
323 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
324 | ids = wid
325 | return ids, cad_cmds
326 |
327 | @classmethod
328 | def from_openmc_surface_inner(cls, surface):
329 | return cls(x0=surface.x0, y0=surface.y0, z0=surface.z0, r2=surface.r2, boundary_type=surface.boundary_type, albedo=surface.albedo, name=surface.name, surface_id=surface.id)
330 |
331 |
332 | class CADYCone(CADSurface, openmc.YCone):
333 |
334 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
335 | cad_cmds = []
336 | cad_cmds.append( f"create frustum height {extents[1]} radius {math.sqrt(self.coefficients['r2'])*extents[1]} top 0")
337 | ids = emit_get_last_id(ent_type, cad_cmds)
338 | cad_cmds.append(f"body {{ {ids} }} move 0 0 -{extents[1]/2.0}")
339 | cad_cmds.append(f"body {{ {ids} }} copy reflect z")
340 | ids2 = emit_get_last_id(ent_type, cad_cmds)
341 | cad_cmds.append(f"unite body {{ {ids} }} {{ {ids2} }}")
342 | cad_cmds.append( f"rotate body {{ {ids} }} about x angle 90")
343 | x0, y0, z0 = self.coefficients['x0'], self.coefficients['y0'], self.coefficients['z0']
344 | cad_cmds.append(f"body {{ {ids} }} move {x0} {y0} {z0}")
345 |
346 | if node.side != '-':
347 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
348 | wid = emit_get_last_id(ent_type , cad_cmds)
349 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
350 | ids = wid
351 | return ids, cad_cmds
352 |
353 | @classmethod
354 | def from_openmc_surface_inner(cls, surface):
355 | return cls(x0=surface.x0, y0=surface.y0, z0=surface.z0, r2=surface.r2, boundary_type=surface.boundary_type, albedo=surface.albedo, name=surface.name, surface_id=surface.id)
356 |
357 |
358 | class CADZCone(CADSurface, openmc.ZCone):
359 |
360 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
361 | cad_cmds = []
362 | cad_cmds.append( f"create frustum height {extents[2]} radius {math.sqrt(self.coefficients['r2'])*extents[2]} top 0")
363 | ids = emit_get_last_id(ent_type, cad_cmds)
364 | cad_cmds.append(f"body {{ {ids} }} move 0 0 -{extents[2]/2.0}")
365 | cad_cmds.append(f"body {{ {ids} }} copy reflect z")
366 | ids2 = emit_get_last_id(ent_type, cad_cmds)
367 | cad_cmds.append(f"unite body {{ {ids} }} {{ {ids2} }}")
368 | x0, y0, z0 = self.coefficients['x0'], self.coefficients['y0'], self.coefficients['z0']
369 | cad_cmds.append(f"body {{ {ids} }} move {x0} {y0} {z0}")
370 |
371 | if node.side != '-':
372 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
373 | wid = emit_get_last_id(ent_type , cad_cmds)
374 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
375 | ids = wid
376 | return ids, cad_cmds
377 |
378 | @classmethod
379 | def from_openmc_surface_inner(cls, surface):
380 | return cls(x0=surface.x0, y0=surface.y0, z0=surface.z0, r2=surface.r2, boundary_type=surface.boundary_type, albedo=surface.albedo, name=surface.name, surface_id=surface.id)
381 |
382 |
383 | class CADTorus(CADSurface):
384 |
385 | def check_coeffs(self):
386 | if self.b != self.c:
387 | raise ValueError("Only torri with constant minor radii are supported")
388 |
389 | @classmethod
390 | def from_openmc_surface_inner(cls, surface):
391 | return cls(x0=surface.x0, y0=surface.y0, z0=surface.z0, a=surface.a, b=surface.b, c=surface.c, boundary_type=surface.boundary_type, albedo=surface.albedo, name=surface.name, surface_id=surface.id)
392 |
393 | class CADXTorus(CADTorus, openmc.XTorus):
394 |
395 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
396 | self.check_coeffs()
397 | cad_cmds = []
398 | cad_cmds.append( f"torus major radius {self.a} minor radius {self.b}" )
399 | ids = emit_get_last_id(ent_type, cad_cmds)
400 | cad_cmds.append( f"rotate body {{ {ids} }} about y angle 90")
401 | if node.side != '-':
402 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
403 | wid = emit_get_last_id(ent_type, cad_cmds)
404 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
405 | move(wid, self.x0, self.y0, self.z0, cad_cmds)
406 | ids = wid
407 | else:
408 | move(ids, self.x0, self.y0, self.z0, cad_cmds)
409 | return ids, cad_cmds
410 |
411 |
412 |
413 | class CADYTorus(CADTorus, openmc.YTorus):
414 |
415 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
416 | self.check_coeffs()
417 | cad_cmds = []
418 | cad_cmds.append( f"torus major radius {self.a} minor radius {self.b}" )
419 | ids = emit_get_last_id(ent_type, cad_cmds)
420 | cad_cmds.append( f"rotate body {{ {ids} }} about x angle 90")
421 | if node.side != '-':
422 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
423 | wid = emit_get_last_id(ent_type, cad_cmds)
424 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
425 | move(wid, self.x0, self.y0, self.z0, cad_cmds)
426 | ids = wid
427 | else:
428 | move(ids, self.x0, self.y0, self.z0, cad_cmds)
429 | return ids, cad_cmds
430 |
431 |
432 | class CADZTorus(CADTorus, openmc.ZTorus):
433 |
434 | def to_cubit_surface_inner(self, ent_type, node, extents, inner_world=None, hex=False):
435 | self.check_coeffs()
436 | cad_cmds = []
437 | cad_cmds.append( f"torus major radius {self.a} minor radius {self.b}" )
438 | ids = emit_get_last_id(ent_type, cad_cmds)
439 | if node.side != '-':
440 | cad_cmds.append( f"brick x {extents[0]} y {extents[1]} z {extents[2]}" )
441 | wid = emit_get_last_id(ent_type, cad_cmds)
442 | cad_cmds.append(f"subtract body {{ {ids} }} from body {{ {wid} }}")
443 | move(wid, self.x0, self.y0, self.z0, cad_cmds)
444 | ids = wid
445 | else:
446 | move(ids, self.x0, self.y0, self.z0, cad_cmds)
447 | return ids, cad_cmds
448 |
449 |
450 | _CAD_SURFACES = [CADPlane, CADXPlane, CADYPlane, CADZPlane, CADCylinder, CADXCylinder, CADYCylinder, CADZCylinder, CADSphere, CADXCone, CADYCone, CADZCone, CADXTorus, CADYTorus, CADZTorus]
451 |
452 | _CAD_SURFACE_DICTIONARY = {s._type: s for s in _CAD_SURFACES}
453 |
--------------------------------------------------------------------------------
/test/assembly.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 1
4 | create prism height 2.0 sides 6 radius 0.5
5 | #{ id1 = Id("body") }
6 | rotate body { id1 } about z angle 30
7 | body { id1 } name "cell 4"
8 | move body { id1 } midpoint location 0.0 1.7320508075688772 0.0
9 | cylinder height 2.0 radius 0.4
10 | #{ id2 = Id("body") }
11 | body { id2 } name "cell 5"
12 | move body { id2 } midpoint location 0.75 1.299038105676658 0.0
13 | cylinder height 2.0 radius 0.4
14 | #{ id3 = Id("body") }
15 | create prism height 2.0 sides 6 radius 0.5
16 | #{ id4 = Id("body") }
17 | rotate body { id4 } about z angle 30
18 | subtract body { id3 } from body { id4 }
19 | body { id4 } name "cell 6"
20 | move body { id4 } midpoint location 0.75 1.299038105676658 0.0
21 | cylinder height 2.0 radius 0.4
22 | #{ id5 = Id("body") }
23 | body { id5 } name "cell 5"
24 | move body { id5 } midpoint location 1.5 0.8660254037844386 0.0
25 | cylinder height 2.0 radius 0.4
26 | #{ id6 = Id("body") }
27 | create prism height 2.0 sides 6 radius 0.5
28 | #{ id7 = Id("body") }
29 | rotate body { id7 } about z angle 30
30 | subtract body { id6 } from body { id7 }
31 | body { id7 } name "cell 6"
32 | move body { id7 } midpoint location 1.5 0.8660254037844386 0.0
33 | cylinder height 2.0 radius 0.4
34 | #{ id8 = Id("body") }
35 | body { id8 } name "cell 5"
36 | move body { id8 } midpoint location 1.5 0.0 0.0
37 | cylinder height 2.0 radius 0.4
38 | #{ id9 = Id("body") }
39 | create prism height 2.0 sides 6 radius 0.5
40 | #{ id10 = Id("body") }
41 | rotate body { id10 } about z angle 30
42 | subtract body { id9 } from body { id10 }
43 | body { id10 } name "cell 6"
44 | move body { id10 } midpoint location 1.5 0.0 0.0
45 | cylinder height 2.0 radius 0.4
46 | #{ id11 = Id("body") }
47 | body { id11 } name "cell 5"
48 | move body { id11 } midpoint location 1.5 -0.8660254037844386 0.0
49 | cylinder height 2.0 radius 0.4
50 | #{ id12 = Id("body") }
51 | create prism height 2.0 sides 6 radius 0.5
52 | #{ id13 = Id("body") }
53 | rotate body { id13 } about z angle 30
54 | subtract body { id12 } from body { id13 }
55 | body { id13 } name "cell 6"
56 | move body { id13 } midpoint location 1.5 -0.8660254037844386 0.0
57 | cylinder height 2.0 radius 0.4
58 | #{ id14 = Id("body") }
59 | body { id14 } name "cell 5"
60 | move body { id14 } midpoint location 0.75 -1.299038105676658 0.0
61 | cylinder height 2.0 radius 0.4
62 | #{ id15 = Id("body") }
63 | create prism height 2.0 sides 6 radius 0.5
64 | #{ id16 = Id("body") }
65 | rotate body { id16 } about z angle 30
66 | subtract body { id15 } from body { id16 }
67 | body { id16 } name "cell 6"
68 | move body { id16 } midpoint location 0.75 -1.299038105676658 0.0
69 | cylinder height 2.0 radius 0.4
70 | #{ id17 = Id("body") }
71 | body { id17 } name "cell 5"
72 | move body { id17 } midpoint location 0.0 -1.7320508075688772 0.0
73 | cylinder height 2.0 radius 0.4
74 | #{ id18 = Id("body") }
75 | create prism height 2.0 sides 6 radius 0.5
76 | #{ id19 = Id("body") }
77 | rotate body { id19 } about z angle 30
78 | subtract body { id18 } from body { id19 }
79 | body { id19 } name "cell 6"
80 | move body { id19 } midpoint location 0.0 -1.7320508075688772 0.0
81 | cylinder height 2.0 radius 0.4
82 | #{ id20 = Id("body") }
83 | body { id20 } name "cell 5"
84 | move body { id20 } midpoint location -0.75 -1.299038105676658 0.0
85 | cylinder height 2.0 radius 0.4
86 | #{ id21 = Id("body") }
87 | create prism height 2.0 sides 6 radius 0.5
88 | #{ id22 = Id("body") }
89 | rotate body { id22 } about z angle 30
90 | subtract body { id21 } from body { id22 }
91 | body { id22 } name "cell 6"
92 | move body { id22 } midpoint location -0.75 -1.299038105676658 0.0
93 | cylinder height 2.0 radius 0.4
94 | #{ id23 = Id("body") }
95 | body { id23 } name "cell 5"
96 | move body { id23 } midpoint location -1.5 -0.8660254037844386 0.0
97 | cylinder height 2.0 radius 0.4
98 | #{ id24 = Id("body") }
99 | create prism height 2.0 sides 6 radius 0.5
100 | #{ id25 = Id("body") }
101 | rotate body { id25 } about z angle 30
102 | subtract body { id24 } from body { id25 }
103 | body { id25 } name "cell 6"
104 | move body { id25 } midpoint location -1.5 -0.8660254037844386 0.0
105 | cylinder height 2.0 radius 0.4
106 | #{ id26 = Id("body") }
107 | body { id26 } name "cell 5"
108 | move body { id26 } midpoint location -1.5 0.0 0.0
109 | cylinder height 2.0 radius 0.4
110 | #{ id27 = Id("body") }
111 | create prism height 2.0 sides 6 radius 0.5
112 | #{ id28 = Id("body") }
113 | rotate body { id28 } about z angle 30
114 | subtract body { id27 } from body { id28 }
115 | body { id28 } name "cell 6"
116 | move body { id28 } midpoint location -1.5 0.0 0.0
117 | cylinder height 2.0 radius 0.4
118 | #{ id29 = Id("body") }
119 | body { id29 } name "cell 5"
120 | move body { id29 } midpoint location -1.5 0.8660254037844386 0.0
121 | cylinder height 2.0 radius 0.4
122 | #{ id30 = Id("body") }
123 | create prism height 2.0 sides 6 radius 0.5
124 | #{ id31 = Id("body") }
125 | rotate body { id31 } about z angle 30
126 | subtract body { id30 } from body { id31 }
127 | body { id31 } name "cell 6"
128 | move body { id31 } midpoint location -1.5 0.8660254037844386 0.0
129 | cylinder height 2.0 radius 0.4
130 | #{ id32 = Id("body") }
131 | body { id32 } name "cell 5"
132 | move body { id32 } midpoint location -0.75 1.299038105676658 0.0
133 | cylinder height 2.0 radius 0.4
134 | #{ id33 = Id("body") }
135 | create prism height 2.0 sides 6 radius 0.5
136 | #{ id34 = Id("body") }
137 | rotate body { id34 } about z angle 30
138 | subtract body { id33 } from body { id34 }
139 | body { id34 } name "cell 6"
140 | move body { id34 } midpoint location -0.75 1.299038105676658 0.0
141 | create prism height 2.0 sides 6 radius 0.5
142 | #{ id35 = Id("body") }
143 | rotate body { id35 } about z angle 30
144 | body { id35 } name "cell 4"
145 | move body { id35 } midpoint location 5.302876193624534e-17 0.8660254037844386 0.0
146 | cylinder height 2.0 radius 0.4
147 | #{ id36 = Id("body") }
148 | body { id36 } name "cell 5"
149 | move body { id36 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
150 | cylinder height 2.0 radius 0.4
151 | #{ id37 = Id("body") }
152 | create prism height 2.0 sides 6 radius 0.5
153 | #{ id38 = Id("body") }
154 | rotate body { id38 } about z angle 30
155 | subtract body { id37 } from body { id38 }
156 | body { id38 } name "cell 6"
157 | move body { id38 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
158 | cylinder height 2.0 radius 0.4
159 | #{ id39 = Id("body") }
160 | body { id39 } name "cell 5"
161 | move body { id39 } midpoint location 0.75 -0.43301270189221913 0.0
162 | cylinder height 2.0 radius 0.4
163 | #{ id40 = Id("body") }
164 | create prism height 2.0 sides 6 radius 0.5
165 | #{ id41 = Id("body") }
166 | rotate body { id41 } about z angle 30
167 | subtract body { id40 } from body { id41 }
168 | body { id41 } name "cell 6"
169 | move body { id41 } midpoint location 0.75 -0.43301270189221913 0.0
170 | cylinder height 2.0 radius 0.4
171 | #{ id42 = Id("body") }
172 | body { id42 } name "cell 5"
173 | move body { id42 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
174 | cylinder height 2.0 radius 0.4
175 | #{ id43 = Id("body") }
176 | create prism height 2.0 sides 6 radius 0.5
177 | #{ id44 = Id("body") }
178 | rotate body { id44 } about z angle 30
179 | subtract body { id43 } from body { id44 }
180 | body { id44 } name "cell 6"
181 | move body { id44 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
182 | cylinder height 2.0 radius 0.4
183 | #{ id45 = Id("body") }
184 | body { id45 } name "cell 5"
185 | move body { id45 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
186 | cylinder height 2.0 radius 0.4
187 | #{ id46 = Id("body") }
188 | create prism height 2.0 sides 6 radius 0.5
189 | #{ id47 = Id("body") }
190 | rotate body { id47 } about z angle 30
191 | subtract body { id46 } from body { id47 }
192 | body { id47 } name "cell 6"
193 | move body { id47 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
194 | cylinder height 2.0 radius 0.4
195 | #{ id48 = Id("body") }
196 | body { id48 } name "cell 5"
197 | move body { id48 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
198 | cylinder height 2.0 radius 0.4
199 | #{ id49 = Id("body") }
200 | create prism height 2.0 sides 6 radius 0.5
201 | #{ id50 = Id("body") }
202 | rotate body { id50 } about z angle 30
203 | subtract body { id49 } from body { id50 }
204 | body { id50 } name "cell 6"
205 | move body { id50 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
206 | cylinder height 2.0 radius 0.4
207 | #{ id51 = Id("body") }
208 | body { id51 } name "cell 5"
209 | move body { id51 } midpoint location 0.0 0.0 0.0
210 | cylinder height 2.0 radius 0.4
211 | #{ id52 = Id("body") }
212 | create prism height 2.0 sides 6 radius 0.5
213 | #{ id53 = Id("body") }
214 | rotate body { id53 } about z angle 30
215 | subtract body { id52 } from body { id53 }
216 | body { id53 } name "cell 6"
217 | move body { id53 } midpoint location 0.0 0.0 0.0
218 | create prism height 2.0 sides 6 radius 0.5
219 | #{ id54 = Id("body") }
220 | rotate body { id54 } about z angle 30
221 | body { id54 } name "cell 4"
222 | move body { id54 } midpoint location 0.0 1.7320508075688772 2.0
223 | cylinder height 2.0 radius 0.4
224 | #{ id55 = Id("body") }
225 | body { id55 } name "cell 2"
226 | move body { id55 } midpoint location 0.75 1.299038105676658 2.0
227 | cylinder height 2.0 radius 0.4
228 | #{ id56 = Id("body") }
229 | create prism height 2.0 sides 6 radius 0.5
230 | #{ id57 = Id("body") }
231 | rotate body { id57 } about z angle 30
232 | subtract body { id56 } from body { id57 }
233 | body { id57 } name "cell 3"
234 | move body { id57 } midpoint location 0.75 1.299038105676658 2.0
235 | cylinder height 2.0 radius 0.4
236 | #{ id58 = Id("body") }
237 | body { id58 } name "cell 2"
238 | move body { id58 } midpoint location 1.5 0.8660254037844386 2.0
239 | cylinder height 2.0 radius 0.4
240 | #{ id59 = Id("body") }
241 | create prism height 2.0 sides 6 radius 0.5
242 | #{ id60 = Id("body") }
243 | rotate body { id60 } about z angle 30
244 | subtract body { id59 } from body { id60 }
245 | body { id60 } name "cell 3"
246 | move body { id60 } midpoint location 1.5 0.8660254037844386 2.0
247 | cylinder height 2.0 radius 0.4
248 | #{ id61 = Id("body") }
249 | body { id61 } name "cell 2"
250 | move body { id61 } midpoint location 1.5 0.0 2.0
251 | cylinder height 2.0 radius 0.4
252 | #{ id62 = Id("body") }
253 | create prism height 2.0 sides 6 radius 0.5
254 | #{ id63 = Id("body") }
255 | rotate body { id63 } about z angle 30
256 | subtract body { id62 } from body { id63 }
257 | body { id63 } name "cell 3"
258 | move body { id63 } midpoint location 1.5 0.0 2.0
259 | cylinder height 2.0 radius 0.4
260 | #{ id64 = Id("body") }
261 | body { id64 } name "cell 2"
262 | move body { id64 } midpoint location 1.5 -0.8660254037844386 2.0
263 | cylinder height 2.0 radius 0.4
264 | #{ id65 = Id("body") }
265 | create prism height 2.0 sides 6 radius 0.5
266 | #{ id66 = Id("body") }
267 | rotate body { id66 } about z angle 30
268 | subtract body { id65 } from body { id66 }
269 | body { id66 } name "cell 3"
270 | move body { id66 } midpoint location 1.5 -0.8660254037844386 2.0
271 | cylinder height 2.0 radius 0.4
272 | #{ id67 = Id("body") }
273 | body { id67 } name "cell 2"
274 | move body { id67 } midpoint location 0.75 -1.299038105676658 2.0
275 | cylinder height 2.0 radius 0.4
276 | #{ id68 = Id("body") }
277 | create prism height 2.0 sides 6 radius 0.5
278 | #{ id69 = Id("body") }
279 | rotate body { id69 } about z angle 30
280 | subtract body { id68 } from body { id69 }
281 | body { id69 } name "cell 3"
282 | move body { id69 } midpoint location 0.75 -1.299038105676658 2.0
283 | cylinder height 2.0 radius 0.4
284 | #{ id70 = Id("body") }
285 | body { id70 } name "cell 2"
286 | move body { id70 } midpoint location 0.0 -1.7320508075688772 2.0
287 | cylinder height 2.0 radius 0.4
288 | #{ id71 = Id("body") }
289 | create prism height 2.0 sides 6 radius 0.5
290 | #{ id72 = Id("body") }
291 | rotate body { id72 } about z angle 30
292 | subtract body { id71 } from body { id72 }
293 | body { id72 } name "cell 3"
294 | move body { id72 } midpoint location 0.0 -1.7320508075688772 2.0
295 | cylinder height 2.0 radius 0.4
296 | #{ id73 = Id("body") }
297 | body { id73 } name "cell 2"
298 | move body { id73 } midpoint location -0.75 -1.299038105676658 2.0
299 | cylinder height 2.0 radius 0.4
300 | #{ id74 = Id("body") }
301 | create prism height 2.0 sides 6 radius 0.5
302 | #{ id75 = Id("body") }
303 | rotate body { id75 } about z angle 30
304 | subtract body { id74 } from body { id75 }
305 | body { id75 } name "cell 3"
306 | move body { id75 } midpoint location -0.75 -1.299038105676658 2.0
307 | cylinder height 2.0 radius 0.4
308 | #{ id76 = Id("body") }
309 | body { id76 } name "cell 2"
310 | move body { id76 } midpoint location -1.5 -0.8660254037844386 2.0
311 | cylinder height 2.0 radius 0.4
312 | #{ id77 = Id("body") }
313 | create prism height 2.0 sides 6 radius 0.5
314 | #{ id78 = Id("body") }
315 | rotate body { id78 } about z angle 30
316 | subtract body { id77 } from body { id78 }
317 | body { id78 } name "cell 3"
318 | move body { id78 } midpoint location -1.5 -0.8660254037844386 2.0
319 | cylinder height 2.0 radius 0.4
320 | #{ id79 = Id("body") }
321 | body { id79 } name "cell 2"
322 | move body { id79 } midpoint location -1.5 0.0 2.0
323 | cylinder height 2.0 radius 0.4
324 | #{ id80 = Id("body") }
325 | create prism height 2.0 sides 6 radius 0.5
326 | #{ id81 = Id("body") }
327 | rotate body { id81 } about z angle 30
328 | subtract body { id80 } from body { id81 }
329 | body { id81 } name "cell 3"
330 | move body { id81 } midpoint location -1.5 0.0 2.0
331 | cylinder height 2.0 radius 0.4
332 | #{ id82 = Id("body") }
333 | body { id82 } name "cell 2"
334 | move body { id82 } midpoint location -1.5 0.8660254037844386 2.0
335 | cylinder height 2.0 radius 0.4
336 | #{ id83 = Id("body") }
337 | create prism height 2.0 sides 6 radius 0.5
338 | #{ id84 = Id("body") }
339 | rotate body { id84 } about z angle 30
340 | subtract body { id83 } from body { id84 }
341 | body { id84 } name "cell 3"
342 | move body { id84 } midpoint location -1.5 0.8660254037844386 2.0
343 | cylinder height 2.0 radius 0.4
344 | #{ id85 = Id("body") }
345 | body { id85 } name "cell 2"
346 | move body { id85 } midpoint location -0.75 1.299038105676658 2.0
347 | cylinder height 2.0 radius 0.4
348 | #{ id86 = Id("body") }
349 | create prism height 2.0 sides 6 radius 0.5
350 | #{ id87 = Id("body") }
351 | rotate body { id87 } about z angle 30
352 | subtract body { id86 } from body { id87 }
353 | body { id87 } name "cell 3"
354 | move body { id87 } midpoint location -0.75 1.299038105676658 2.0
355 | create prism height 2.0 sides 6 radius 0.5
356 | #{ id88 = Id("body") }
357 | rotate body { id88 } about z angle 30
358 | body { id88 } name "cell 4"
359 | move body { id88 } midpoint location 5.302876193624534e-17 0.8660254037844386 2.0
360 | cylinder height 2.0 radius 0.4
361 | #{ id89 = Id("body") }
362 | body { id89 } name "cell 2"
363 | move body { id89 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
364 | cylinder height 2.0 radius 0.4
365 | #{ id90 = Id("body") }
366 | create prism height 2.0 sides 6 radius 0.5
367 | #{ id91 = Id("body") }
368 | rotate body { id91 } about z angle 30
369 | subtract body { id90 } from body { id91 }
370 | body { id91 } name "cell 3"
371 | move body { id91 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
372 | cylinder height 2.0 radius 0.4
373 | #{ id92 = Id("body") }
374 | body { id92 } name "cell 2"
375 | move body { id92 } midpoint location 0.75 -0.43301270189221913 2.0
376 | cylinder height 2.0 radius 0.4
377 | #{ id93 = Id("body") }
378 | create prism height 2.0 sides 6 radius 0.5
379 | #{ id94 = Id("body") }
380 | rotate body { id94 } about z angle 30
381 | subtract body { id93 } from body { id94 }
382 | body { id94 } name "cell 3"
383 | move body { id94 } midpoint location 0.75 -0.43301270189221913 2.0
384 | cylinder height 2.0 radius 0.4
385 | #{ id95 = Id("body") }
386 | body { id95 } name "cell 2"
387 | move body { id95 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
388 | cylinder height 2.0 radius 0.4
389 | #{ id96 = Id("body") }
390 | create prism height 2.0 sides 6 radius 0.5
391 | #{ id97 = Id("body") }
392 | rotate body { id97 } about z angle 30
393 | subtract body { id96 } from body { id97 }
394 | body { id97 } name "cell 3"
395 | move body { id97 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
396 | cylinder height 2.0 radius 0.4
397 | #{ id98 = Id("body") }
398 | body { id98 } name "cell 2"
399 | move body { id98 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
400 | cylinder height 2.0 radius 0.4
401 | #{ id99 = Id("body") }
402 | create prism height 2.0 sides 6 radius 0.5
403 | #{ id100 = Id("body") }
404 | rotate body { id100 } about z angle 30
405 | subtract body { id99 } from body { id100 }
406 | body { id100 } name "cell 3"
407 | move body { id100 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
408 | cylinder height 2.0 radius 0.4
409 | #{ id101 = Id("body") }
410 | body { id101 } name "cell 2"
411 | move body { id101 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
412 | cylinder height 2.0 radius 0.4
413 | #{ id102 = Id("body") }
414 | create prism height 2.0 sides 6 radius 0.5
415 | #{ id103 = Id("body") }
416 | rotate body { id103 } about z angle 30
417 | subtract body { id102 } from body { id103 }
418 | body { id103 } name "cell 3"
419 | move body { id103 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
420 | cylinder height 2.0 radius 0.4
421 | #{ id104 = Id("body") }
422 | body { id104 } name "cell 2"
423 | move body { id104 } midpoint location 0.0 0.0 2.0
424 | cylinder height 2.0 radius 0.4
425 | #{ id105 = Id("body") }
426 | create prism height 2.0 sides 6 radius 0.5
427 | #{ id106 = Id("body") }
428 | rotate body { id106 } about z angle 30
429 | subtract body { id105 } from body { id106 }
430 | body { id106 } name "cell 3"
431 | move body { id106 } midpoint location 0.0 0.0 2.0
432 | create prism height 2.0 sides 6 radius 0.5
433 | #{ id107 = Id("body") }
434 | rotate body { id107 } about z angle 30
435 | body { id107 } name "cell 4"
436 | move body { id107 } midpoint location 0.0 1.7320508075688772 4.0
437 | cylinder height 2.0 radius 0.4
438 | #{ id108 = Id("body") }
439 | body { id108 } name "cell 5"
440 | move body { id108 } midpoint location 0.75 1.299038105676658 4.0
441 | cylinder height 2.0 radius 0.4
442 | #{ id109 = Id("body") }
443 | create prism height 2.0 sides 6 radius 0.5
444 | #{ id110 = Id("body") }
445 | rotate body { id110 } about z angle 30
446 | subtract body { id109 } from body { id110 }
447 | body { id110 } name "cell 6"
448 | move body { id110 } midpoint location 0.75 1.299038105676658 4.0
449 | cylinder height 2.0 radius 0.4
450 | #{ id111 = Id("body") }
451 | body { id111 } name "cell 5"
452 | move body { id111 } midpoint location 1.5 0.8660254037844386 4.0
453 | cylinder height 2.0 radius 0.4
454 | #{ id112 = Id("body") }
455 | create prism height 2.0 sides 6 radius 0.5
456 | #{ id113 = Id("body") }
457 | rotate body { id113 } about z angle 30
458 | subtract body { id112 } from body { id113 }
459 | body { id113 } name "cell 6"
460 | move body { id113 } midpoint location 1.5 0.8660254037844386 4.0
461 | cylinder height 2.0 radius 0.4
462 | #{ id114 = Id("body") }
463 | body { id114 } name "cell 5"
464 | move body { id114 } midpoint location 1.5 0.0 4.0
465 | cylinder height 2.0 radius 0.4
466 | #{ id115 = Id("body") }
467 | create prism height 2.0 sides 6 radius 0.5
468 | #{ id116 = Id("body") }
469 | rotate body { id116 } about z angle 30
470 | subtract body { id115 } from body { id116 }
471 | body { id116 } name "cell 6"
472 | move body { id116 } midpoint location 1.5 0.0 4.0
473 | cylinder height 2.0 radius 0.4
474 | #{ id117 = Id("body") }
475 | body { id117 } name "cell 5"
476 | move body { id117 } midpoint location 1.5 -0.8660254037844386 4.0
477 | cylinder height 2.0 radius 0.4
478 | #{ id118 = Id("body") }
479 | create prism height 2.0 sides 6 radius 0.5
480 | #{ id119 = Id("body") }
481 | rotate body { id119 } about z angle 30
482 | subtract body { id118 } from body { id119 }
483 | body { id119 } name "cell 6"
484 | move body { id119 } midpoint location 1.5 -0.8660254037844386 4.0
485 | cylinder height 2.0 radius 0.4
486 | #{ id120 = Id("body") }
487 | body { id120 } name "cell 5"
488 | move body { id120 } midpoint location 0.75 -1.299038105676658 4.0
489 | cylinder height 2.0 radius 0.4
490 | #{ id121 = Id("body") }
491 | create prism height 2.0 sides 6 radius 0.5
492 | #{ id122 = Id("body") }
493 | rotate body { id122 } about z angle 30
494 | subtract body { id121 } from body { id122 }
495 | body { id122 } name "cell 6"
496 | move body { id122 } midpoint location 0.75 -1.299038105676658 4.0
497 | cylinder height 2.0 radius 0.4
498 | #{ id123 = Id("body") }
499 | body { id123 } name "cell 5"
500 | move body { id123 } midpoint location 0.0 -1.7320508075688772 4.0
501 | cylinder height 2.0 radius 0.4
502 | #{ id124 = Id("body") }
503 | create prism height 2.0 sides 6 radius 0.5
504 | #{ id125 = Id("body") }
505 | rotate body { id125 } about z angle 30
506 | subtract body { id124 } from body { id125 }
507 | body { id125 } name "cell 6"
508 | move body { id125 } midpoint location 0.0 -1.7320508075688772 4.0
509 | cylinder height 2.0 radius 0.4
510 | #{ id126 = Id("body") }
511 | body { id126 } name "cell 5"
512 | move body { id126 } midpoint location -0.75 -1.299038105676658 4.0
513 | cylinder height 2.0 radius 0.4
514 | #{ id127 = Id("body") }
515 | create prism height 2.0 sides 6 radius 0.5
516 | #{ id128 = Id("body") }
517 | rotate body { id128 } about z angle 30
518 | subtract body { id127 } from body { id128 }
519 | body { id128 } name "cell 6"
520 | move body { id128 } midpoint location -0.75 -1.299038105676658 4.0
521 | cylinder height 2.0 radius 0.4
522 | #{ id129 = Id("body") }
523 | body { id129 } name "cell 5"
524 | move body { id129 } midpoint location -1.5 -0.8660254037844386 4.0
525 | cylinder height 2.0 radius 0.4
526 | #{ id130 = Id("body") }
527 | create prism height 2.0 sides 6 radius 0.5
528 | #{ id131 = Id("body") }
529 | rotate body { id131 } about z angle 30
530 | subtract body { id130 } from body { id131 }
531 | body { id131 } name "cell 6"
532 | move body { id131 } midpoint location -1.5 -0.8660254037844386 4.0
533 | cylinder height 2.0 radius 0.4
534 | #{ id132 = Id("body") }
535 | body { id132 } name "cell 5"
536 | move body { id132 } midpoint location -1.5 0.0 4.0
537 | cylinder height 2.0 radius 0.4
538 | #{ id133 = Id("body") }
539 | create prism height 2.0 sides 6 radius 0.5
540 | #{ id134 = Id("body") }
541 | rotate body { id134 } about z angle 30
542 | subtract body { id133 } from body { id134 }
543 | body { id134 } name "cell 6"
544 | move body { id134 } midpoint location -1.5 0.0 4.0
545 | cylinder height 2.0 radius 0.4
546 | #{ id135 = Id("body") }
547 | body { id135 } name "cell 5"
548 | move body { id135 } midpoint location -1.5 0.8660254037844386 4.0
549 | cylinder height 2.0 radius 0.4
550 | #{ id136 = Id("body") }
551 | create prism height 2.0 sides 6 radius 0.5
552 | #{ id137 = Id("body") }
553 | rotate body { id137 } about z angle 30
554 | subtract body { id136 } from body { id137 }
555 | body { id137 } name "cell 6"
556 | move body { id137 } midpoint location -1.5 0.8660254037844386 4.0
557 | cylinder height 2.0 radius 0.4
558 | #{ id138 = Id("body") }
559 | body { id138 } name "cell 5"
560 | move body { id138 } midpoint location -0.75 1.299038105676658 4.0
561 | cylinder height 2.0 radius 0.4
562 | #{ id139 = Id("body") }
563 | create prism height 2.0 sides 6 radius 0.5
564 | #{ id140 = Id("body") }
565 | rotate body { id140 } about z angle 30
566 | subtract body { id139 } from body { id140 }
567 | body { id140 } name "cell 6"
568 | move body { id140 } midpoint location -0.75 1.299038105676658 4.0
569 | create prism height 2.0 sides 6 radius 0.5
570 | #{ id141 = Id("body") }
571 | rotate body { id141 } about z angle 30
572 | body { id141 } name "cell 4"
573 | move body { id141 } midpoint location 5.302876193624534e-17 0.8660254037844386 4.0
574 | cylinder height 2.0 radius 0.4
575 | #{ id142 = Id("body") }
576 | body { id142 } name "cell 5"
577 | move body { id142 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
578 | cylinder height 2.0 radius 0.4
579 | #{ id143 = Id("body") }
580 | create prism height 2.0 sides 6 radius 0.5
581 | #{ id144 = Id("body") }
582 | rotate body { id144 } about z angle 30
583 | subtract body { id143 } from body { id144 }
584 | body { id144 } name "cell 6"
585 | move body { id144 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
586 | cylinder height 2.0 radius 0.4
587 | #{ id145 = Id("body") }
588 | body { id145 } name "cell 5"
589 | move body { id145 } midpoint location 0.75 -0.43301270189221913 4.0
590 | cylinder height 2.0 radius 0.4
591 | #{ id146 = Id("body") }
592 | create prism height 2.0 sides 6 radius 0.5
593 | #{ id147 = Id("body") }
594 | rotate body { id147 } about z angle 30
595 | subtract body { id146 } from body { id147 }
596 | body { id147 } name "cell 6"
597 | move body { id147 } midpoint location 0.75 -0.43301270189221913 4.0
598 | cylinder height 2.0 radius 0.4
599 | #{ id148 = Id("body") }
600 | body { id148 } name "cell 5"
601 | move body { id148 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
602 | cylinder height 2.0 radius 0.4
603 | #{ id149 = Id("body") }
604 | create prism height 2.0 sides 6 radius 0.5
605 | #{ id150 = Id("body") }
606 | rotate body { id150 } about z angle 30
607 | subtract body { id149 } from body { id150 }
608 | body { id150 } name "cell 6"
609 | move body { id150 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
610 | cylinder height 2.0 radius 0.4
611 | #{ id151 = Id("body") }
612 | body { id151 } name "cell 5"
613 | move body { id151 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
614 | cylinder height 2.0 radius 0.4
615 | #{ id152 = Id("body") }
616 | create prism height 2.0 sides 6 radius 0.5
617 | #{ id153 = Id("body") }
618 | rotate body { id153 } about z angle 30
619 | subtract body { id152 } from body { id153 }
620 | body { id153 } name "cell 6"
621 | move body { id153 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
622 | cylinder height 2.0 radius 0.4
623 | #{ id154 = Id("body") }
624 | body { id154 } name "cell 5"
625 | move body { id154 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
626 | cylinder height 2.0 radius 0.4
627 | #{ id155 = Id("body") }
628 | create prism height 2.0 sides 6 radius 0.5
629 | #{ id156 = Id("body") }
630 | rotate body { id156 } about z angle 30
631 | subtract body { id155 } from body { id156 }
632 | body { id156 } name "cell 6"
633 | move body { id156 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
634 | cylinder height 2.0 radius 0.4
635 | #{ id157 = Id("body") }
636 | body { id157 } name "cell 5"
637 | move body { id157 } midpoint location 0.0 0.0 4.0
638 | cylinder height 2.0 radius 0.4
639 | #{ id158 = Id("body") }
640 | create prism height 2.0 sides 6 radius 0.5
641 | #{ id159 = Id("body") }
642 | rotate body { id159 } about z angle 30
643 | subtract body { id158 } from body { id159 }
644 | body { id159 } name "cell 6"
645 | move body { id159 } midpoint location 0.0 0.0 4.0
646 |
--------------------------------------------------------------------------------
/test/lattice-hexagonal.jou:
--------------------------------------------------------------------------------
1 | set graphics off
2 | set journal off
3 | #CELL 1
4 | create prism height 2.0 sides 6 radius 0.5
5 | #{ id1 = Id("body") }
6 | rotate body { id1 } about z angle 30
7 | body { id1 } name "cell 4"
8 | move body { id1 } midpoint location 0.0 1.7320508075688772 0.0
9 | cylinder height 2.0 radius 0.4
10 | #{ id2 = Id("body") }
11 | body { id2 } name "cell 5"
12 | move body { id2 } midpoint location 0.75 1.299038105676658 0.0
13 | cylinder height 2.0 radius 0.4
14 | #{ id3 = Id("body") }
15 | create prism height 2.0 sides 6 radius 0.5
16 | #{ id4 = Id("body") }
17 | rotate body { id4 } about z angle 30
18 | subtract body { id3 } from body { id4 }
19 | body { id4 } name "cell 6"
20 | move body { id4 } midpoint location 0.75 1.299038105676658 0.0
21 | cylinder height 2.0 radius 0.4
22 | #{ id5 = Id("body") }
23 | body { id5 } name "cell 5"
24 | move body { id5 } midpoint location 1.5 0.8660254037844386 0.0
25 | cylinder height 2.0 radius 0.4
26 | #{ id6 = Id("body") }
27 | create prism height 2.0 sides 6 radius 0.5
28 | #{ id7 = Id("body") }
29 | rotate body { id7 } about z angle 30
30 | subtract body { id6 } from body { id7 }
31 | body { id7 } name "cell 6"
32 | move body { id7 } midpoint location 1.5 0.8660254037844386 0.0
33 | cylinder height 2.0 radius 0.4
34 | #{ id8 = Id("body") }
35 | body { id8 } name "cell 5"
36 | move body { id8 } midpoint location 1.5 0.0 0.0
37 | cylinder height 2.0 radius 0.4
38 | #{ id9 = Id("body") }
39 | create prism height 2.0 sides 6 radius 0.5
40 | #{ id10 = Id("body") }
41 | rotate body { id10 } about z angle 30
42 | subtract body { id9 } from body { id10 }
43 | body { id10 } name "cell 6"
44 | move body { id10 } midpoint location 1.5 0.0 0.0
45 | cylinder height 2.0 radius 0.4
46 | #{ id11 = Id("body") }
47 | body { id11 } name "cell 5"
48 | move body { id11 } midpoint location 1.5 -0.8660254037844386 0.0
49 | cylinder height 2.0 radius 0.4
50 | #{ id12 = Id("body") }
51 | create prism height 2.0 sides 6 radius 0.5
52 | #{ id13 = Id("body") }
53 | rotate body { id13 } about z angle 30
54 | subtract body { id12 } from body { id13 }
55 | body { id13 } name "cell 6"
56 | move body { id13 } midpoint location 1.5 -0.8660254037844386 0.0
57 | cylinder height 2.0 radius 0.4
58 | #{ id14 = Id("body") }
59 | body { id14 } name "cell 5"
60 | move body { id14 } midpoint location 0.75 -1.299038105676658 0.0
61 | cylinder height 2.0 radius 0.4
62 | #{ id15 = Id("body") }
63 | create prism height 2.0 sides 6 radius 0.5
64 | #{ id16 = Id("body") }
65 | rotate body { id16 } about z angle 30
66 | subtract body { id15 } from body { id16 }
67 | body { id16 } name "cell 6"
68 | move body { id16 } midpoint location 0.75 -1.299038105676658 0.0
69 | cylinder height 2.0 radius 0.4
70 | #{ id17 = Id("body") }
71 | body { id17 } name "cell 5"
72 | move body { id17 } midpoint location 0.0 -1.7320508075688772 0.0
73 | cylinder height 2.0 radius 0.4
74 | #{ id18 = Id("body") }
75 | create prism height 2.0 sides 6 radius 0.5
76 | #{ id19 = Id("body") }
77 | rotate body { id19 } about z angle 30
78 | subtract body { id18 } from body { id19 }
79 | body { id19 } name "cell 6"
80 | move body { id19 } midpoint location 0.0 -1.7320508075688772 0.0
81 | cylinder height 2.0 radius 0.4
82 | #{ id20 = Id("body") }
83 | body { id20 } name "cell 5"
84 | move body { id20 } midpoint location -0.75 -1.299038105676658 0.0
85 | cylinder height 2.0 radius 0.4
86 | #{ id21 = Id("body") }
87 | create prism height 2.0 sides 6 radius 0.5
88 | #{ id22 = Id("body") }
89 | rotate body { id22 } about z angle 30
90 | subtract body { id21 } from body { id22 }
91 | body { id22 } name "cell 6"
92 | move body { id22 } midpoint location -0.75 -1.299038105676658 0.0
93 | cylinder height 2.0 radius 0.4
94 | #{ id23 = Id("body") }
95 | body { id23 } name "cell 5"
96 | move body { id23 } midpoint location -1.5 -0.8660254037844386 0.0
97 | cylinder height 2.0 radius 0.4
98 | #{ id24 = Id("body") }
99 | create prism height 2.0 sides 6 radius 0.5
100 | #{ id25 = Id("body") }
101 | rotate body { id25 } about z angle 30
102 | subtract body { id24 } from body { id25 }
103 | body { id25 } name "cell 6"
104 | move body { id25 } midpoint location -1.5 -0.8660254037844386 0.0
105 | cylinder height 2.0 radius 0.4
106 | #{ id26 = Id("body") }
107 | body { id26 } name "cell 5"
108 | move body { id26 } midpoint location -1.5 0.0 0.0
109 | cylinder height 2.0 radius 0.4
110 | #{ id27 = Id("body") }
111 | create prism height 2.0 sides 6 radius 0.5
112 | #{ id28 = Id("body") }
113 | rotate body { id28 } about z angle 30
114 | subtract body { id27 } from body { id28 }
115 | body { id28 } name "cell 6"
116 | move body { id28 } midpoint location -1.5 0.0 0.0
117 | cylinder height 2.0 radius 0.4
118 | #{ id29 = Id("body") }
119 | body { id29 } name "cell 5"
120 | move body { id29 } midpoint location -1.5 0.8660254037844386 0.0
121 | cylinder height 2.0 radius 0.4
122 | #{ id30 = Id("body") }
123 | create prism height 2.0 sides 6 radius 0.5
124 | #{ id31 = Id("body") }
125 | rotate body { id31 } about z angle 30
126 | subtract body { id30 } from body { id31 }
127 | body { id31 } name "cell 6"
128 | move body { id31 } midpoint location -1.5 0.8660254037844386 0.0
129 | cylinder height 2.0 radius 0.4
130 | #{ id32 = Id("body") }
131 | body { id32 } name "cell 5"
132 | move body { id32 } midpoint location -0.75 1.299038105676658 0.0
133 | cylinder height 2.0 radius 0.4
134 | #{ id33 = Id("body") }
135 | create prism height 2.0 sides 6 radius 0.5
136 | #{ id34 = Id("body") }
137 | rotate body { id34 } about z angle 30
138 | subtract body { id33 } from body { id34 }
139 | body { id34 } name "cell 6"
140 | move body { id34 } midpoint location -0.75 1.299038105676658 0.0
141 | create prism height 2.0 sides 6 radius 0.5
142 | #{ id35 = Id("body") }
143 | rotate body { id35 } about z angle 30
144 | body { id35 } name "cell 4"
145 | move body { id35 } midpoint location 5.302876193624534e-17 0.8660254037844386 0.0
146 | cylinder height 2.0 radius 0.4
147 | #{ id36 = Id("body") }
148 | body { id36 } name "cell 5"
149 | move body { id36 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
150 | cylinder height 2.0 radius 0.4
151 | #{ id37 = Id("body") }
152 | create prism height 2.0 sides 6 radius 0.5
153 | #{ id38 = Id("body") }
154 | rotate body { id38 } about z angle 30
155 | subtract body { id37 } from body { id38 }
156 | body { id38 } name "cell 6"
157 | move body { id38 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
158 | cylinder height 2.0 radius 0.4
159 | #{ id39 = Id("body") }
160 | body { id39 } name "cell 5"
161 | move body { id39 } midpoint location 0.75 -0.43301270189221913 0.0
162 | cylinder height 2.0 radius 0.4
163 | #{ id40 = Id("body") }
164 | create prism height 2.0 sides 6 radius 0.5
165 | #{ id41 = Id("body") }
166 | rotate body { id41 } about z angle 30
167 | subtract body { id40 } from body { id41 }
168 | body { id41 } name "cell 6"
169 | move body { id41 } midpoint location 0.75 -0.43301270189221913 0.0
170 | cylinder height 2.0 radius 0.4
171 | #{ id42 = Id("body") }
172 | body { id42 } name "cell 5"
173 | move body { id42 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
174 | cylinder height 2.0 radius 0.4
175 | #{ id43 = Id("body") }
176 | create prism height 2.0 sides 6 radius 0.5
177 | #{ id44 = Id("body") }
178 | rotate body { id44 } about z angle 30
179 | subtract body { id43 } from body { id44 }
180 | body { id44 } name "cell 6"
181 | move body { id44 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
182 | cylinder height 2.0 radius 0.4
183 | #{ id45 = Id("body") }
184 | body { id45 } name "cell 5"
185 | move body { id45 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
186 | cylinder height 2.0 radius 0.4
187 | #{ id46 = Id("body") }
188 | create prism height 2.0 sides 6 radius 0.5
189 | #{ id47 = Id("body") }
190 | rotate body { id47 } about z angle 30
191 | subtract body { id46 } from body { id47 }
192 | body { id47 } name "cell 6"
193 | move body { id47 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
194 | cylinder height 2.0 radius 0.4
195 | #{ id48 = Id("body") }
196 | body { id48 } name "cell 5"
197 | move body { id48 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
198 | cylinder height 2.0 radius 0.4
199 | #{ id49 = Id("body") }
200 | create prism height 2.0 sides 6 radius 0.5
201 | #{ id50 = Id("body") }
202 | rotate body { id50 } about z angle 30
203 | subtract body { id49 } from body { id50 }
204 | body { id50 } name "cell 6"
205 | move body { id50 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
206 | cylinder height 2.0 radius 0.4
207 | #{ id51 = Id("body") }
208 | body { id51 } name "cell 5"
209 | move body { id51 } midpoint location 0.0 0.0 0.0
210 | cylinder height 2.0 radius 0.4
211 | #{ id52 = Id("body") }
212 | create prism height 2.0 sides 6 radius 0.5
213 | #{ id53 = Id("body") }
214 | rotate body { id53 } about z angle 30
215 | subtract body { id52 } from body { id53 }
216 | body { id53 } name "cell 6"
217 | move body { id53 } midpoint location 0.0 0.0 0.0
218 | create prism height 2.0 sides 6 radius 0.5
219 | #{ id54 = Id("body") }
220 | rotate body { id54 } about z angle 30
221 | body { id54 } name "cell 4"
222 | move body { id54 } midpoint location 0.0 1.7320508075688772 2.0
223 | cylinder height 2.0 radius 0.4
224 | #{ id55 = Id("body") }
225 | body { id55 } name "cell 2"
226 | move body { id55 } midpoint location 0.75 1.299038105676658 2.0
227 | cylinder height 2.0 radius 0.4
228 | #{ id56 = Id("body") }
229 | create prism height 2.0 sides 6 radius 0.5
230 | #{ id57 = Id("body") }
231 | rotate body { id57 } about z angle 30
232 | subtract body { id56 } from body { id57 }
233 | body { id57 } name "cell 3"
234 | move body { id57 } midpoint location 0.75 1.299038105676658 2.0
235 | cylinder height 2.0 radius 0.4
236 | #{ id58 = Id("body") }
237 | body { id58 } name "cell 2"
238 | move body { id58 } midpoint location 1.5 0.8660254037844386 2.0
239 | cylinder height 2.0 radius 0.4
240 | #{ id59 = Id("body") }
241 | create prism height 2.0 sides 6 radius 0.5
242 | #{ id60 = Id("body") }
243 | rotate body { id60 } about z angle 30
244 | subtract body { id59 } from body { id60 }
245 | body { id60 } name "cell 3"
246 | move body { id60 } midpoint location 1.5 0.8660254037844386 2.0
247 | cylinder height 2.0 radius 0.4
248 | #{ id61 = Id("body") }
249 | body { id61 } name "cell 2"
250 | move body { id61 } midpoint location 1.5 0.0 2.0
251 | cylinder height 2.0 radius 0.4
252 | #{ id62 = Id("body") }
253 | create prism height 2.0 sides 6 radius 0.5
254 | #{ id63 = Id("body") }
255 | rotate body { id63 } about z angle 30
256 | subtract body { id62 } from body { id63 }
257 | body { id63 } name "cell 3"
258 | move body { id63 } midpoint location 1.5 0.0 2.0
259 | cylinder height 2.0 radius 0.4
260 | #{ id64 = Id("body") }
261 | body { id64 } name "cell 2"
262 | move body { id64 } midpoint location 1.5 -0.8660254037844386 2.0
263 | cylinder height 2.0 radius 0.4
264 | #{ id65 = Id("body") }
265 | create prism height 2.0 sides 6 radius 0.5
266 | #{ id66 = Id("body") }
267 | rotate body { id66 } about z angle 30
268 | subtract body { id65 } from body { id66 }
269 | body { id66 } name "cell 3"
270 | move body { id66 } midpoint location 1.5 -0.8660254037844386 2.0
271 | cylinder height 2.0 radius 0.4
272 | #{ id67 = Id("body") }
273 | body { id67 } name "cell 2"
274 | move body { id67 } midpoint location 0.75 -1.299038105676658 2.0
275 | cylinder height 2.0 radius 0.4
276 | #{ id68 = Id("body") }
277 | create prism height 2.0 sides 6 radius 0.5
278 | #{ id69 = Id("body") }
279 | rotate body { id69 } about z angle 30
280 | subtract body { id68 } from body { id69 }
281 | body { id69 } name "cell 3"
282 | move body { id69 } midpoint location 0.75 -1.299038105676658 2.0
283 | cylinder height 2.0 radius 0.4
284 | #{ id70 = Id("body") }
285 | body { id70 } name "cell 2"
286 | move body { id70 } midpoint location 0.0 -1.7320508075688772 2.0
287 | cylinder height 2.0 radius 0.4
288 | #{ id71 = Id("body") }
289 | create prism height 2.0 sides 6 radius 0.5
290 | #{ id72 = Id("body") }
291 | rotate body { id72 } about z angle 30
292 | subtract body { id71 } from body { id72 }
293 | body { id72 } name "cell 3"
294 | move body { id72 } midpoint location 0.0 -1.7320508075688772 2.0
295 | cylinder height 2.0 radius 0.4
296 | #{ id73 = Id("body") }
297 | body { id73 } name "cell 2"
298 | move body { id73 } midpoint location -0.75 -1.299038105676658 2.0
299 | cylinder height 2.0 radius 0.4
300 | #{ id74 = Id("body") }
301 | create prism height 2.0 sides 6 radius 0.5
302 | #{ id75 = Id("body") }
303 | rotate body { id75 } about z angle 30
304 | subtract body { id74 } from body { id75 }
305 | body { id75 } name "cell 3"
306 | move body { id75 } midpoint location -0.75 -1.299038105676658 2.0
307 | cylinder height 2.0 radius 0.4
308 | #{ id76 = Id("body") }
309 | body { id76 } name "cell 2"
310 | move body { id76 } midpoint location -1.5 -0.8660254037844386 2.0
311 | cylinder height 2.0 radius 0.4
312 | #{ id77 = Id("body") }
313 | create prism height 2.0 sides 6 radius 0.5
314 | #{ id78 = Id("body") }
315 | rotate body { id78 } about z angle 30
316 | subtract body { id77 } from body { id78 }
317 | body { id78 } name "cell 3"
318 | move body { id78 } midpoint location -1.5 -0.8660254037844386 2.0
319 | cylinder height 2.0 radius 0.4
320 | #{ id79 = Id("body") }
321 | body { id79 } name "cell 2"
322 | move body { id79 } midpoint location -1.5 0.0 2.0
323 | cylinder height 2.0 radius 0.4
324 | #{ id80 = Id("body") }
325 | create prism height 2.0 sides 6 radius 0.5
326 | #{ id81 = Id("body") }
327 | rotate body { id81 } about z angle 30
328 | subtract body { id80 } from body { id81 }
329 | body { id81 } name "cell 3"
330 | move body { id81 } midpoint location -1.5 0.0 2.0
331 | cylinder height 2.0 radius 0.4
332 | #{ id82 = Id("body") }
333 | body { id82 } name "cell 2"
334 | move body { id82 } midpoint location -1.5 0.8660254037844386 2.0
335 | cylinder height 2.0 radius 0.4
336 | #{ id83 = Id("body") }
337 | create prism height 2.0 sides 6 radius 0.5
338 | #{ id84 = Id("body") }
339 | rotate body { id84 } about z angle 30
340 | subtract body { id83 } from body { id84 }
341 | body { id84 } name "cell 3"
342 | move body { id84 } midpoint location -1.5 0.8660254037844386 2.0
343 | cylinder height 2.0 radius 0.4
344 | #{ id85 = Id("body") }
345 | body { id85 } name "cell 2"
346 | move body { id85 } midpoint location -0.75 1.299038105676658 2.0
347 | cylinder height 2.0 radius 0.4
348 | #{ id86 = Id("body") }
349 | create prism height 2.0 sides 6 radius 0.5
350 | #{ id87 = Id("body") }
351 | rotate body { id87 } about z angle 30
352 | subtract body { id86 } from body { id87 }
353 | body { id87 } name "cell 3"
354 | move body { id87 } midpoint location -0.75 1.299038105676658 2.0
355 | create prism height 2.0 sides 6 radius 0.5
356 | #{ id88 = Id("body") }
357 | rotate body { id88 } about z angle 30
358 | body { id88 } name "cell 4"
359 | move body { id88 } midpoint location 5.302876193624534e-17 0.8660254037844386 2.0
360 | cylinder height 2.0 radius 0.4
361 | #{ id89 = Id("body") }
362 | body { id89 } name "cell 2"
363 | move body { id89 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
364 | cylinder height 2.0 radius 0.4
365 | #{ id90 = Id("body") }
366 | create prism height 2.0 sides 6 radius 0.5
367 | #{ id91 = Id("body") }
368 | rotate body { id91 } about z angle 30
369 | subtract body { id90 } from body { id91 }
370 | body { id91 } name "cell 3"
371 | move body { id91 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
372 | cylinder height 2.0 radius 0.4
373 | #{ id92 = Id("body") }
374 | body { id92 } name "cell 2"
375 | move body { id92 } midpoint location 0.75 -0.43301270189221913 2.0
376 | cylinder height 2.0 radius 0.4
377 | #{ id93 = Id("body") }
378 | create prism height 2.0 sides 6 radius 0.5
379 | #{ id94 = Id("body") }
380 | rotate body { id94 } about z angle 30
381 | subtract body { id93 } from body { id94 }
382 | body { id94 } name "cell 3"
383 | move body { id94 } midpoint location 0.75 -0.43301270189221913 2.0
384 | cylinder height 2.0 radius 0.4
385 | #{ id95 = Id("body") }
386 | body { id95 } name "cell 2"
387 | move body { id95 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
388 | cylinder height 2.0 radius 0.4
389 | #{ id96 = Id("body") }
390 | create prism height 2.0 sides 6 radius 0.5
391 | #{ id97 = Id("body") }
392 | rotate body { id97 } about z angle 30
393 | subtract body { id96 } from body { id97 }
394 | body { id97 } name "cell 3"
395 | move body { id97 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
396 | cylinder height 2.0 radius 0.4
397 | #{ id98 = Id("body") }
398 | body { id98 } name "cell 2"
399 | move body { id98 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
400 | cylinder height 2.0 radius 0.4
401 | #{ id99 = Id("body") }
402 | create prism height 2.0 sides 6 radius 0.5
403 | #{ id100 = Id("body") }
404 | rotate body { id100 } about z angle 30
405 | subtract body { id99 } from body { id100 }
406 | body { id100 } name "cell 3"
407 | move body { id100 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
408 | cylinder height 2.0 radius 0.4
409 | #{ id101 = Id("body") }
410 | body { id101 } name "cell 2"
411 | move body { id101 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
412 | cylinder height 2.0 radius 0.4
413 | #{ id102 = Id("body") }
414 | create prism height 2.0 sides 6 radius 0.5
415 | #{ id103 = Id("body") }
416 | rotate body { id103 } about z angle 30
417 | subtract body { id102 } from body { id103 }
418 | body { id103 } name "cell 3"
419 | move body { id103 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
420 | cylinder height 2.0 radius 0.4
421 | #{ id104 = Id("body") }
422 | body { id104 } name "cell 2"
423 | move body { id104 } midpoint location 0.0 0.0 2.0
424 | cylinder height 2.0 radius 0.4
425 | #{ id105 = Id("body") }
426 | create prism height 2.0 sides 6 radius 0.5
427 | #{ id106 = Id("body") }
428 | rotate body { id106 } about z angle 30
429 | subtract body { id105 } from body { id106 }
430 | body { id106 } name "cell 3"
431 | move body { id106 } midpoint location 0.0 0.0 2.0
432 | create prism height 2.0 sides 6 radius 0.5
433 | #{ id107 = Id("body") }
434 | rotate body { id107 } about z angle 30
435 | body { id107 } name "cell 4"
436 | move body { id107 } midpoint location 0.0 1.7320508075688772 4.0
437 | cylinder height 2.0 radius 0.4
438 | #{ id108 = Id("body") }
439 | body { id108 } name "cell 5"
440 | move body { id108 } midpoint location 0.75 1.299038105676658 4.0
441 | cylinder height 2.0 radius 0.4
442 | #{ id109 = Id("body") }
443 | create prism height 2.0 sides 6 radius 0.5
444 | #{ id110 = Id("body") }
445 | rotate body { id110 } about z angle 30
446 | subtract body { id109 } from body { id110 }
447 | body { id110 } name "cell 6"
448 | move body { id110 } midpoint location 0.75 1.299038105676658 4.0
449 | cylinder height 2.0 radius 0.4
450 | #{ id111 = Id("body") }
451 | body { id111 } name "cell 5"
452 | move body { id111 } midpoint location 1.5 0.8660254037844386 4.0
453 | cylinder height 2.0 radius 0.4
454 | #{ id112 = Id("body") }
455 | create prism height 2.0 sides 6 radius 0.5
456 | #{ id113 = Id("body") }
457 | rotate body { id113 } about z angle 30
458 | subtract body { id112 } from body { id113 }
459 | body { id113 } name "cell 6"
460 | move body { id113 } midpoint location 1.5 0.8660254037844386 4.0
461 | cylinder height 2.0 radius 0.4
462 | #{ id114 = Id("body") }
463 | body { id114 } name "cell 5"
464 | move body { id114 } midpoint location 1.5 0.0 4.0
465 | cylinder height 2.0 radius 0.4
466 | #{ id115 = Id("body") }
467 | create prism height 2.0 sides 6 radius 0.5
468 | #{ id116 = Id("body") }
469 | rotate body { id116 } about z angle 30
470 | subtract body { id115 } from body { id116 }
471 | body { id116 } name "cell 6"
472 | move body { id116 } midpoint location 1.5 0.0 4.0
473 | cylinder height 2.0 radius 0.4
474 | #{ id117 = Id("body") }
475 | body { id117 } name "cell 5"
476 | move body { id117 } midpoint location 1.5 -0.8660254037844386 4.0
477 | cylinder height 2.0 radius 0.4
478 | #{ id118 = Id("body") }
479 | create prism height 2.0 sides 6 radius 0.5
480 | #{ id119 = Id("body") }
481 | rotate body { id119 } about z angle 30
482 | subtract body { id118 } from body { id119 }
483 | body { id119 } name "cell 6"
484 | move body { id119 } midpoint location 1.5 -0.8660254037844386 4.0
485 | cylinder height 2.0 radius 0.4
486 | #{ id120 = Id("body") }
487 | body { id120 } name "cell 5"
488 | move body { id120 } midpoint location 0.75 -1.299038105676658 4.0
489 | cylinder height 2.0 radius 0.4
490 | #{ id121 = Id("body") }
491 | create prism height 2.0 sides 6 radius 0.5
492 | #{ id122 = Id("body") }
493 | rotate body { id122 } about z angle 30
494 | subtract body { id121 } from body { id122 }
495 | body { id122 } name "cell 6"
496 | move body { id122 } midpoint location 0.75 -1.299038105676658 4.0
497 | cylinder height 2.0 radius 0.4
498 | #{ id123 = Id("body") }
499 | body { id123 } name "cell 5"
500 | move body { id123 } midpoint location 0.0 -1.7320508075688772 4.0
501 | cylinder height 2.0 radius 0.4
502 | #{ id124 = Id("body") }
503 | create prism height 2.0 sides 6 radius 0.5
504 | #{ id125 = Id("body") }
505 | rotate body { id125 } about z angle 30
506 | subtract body { id124 } from body { id125 }
507 | body { id125 } name "cell 6"
508 | move body { id125 } midpoint location 0.0 -1.7320508075688772 4.0
509 | cylinder height 2.0 radius 0.4
510 | #{ id126 = Id("body") }
511 | body { id126 } name "cell 5"
512 | move body { id126 } midpoint location -0.75 -1.299038105676658 4.0
513 | cylinder height 2.0 radius 0.4
514 | #{ id127 = Id("body") }
515 | create prism height 2.0 sides 6 radius 0.5
516 | #{ id128 = Id("body") }
517 | rotate body { id128 } about z angle 30
518 | subtract body { id127 } from body { id128 }
519 | body { id128 } name "cell 6"
520 | move body { id128 } midpoint location -0.75 -1.299038105676658 4.0
521 | cylinder height 2.0 radius 0.4
522 | #{ id129 = Id("body") }
523 | body { id129 } name "cell 5"
524 | move body { id129 } midpoint location -1.5 -0.8660254037844386 4.0
525 | cylinder height 2.0 radius 0.4
526 | #{ id130 = Id("body") }
527 | create prism height 2.0 sides 6 radius 0.5
528 | #{ id131 = Id("body") }
529 | rotate body { id131 } about z angle 30
530 | subtract body { id130 } from body { id131 }
531 | body { id131 } name "cell 6"
532 | move body { id131 } midpoint location -1.5 -0.8660254037844386 4.0
533 | cylinder height 2.0 radius 0.4
534 | #{ id132 = Id("body") }
535 | body { id132 } name "cell 5"
536 | move body { id132 } midpoint location -1.5 0.0 4.0
537 | cylinder height 2.0 radius 0.4
538 | #{ id133 = Id("body") }
539 | create prism height 2.0 sides 6 radius 0.5
540 | #{ id134 = Id("body") }
541 | rotate body { id134 } about z angle 30
542 | subtract body { id133 } from body { id134 }
543 | body { id134 } name "cell 6"
544 | move body { id134 } midpoint location -1.5 0.0 4.0
545 | cylinder height 2.0 radius 0.4
546 | #{ id135 = Id("body") }
547 | body { id135 } name "cell 5"
548 | move body { id135 } midpoint location -1.5 0.8660254037844386 4.0
549 | cylinder height 2.0 radius 0.4
550 | #{ id136 = Id("body") }
551 | create prism height 2.0 sides 6 radius 0.5
552 | #{ id137 = Id("body") }
553 | rotate body { id137 } about z angle 30
554 | subtract body { id136 } from body { id137 }
555 | body { id137 } name "cell 6"
556 | move body { id137 } midpoint location -1.5 0.8660254037844386 4.0
557 | cylinder height 2.0 radius 0.4
558 | #{ id138 = Id("body") }
559 | body { id138 } name "cell 5"
560 | move body { id138 } midpoint location -0.75 1.299038105676658 4.0
561 | cylinder height 2.0 radius 0.4
562 | #{ id139 = Id("body") }
563 | create prism height 2.0 sides 6 radius 0.5
564 | #{ id140 = Id("body") }
565 | rotate body { id140 } about z angle 30
566 | subtract body { id139 } from body { id140 }
567 | body { id140 } name "cell 6"
568 | move body { id140 } midpoint location -0.75 1.299038105676658 4.0
569 | create prism height 2.0 sides 6 radius 0.5
570 | #{ id141 = Id("body") }
571 | rotate body { id141 } about z angle 30
572 | body { id141 } name "cell 4"
573 | move body { id141 } midpoint location 5.302876193624534e-17 0.8660254037844386 4.0
574 | cylinder height 2.0 radius 0.4
575 | #{ id142 = Id("body") }
576 | body { id142 } name "cell 5"
577 | move body { id142 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
578 | cylinder height 2.0 radius 0.4
579 | #{ id143 = Id("body") }
580 | create prism height 2.0 sides 6 radius 0.5
581 | #{ id144 = Id("body") }
582 | rotate body { id144 } about z angle 30
583 | subtract body { id143 } from body { id144 }
584 | body { id144 } name "cell 6"
585 | move body { id144 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
586 | cylinder height 2.0 radius 0.4
587 | #{ id145 = Id("body") }
588 | body { id145 } name "cell 5"
589 | move body { id145 } midpoint location 0.75 -0.43301270189221913 4.0
590 | cylinder height 2.0 radius 0.4
591 | #{ id146 = Id("body") }
592 | create prism height 2.0 sides 6 radius 0.5
593 | #{ id147 = Id("body") }
594 | rotate body { id147 } about z angle 30
595 | subtract body { id146 } from body { id147 }
596 | body { id147 } name "cell 6"
597 | move body { id147 } midpoint location 0.75 -0.43301270189221913 4.0
598 | cylinder height 2.0 radius 0.4
599 | #{ id148 = Id("body") }
600 | body { id148 } name "cell 5"
601 | move body { id148 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
602 | cylinder height 2.0 radius 0.4
603 | #{ id149 = Id("body") }
604 | create prism height 2.0 sides 6 radius 0.5
605 | #{ id150 = Id("body") }
606 | rotate body { id150 } about z angle 30
607 | subtract body { id149 } from body { id150 }
608 | body { id150 } name "cell 6"
609 | move body { id150 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
610 | cylinder height 2.0 radius 0.4
611 | #{ id151 = Id("body") }
612 | body { id151 } name "cell 5"
613 | move body { id151 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
614 | cylinder height 2.0 radius 0.4
615 | #{ id152 = Id("body") }
616 | create prism height 2.0 sides 6 radius 0.5
617 | #{ id153 = Id("body") }
618 | rotate body { id153 } about z angle 30
619 | subtract body { id152 } from body { id153 }
620 | body { id153 } name "cell 6"
621 | move body { id153 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
622 | cylinder height 2.0 radius 0.4
623 | #{ id154 = Id("body") }
624 | body { id154 } name "cell 5"
625 | move body { id154 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
626 | cylinder height 2.0 radius 0.4
627 | #{ id155 = Id("body") }
628 | create prism height 2.0 sides 6 radius 0.5
629 | #{ id156 = Id("body") }
630 | rotate body { id156 } about z angle 30
631 | subtract body { id155 } from body { id156 }
632 | body { id156 } name "cell 6"
633 | move body { id156 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
634 | cylinder height 2.0 radius 0.4
635 | #{ id157 = Id("body") }
636 | body { id157 } name "cell 5"
637 | move body { id157 } midpoint location 0.0 0.0 4.0
638 | cylinder height 2.0 radius 0.4
639 | #{ id158 = Id("body") }
640 | create prism height 2.0 sides 6 radius 0.5
641 | #{ id159 = Id("body") }
642 | rotate body { id159 } about z angle 30
643 | subtract body { id158 } from body { id159 }
644 | body { id159 } name "cell 6"
645 | move body { id159 } midpoint location 0.0 0.0 4.0
646 |
--------------------------------------------------------------------------------
/test/gold/lattice-hexagonal.jou:
--------------------------------------------------------------------------------
1 | set echo off
2 | set info off
3 | set warning off
4 | graphics pause
5 | set journal off
6 | set default autosize off
7 | #CELL 1
8 | create prism height 2.0 sides 6 radius 0.5
9 | #{ id1 = Id("body") }
10 | rotate body { id1 } about z angle 30
11 | body { id1 } name "cell 4"
12 | move body { id1 } midpoint location 0.0 1.7320508075688772 0.0
13 | cylinder height 2.0 radius 0.4
14 | #{ id2 = Id("body") }
15 | body { id2 } name "cell 5"
16 | move body { id2 } midpoint location 0.75 1.299038105676658 0.0
17 | cylinder height 2.0 radius 0.4
18 | #{ id3 = Id("body") }
19 | create prism height 2.0 sides 6 radius 0.5
20 | #{ id4 = Id("body") }
21 | rotate body { id4 } about z angle 30
22 | subtract body { id3 } from body { id4 }
23 | body { id4 } name "cell 6"
24 | move body { id4 } midpoint location 0.75 1.299038105676658 0.0
25 | cylinder height 2.0 radius 0.4
26 | #{ id5 = Id("body") }
27 | body { id5 } name "cell 5"
28 | move body { id5 } midpoint location 1.5 0.8660254037844386 0.0
29 | cylinder height 2.0 radius 0.4
30 | #{ id6 = Id("body") }
31 | create prism height 2.0 sides 6 radius 0.5
32 | #{ id7 = Id("body") }
33 | rotate body { id7 } about z angle 30
34 | subtract body { id6 } from body { id7 }
35 | body { id7 } name "cell 6"
36 | move body { id7 } midpoint location 1.5 0.8660254037844386 0.0
37 | cylinder height 2.0 radius 0.4
38 | #{ id8 = Id("body") }
39 | body { id8 } name "cell 5"
40 | move body { id8 } midpoint location 1.5 0.0 0.0
41 | cylinder height 2.0 radius 0.4
42 | #{ id9 = Id("body") }
43 | create prism height 2.0 sides 6 radius 0.5
44 | #{ id10 = Id("body") }
45 | rotate body { id10 } about z angle 30
46 | subtract body { id9 } from body { id10 }
47 | body { id10 } name "cell 6"
48 | move body { id10 } midpoint location 1.5 0.0 0.0
49 | cylinder height 2.0 radius 0.4
50 | #{ id11 = Id("body") }
51 | body { id11 } name "cell 5"
52 | move body { id11 } midpoint location 1.5 -0.8660254037844386 0.0
53 | cylinder height 2.0 radius 0.4
54 | #{ id12 = Id("body") }
55 | create prism height 2.0 sides 6 radius 0.5
56 | #{ id13 = Id("body") }
57 | rotate body { id13 } about z angle 30
58 | subtract body { id12 } from body { id13 }
59 | body { id13 } name "cell 6"
60 | move body { id13 } midpoint location 1.5 -0.8660254037844386 0.0
61 | cylinder height 2.0 radius 0.4
62 | #{ id14 = Id("body") }
63 | body { id14 } name "cell 5"
64 | move body { id14 } midpoint location 0.75 -1.299038105676658 0.0
65 | cylinder height 2.0 radius 0.4
66 | #{ id15 = Id("body") }
67 | create prism height 2.0 sides 6 radius 0.5
68 | #{ id16 = Id("body") }
69 | rotate body { id16 } about z angle 30
70 | subtract body { id15 } from body { id16 }
71 | body { id16 } name "cell 6"
72 | move body { id16 } midpoint location 0.75 -1.299038105676658 0.0
73 | cylinder height 2.0 radius 0.4
74 | #{ id17 = Id("body") }
75 | body { id17 } name "cell 5"
76 | move body { id17 } midpoint location 0.0 -1.7320508075688772 0.0
77 | cylinder height 2.0 radius 0.4
78 | #{ id18 = Id("body") }
79 | create prism height 2.0 sides 6 radius 0.5
80 | #{ id19 = Id("body") }
81 | rotate body { id19 } about z angle 30
82 | subtract body { id18 } from body { id19 }
83 | body { id19 } name "cell 6"
84 | move body { id19 } midpoint location 0.0 -1.7320508075688772 0.0
85 | cylinder height 2.0 radius 0.4
86 | #{ id20 = Id("body") }
87 | body { id20 } name "cell 5"
88 | move body { id20 } midpoint location -0.75 -1.299038105676658 0.0
89 | cylinder height 2.0 radius 0.4
90 | #{ id21 = Id("body") }
91 | create prism height 2.0 sides 6 radius 0.5
92 | #{ id22 = Id("body") }
93 | rotate body { id22 } about z angle 30
94 | subtract body { id21 } from body { id22 }
95 | body { id22 } name "cell 6"
96 | move body { id22 } midpoint location -0.75 -1.299038105676658 0.0
97 | cylinder height 2.0 radius 0.4
98 | #{ id23 = Id("body") }
99 | body { id23 } name "cell 5"
100 | move body { id23 } midpoint location -1.5 -0.8660254037844386 0.0
101 | cylinder height 2.0 radius 0.4
102 | #{ id24 = Id("body") }
103 | create prism height 2.0 sides 6 radius 0.5
104 | #{ id25 = Id("body") }
105 | rotate body { id25 } about z angle 30
106 | subtract body { id24 } from body { id25 }
107 | body { id25 } name "cell 6"
108 | move body { id25 } midpoint location -1.5 -0.8660254037844386 0.0
109 | cylinder height 2.0 radius 0.4
110 | #{ id26 = Id("body") }
111 | body { id26 } name "cell 5"
112 | move body { id26 } midpoint location -1.5 0.0 0.0
113 | cylinder height 2.0 radius 0.4
114 | #{ id27 = Id("body") }
115 | create prism height 2.0 sides 6 radius 0.5
116 | #{ id28 = Id("body") }
117 | rotate body { id28 } about z angle 30
118 | subtract body { id27 } from body { id28 }
119 | body { id28 } name "cell 6"
120 | move body { id28 } midpoint location -1.5 0.0 0.0
121 | cylinder height 2.0 radius 0.4
122 | #{ id29 = Id("body") }
123 | body { id29 } name "cell 5"
124 | move body { id29 } midpoint location -1.5 0.8660254037844386 0.0
125 | cylinder height 2.0 radius 0.4
126 | #{ id30 = Id("body") }
127 | create prism height 2.0 sides 6 radius 0.5
128 | #{ id31 = Id("body") }
129 | rotate body { id31 } about z angle 30
130 | subtract body { id30 } from body { id31 }
131 | body { id31 } name "cell 6"
132 | move body { id31 } midpoint location -1.5 0.8660254037844386 0.0
133 | cylinder height 2.0 radius 0.4
134 | #{ id32 = Id("body") }
135 | body { id32 } name "cell 5"
136 | move body { id32 } midpoint location -0.75 1.299038105676658 0.0
137 | cylinder height 2.0 radius 0.4
138 | #{ id33 = Id("body") }
139 | create prism height 2.0 sides 6 radius 0.5
140 | #{ id34 = Id("body") }
141 | rotate body { id34 } about z angle 30
142 | subtract body { id33 } from body { id34 }
143 | body { id34 } name "cell 6"
144 | move body { id34 } midpoint location -0.75 1.299038105676658 0.0
145 | create prism height 2.0 sides 6 radius 0.5
146 | #{ id35 = Id("body") }
147 | rotate body { id35 } about z angle 30
148 | body { id35 } name "cell 4"
149 | move body { id35 } midpoint location 5.302876193624534e-17 0.8660254037844386 0.0
150 | cylinder height 2.0 radius 0.4
151 | #{ id36 = Id("body") }
152 | body { id36 } name "cell 5"
153 | move body { id36 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
154 | cylinder height 2.0 radius 0.4
155 | #{ id37 = Id("body") }
156 | create prism height 2.0 sides 6 radius 0.5
157 | #{ id38 = Id("body") }
158 | rotate body { id38 } about z angle 30
159 | subtract body { id37 } from body { id38 }
160 | body { id38 } name "cell 6"
161 | move body { id38 } midpoint location 0.7499999999999999 0.4330127018922193 0.0
162 | cylinder height 2.0 radius 0.4
163 | #{ id39 = Id("body") }
164 | body { id39 } name "cell 5"
165 | move body { id39 } midpoint location 0.75 -0.43301270189221913 0.0
166 | cylinder height 2.0 radius 0.4
167 | #{ id40 = Id("body") }
168 | create prism height 2.0 sides 6 radius 0.5
169 | #{ id41 = Id("body") }
170 | rotate body { id41 } about z angle 30
171 | subtract body { id40 } from body { id41 }
172 | body { id41 } name "cell 6"
173 | move body { id41 } midpoint location 0.75 -0.43301270189221913 0.0
174 | cylinder height 2.0 radius 0.4
175 | #{ id42 = Id("body") }
176 | body { id42 } name "cell 5"
177 | move body { id42 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
178 | cylinder height 2.0 radius 0.4
179 | #{ id43 = Id("body") }
180 | create prism height 2.0 sides 6 radius 0.5
181 | #{ id44 = Id("body") }
182 | rotate body { id44 } about z angle 30
183 | subtract body { id43 } from body { id44 }
184 | body { id44 } name "cell 6"
185 | move body { id44 } midpoint location 5.302876193624534e-17 -0.8660254037844386 0.0
186 | cylinder height 2.0 radius 0.4
187 | #{ id45 = Id("body") }
188 | body { id45 } name "cell 5"
189 | move body { id45 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
190 | cylinder height 2.0 radius 0.4
191 | #{ id46 = Id("body") }
192 | create prism height 2.0 sides 6 radius 0.5
193 | #{ id47 = Id("body") }
194 | rotate body { id47 } about z angle 30
195 | subtract body { id46 } from body { id47 }
196 | body { id47 } name "cell 6"
197 | move body { id47 } midpoint location -0.7499999999999998 -0.4330127018922196 0.0
198 | cylinder height 2.0 radius 0.4
199 | #{ id48 = Id("body") }
200 | body { id48 } name "cell 5"
201 | move body { id48 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
202 | cylinder height 2.0 radius 0.4
203 | #{ id49 = Id("body") }
204 | create prism height 2.0 sides 6 radius 0.5
205 | #{ id50 = Id("body") }
206 | rotate body { id50 } about z angle 30
207 | subtract body { id49 } from body { id50 }
208 | body { id50 } name "cell 6"
209 | move body { id50 } midpoint location -0.7499999999999999 0.4330127018922194 0.0
210 | cylinder height 2.0 radius 0.4
211 | #{ id51 = Id("body") }
212 | body { id51 } name "cell 5"
213 | move body { id51 } midpoint location 0.0 0.0 0.0
214 | cylinder height 2.0 radius 0.4
215 | #{ id52 = Id("body") }
216 | create prism height 2.0 sides 6 radius 0.5
217 | #{ id53 = Id("body") }
218 | rotate body { id53 } about z angle 30
219 | subtract body { id52 } from body { id53 }
220 | body { id53 } name "cell 6"
221 | move body { id53 } midpoint location 0.0 0.0 0.0
222 | create prism height 2.0 sides 6 radius 0.5
223 | #{ id54 = Id("body") }
224 | rotate body { id54 } about z angle 30
225 | body { id54 } name "cell 4"
226 | move body { id54 } midpoint location 0.0 1.7320508075688772 2.0
227 | cylinder height 2.0 radius 0.4
228 | #{ id55 = Id("body") }
229 | body { id55 } name "cell 2"
230 | move body { id55 } midpoint location 0.75 1.299038105676658 2.0
231 | cylinder height 2.0 radius 0.4
232 | #{ id56 = Id("body") }
233 | create prism height 2.0 sides 6 radius 0.5
234 | #{ id57 = Id("body") }
235 | rotate body { id57 } about z angle 30
236 | subtract body { id56 } from body { id57 }
237 | body { id57 } name "cell 3"
238 | move body { id57 } midpoint location 0.75 1.299038105676658 2.0
239 | cylinder height 2.0 radius 0.4
240 | #{ id58 = Id("body") }
241 | body { id58 } name "cell 2"
242 | move body { id58 } midpoint location 1.5 0.8660254037844386 2.0
243 | cylinder height 2.0 radius 0.4
244 | #{ id59 = Id("body") }
245 | create prism height 2.0 sides 6 radius 0.5
246 | #{ id60 = Id("body") }
247 | rotate body { id60 } about z angle 30
248 | subtract body { id59 } from body { id60 }
249 | body { id60 } name "cell 3"
250 | move body { id60 } midpoint location 1.5 0.8660254037844386 2.0
251 | cylinder height 2.0 radius 0.4
252 | #{ id61 = Id("body") }
253 | body { id61 } name "cell 2"
254 | move body { id61 } midpoint location 1.5 0.0 2.0
255 | cylinder height 2.0 radius 0.4
256 | #{ id62 = Id("body") }
257 | create prism height 2.0 sides 6 radius 0.5
258 | #{ id63 = Id("body") }
259 | rotate body { id63 } about z angle 30
260 | subtract body { id62 } from body { id63 }
261 | body { id63 } name "cell 3"
262 | move body { id63 } midpoint location 1.5 0.0 2.0
263 | cylinder height 2.0 radius 0.4
264 | #{ id64 = Id("body") }
265 | body { id64 } name "cell 2"
266 | move body { id64 } midpoint location 1.5 -0.8660254037844386 2.0
267 | cylinder height 2.0 radius 0.4
268 | #{ id65 = Id("body") }
269 | create prism height 2.0 sides 6 radius 0.5
270 | #{ id66 = Id("body") }
271 | rotate body { id66 } about z angle 30
272 | subtract body { id65 } from body { id66 }
273 | body { id66 } name "cell 3"
274 | move body { id66 } midpoint location 1.5 -0.8660254037844386 2.0
275 | cylinder height 2.0 radius 0.4
276 | #{ id67 = Id("body") }
277 | body { id67 } name "cell 2"
278 | move body { id67 } midpoint location 0.75 -1.299038105676658 2.0
279 | cylinder height 2.0 radius 0.4
280 | #{ id68 = Id("body") }
281 | create prism height 2.0 sides 6 radius 0.5
282 | #{ id69 = Id("body") }
283 | rotate body { id69 } about z angle 30
284 | subtract body { id68 } from body { id69 }
285 | body { id69 } name "cell 3"
286 | move body { id69 } midpoint location 0.75 -1.299038105676658 2.0
287 | cylinder height 2.0 radius 0.4
288 | #{ id70 = Id("body") }
289 | body { id70 } name "cell 2"
290 | move body { id70 } midpoint location 0.0 -1.7320508075688772 2.0
291 | cylinder height 2.0 radius 0.4
292 | #{ id71 = Id("body") }
293 | create prism height 2.0 sides 6 radius 0.5
294 | #{ id72 = Id("body") }
295 | rotate body { id72 } about z angle 30
296 | subtract body { id71 } from body { id72 }
297 | body { id72 } name "cell 3"
298 | move body { id72 } midpoint location 0.0 -1.7320508075688772 2.0
299 | cylinder height 2.0 radius 0.4
300 | #{ id73 = Id("body") }
301 | body { id73 } name "cell 2"
302 | move body { id73 } midpoint location -0.75 -1.299038105676658 2.0
303 | cylinder height 2.0 radius 0.4
304 | #{ id74 = Id("body") }
305 | create prism height 2.0 sides 6 radius 0.5
306 | #{ id75 = Id("body") }
307 | rotate body { id75 } about z angle 30
308 | subtract body { id74 } from body { id75 }
309 | body { id75 } name "cell 3"
310 | move body { id75 } midpoint location -0.75 -1.299038105676658 2.0
311 | cylinder height 2.0 radius 0.4
312 | #{ id76 = Id("body") }
313 | body { id76 } name "cell 2"
314 | move body { id76 } midpoint location -1.5 -0.8660254037844386 2.0
315 | cylinder height 2.0 radius 0.4
316 | #{ id77 = Id("body") }
317 | create prism height 2.0 sides 6 radius 0.5
318 | #{ id78 = Id("body") }
319 | rotate body { id78 } about z angle 30
320 | subtract body { id77 } from body { id78 }
321 | body { id78 } name "cell 3"
322 | move body { id78 } midpoint location -1.5 -0.8660254037844386 2.0
323 | cylinder height 2.0 radius 0.4
324 | #{ id79 = Id("body") }
325 | body { id79 } name "cell 2"
326 | move body { id79 } midpoint location -1.5 0.0 2.0
327 | cylinder height 2.0 radius 0.4
328 | #{ id80 = Id("body") }
329 | create prism height 2.0 sides 6 radius 0.5
330 | #{ id81 = Id("body") }
331 | rotate body { id81 } about z angle 30
332 | subtract body { id80 } from body { id81 }
333 | body { id81 } name "cell 3"
334 | move body { id81 } midpoint location -1.5 0.0 2.0
335 | cylinder height 2.0 radius 0.4
336 | #{ id82 = Id("body") }
337 | body { id82 } name "cell 2"
338 | move body { id82 } midpoint location -1.5 0.8660254037844386 2.0
339 | cylinder height 2.0 radius 0.4
340 | #{ id83 = Id("body") }
341 | create prism height 2.0 sides 6 radius 0.5
342 | #{ id84 = Id("body") }
343 | rotate body { id84 } about z angle 30
344 | subtract body { id83 } from body { id84 }
345 | body { id84 } name "cell 3"
346 | move body { id84 } midpoint location -1.5 0.8660254037844386 2.0
347 | cylinder height 2.0 radius 0.4
348 | #{ id85 = Id("body") }
349 | body { id85 } name "cell 2"
350 | move body { id85 } midpoint location -0.75 1.299038105676658 2.0
351 | cylinder height 2.0 radius 0.4
352 | #{ id86 = Id("body") }
353 | create prism height 2.0 sides 6 radius 0.5
354 | #{ id87 = Id("body") }
355 | rotate body { id87 } about z angle 30
356 | subtract body { id86 } from body { id87 }
357 | body { id87 } name "cell 3"
358 | move body { id87 } midpoint location -0.75 1.299038105676658 2.0
359 | create prism height 2.0 sides 6 radius 0.5
360 | #{ id88 = Id("body") }
361 | rotate body { id88 } about z angle 30
362 | body { id88 } name "cell 4"
363 | move body { id88 } midpoint location 5.302876193624534e-17 0.8660254037844386 2.0
364 | cylinder height 2.0 radius 0.4
365 | #{ id89 = Id("body") }
366 | body { id89 } name "cell 2"
367 | move body { id89 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
368 | cylinder height 2.0 radius 0.4
369 | #{ id90 = Id("body") }
370 | create prism height 2.0 sides 6 radius 0.5
371 | #{ id91 = Id("body") }
372 | rotate body { id91 } about z angle 30
373 | subtract body { id90 } from body { id91 }
374 | body { id91 } name "cell 3"
375 | move body { id91 } midpoint location 0.7499999999999999 0.4330127018922193 2.0
376 | cylinder height 2.0 radius 0.4
377 | #{ id92 = Id("body") }
378 | body { id92 } name "cell 2"
379 | move body { id92 } midpoint location 0.75 -0.43301270189221913 2.0
380 | cylinder height 2.0 radius 0.4
381 | #{ id93 = Id("body") }
382 | create prism height 2.0 sides 6 radius 0.5
383 | #{ id94 = Id("body") }
384 | rotate body { id94 } about z angle 30
385 | subtract body { id93 } from body { id94 }
386 | body { id94 } name "cell 3"
387 | move body { id94 } midpoint location 0.75 -0.43301270189221913 2.0
388 | cylinder height 2.0 radius 0.4
389 | #{ id95 = Id("body") }
390 | body { id95 } name "cell 2"
391 | move body { id95 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
392 | cylinder height 2.0 radius 0.4
393 | #{ id96 = Id("body") }
394 | create prism height 2.0 sides 6 radius 0.5
395 | #{ id97 = Id("body") }
396 | rotate body { id97 } about z angle 30
397 | subtract body { id96 } from body { id97 }
398 | body { id97 } name "cell 3"
399 | move body { id97 } midpoint location 5.302876193624534e-17 -0.8660254037844386 2.0
400 | cylinder height 2.0 radius 0.4
401 | #{ id98 = Id("body") }
402 | body { id98 } name "cell 2"
403 | move body { id98 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
404 | cylinder height 2.0 radius 0.4
405 | #{ id99 = Id("body") }
406 | create prism height 2.0 sides 6 radius 0.5
407 | #{ id100 = Id("body") }
408 | rotate body { id100 } about z angle 30
409 | subtract body { id99 } from body { id100 }
410 | body { id100 } name "cell 3"
411 | move body { id100 } midpoint location -0.7499999999999998 -0.4330127018922196 2.0
412 | cylinder height 2.0 radius 0.4
413 | #{ id101 = Id("body") }
414 | body { id101 } name "cell 2"
415 | move body { id101 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
416 | cylinder height 2.0 radius 0.4
417 | #{ id102 = Id("body") }
418 | create prism height 2.0 sides 6 radius 0.5
419 | #{ id103 = Id("body") }
420 | rotate body { id103 } about z angle 30
421 | subtract body { id102 } from body { id103 }
422 | body { id103 } name "cell 3"
423 | move body { id103 } midpoint location -0.7499999999999999 0.4330127018922194 2.0
424 | cylinder height 2.0 radius 0.4
425 | #{ id104 = Id("body") }
426 | body { id104 } name "cell 2"
427 | move body { id104 } midpoint location 0.0 0.0 2.0
428 | cylinder height 2.0 radius 0.4
429 | #{ id105 = Id("body") }
430 | create prism height 2.0 sides 6 radius 0.5
431 | #{ id106 = Id("body") }
432 | rotate body { id106 } about z angle 30
433 | subtract body { id105 } from body { id106 }
434 | body { id106 } name "cell 3"
435 | move body { id106 } midpoint location 0.0 0.0 2.0
436 | create prism height 2.0 sides 6 radius 0.5
437 | #{ id107 = Id("body") }
438 | rotate body { id107 } about z angle 30
439 | body { id107 } name "cell 4"
440 | move body { id107 } midpoint location 0.0 1.7320508075688772 4.0
441 | cylinder height 2.0 radius 0.4
442 | #{ id108 = Id("body") }
443 | body { id108 } name "cell 5"
444 | move body { id108 } midpoint location 0.75 1.299038105676658 4.0
445 | cylinder height 2.0 radius 0.4
446 | #{ id109 = Id("body") }
447 | create prism height 2.0 sides 6 radius 0.5
448 | #{ id110 = Id("body") }
449 | rotate body { id110 } about z angle 30
450 | subtract body { id109 } from body { id110 }
451 | body { id110 } name "cell 6"
452 | move body { id110 } midpoint location 0.75 1.299038105676658 4.0
453 | cylinder height 2.0 radius 0.4
454 | #{ id111 = Id("body") }
455 | body { id111 } name "cell 5"
456 | move body { id111 } midpoint location 1.5 0.8660254037844386 4.0
457 | cylinder height 2.0 radius 0.4
458 | #{ id112 = Id("body") }
459 | create prism height 2.0 sides 6 radius 0.5
460 | #{ id113 = Id("body") }
461 | rotate body { id113 } about z angle 30
462 | subtract body { id112 } from body { id113 }
463 | body { id113 } name "cell 6"
464 | move body { id113 } midpoint location 1.5 0.8660254037844386 4.0
465 | cylinder height 2.0 radius 0.4
466 | #{ id114 = Id("body") }
467 | body { id114 } name "cell 5"
468 | move body { id114 } midpoint location 1.5 0.0 4.0
469 | cylinder height 2.0 radius 0.4
470 | #{ id115 = Id("body") }
471 | create prism height 2.0 sides 6 radius 0.5
472 | #{ id116 = Id("body") }
473 | rotate body { id116 } about z angle 30
474 | subtract body { id115 } from body { id116 }
475 | body { id116 } name "cell 6"
476 | move body { id116 } midpoint location 1.5 0.0 4.0
477 | cylinder height 2.0 radius 0.4
478 | #{ id117 = Id("body") }
479 | body { id117 } name "cell 5"
480 | move body { id117 } midpoint location 1.5 -0.8660254037844386 4.0
481 | cylinder height 2.0 radius 0.4
482 | #{ id118 = Id("body") }
483 | create prism height 2.0 sides 6 radius 0.5
484 | #{ id119 = Id("body") }
485 | rotate body { id119 } about z angle 30
486 | subtract body { id118 } from body { id119 }
487 | body { id119 } name "cell 6"
488 | move body { id119 } midpoint location 1.5 -0.8660254037844386 4.0
489 | cylinder height 2.0 radius 0.4
490 | #{ id120 = Id("body") }
491 | body { id120 } name "cell 5"
492 | move body { id120 } midpoint location 0.75 -1.299038105676658 4.0
493 | cylinder height 2.0 radius 0.4
494 | #{ id121 = Id("body") }
495 | create prism height 2.0 sides 6 radius 0.5
496 | #{ id122 = Id("body") }
497 | rotate body { id122 } about z angle 30
498 | subtract body { id121 } from body { id122 }
499 | body { id122 } name "cell 6"
500 | move body { id122 } midpoint location 0.75 -1.299038105676658 4.0
501 | cylinder height 2.0 radius 0.4
502 | #{ id123 = Id("body") }
503 | body { id123 } name "cell 5"
504 | move body { id123 } midpoint location 0.0 -1.7320508075688772 4.0
505 | cylinder height 2.0 radius 0.4
506 | #{ id124 = Id("body") }
507 | create prism height 2.0 sides 6 radius 0.5
508 | #{ id125 = Id("body") }
509 | rotate body { id125 } about z angle 30
510 | subtract body { id124 } from body { id125 }
511 | body { id125 } name "cell 6"
512 | move body { id125 } midpoint location 0.0 -1.7320508075688772 4.0
513 | cylinder height 2.0 radius 0.4
514 | #{ id126 = Id("body") }
515 | body { id126 } name "cell 5"
516 | move body { id126 } midpoint location -0.75 -1.299038105676658 4.0
517 | cylinder height 2.0 radius 0.4
518 | #{ id127 = Id("body") }
519 | create prism height 2.0 sides 6 radius 0.5
520 | #{ id128 = Id("body") }
521 | rotate body { id128 } about z angle 30
522 | subtract body { id127 } from body { id128 }
523 | body { id128 } name "cell 6"
524 | move body { id128 } midpoint location -0.75 -1.299038105676658 4.0
525 | cylinder height 2.0 radius 0.4
526 | #{ id129 = Id("body") }
527 | body { id129 } name "cell 5"
528 | move body { id129 } midpoint location -1.5 -0.8660254037844386 4.0
529 | cylinder height 2.0 radius 0.4
530 | #{ id130 = Id("body") }
531 | create prism height 2.0 sides 6 radius 0.5
532 | #{ id131 = Id("body") }
533 | rotate body { id131 } about z angle 30
534 | subtract body { id130 } from body { id131 }
535 | body { id131 } name "cell 6"
536 | move body { id131 } midpoint location -1.5 -0.8660254037844386 4.0
537 | cylinder height 2.0 radius 0.4
538 | #{ id132 = Id("body") }
539 | body { id132 } name "cell 5"
540 | move body { id132 } midpoint location -1.5 0.0 4.0
541 | cylinder height 2.0 radius 0.4
542 | #{ id133 = Id("body") }
543 | create prism height 2.0 sides 6 radius 0.5
544 | #{ id134 = Id("body") }
545 | rotate body { id134 } about z angle 30
546 | subtract body { id133 } from body { id134 }
547 | body { id134 } name "cell 6"
548 | move body { id134 } midpoint location -1.5 0.0 4.0
549 | cylinder height 2.0 radius 0.4
550 | #{ id135 = Id("body") }
551 | body { id135 } name "cell 5"
552 | move body { id135 } midpoint location -1.5 0.8660254037844386 4.0
553 | cylinder height 2.0 radius 0.4
554 | #{ id136 = Id("body") }
555 | create prism height 2.0 sides 6 radius 0.5
556 | #{ id137 = Id("body") }
557 | rotate body { id137 } about z angle 30
558 | subtract body { id136 } from body { id137 }
559 | body { id137 } name "cell 6"
560 | move body { id137 } midpoint location -1.5 0.8660254037844386 4.0
561 | cylinder height 2.0 radius 0.4
562 | #{ id138 = Id("body") }
563 | body { id138 } name "cell 5"
564 | move body { id138 } midpoint location -0.75 1.299038105676658 4.0
565 | cylinder height 2.0 radius 0.4
566 | #{ id139 = Id("body") }
567 | create prism height 2.0 sides 6 radius 0.5
568 | #{ id140 = Id("body") }
569 | rotate body { id140 } about z angle 30
570 | subtract body { id139 } from body { id140 }
571 | body { id140 } name "cell 6"
572 | move body { id140 } midpoint location -0.75 1.299038105676658 4.0
573 | create prism height 2.0 sides 6 radius 0.5
574 | #{ id141 = Id("body") }
575 | rotate body { id141 } about z angle 30
576 | body { id141 } name "cell 4"
577 | move body { id141 } midpoint location 5.302876193624534e-17 0.8660254037844386 4.0
578 | cylinder height 2.0 radius 0.4
579 | #{ id142 = Id("body") }
580 | body { id142 } name "cell 5"
581 | move body { id142 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
582 | cylinder height 2.0 radius 0.4
583 | #{ id143 = Id("body") }
584 | create prism height 2.0 sides 6 radius 0.5
585 | #{ id144 = Id("body") }
586 | rotate body { id144 } about z angle 30
587 | subtract body { id143 } from body { id144 }
588 | body { id144 } name "cell 6"
589 | move body { id144 } midpoint location 0.7499999999999999 0.4330127018922193 4.0
590 | cylinder height 2.0 radius 0.4
591 | #{ id145 = Id("body") }
592 | body { id145 } name "cell 5"
593 | move body { id145 } midpoint location 0.75 -0.43301270189221913 4.0
594 | cylinder height 2.0 radius 0.4
595 | #{ id146 = Id("body") }
596 | create prism height 2.0 sides 6 radius 0.5
597 | #{ id147 = Id("body") }
598 | rotate body { id147 } about z angle 30
599 | subtract body { id146 } from body { id147 }
600 | body { id147 } name "cell 6"
601 | move body { id147 } midpoint location 0.75 -0.43301270189221913 4.0
602 | cylinder height 2.0 radius 0.4
603 | #{ id148 = Id("body") }
604 | body { id148 } name "cell 5"
605 | move body { id148 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
606 | cylinder height 2.0 radius 0.4
607 | #{ id149 = Id("body") }
608 | create prism height 2.0 sides 6 radius 0.5
609 | #{ id150 = Id("body") }
610 | rotate body { id150 } about z angle 30
611 | subtract body { id149 } from body { id150 }
612 | body { id150 } name "cell 6"
613 | move body { id150 } midpoint location 5.302876193624534e-17 -0.8660254037844386 4.0
614 | cylinder height 2.0 radius 0.4
615 | #{ id151 = Id("body") }
616 | body { id151 } name "cell 5"
617 | move body { id151 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
618 | cylinder height 2.0 radius 0.4
619 | #{ id152 = Id("body") }
620 | create prism height 2.0 sides 6 radius 0.5
621 | #{ id153 = Id("body") }
622 | rotate body { id153 } about z angle 30
623 | subtract body { id152 } from body { id153 }
624 | body { id153 } name "cell 6"
625 | move body { id153 } midpoint location -0.7499999999999998 -0.4330127018922196 4.0
626 | cylinder height 2.0 radius 0.4
627 | #{ id154 = Id("body") }
628 | body { id154 } name "cell 5"
629 | move body { id154 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
630 | cylinder height 2.0 radius 0.4
631 | #{ id155 = Id("body") }
632 | create prism height 2.0 sides 6 radius 0.5
633 | #{ id156 = Id("body") }
634 | rotate body { id156 } about z angle 30
635 | subtract body { id155 } from body { id156 }
636 | body { id156 } name "cell 6"
637 | move body { id156 } midpoint location -0.7499999999999999 0.4330127018922194 4.0
638 | cylinder height 2.0 radius 0.4
639 | #{ id157 = Id("body") }
640 | body { id157 } name "cell 5"
641 | move body { id157 } midpoint location 0.0 0.0 4.0
642 | cylinder height 2.0 radius 0.4
643 | #{ id158 = Id("body") }
644 | create prism height 2.0 sides 6 radius 0.5
645 | #{ id159 = Id("body") }
646 | rotate body { id159 } about z angle 30
647 | subtract body { id158 } from body { id159 }
648 | body { id159 } name "cell 6"
649 | move body { id159 } midpoint location 0.0 0.0 4.0
650 | graphics flush
651 | set default autosize on
652 | zoom reset
653 | set echo on
654 | set info on
655 | set warning on
656 | set journal on
657 |
--------------------------------------------------------------------------------
/src/openmc_cad_adapter/to_cubit_journal.py:
--------------------------------------------------------------------------------
1 | from argparse import ArgumentParser
2 | from collections.abc import Iterable
3 | import math
4 | from numbers import Real
5 | from pathlib import Path
6 | import sys
7 | import warnings
8 |
9 | import numpy as np
10 |
11 | try:
12 | import openmc
13 | except ImportError as e:
14 | raise type(e)("Please install OpenMC's Python API to use the CAD conversion tool")
15 |
16 | from openmc.region import Region, Complement, Intersection, Union
17 | from openmc.surface import Halfspace, Quadric
18 | from openmc.lattice import Lattice, HexLattice
19 |
20 | from .gqs import *
21 | from .cubit_util import emit_get_last_id, reset_cubit_ids, new_variable
22 | from .geom_util import rotate, move
23 | from .cubit_util import emit_get_last_id, reset_cubit_ids, new_variable
24 | from .geom_util import rotate, move
25 | from .cubit_util import emit_get_last_id, reset_cubit_ids, new_variable
26 | from .geom_util import rotate, move
27 |
28 | from .surfaces import _CAD_SURFACE_DICTIONARY
29 |
30 | def flatten(S):
31 | if S == []:
32 | return S
33 | if isinstance(S[0], list):
34 | return flatten(S[0]) + flatten(S[1:])
35 | return S[:1] + flatten(S[1:])
36 |
37 |
38 | def to_cubit_journal(geometry : openmc.Geometry, world : Iterable[Real] = None,
39 | cells: Iterable[int, openmc.Cell] = None,
40 | filename: str = "openmc.jou",
41 | to_cubit: bool = False,
42 | seen: set = set()):
43 | """Convert an OpenMC geometry to a Cubit journal.
44 |
45 | Parameters
46 | ----------
47 | geometry : openmc.Geometry
48 | The geometry to convert to a Cubit journal.
49 | world : Iterable[Real], optional
50 | Extents of the model in X, Y, and Z. Defaults to None.
51 | cells : Iterable[int, openmc.Cell], optional
52 | List of cells or cell IDs to write to individual journal files. If None,
53 | all cells will be written to the same journal file. Defaults to None.
54 | filename : str, optional
55 | Output filename. Defaults to "openmc.jou".
56 | to_cubit : bool, optional
57 | Uses the cubit Python module to write the model as a .cub5 file.
58 | Defaults to False.
59 | seen : set, optional
60 | Internal parameter.
61 |
62 | """
63 | reset_cubit_ids()
64 |
65 | if not filename.endswith('.jou'):
66 | filename += '.jou'
67 |
68 | if isinstance(geometry, openmc.Model):
69 | geometry = geometry.geometry
70 |
71 | if cells is not None:
72 | cells = [c if not isinstance(c, openmc.Cell) else c.id for c in cells]
73 |
74 | if to_cubit:
75 | try:
76 | import cubit
77 | except ImportError:
78 | raise ImportError("Cubit Python API not found. Please install Cubit to use this feature.")
79 |
80 | geom = geometry
81 |
82 | if world is None:
83 | bbox = geometry.bounding_box
84 | if not all(np.isfinite(bbox[0])) or not all(np.isfinite(bbox[1])):
85 | raise RuntimeError('Model bounds were not provided and the bounding box determined by OpenMC is not finite.'
86 | ' Please provide a world size argument to proceed')
87 | # to ensure that the box
88 | box_max = np.max(np.abs(bbox[0], bbox[1]).T)
89 | world = (2 * box_max, 2 * box_max, 2 * box_max)
90 |
91 | if world is None:
92 | raise RuntimeError("Model extents could not be determined automatically and must be provided manually")
93 |
94 | w = world
95 |
96 | cmds = []
97 | cmds.extend( [
98 | #"set undo off",
99 | #"set default autosizing off", # especially when the CAD is complex (contains many spline surfaces) this can have a massive effect
100 | #"set info off",
101 | #"set warning off",
102 | ])
103 | def cubit_cmd(s):
104 | cmds.append(s)
105 |
106 |
107 | def surface_to_cubit_journal(node, w, indent = 0, inner_world = None, hex = False, ent_type = "body", materials='group'):
108 | def ind():
109 | return ' ' * (2*indent)
110 | if isinstance(node, Halfspace):
111 | seen.add( node.surface )
112 | surface = node.surface
113 |
114 | nonlocal cmds
115 |
116 | def reverse():
117 | return "reverse" if node.side == '-' else ""
118 |
119 | if cad_surface := _CAD_SURFACE_DICTIONARY.get(surface._type):
120 | cad_surface = cad_surface.from_openmc_surface(surface)
121 | ids, cad_cmds = cad_surface.to_cubit_surface(ent_type, node, w, inner_world, hex)
122 | cmds += cad_cmds
123 | return ids
124 | elif surface._type == "quadric":
125 | (gq_type, A_, B_, C_, K_, translation, rotation_matrix) = characterize_general_quadratic(surface)
126 |
127 | def rotation_to_axis_angle( mat ):
128 | x = mat[2, 1]-mat[1, 2]
129 | y = mat[0, 2]-mat[2, 0]
130 | z = mat[1, 0]-mat[0, 1]
131 | r = math.hypot( x, math.hypot( y,z ))
132 | t = mat[0,0] + mat[1,1] + mat[2,2]
133 | theta = math.atan2(r,t-1)
134 |
135 | if abs(theta) <= np.finfo(np.float64).eps:
136 | return ( np.array([ 0, 0, 0 ]), 0 )
137 | elif abs( theta - math.pi ) <= np.finfo(np.float64).eps:
138 | # theta is pi (180 degrees) or extremely close to it
139 | # find the column of mat with the largest diagonal
140 | col = 0
141 | if mat[1,1] > mat[col,col]: col = 1
142 | if mat[2,2] > mat[col,col]: col = 2
143 |
144 | axis = np.array([ 0, 0, 0 ])
145 |
146 | axis[col] = math.sqrt( (mat[col,col]+1)/2 )
147 | denom = 2*axis[col]
148 | axis[(col+1)%3] = mat[col,(col+1)%3] / denom
149 | axis[(col+2)%3] = mat[col,(col+2)%3] / denom
150 | return ( axis, theta )
151 | else:
152 | axis = np.array([ x/r, y/r, z/r ])
153 | return ( axis, theta )
154 | (r_axis, r_theta ) = rotation_to_axis_angle( rotation_matrix )
155 | #compensate for cubits insertion of a negative
156 | r_degs = - math.degrees( r_theta )
157 | print( r_axis, math.degrees( r_theta ), r_degs )
158 | if gq_type == ELLIPSOID : #1
159 | r1 = math.sqrt( abs( -K_/A_ ) )
160 | r2 = math.sqrt( abs( -K_/B_ ) )
161 | r3 = math.sqrt( abs( -K_/C_ ) )
162 | cmds.append( f"sphere radius 1")
163 | ids = emit_get_last_id( ent_type , cmds)
164 | cmds.append( f"body {{ { ids } }} scale x { r1 } y { r2 } z { r3 }")
165 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
166 | elif gq_type == ELLIPTIC_CYLINDER : #7
167 | if A_ == 0:
168 | print( "X", gq_type, A_, B_, C_, K_, r_axis, r_degs )
169 | h = inner_world[0] if inner_world else w[0]
170 | r1 = math.sqrt( abs( K_/C_ ) )
171 | r2 = math.sqrt( abs( K_/B_ ) )
172 | cmds.append( f"cylinder height {h} Major Radius {r1} Minor Radius {r2}")
173 | ids = emit_get_last_id( ent_type , cmds)
174 | cmds.append( f"rotate body {{ { ids } }} about y angle 90")
175 | if node.side != '-':
176 | wid = 0
177 | if inner_world:
178 | if hex:
179 | cmds.append( f"create prism height {inner_world[2]} sides 6 radius { inner_world[0] / 2 } " )
180 | wid = emit_get_last_id( ent_type , cmds)
181 | cmds.append( f"rotate body {{ {wid} }} about z angle 30" )
182 | cmds.append( f"rotate body {{ {wid} }} about y angle 90")
183 | else:
184 | cmds.append( f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}" )
185 | wid = emit_get_last_id( ent_type , cmds)
186 | else:
187 | cmds.append( f"brick x {w[0]} y {w[1]} z {w[2]}" )
188 | wid = emit_get_last_id( ent_type , cmds)
189 | cmds.append( f"subtract body {{ { ids } }} from body {{ { wid } }}" )
190 | cmds.append( f"Rotate body {{ {wid } }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
191 | move( wid, translation[0,0], translation[1,0], translation[2,0], cmds)
192 | return wid
193 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
194 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
195 | return ids
196 | if B_ == 0:
197 | print( "Y", gq_type, A_, B_, C_, K_ )
198 | h = inner_world[1] if inner_world else w[1]
199 | r1 = math.sqrt( abs( K_/A_ ) )
200 | r2 = math.sqrt( abs( K_/C_ ) )
201 | cmds.append( f"cylinder height {h} Major Radius {r1} Minor Radius {r2}")
202 | ids = emit_get_last_id( ent_type , cmds)
203 | cmds.append( f"rotate body {{ { ids } }} about x angle 90")
204 | if node.side != '-':
205 | wid = 0
206 | if inner_world:
207 | if hex:
208 | cmds.append( f"create prism height {inner_world[2]} sides 6 radius { inner_world[0] / 2 } " )
209 | wid = emit_get_last_id( ent_type , cmds)
210 | cmds.append( f"rotate body {{ {wid} }} about z angle 30" )
211 | cmds.append( f"rotate body {{ {wid} }} about y angle 90")
212 | else:
213 | cmds.append( f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}" )
214 | wid = emit_get_last_id( ent_type , cmds)
215 | else:
216 | cmds.append( f"brick x {w[0]} y {w[1]} z {w[2]}" )
217 | wid = emit_get_last_id( ent_type , cmds)
218 | cmds.append( f"subtract body {{ { ids } }} from body {{ { wid } }}" )
219 | cmds.append( f"Rotate body {{ {wid } }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
220 | move( wid, translation[0,0], translation[1,0], translation[2,0], cmds)
221 | return wid
222 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
223 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
224 | return ids
225 | if C_ == 0:
226 | print( "Z", gq_type, A_, B_, C_, K_ )
227 | h = inner_world[2] if inner_world else w[2]
228 | r1 = math.sqrt( abs( K_/A_ ) )
229 | r2 = math.sqrt( abs( K_/B_ ) )
230 | cmds.append( f"cylinder height {h} Major Radius {r1} Minor Radius {r2}")
231 | ids = emit_get_last_id( ent_type , cmds)
232 | if node.side != '-':
233 | wid = 0
234 | if inner_world:
235 | if hex:
236 | cmds.append( f"create prism height {inner_world[2]} sides 6 radius { inner_world[0] / 2 } " )
237 | wid = emit_get_last_id( ent_type , cmds)
238 | cmds.append( f"rotate body {{ {wid} }} about z angle 30" )
239 | cmds.append( f"rotate body {{ {wid} }} about y angle 90")
240 | else:
241 | cmds.append( f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}" )
242 | wid = emit_get_last_id( ent_type , cmds)
243 | else:
244 | cmds.append( f"brick x {w[0]} y {w[1]} z {w[2]}" )
245 | wid = emit_get_last_id( ent_type , cmds)
246 | cmds.append( f"subtract body {{ { ids } }} from body {{ { wid } }}" )
247 | cmds.append( f"Rotate body {{ {wid } }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
248 | move( wid, translation[0,0], translation[1,0], translation[2,0], cmds)
249 | return wid
250 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
251 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
252 | return ids
253 | elif gq_type == ELLIPTIC_CONE : #3
254 | if A_ == 0:
255 | h = inner_world[0] if inner_world else w[0]
256 | minor = math.sqrt( abs( -A_/C_ ) )
257 | major = math.sqrt( abs( -A_/B_ ) )
258 | rot_angle = - 90
259 | rot_axis = 1
260 | cmds.append( f"create frustum height {h} Major Radius {major} Minor Radius {minor} top 0")
261 | ids = emit_get_last_id( ent_type , cmds)
262 | cmds.append( f"rotate body {{ { ids } }} about y angle -90")
263 | cmds.append( f"copy body {{ { ids } }}")
264 | mirror = emit_get_last_id( ent_type , cmds)
265 | cmds.append( f"rotate body {{ { mirror } }} about 0 0 0 angle 180")
266 | cmds.append( f"unit body {{ { ids } }} {{ { mirror } }}")
267 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
268 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
269 | return ids
270 | if B_ == 0:
271 | h = inner_world[1] if inner_world else w[1]
272 | minor = math.sqrt( abs( -B_/A_ ) )
273 | major = math.sqrt( abs( -B_/C_ ) )
274 | rot_angle = 90
275 | rot_axis = 0
276 | cmds.append( f"create frustum height {h} Major Radius {major} Minor Radius {minor} top 0")
277 | ids = emit_get_last_id( ent_type , cmds)
278 | cmds.append( f"rotate body {{ { ids } }} about x angle 90")
279 | cmds.append( f"copy body {{ { ids } }}")
280 | mirror = emit_get_last_id( ent_type , cmds)
281 | cmds.append( f"rotate body {{ { mirror } }} about 0 0 0 angle 180")
282 | cmds.append( f"unit body {{ { ids } }} {{ { mirror } }}")
283 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
284 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
285 | return ids
286 | if C_ == 0:
287 | h = inner_world[2] if inner_world else w[2]
288 | minor = math.sqrt( abs( -C_/A_ ) )
289 | major = math.sqrt( abs( -C_/B_ ) )
290 | rot_angle = 180
291 | rot_axis = 0
292 | cmds.append( f"create frustum height {h} Major Radius {major} Minor Radius {minor} top 0")
293 | ids = emit_get_last_id( ent_type , cmds)
294 | cmds.append( f"copy body {{ { ids } }}")
295 | mirror = emit_get_last_id( ent_type , cmds)
296 | cmds.append( f"rotate body {{ { mirror } }} about 0 0 0 angle 180")
297 | cmds.append( f"unit body {{ { ids } }} {{ { mirror } }}")
298 | cmds.append( f"Rotate body {{ {ids} }} about 0 0 0 direction {r_axis[0]} {r_axis[1]} {r_axis[2]} Angle {r_degs}")
299 | move( ids, translation[0,0], translation[1,0], translation[2,0], cmds)
300 | return ids
301 | else:
302 | raise NotImplementedError(f"{surface.type} not implemented")
303 | else:
304 | raise NotImplementedError(f"{surface.type} not implemented")
305 | elif isinstance(node, Complement):
306 | print( "Complement:" )
307 | id = surface_to_cubit_journal(node.node, w, indent + 1, inner_world, ent_type = ent_type )
308 | cmds.append( f"brick x {w[0]} y {w[1]} z {w[2]}" )
309 | wid = emit_get_last_id( ent_type , cmds)
310 | cmds.append( f"subtract body {{ {id} }} from body {{ {wid} }}" )
311 | return emit_get_last_id( ent_type , cmds)
312 | elif isinstance(node, Intersection):
313 | last = 0
314 | if len( node ) > 0:
315 | last = surface_to_cubit_journal( node[0], w, indent + 1, inner_world, ent_type = ent_type ,)
316 | for subnode in node[1:]:
317 | s = surface_to_cubit_journal( subnode, w, indent + 1, inner_world, ent_type = ent_type ,)
318 | before = emit_get_last_id(cmds=cmds)
319 | cmds.append( f"intersect {ent_type} {{ {last} }} {{ {s} }}" )
320 | after = emit_get_last_id(cmds=cmds)
321 | last = new_variable()
322 | cmds.append( f"#{{{last} = ( {before} == {after} ) ? {s} : {after}}}" )
323 | if inner_world:
324 | cmds.append( f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}" )
325 | iwid = emit_get_last_id( ent_type , cmds)
326 | cmds.append( f"intersect {ent_type} {{ {last} }} {{ {iwid} }}" )
327 | return emit_get_last_id( ent_type , cmds)
328 | return last
329 | elif isinstance(node, Union):
330 | if len( node ) > 0:
331 | local_ent_type = "body"
332 | first = surface_to_cubit_journal( node[0], w, indent + 1, inner_world, ent_type = local_ent_type )
333 | for subnode in node[1:]:
334 | s = surface_to_cubit_journal( subnode, w, indent + 1, inner_world, ent_type = local_ent_type )
335 | cmds.append( f"unite {local_ent_type} {{ {first} }} {{ {s} }}" )
336 | if inner_world:
337 | cmds.append( f"brick x {inner_world[0]} y {inner_world[1]} z {inner_world[2]}" )
338 | iwid = emit_get_last_id( local_ent_type , cmds)
339 | cmds.append( f"intersect {ent_type} {{ {last} }} {{ {iwid} }}" )
340 | return first
341 | return first
342 | elif isinstance(node, Quadric):
343 | pass
344 | else:
345 | raise NotImplementedError(f"{node} not implemented")
346 |
347 | def process_node_or_fill( node, w, indent = 0, offset = [0, 0], inner_world = None, outer_ll = None, ent_type = "body", hex = False ):
348 | def ind():
349 | return ' ' * (2*indent)
350 | seen.add( node )
351 | results = []
352 | if hasattr( node, "region" ) and not ( hasattr( node, "fill" ) and isinstance(node.fill, Lattice) ):
353 | if node.region != None:
354 | id = surface_to_cubit_journal( node.region, w, indent, inner_world, hex = hex )
355 | results.append( id )
356 | elif hex:
357 | cmds.append( f"create prism height {inner_world[2]} sides 6 radius { ( inner_world[0] / 2) }" )
358 | wid = emit_get_last_id( ent_type , cmds)
359 | cmds.append( f"rotate body {{ {wid} }} about z angle 30" )
360 | results.append( wid )
361 |
362 | if hasattr( node, "fill" ) and isinstance(node.fill, Lattice):
363 | id = process_node_or_fill( node.fill, w, indent + 1, offset, inner_world )
364 | results.append( id )
365 | if hasattr( node, "universes" ):
366 | pitch = node._pitch
367 | if isinstance( node, HexLattice ) :
368 | three_d_hex_lattice = len( node._pitch ) > 1
369 | #three_d_hex_lattice = len( node.center ) > 2
370 | #3d hex lattice
371 | if three_d_hex_lattice:
372 | center = [ node.center[0], node.center[1], node.center[1] ]
373 | ii = 0
374 | for uss in node.universes:
375 | z = ii * pitch[1]
376 | j = 0
377 | for us in uss:
378 | k = 0
379 | ring_id = ( len( uss ) - j -1 )
380 | #print( "RING_ID", ring_id )
381 | def draw_hex_cell( n, cell, x, y ):
382 | #print( i, j, k, len( node.universes ), len( uss), len( us ), x, y )
383 | id = process_node_or_fill( cell, [ w[0], w[1], w[2] ], indent + 1, offset = [x,y,z], inner_world=[ pitch[0], pitch[0], pitch[1] ], outer_ll=outer_ll if outer_ll else [ node.center[0], node.center[1] ], hex = True )
384 | ids = str( id )
385 | if isinstance( id, list ):
386 | ids = ' '.join( map(str, id) )
387 | else:
388 | pass
389 | if ids != '':
390 | cmds.append( f"move body {{ {ids} }} midpoint location {x} {y} {z}" )
391 | side_to_side_diameter = pitch[0]/2 * math.sqrt( 3 )
392 | center_to_mid_side_diameter = ( ( pitch[0] / 2 ) * math.sin( math.pi / 6 ) ) + pitch[0] / 2
393 | if ring_id < 2:
394 | for u in us:
395 | for n, cell in u._cells.items():
396 | #print( n, cell )
397 | theta = 2 * math.pi * -k / len( us ) + math.pi / 2
398 | r = ( len( uss ) - j -1 ) * side_to_side_diameter
399 | x = r * math.cos( theta )
400 | y = r * math.sin( theta )
401 | draw_hex_cell( n, cell, x, y )
402 | k = k + 1
403 | else:
404 | x = 0
405 | x_pos = 0
406 | y_pos = 0
407 | r = ring_id
408 | for i in range( r, 0, -1 ):
409 | x_pos = x * center_to_mid_side_diameter
410 | y_pos = ring_id * side_to_side_diameter - ( x ) * 0.5 * side_to_side_diameter
411 | for n, cell in us[k]._cells.items():
412 | draw_hex_cell( n, cell, x_pos, y_pos )
413 | #print( r, k, x, x_pos, y_pos )
414 | k = k + 1
415 | x = x + 1
416 | y_pos = ring_id * side_to_side_diameter - ( x ) * 0.5 * side_to_side_diameter
417 | for i in range( r, 0, -1 ):
418 | x_pos = x * center_to_mid_side_diameter
419 | for n, cell in us[k]._cells.items():
420 | draw_hex_cell( n, cell, x_pos, y_pos )
421 | #print( r, k, x, x_pos, y_pos )
422 | y_pos = y_pos - side_to_side_diameter
423 | k = k + 1
424 | for i in range( r, 0, -1 ):
425 | x_pos = x * center_to_mid_side_diameter
426 | y_pos = - ring_id * side_to_side_diameter + ( x ) * 0.5 * side_to_side_diameter
427 | for n, cell in us[k]._cells.items():
428 | draw_hex_cell( n, cell, x_pos, y_pos )
429 | #print( r, k, x, x_pos, y_pos )
430 | k = k + 1
431 | x = x - 1
432 | for i in range( r, 0, -1 ):
433 | x_pos = x * center_to_mid_side_diameter
434 | y_pos = - ring_id * side_to_side_diameter - ( x ) * 0.5 * side_to_side_diameter
435 | for n, cell in us[k]._cells.items():
436 | draw_hex_cell( n, cell, x_pos, y_pos )
437 | #print( r, k, x, x_pos, y_pos )
438 | k = k + 1
439 | x = x - 1
440 | y_pos = - ring_id * side_to_side_diameter - ( x ) * 0.5 * side_to_side_diameter
441 | for i in range( r, 0, -1 ):
442 | x_pos = x * center_to_mid_side_diameter
443 | for n, cell in us[k]._cells.items():
444 | draw_hex_cell( n, cell, x_pos, y_pos )
445 | #print( r, k, x, x_pos, y_pos )
446 | y_pos = y_pos + side_to_side_diameter
447 | k = k + 1
448 | for i in range( r, 0, -1 ):
449 | x_pos = x * center_to_mid_side_diameter
450 | y_pos = ring_id * side_to_side_diameter + ( x ) * 0.5 * side_to_side_diameter
451 | for n, cell in us[k]._cells.items():
452 | draw_hex_cell( n, cell, x_pos, y_pos )
453 | #print( r, k, x, x_pos, y_pos )
454 | k = k + 1
455 | x = x + 1
456 | j = j + 1
457 | ii = ii + 1
458 | #2d hex lattice
459 | else:
460 | center = [ node.center[0], node.center[1] ]
461 | i = 0
462 | for us in node.universes:
463 | j = 0
464 | for u in us:
465 | for n, cell in u._cells.items():
466 | #print( n, cell )
467 | theta = 2 * math.pi * -j / len( us ) + math.pi / 2
468 | r = ( len( uss ) - i -1 ) * pitch[0]
469 | x = r * math.cos( theta )
470 | y = r * math.sin( theta )
471 | #print( n, i, j, k, len( node.universes ), len( uss), len( us ), x, y, theta )
472 | id = process_node_or_fill( cell, [ w[0], w[1], w[2] ], indent + 1, offset = [x,y], inner_world=[ pitch[0], pitch[0], pitch[1] ], outer_ll=outer_ll if outer_ll else [ node.center[0], node.center[1] ], hex = True )
473 | ids = str( id )
474 | if isinstance( id, list ):
475 | ids = ' '.join( map(str, id) )
476 | #results.extend( id )
477 | else:
478 | #results.append( id )
479 | pass
480 | if ids != '':
481 | cmds.append( f"move body {{ {ids} }} midpoint location {x} {y} {z}" )
482 | j = j + 1
483 | i = i + 1
484 |
485 | elif isinstance( node, Lattice ):
486 | ll = [ node.lower_left[0], node.lower_left[1] ]
487 | if outer_ll:
488 | ll = outer_ll
489 | ll[0] = ll[0] + pitch[0] / 2
490 | ll[1] = ll[1] + pitch[1] / 2
491 | i = 0
492 | for us in node.universes:
493 | j = 0
494 | for u in us:
495 | for n, cell in u._cells.items():
496 | x = ll[0] + j * pitch[0] + offset[0]
497 | y = ll[1] + i * pitch[1] + offset[1]
498 | #print( ind(), "UCell:", n, cell )
499 | id = process_node_or_fill( cell, [ w[0], w[1], w[2] ], indent + 1, offset = [x,y], inner_world=[ pitch[0], pitch[1], w[2] ], outer_ll=outer_ll if outer_ll else [ node.lower_left[0], node.lower_left[1] ] )
500 | ids = str( id )
501 | if isinstance( id, list ):
502 | ids = ' '.join( map(str, id) )
503 | #results.extend( id )
504 | else:
505 | #results.append( id )
506 | pass
507 | if ids != '':
508 | cmds.append( f"move body {{ {ids} }} midpoint location {x} {y} 0 except z" )
509 | j = j + 1
510 | i = i + 1
511 | #FIXME rotate and tranlate
512 | r = flatten( results )
513 | if len( r ) > 0:
514 | if node.name:
515 | cmds.append( f"body {{ {r[0]} }} name \"{node.name}\"" )
516 | else:
517 | cmds.append( f"body {{ {r[0]} }} name \"Cell_{node.id}\"" )
518 | return r
519 |
520 | def do_cell(cell, cell_ids: Iterable[int] = None):
521 | before = len( cmds )
522 | cmds.append( f"#CELL {cell.id}" )
523 | vol_or_body = process_node_or_fill( cell, w )
524 | if cell.fill is None:
525 | cmds.append(f'group "mat:void" add body {{ { vol_or_body[0] } }} ')
526 | elif cell.fill_type == "material":
527 | mat_identifier = f"mat:{cell.fill.id}"
528 | # use material names when possible
529 | if cell.fill.name is not None and cell.fill.name:
530 | mat_identifier = f"mat:{cell.fill.name}"
531 | if len(mat_identifier) > 32:
532 | mat_identifier = mat_identifier[:32]
533 | warnings.warn(f'Truncating material name {mat_identifier} to 32 characters')
534 | cmds.append( f'group \"{mat_identifier}\" add body {{ { vol_or_body[0] } }} ' )
535 | after = len( cmds )
536 |
537 | if cell_ids is not None and cell.id in cell_ids:
538 | if filename.endswith(".jou"):
539 | cell_filename = filename[:-4] + f"_cell{cell.id}.jou"
540 | else:
541 | cell_filename = filename + f"_cell{cell.id}"
542 | write_journal_file(cell_filename, cmds[before:after])
543 |
544 | for cell in geom.root_universe._cells.values():
545 | if cells is not None and cell.id in cells:
546 | do_cell( cell, cell_ids=cells)
547 | else:
548 | do_cell( cell )
549 |
550 | if filename:
551 | write_journal_file(filename, cmds)
552 |
553 | if to_cubit:
554 | cubit.cmd( "reset" )
555 | for x in cmds:
556 | cubit.cmd( x )
557 | cubit.cmd(f"save as {filename[:-4]}.cub overwrite")
558 |
559 |
560 | def write_journal_file(filename, cmds, verbose_journal=False):
561 | with open(filename, "w") as f:
562 | if not verbose_journal:
563 | f.write("set echo off\n")
564 | f.write("set info off\n")
565 | f.write("set warning off\n")
566 | f.write("graphics pause\n")
567 | f.write("set journal off\n")
568 | f.write("set default autosize off\n")
569 | for x in cmds:
570 | f.write(x + "\n")
571 | if not verbose_journal:
572 | f.write("graphics flush\n")
573 | f.write("set default autosize on\n")
574 | f.write("zoom reset\n")
575 | f.write("set echo on\n")
576 | f.write("set info on\n")
577 | f.write("set warning on\n")
578 | f.write("set journal on\n")
579 |
580 |
581 | def material_assignment(cell, geom_id, assignment_type='group'):
582 | if cell.fill is None:
583 | mat_identifier = "mat:void"
584 | elif cell.fill_type == "material":
585 | mat_identifier = f"mat:{cell.fill.id}"
586 | # use material names when possible
587 | if cell.fill.name is not None and cell.fill.name:
588 | mat_identifier = f"mat:{cell.fill.name}"
589 | else:
590 | return []
591 |
592 | if len(mat_identifier) > 32:
593 | mat_identifier = mat_identifier[:32]
594 | warnings.warn(f'Truncating material name {mat_identifier} to 32 characters')
595 |
596 | cmds = []
597 | if assignment_type == 'group':
598 | cmds.append(f'group \"{mat_identifier}\" add body {{ { geom_id } }}')
599 | else:
600 | raise ValueError(f"Unknown material assignment type requested: {assignment_type}")
601 |
602 | return cmds
603 |
604 |
605 | def openmc_to_cad():
606 | """Command-line interface for OpenMC to CAD model conversion"""
607 | parser = ArgumentParser()
608 | parser.add_argument('input', help='Path to a OpenMC model.xml file or path to a directory containing OpenMC XMLs')
609 | parser.add_argument('-o', '--output', help='Output filename', default='openmc.jou')
610 | parser.add_argument('-w', '--world-size', help='Maximum width of the geometry in X, Y, and Z', nargs=3, type=int)
611 | parser.add_argument('-c', '--cells', help='List of cell IDs to convert', nargs='+', type=int)
612 | parser.add_argument('--to-cubit', help='Run Cubit', default=False, action='store_true')
613 | parser.add_argument('--cubit-path', help='Path to Cubit bin directory', default=None, type=str)
614 | args = parser.parse_args()
615 |
616 | model_path = Path(args.input)
617 |
618 | if model_path.is_dir():
619 | if not (model_path / 'settings.xml').exists():
620 | raise IOError(f'Unable to locate settings.xml in {model_path}')
621 | model = openmc.Model.from_xml(*[model_path / f for f in ('geometry.xml', 'materials.xml', 'settings.xml')])
622 | else:
623 | model = openmc.Model.from_model_xml(model_path)
624 |
625 | if args.cubit_path is not None:
626 | sys.path.append(args.cubit_path)
627 |
628 | to_cubit_journal(model.geometry, world=args.world_size, filename=args.output, cells=args.cells, to_cubit=args.to_cubit)
629 |
630 |
631 | __all__ = ['CADPlane', 'CADXPlane', 'CADYPlane', 'CADZPlane',
632 | 'CADCylinder', 'CADXCylinder', 'CADYCylinder', 'CADZCylinder',
633 | 'CADSphere', 'CADXCone', 'CADYCone', 'CADZCone', 'CADXTorus', 'CADYTorus', 'CADZTorus']
--------------------------------------------------------------------------------