Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Commit

Permalink
Merge pull request #45 from fusion-energy/develop
Browse files Browse the repository at this point in the history
updating docs and checking cad quality
  • Loading branch information
shimwell authored Sep 22, 2021
2 parents ff6d4c8 + 90931a8 commit fb1fbc5
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 63 deletions.
15 changes: 15 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Shimwell"
given-names: "Jonathan"
orcid: "https://orcid.org/0000-0001-6909-0946"
- family-names: "Labrie-Cleary"
given-names: "Luke"
- family-names: "Gray"
given-names: "Ander"
orcid: "https://orcid.org/0000-0002-1585-0900"
title: "cad-to-h5m"
version: 0.3.0
date-released: 2021-9-15
url: "https://github.com/fusion-energy/cad_to_h5m"
35 changes: 24 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ It is also possible to convert .sat files in the following way.
cad-to-h5m -i part1.sat -o dagmc.h5m -t mat:1 -c /opt/Coreform-Cubit-2021.5/bin/
``` -->

# Installation

The package is available via the PyPi package manager and the recommended
method of installing is via pip.
```bash
pip install cad_to_h5m
```

In addition [Cubit](https://coreform.com/products/coreform-cubit/) and the
[Svalinn Plugin](https://github.com/svalinn/Cubit-plugin) needs to be
installed to make full use of this package.

# Python API usage

Creating a h5m file from a single STP file called ```part1.stp``` and applying
Expand Down Expand Up @@ -142,11 +154,22 @@ cad_to_h5m(
cubit_filename='unstructured_mesh_file.cub'
)
```
mbconvert is a terminal command that is part of MOAB.
The ```cub``` file produced contains a tet mesh as well as the faceted geometry.
The tet mesh can be extracted and converted to another ```h5m``` file for use in
openmc. MOAB is needed to convert the file and includes the command line tool
```mbconvert```, MOAB can be installed into a conda environment with:

```
conda install -c conda-forge moab
```
Then ```mbconvert``` can be used to extract and convert the tet mesh from the
```cub``` file into a ```h5m``` file.

```bash
mbconvert unstructured_mesh_file.cub unstructured_mesh_file.h5m
```


Scaling geometry is also possible. This is useful as particle transport codes
often make use of cm as the default unit. CAD files typically appear in mm as
the default limit. Some CAD packages ignore units while others make use of them.
Expand Down Expand Up @@ -189,13 +212,3 @@ cad_to_h5m(
implicit_complement_material_tag = 'm2'
)
```
# Installation

The package is available via the PyPi package manager and the recommended
method of installing is via pip.
```bash
pip install cad_to_h5m
```

Some Python dependencies (such as Numpy) are installed during the ```pip install cad_to_h5m``` process, however [Cubit](https://coreform.com/products/coreform-cubit/) needs
to be installed seperatly to make full use of this package.
64 changes: 28 additions & 36 deletions cad_to_h5m/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def cad_to_h5m(
use in DAGMC enabled particle transport codes.
cubit_filename: the file name of the output cubit file. Should end with .cub
or .cub5. Includes any tet meshes produced and therefore this output
can be useful for producing unstructured meshs for use in DAGMC
can be useful for producing unstructured meshes for use in DAGMC
simulations.
cubit_path: the path to the Cubit directory used to import Cubit from. On
Ubuntu with Cubit 2021.5 this would be "/opt/Coreform-Cubit-2021.5/bin/"
Expand Down Expand Up @@ -101,7 +101,7 @@ def cad_to_h5m(
except ImportError:
msg = (
"import cubit failed, cubit was not importable from the "
"provided path {cubit_path}"
f"provided path {cubit_path}"
)
raise ImportError(msg)

Expand All @@ -111,7 +111,7 @@ def cad_to_h5m(
files_with_tags, cubit)
print(geometry_details)

scale_geometry(cubit, geometry_details)
scale_geometry(geometry_details, cubit)

tag_geometry_with_mats(
geometry_details, implicit_complement_material_tag, cubit
Expand Down Expand Up @@ -140,32 +140,29 @@ def cad_to_h5m(
return h5m_filename


def create_tet_mesh(geometry_details, exo_filename, cubit):
def create_tet_mesh(geometry_details, cubit):
cubit.cmd("Trimesher volume gradation 1.3")

cubit.cmd("volume all size auto factor 5")
for entry in geometry_details:
print('entry=', entry)
if "tet_mesh" in entry.keys():
for volume in entry["volumes"]:
print('volume=', volume)
cubit.cmd(
"volume " + str(volume) + " size auto factor 6"
) # this number is the size of the mesh 1 is small 10 is large
cubit.cmd("volume all scheme tetmesh proximity layers off")
# example entry ' size 0.5'
cubit.cmd(f"volume {volume} " + entry["tet_mesh"])
cubit.cmd("mesh volume " + str(volume))
print('meshed some volumes')


def scale_geometry(cubit, geometry_details):
def scale_geometry(geometry_details: dict, cubit):
for entry in geometry_details:
if 'scale' in entry.keys():
cubit.cmd(
f'volume {" ".join(entry["volumes"])} scale {entry["scale"]}')


# TODO implent a flag to allow tet file info to be saved
# def save_tet_details_to_json_file(
# geometry_details,
# filename="mesh_details.json"):
Expand All @@ -179,14 +176,15 @@ def scale_geometry(cubit, geometry_details):
# with open(filename, "w") as outfile:
# json.dump(geometry_details, outfile, indent=4)


def save_output_files(
make_watertight,
geometry_details,
h5m_filename,
cubit_filename,
geometry_details_filename,
faceting_tolerance,
exo_filename,
make_watertight: bool,
geometry_details: dict,
h5m_filename: str,
cubit_filename: str,
geometry_details_filename: str,
faceting_tolerance: float,
exo_filename: str,
cubit,
):
"""This saves the output files"""
Expand Down Expand Up @@ -215,7 +213,7 @@ def save_output_files(
+ str(faceting_tolerance)
)

create_tet_mesh(geometry_details, exo_filename, cubit)
create_tet_mesh(geometry_details, cubit)

if exo_filename is not None:
Path(exo_filename).parents[0].mkdir(parents=True, exist_ok=True)
Expand All @@ -231,11 +229,16 @@ def imprint_geometry(cubit):
cubit.cmd("imprint body all")


def merge_geometry(merge_tolerance, cubit):
# optional as there is a default
def merge_geometry(merge_tolerance: float, cubit):
"""merges the geometry with te specified tolerance
Args:
merge_tolerance: The allowable distance between surfaces before merging
them together. Optional as there is a default built into the DAGMC
export command
"""
cubit.cmd(f"merge tolerance {merge_tolerance}")
cubit.cmd("merge vol all group_results")
cubit.cmd("graphics tol angle 3")


def find_all_surfaces_of_reflecting_wedge(new_vols, cubit):
Expand All @@ -256,8 +259,6 @@ def find_all_surfaces_of_reflecting_wedge(new_vols, cubit):
print("surface_info_dict", surface_info_dict)
return surface_info_dict

# todo additional testing required


def find_reflecting_surfaces_of_reflecting_wedge(
geometry_details, surface_reflectivity_name, cubit
Expand Down Expand Up @@ -330,15 +331,9 @@ def tag_geometry_with_mats(

def find_number_of_volumes_in_each_step_file(files_with_tags, cubit):
""" """
body_ids = ""
volumes_in_each_step_file = []
# all_groups=cubit.parse_cubit_list("group","all")
# starting_group_id = len(all_groups)
for entry in files_with_tags:
print(entry)
# starting_group_id = starting_group_id +1
print(f'loading {entry["cad_filename"]}')
current_vols = cubit.parse_cubit_list("volume", "all")
# print(os.path.join(basefolder, entry['cad_filename']))
if entry["cad_filename"].endswith(
".stp") or entry["cad_filename"].endswith(".step"):
import_type = "step"
Expand All @@ -352,8 +347,6 @@ def find_number_of_volumes_in_each_step_file(files_with_tags, cubit):
msg = f'File with filename {entry["cad_filename"]} could not be found'
raise FileNotFoundError(msg)
short_file_name = os.path.split(entry["cad_filename"])[-1]
# print('short_file_name',short_file_name)
# cubit.cmd('import '+import_type+' "' + entry['stp_filename'] + '" separate_bodies no_surfaces no_curves no_vertices group "'+str(short_file_name)+'"')
cubit.cmd(
"import "
+ import_type
Expand All @@ -364,11 +357,6 @@ def find_number_of_volumes_in_each_step_file(files_with_tags, cubit):
all_vols = cubit.parse_cubit_list("volume", "all")
new_vols = set(current_vols).symmetric_difference(set(all_vols))
new_vols = list(map(str, new_vols))
print("new_vols", new_vols, type(new_vols))
current_bodies = cubit.parse_cubit_list("body", "all")
print("current_bodies", current_bodies)
# volumes_in_group = cubit.cmd('volume in group '+str(starting_group_id))
# print('volumes_in_group',volumes_in_group,type(volumes_in_group))
if len(new_vols) > 1:
cubit.cmd(
"unite vol " +
Expand All @@ -394,4 +382,8 @@ def find_number_of_volumes_in_each_step_file(files_with_tags, cubit):
entry["surface_reflectivity"])
cubit.cmd("separate body all")

# checks the cad is clean and catches some errors with the geometry early
cubit.cmd("validate vol all")
cubit.cmd("autoheal analyze vol all")

return files_with_tags, sum(all_vols)
3 changes: 0 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,5 @@
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
],
tests_require=[
"pytest",
],
python_requires='>=3.6',
)
28 changes: 15 additions & 13 deletions tests/test_python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,27 @@
import urllib.request
from pathlib import Path

import pytest
from cad_to_h5m import cad_to_h5m


class TestApiUsage(unittest.TestCase):
def setUp(self):

if not Path("tests/v0.0.1.tar.gz").is_file():
if not Path("tests/v0.0.2.tar.gz").is_file():
url = "https://github.com/Shimwell/fusion_example_for_openmc_using_paramak/archive/refs/tags/v0.0.1.tar.gz"
urllib.request.urlretrieve(url, "tests/v0.0.1.tar.gz")

tar = tarfile.open("tests/v0.0.1.tar.gz", "r:gz")
tar.extractall("tests")
tar.close()
tar = tarfile.open("tests/v0.0.1.tar.gz", "r:gz")
tar.extractall("tests")
tar.close()

url = "https://raw.githubusercontent.com/fusion-energy/neutronics_workflow/main/example_01_single_volume_cell_tally/stage_1_output/steel.stp"
urllib.request.urlretrieve(url, "tests/steel.stp")
if not Path("tests/v0.0.2.tar.gz").is_file():
url = "https://github.com/fusion-energy/neutronics_workflow/archive/refs/tags/v0.0.2.tar.gz"
urllib.request.urlretrieve(url, "tests/v0.0.2.tar.gz")

tar = tarfile.open("tests/v0.0.2.tar.gz", "r:gz")
tar.extractall("tests")
tar.close()

def test_h5m_file_creation(self):
"""Checks that a h5m file is created from stp files when make_watertight
Expand Down Expand Up @@ -148,10 +152,9 @@ def test_exo_file_creation_with_different_sizes(self):
cad_to_h5m(
files_with_tags=[
{
"cad_filename": "tests/steel.stp",
"cad_filename": "tests/neutronics_workflow-0.0.2/example_01_single_volume_cell_tally/stage_1_output/steel.stp",
"material_tag": "mat1",
"tet_mesh": "size 2"
}],
"tet_mesh": "size 2"}],
exo_filename="umesh_2.exo",
)

Expand All @@ -162,10 +165,9 @@ def test_exo_file_creation_with_different_sizes(self):
cad_to_h5m(
files_with_tags=[
{
"cad_filename": "tests/steel.stp",
"cad_filename": "tests/neutronics_workflow-0.0.2/example_01_single_volume_cell_tally/stage_1_output/steel.stp",
"material_tag": "mat1",
"tet_mesh": "size 3"
}],
"tet_mesh": "size 3"}],
exo_filename="umesh_3.exo",
)

Expand Down

0 comments on commit fb1fbc5

Please sign in to comment.