From 09760e0500c4f4dde1aec5b8a510e50eca107092 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 2 Sep 2021 23:09:05 +0100 Subject: [PATCH 1/9] added libmesh umesh method --- openmc_dagmc_wrapper/neutronics_model.py | 71 ++++++++++++++++-------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/openmc_dagmc_wrapper/neutronics_model.py b/openmc_dagmc_wrapper/neutronics_model.py index 7c25c09..5611304 100644 --- a/openmc_dagmc_wrapper/neutronics_model.py +++ b/openmc_dagmc_wrapper/neutronics_model.py @@ -19,8 +19,9 @@ class NeutronicsModel: materials, source and neutronics tallies. Arguments: - source (openmc.Source()): the particle source to use during the - OpenMC simulation. + h5m_filename: the name of the faceted h5m DAGMC geometry file. + exo_filename: the name of the tet mesh in Exodus format. + source: the particle source to use during the OpenMC simulation. materials: Where the dictionary keys are the material tag and the dictionary values are either a string, openmc.Material, neutronics-material-maker.Material or @@ -68,6 +69,7 @@ def __init__( source: openmc.Source(), materials: dict, cell_tallies: Optional[List[str]] = None, + exo_filename: Optional[str] = None, mesh_tally_2d: Optional[List[str]] = None, mesh_tally_3d: Optional[List[str]] = None, mesh_2d_resolution: Optional[Tuple[int, int, int]] = (400, 400), @@ -87,6 +89,7 @@ def __init__( ): self.materials = materials self.h5m_filename = h5m_filename + self.exo_filename = exo_filename self.source = source self.cell_tallies = cell_tallies self.mesh_tally_2d = mesh_tally_2d @@ -117,7 +120,17 @@ def h5m_filename(self, value): if isinstance(value, str): self._h5m_filename = value else: - raise TypeError("NeutronicsModelFromReactor.geometry should be a string") + raise TypeError("NeutronicsModelFromReactor.h5m_filename should be a string") + @property + def exo_filename(self): + return self._exo_filename + + @exo_filename.setter + def exo_filename(self, value): + if isinstance(value, (str, type(None))): + self._exo_filename = value + else: + raise TypeError("NeutronicsModelFromReactor.exo_filename should be a string") @property def source(self): @@ -126,10 +139,8 @@ def source(self): @source.setter def source(self, value): if not isinstance(value, (openmc.Source, type(None))): - raise TypeError( - "NeutronicsModelFromReactor.source should be an \ - openmc.Source() object" - ) + msg = "NeutronicsModelFromReactor.source should be an openmc.Source() object" + raise TypeError(msg) self._source = value @property @@ -141,8 +152,7 @@ def cell_tallies(self, value): if value is not None: if not isinstance(value, list): raise TypeError( - "NeutronicsModelFromReactor.cell_tallies should be a\ - list" + "NeutronicsModelFromReactor.cell_tallies should be a list" ) output_options = ( ["TBR", "heating", "flux", "spectra", "absorption"] @@ -242,20 +252,20 @@ def materials(self, value): # raise ValueError("The minimum of setting for simulation_batches is 2") # self._simulation_batches = value - @property - def simulation_particles_per_batch(self): - return self._simulation_particles_per_batch - - @simulation_particles_per_batch.setter - def simulation_particles_per_batch(self, value): - if isinstance(value, float): - value = int(value) - if not isinstance(value, int): - raise TypeError( - "NeutronicsModelFromReactor.simulation_particles_per_batch\ - should be an int" - ) - self._simulation_particles_per_batch = value + # @property + # def simulation_particles_per_batch(self): + # return self._simulation_particles_per_batch + + # @simulation_particles_per_batch.setter + # def simulation_particles_per_batch(self, value): + # if isinstance(value, float): + # value = int(value) + # if not isinstance(value, int): + # raise TypeError( + # "NeutronicsModelFromReactor.simulation_particles_per_batch\ + # should be an int" + # ) + # self._simulation_particles_per_batch = value def create_material(self, material_tag: str, material_entry): if isinstance(material_entry, str): @@ -448,6 +458,7 @@ def export_xml( dag_univ = openmc.DAGMCUniverse(self.h5m_filename) geom = openmc.Geometry(root=dag_univ) + # settings for the number of neutrons to simulate settings = openmc.Settings() settings.batches = simulation_batches @@ -463,6 +474,20 @@ def export_xml( # details about what neutrons interactions to keep track of (tally) self.tallies = openmc.Tallies() + if self.exo_filename is not None: + # moab would require a cub file export and mbconvert to h5 format + # umesh = openmc.UnstructuredMesh(self.exo_filename, library='moab') + umesh = openmc.UnstructuredMesh(self.exo_filename, library='libmesh') + mesh_filter = openmc.MeshFilter(umesh) + + for standard_tally in self.mesh_tally_3d: + score = standard_tally + prefix = standard_tally + tally = openmc.Tally(name=prefix + "_on_3D_u_mesh") + tally.filters = [mesh_filter] + tally.scores = [score] + self.tallies.append(tally) + if self.mesh_tally_3d is not None: mesh_xyz = openmc.RegularMesh(mesh_id=1, name="3d_mesh") mesh_xyz.dimension = self.mesh_3d_resolution From 733a616424cf7dac4468204e8db1f2d5312bf3f9 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 17:01:18 +0100 Subject: [PATCH 2/9] added tet mesh support --- openmc_dagmc_wrapper/neutronics_model.py | 49 +++++++++++++++--------- openmc_dagmc_wrapper/utils.py | 5 ++- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/openmc_dagmc_wrapper/neutronics_model.py b/openmc_dagmc_wrapper/neutronics_model.py index 5611304..4ccb0a4 100644 --- a/openmc_dagmc_wrapper/neutronics_model.py +++ b/openmc_dagmc_wrapper/neutronics_model.py @@ -20,7 +20,7 @@ class NeutronicsModel: Arguments: h5m_filename: the name of the faceted h5m DAGMC geometry file. - exo_filename: the name of the tet mesh in Exodus format. + tet_mesh_filename: the name of the tet mesh in Exodus format. source: the particle source to use during the OpenMC simulation. materials: Where the dictionary keys are the material tag and the dictionary values are either a string, openmc.Material, @@ -69,9 +69,10 @@ def __init__( source: openmc.Source(), materials: dict, cell_tallies: Optional[List[str]] = None, - exo_filename: Optional[str] = None, + tet_mesh_filename: Optional[str] = None, mesh_tally_2d: Optional[List[str]] = None, mesh_tally_3d: Optional[List[str]] = None, + mesh_tally_tet: Optional[List[str]] = None, mesh_2d_resolution: Optional[Tuple[int, int, int]] = (400, 400), mesh_3d_resolution: Optional[Tuple[int, int, int]] = (100, 100, 100), mesh_2d_corners: Optional[ @@ -89,11 +90,12 @@ def __init__( ): self.materials = materials self.h5m_filename = h5m_filename - self.exo_filename = exo_filename + self.tet_mesh_filename = tet_mesh_filename self.source = source self.cell_tallies = cell_tallies self.mesh_tally_2d = mesh_tally_2d self.mesh_tally_3d = mesh_tally_3d + self.mesh_tally_tet = mesh_tally_tet self.mesh_2d_resolution = mesh_2d_resolution self.mesh_3d_resolution = mesh_3d_resolution @@ -122,15 +124,15 @@ def h5m_filename(self, value): else: raise TypeError("NeutronicsModelFromReactor.h5m_filename should be a string") @property - def exo_filename(self): - return self._exo_filename + def tet_mesh_filename(self): + return self._tet_mesh_filename - @exo_filename.setter - def exo_filename(self, value): + @tet_mesh_filename.setter + def tet_mesh_filename(self, value): if isinstance(value, (str, type(None))): - self._exo_filename = value + self._tet_mesh_filename = value else: - raise TypeError("NeutronicsModelFromReactor.exo_filename should be a string") + raise TypeError("NeutronicsModelFromReactor.tet_mesh_filename should be a string") @property def source(self): @@ -370,9 +372,10 @@ def export_xml( simulation_particles_per_batch: int, source=None, max_lost_particles: Optional[int] = 0, - mesh_tally_3d: Optional[float] = None, - mesh_tally_2d: Optional[float] = None, - cell_tallies: Optional[float] = None, + mesh_tally_3d: Optional[List[str]] = None, + mesh_tally_tet: Optional[List[str]] = None, + mesh_tally_2d: Optional[List[str]] = None, + cell_tallies: Optional[List[str]] = None, mesh_2d_resolution: Optional[Tuple[int, int, int]] = None, mesh_3d_resolution: Optional[Tuple[int, int, int]] = None, mesh_2d_corners: Optional[ @@ -435,6 +438,8 @@ def export_xml( source = self.source if mesh_tally_3d is None: mesh_tally_3d = self.mesh_tally_3d + if mesh_tally_tet is None: + mesh_tally_tet = self.mesh_tally_tet if mesh_tally_2d is None: mesh_tally_2d = self.mesh_tally_2d if cell_tallies is None: @@ -474,17 +479,23 @@ def export_xml( # details about what neutrons interactions to keep track of (tally) self.tallies = openmc.Tallies() - if self.exo_filename is not None: - # moab would require a cub file export and mbconvert to h5 format - # umesh = openmc.UnstructuredMesh(self.exo_filename, library='moab') - umesh = openmc.UnstructuredMesh(self.exo_filename, library='libmesh') - mesh_filter = openmc.MeshFilter(umesh) + if self.tet_mesh_filename is not None: + if self.tet_mesh_filename.endswith('.exo'): + # requires a exo file export from cubit + umesh = openmc.UnstructuredMesh(self.tet_mesh_filename, library='libmesh') + elif self.tet_mesh_filename.endswith('.h5m'): + # requires a .cub file export from cubit and mbconvert to h5m format + umesh = openmc.UnstructuredMesh(self.tet_mesh_filename, library='moab') + else: + raise ValueError('only h5m or exo files are accepted as valid tet_mesh_filename values') - for standard_tally in self.mesh_tally_3d: + umesh_filter = openmc.MeshFilter(umesh) + + for standard_tally in self.mesh_tally_tet: score = standard_tally prefix = standard_tally tally = openmc.Tally(name=prefix + "_on_3D_u_mesh") - tally.filters = [mesh_filter] + tally.filters = [umesh_filter] tally.scores = [score] self.tallies.append(tally) diff --git a/openmc_dagmc_wrapper/utils.py b/openmc_dagmc_wrapper/utils.py index 12ed959..4a9e4d9 100644 --- a/openmc_dagmc_wrapper/utils.py +++ b/openmc_dagmc_wrapper/utils.py @@ -210,7 +210,7 @@ def get_neutronics_results_from_statepoint_file( # access the tallies for tally in statepoint.tallies.values(): - + print(f'processing {tally.name}') if tally.name.endswith("TBR"): data_frame = tally.get_pandas_dataframe() @@ -306,6 +306,9 @@ def get_neutronics_results_from_statepoint_file( + ".vtk", ) + elif "_on_3D_u_mesh" in tally.name: + pass + # openmc makes vtk files for unstructured mesh files automatically else: # this must be a standard score cell tally data_frame = tally.get_pandas_dataframe() From f832d2f04fc797c51e550952a976c72614bf67c9 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 17:05:15 +0100 Subject: [PATCH 3/9] added autopep8 --- .github/workflows/autopep8.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/autopep8.yml diff --git a/.github/workflows/autopep8.yml b/.github/workflows/autopep8.yml new file mode 100644 index 0000000..6641dc6 --- /dev/null +++ b/.github/workflows/autopep8.yml @@ -0,0 +1,24 @@ +name: autopep8 +on: pull_request +jobs: + autopep8: + # Check if the PR is not from a fork + if: github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.head_ref }} + - name: autopep8 + id: autopep8 + uses: peter-evans/autopep8@v1 + with: + args: --exclude=make_faceteted_neutronics_model.py --exit-code --recursive --in-place --aggressive --aggressive . + - name: Commit autopep8 changes + if: steps.autopep8.outputs.exit-code == 2 + run: | + git config --global user.name 'autopep8' + git config --global user.email 'autopep8@users.noreply.github.com' + git commit -am "Automated autopep8 fixes" + git push \ No newline at end of file From fc9a69894404f3b1c194dd10af622b171ebbef7d Mon Sep 17 00:00:00 2001 From: autopep8 Date: Sun, 5 Sep 2021 16:22:56 +0000 Subject: [PATCH 4/9] Automated autopep8 fixes --- docs/source/conf.py | 7 ++- examples/segmented_blanket_ball_reactor.py | 12 ++-- openmc_dagmc_wrapper/neutronics_model.py | 65 +++++++++++++--------- openmc_dagmc_wrapper/utils.py | 34 ++++++++--- setup.py | 3 +- tests/notebook_testing.py | 5 +- tests/test_neutronics_model.py | 36 ++++++------ tests/test_neutronics_utils.py | 13 ++--- tests/test_reactor_neutronics.py | 7 +-- tests/test_shape_neutronics.py | 24 ++++---- 10 files changed, 124 insertions(+), 82 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5f36bef..7a05bcb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -148,7 +148,12 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "paramak-neutronics", "Paramak Documentation", [author], 1)] +man_pages = [ + (master_doc, + "paramak-neutronics", + "Paramak Documentation", + [author], + 1)] # -- Options for Texinfo output ---------------------------------------------- diff --git a/examples/segmented_blanket_ball_reactor.py b/examples/segmented_blanket_ball_reactor.py index 97ba5c4..7efedbe 100644 --- a/examples/segmented_blanket_ball_reactor.py +++ b/examples/segmented_blanket_ball_reactor.py @@ -59,7 +59,8 @@ def make_model_and_simulate(): temperature=blanket_rear_wall_coolant_temperature, pressure=blanket_rear_wall_coolant_pressure, ), - nmm.Material.from_library(name=blanket_rear_wall_structural_material), + nmm.Material.from_library( + name=blanket_rear_wall_structural_material), ], fracs=[ blanket_rear_wall_coolant_fraction, @@ -156,7 +157,8 @@ def make_model_and_simulate(): temperature=center_column_shield_coolant_temperature_k, pressure=center_column_shield_coolant_pressure_Pa, ), - nmm.Material.from_library(name=center_column_shield_structural_material), + nmm.Material.from_library( + name=center_column_shield_structural_material), ], fracs=[ center_column_shield_coolant_fraction, @@ -184,8 +186,10 @@ def make_model_and_simulate(): temperature=inboard_tf_coils_coolant_temperature_k, pressure=inboard_tf_coils_coolant_pressure_Pa, ), - nmm.Material.from_library(name=inboard_tf_coils_conductor_material), - nmm.Material.from_library(name=inboard_tf_coils_structure_material), + nmm.Material.from_library( + name=inboard_tf_coils_conductor_material), + nmm.Material.from_library( + name=inboard_tf_coils_structure_material), ], fracs=[ inboard_tf_coils_coolant_fraction, diff --git a/openmc_dagmc_wrapper/neutronics_model.py b/openmc_dagmc_wrapper/neutronics_model.py index 4ccb0a4..03ac1de 100644 --- a/openmc_dagmc_wrapper/neutronics_model.py +++ b/openmc_dagmc_wrapper/neutronics_model.py @@ -122,7 +122,9 @@ def h5m_filename(self, value): if isinstance(value, str): self._h5m_filename = value else: - raise TypeError("NeutronicsModelFromReactor.h5m_filename should be a string") + raise TypeError( + "NeutronicsModelFromReactor.h5m_filename should be a string") + @property def tet_mesh_filename(self): return self._tet_mesh_filename @@ -132,7 +134,8 @@ def tet_mesh_filename(self, value): if isinstance(value, (str, type(None))): self._tet_mesh_filename = value else: - raise TypeError("NeutronicsModelFromReactor.tet_mesh_filename should be a string") + raise TypeError( + "NeutronicsModelFromReactor.tet_mesh_filename should be a string") @property def source(self): @@ -310,7 +313,8 @@ def create_openmc_materials(self): openmc_materials = {} for material_tag, material_entry in self.materials.items(): - openmc_material = self.create_material(material_tag, material_entry) + openmc_material = self.create_material( + material_tag, material_entry) openmc_materials[material_tag] = openmc_material self.openmc_materials = openmc_materials @@ -463,7 +467,6 @@ def export_xml( dag_univ = openmc.DAGMCUniverse(self.h5m_filename) geom = openmc.Geometry(root=dag_univ) - # settings for the number of neutrons to simulate settings = openmc.Settings() settings.batches = simulation_batches @@ -482,12 +485,16 @@ def export_xml( if self.tet_mesh_filename is not None: if self.tet_mesh_filename.endswith('.exo'): # requires a exo file export from cubit - umesh = openmc.UnstructuredMesh(self.tet_mesh_filename, library='libmesh') + umesh = openmc.UnstructuredMesh( + self.tet_mesh_filename, library='libmesh') elif self.tet_mesh_filename.endswith('.h5m'): - # requires a .cub file export from cubit and mbconvert to h5m format - umesh = openmc.UnstructuredMesh(self.tet_mesh_filename, library='moab') + # requires a .cub file export from cubit and mbconvert to h5m + # format + umesh = openmc.UnstructuredMesh( + self.tet_mesh_filename, library='moab') else: - raise ValueError('only h5m or exo files are accepted as valid tet_mesh_filename values') + raise ValueError( + 'only h5m or exo files are accepted as valid tet_mesh_filename values') umesh_filter = openmc.MeshFilter(umesh) @@ -598,7 +605,6 @@ def export_xml( mesh_yz.lower_left = self.mesh_2d_corners[0] mesh_yz.upper_right = self.mesh_2d_corners[1] - for standard_tally in self.mesh_tally_2d: score = standard_tally prefix = standard_tally @@ -631,14 +637,16 @@ def export_xml( energy_bins = openmc.mgxs.GROUP_STRUCTURES["CCFE-709"] energy_filter = openmc.EnergyFilter(energy_bins) - neutron_particle_filter = openmc.ParticleFilter(["neutron"]) + neutron_particle_filter = openmc.ParticleFilter([ + "neutron"]) self._add_tally_for_every_material( "neutron_spectra", "flux", [neutron_particle_filter, energy_filter], ) if self.photon_transport is True: - photon_particle_filter = openmc.ParticleFilter(["photon"]) + photon_particle_filter = openmc.ParticleFilter([ + "photon"]) self._add_tally_for_every_material( "photon_spectra", "flux", @@ -722,22 +730,22 @@ def simulate( "The simulation_batches argument must be an int" ) if simulation_batches < 2: - raise ValueError("The minimum of setting for simulation_batches is 2") - + raise ValueError( + "The minimum of setting for simulation_batches is 2") if isinstance(simulation_particles_per_batch, float): - simulation_particles_per_batch = int(simulation_particles_per_batch) + simulation_particles_per_batch = int( + simulation_particles_per_batch) if not isinstance(simulation_particles_per_batch, int): msg = ("NeutronicsModelFromReactor.simulation_particles_per_batch" "should be an int") raise TypeError(msg) - if export_xml is True: self.export_xml( - simulation_batches = simulation_batches, - simulation_particles_per_batch = simulation_particles_per_batch, - max_lost_particles = max_lost_particles, + simulation_batches=simulation_batches, + simulation_particles_per_batch=simulation_particles_per_batch, + max_lost_particles=max_lost_particles, ) # checks all the nessecary files are found @@ -756,8 +764,8 @@ def simulate( raise FileNotFoundError(msg) if not Path(self.h5m_filename).is_file(): - msg = f"""{self.h5m_filename} file was not found. Please set - export_h5m to True or use the export_h5m() methods to create + msg = f"""{self.h5m_filename} file was not found. Please set + export_h5m to True or use the export_h5m() methods to create the dagmc.h5m file""" raise FileNotFoundError(msg) @@ -766,10 +774,10 @@ def simulate( silently_remove_file("summary.h5") silently_remove_file("statepoint." + str(simulation_batches) + ".h5") - self.statepoint_filename = self.model.run(output=verbose, threads=threads) + self.statepoint_filename = self.model.run( + output=verbose, threads=threads) self.results = get_neutronics_results_from_statepoint_file( - statepoint_filename=self.statepoint_filename, fusion_power=self.fusion_power - ) + statepoint_filename=self.statepoint_filename, fusion_power=self.fusion_power) with open(cell_tally_results_filename, "w") as outfile: json.dump(self.results, outfile, indent=4, sort_keys=True) @@ -812,9 +820,14 @@ def export_html( source_filename = create_initial_particles( self.source, number_of_source_particles ) - points = extract_points_from_initial_source(source_filename, view_plane) - - figure.add_trace(plotly_trace(points=points, mode="markers", name="source")) + points = extract_points_from_initial_source( + source_filename, view_plane) + + figure.add_trace( + plotly_trace( + points=points, + mode="markers", + name="source")) if filename is not None: diff --git a/openmc_dagmc_wrapper/utils.py b/openmc_dagmc_wrapper/utils.py index 4a9e4d9..802b269 100644 --- a/openmc_dagmc_wrapper/utils.py +++ b/openmc_dagmc_wrapper/utils.py @@ -81,6 +81,7 @@ def plotly_trace( return trace + def load_moab_file(filename: str): """Loads a h5m into a Moab Core object and returns the object""" moab_core = core.Core() @@ -130,7 +131,8 @@ def find_volume_ids_in_h5m(filename: Optional[str] = "dagmc.h5m") -> List[str]: return sorted(list(ids)) -def find_material_groups_in_h5m(filename: Optional[str] = "dagmc.h5m") -> List[str]: +def find_material_groups_in_h5m( + filename: Optional[str] = "dagmc.h5m") -> List[str]: """Reads in a DAGMC h5m file and uses mbsize to find the names of the material groups in the file @@ -266,7 +268,13 @@ def get_neutronics_results_from_statepoint_file( _save_2d_mesh_tally_as_png( score=score, tally=tally, - filename=tally.name.replace("(", "").replace(")", "").replace(",", "-"), + filename=tally.name.replace( + "(", + "").replace( + ")", + "").replace( + ",", + "-"), ) elif "_on_3D_mesh" in tally.name: @@ -302,8 +310,14 @@ def get_neutronics_results_from_statepoint_file( tally_label=tally.name, tally_data=data, error_data=error, - outfile=tally.name.replace("(", "").replace(")", "").replace(",", "-") - + ".vtk", + outfile=tally.name.replace( + "(", + "").replace( + ")", + "").replace( + ",", + "-") + + ".vtk", ) elif "_on_3D_u_mesh" in tally.name: @@ -406,7 +420,9 @@ def write_3d_mesh_tally_to_vtk( return outfile -def create_initial_particles(source, number_of_source_particles: int = 2000) -> str: +def create_initial_particles( + source, + number_of_source_particles: int = 2000) -> str: """Accepts an openmc source and creates an initial_source.h5 that can be used to find intial xyz, direction and energy of the partice source. @@ -509,10 +525,14 @@ def extract_points_from_initial_source( elif view_plane == "ZX": points.append((particle[0][2], particle[0][0])) elif view_plane == "RZ": - xy_coord = math.pow(particle[0][0], 2) + math.pow(particle[0][1], 2) + xy_coord = math.pow(particle[0][0], 2) + \ + math.pow(particle[0][1], 2) points.append((math.sqrt(xy_coord), particle[0][2])) elif view_plane == "XYZ": points.append((particle[0][0], particle[0][1], particle[0][2])) else: - raise ValueError("view_plane value of ", view_plane, " is not supported") + raise ValueError( + "view_plane value of ", + view_plane, + " is not supported") return points diff --git a/setup.py b/setup.py index 7cb7db3..be69475 100644 --- a/setup.py +++ b/setup.py @@ -36,5 +36,6 @@ "nbformat", "nbconvert" ], - # openmc, dagmc, moab are also needed and embree and double down are also optionally needed but not avaible on PyPi + # openmc, dagmc, moab are also needed and embree and double down are also + # optionally needed but not avaible on PyPi ) diff --git a/tests/notebook_testing.py b/tests/notebook_testing.py index ae4b7df..c3f96c1 100644 --- a/tests/notebook_testing.py +++ b/tests/notebook_testing.py @@ -21,7 +21,10 @@ def notebook_run(path): ep = ExecutePreprocessor(kernel_name=kernel_name, timeout=800) try: - ep.preprocess(note_book, {"metadata": {"path": this_file_directory}}) + ep.preprocess( + note_book, { + "metadata": { + "path": this_file_directory}}) except CellExecutionError as e: if "SKIP" in e.traceback: diff --git a/tests/test_neutronics_model.py b/tests/test_neutronics_model.py index 4eeb35b..4489380 100644 --- a/tests/test_neutronics_model.py +++ b/tests/test_neutronics_model.py @@ -13,7 +13,7 @@ class TestShape(unittest.TestCase): including neutronics simulations using""" def setUp(self): - + url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_02_multi_volume_cell_tally/stage_2_output/dagmc.h5m" local_filename = 'dagmc_bigger.h5m' @@ -21,34 +21,32 @@ def setUp(self): if not Path(local_filename).is_file(): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): + for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) - + self.h5m_filename_bigger = local_filename - self.material_description={ - "tungsten": "tungsten", - "steel": "Steel, Carbon", - "flibe": "FLiNaBe", - "copper": "copper", - } + self.material_description = { + "tungsten": "tungsten", + "steel": "Steel, Carbon", + "flibe": "FLiNaBe", + "copper": "copper", + } url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_01_single_volume_cell_tally/stage_2_output/dagmc.h5m" local_filename = 'dagmc_smaller.h5m' - if not Path(local_filename).is_file(): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: # filter out keep-alive new chunks + for chunk in r.iter_content(chunk_size=1024): + if chunk: # filter out keep-alive new chunks f.write(chunk) self.h5m_filename_smaller = local_filename - # makes the openmc neutron source at x,y,z 0, 0, 0 with isotropic # directions and 14MeV neutrons source = openmc.Source() @@ -341,7 +339,6 @@ def test_neutronics_component_cell_simulation_heating(self): cell_tallies=["heating", "flux", "TBR", "spectra"], ) - # performs an openmc simulation on the model output_filename = my_model.simulate( simulation_batches=2, @@ -489,7 +486,8 @@ def test_neutronics_component_3d_and_2d_mesh_simulation(self): assert Path("heating_on_2D_mesh_xy.png").exists() is True assert Path("heating_on_2D_mesh_yz.png").exists() is True - def test_neutronics_component_3d_and_2d_mesh_simulation_with_corner_points(self): + def test_neutronics_component_3d_and_2d_mesh_simulation_with_corner_points( + self): """Makes a neutronics model and simulates with a 3D and 2D mesh tally and checks that the vtk and png files are produced. This checks the mesh ID values don't overlap""" @@ -595,7 +593,9 @@ def test_missing_xml_file_error_handling(): my_model.simulate(export_xml=False) - self.assertRaises(FileNotFoundError, test_missing_xml_file_error_handling) + self.assertRaises( + FileNotFoundError, + test_missing_xml_file_error_handling) def test_simulations_with_missing_h5m_files(self): """Creates NeutronicsModel objects and trys to perform simulation @@ -620,7 +620,9 @@ def test_missing_h5m_file_error_handling(): my_model.simulate() - self.assertRaises(FileNotFoundError, test_missing_h5m_file_error_handling) + self.assertRaises( + FileNotFoundError, + test_missing_h5m_file_error_handling) class TestNeutronicsBallReactor(unittest.TestCase): diff --git a/tests/test_neutronics_utils.py b/tests/test_neutronics_utils.py index 9241134..b930831 100644 --- a/tests/test_neutronics_utils.py +++ b/tests/test_neutronics_utils.py @@ -11,20 +11,18 @@ class TestNeutronicsUtilityFunctions(unittest.TestCase): def setUp(self): - + url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_02_multi_volume_cell_tally/stage_2_output/dagmc.h5m" local_filename = 'dagmc_bigger.h5m' - if not Path(local_filename).is_file(): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): + for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) - # def test_create_initial_source_file(self): # """Creates an initial_source.h5 from a point source""" @@ -110,10 +108,11 @@ def test_find_volume_ids_in_h5_file(self): """exports a h5m with a known number of volumes and checks they are found using the find_volume_ids_in_h5m utility function""" + list_of_mats = openmc_dagmc_wrapper.find_volume_ids_in_h5m( + filename="dagmc_bigger.h5m") - list_of_mats = openmc_dagmc_wrapper.find_volume_ids_in_h5m(filename="dagmc_bigger.h5m") - - assert len(list_of_mats) == len([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]) + assert len(list_of_mats) == len( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]) assert 1 in list_of_mats # def test_create_initial_particles(self): diff --git a/tests/test_reactor_neutronics.py b/tests/test_reactor_neutronics.py index 0f2c768..d3283b9 100644 --- a/tests/test_reactor_neutronics.py +++ b/tests/test_reactor_neutronics.py @@ -12,20 +12,19 @@ class TestNeutronicsModelWithReactor(unittest.TestCase): """Tests Shape object arguments that involve neutronics usage""" def setUp(self): - - url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_02_multi_volume_cell_tally/stage_2_output/dagmc.h5m" + url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_02_multi_volume_cell_tally/stage_2_output/dagmc.h5m" local_filename = 'dagmc_bigger.h5m' if not Path(local_filename).is_file(): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): + for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) - self.material_description_bigger={ + self.material_description_bigger = { 'pf_coil_case_mat': 'Be', 'center_column_shield_mat': 'Be', 'blanket_rear_wall_mat': 'Be', diff --git a/tests/test_shape_neutronics.py b/tests/test_shape_neutronics.py index 09045b8..52ae170 100644 --- a/tests/test_shape_neutronics.py +++ b/tests/test_shape_neutronics.py @@ -11,9 +11,8 @@ class TestObjectNeutronicsArguments(unittest.TestCase): """Tests Shape object arguments that involve neutronics usage""" - def setUp(self): - + url = "https://github.com/fusion-energy/neutronics_workflow/raw/main/example_02_multi_volume_cell_tally/stage_2_output/dagmc.h5m" local_filename = 'dagmc_bigger.h5m' @@ -22,11 +21,11 @@ def setUp(self): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): + for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) - - self.material_description_bigger={ + + self.material_description_bigger = { 'pf_coil_case_mat': 'Be', 'center_column_shield_mat': 'Be', 'blanket_rear_wall_mat': 'Be', @@ -47,13 +46,13 @@ def setUp(self): r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: # filter out keep-alive new chunks + for chunk in r.iter_content(chunk_size=1024): + if chunk: # filter out keep-alive new chunks f.write(chunk) self.h5m_filename_smaller_smaller = local_filename - self.material_description_smaller={ + self.material_description_smaller = { 'mat1': 'Be', } @@ -70,17 +69,16 @@ def test_cell_tally_simulation(self): h5m_filename="dagmc_bigger.h5m", source=self.source, materials=self.material_description_bigger, - cell_tallies = ['TBR'] + cell_tallies=['TBR'] ) my_model.simulate( - simulation_batches = 2, - simulation_particles_per_batch = 20, + simulation_batches=2, + simulation_particles_per_batch=20, ) assert my_model.results['TBR']['result'] > 0. - def test_bounding_box_size(self): my_model = openmc_dagmc_wrapper.NeutronicsModel( @@ -91,7 +89,6 @@ def test_bounding_box_size(self): bounding_box = my_model.find_bounding_box() - print(bounding_box) assert len(bounding_box) == 2 assert len(bounding_box[0]) == 3 @@ -103,7 +100,6 @@ def test_bounding_box_size(self): assert bounding_box[1][1] == pytest.approx(10005, abs=0.1) assert bounding_box[1][2] == pytest.approx(10005, abs=0.1) - def test_bounding_box_size_2(self): my_model = openmc_dagmc_wrapper.NeutronicsModel( From 6a631799329b4baecaf2c5222d4804e88b79d069 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 19:28:56 +0100 Subject: [PATCH 5/9] tidy up --- openmc_dagmc_wrapper/neutronics_model.py | 67 ++++++++---------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/openmc_dagmc_wrapper/neutronics_model.py b/openmc_dagmc_wrapper/neutronics_model.py index 4ccb0a4..102ed08 100644 --- a/openmc_dagmc_wrapper/neutronics_model.py +++ b/openmc_dagmc_wrapper/neutronics_model.py @@ -20,7 +20,8 @@ class NeutronicsModel: Arguments: h5m_filename: the name of the faceted h5m DAGMC geometry file. - tet_mesh_filename: the name of the tet mesh in Exodus format. + tet_mesh_filename: the name of the tet mesh in h5m (DAGMC) or Exodus + format. source: the particle source to use during the OpenMC simulation. materials: Where the dictionary keys are the material tag and the dictionary values are either a string, openmc.Material, @@ -41,6 +42,10 @@ class NeutronicsModel: options include heating and flux , MT numbers and OpenMC standard scores such as (n,Xa) which is helium production are also supported https://docs.openmc.org/en/latest/usersguide/tallies.html#scores + mesh_tally_tet: the tallies to calculate on the tet mesh, options + include heating and flux , MT numbers and OpenMC standard + scores such as (n,Xa) which is helium production are also supported + https://docs.openmc.org/en/latest/usersguide/tallies.html#scores. mesh_3d_resolution: The 3D mesh resolution in the height, width and depth directions. The larger the resolution the finer the mesh and the more computational intensity is required to converge each mesh @@ -122,7 +127,8 @@ def h5m_filename(self, value): if isinstance(value, str): self._h5m_filename = value else: - raise TypeError("NeutronicsModelFromReactor.h5m_filename should be a string") + msg = "NeutronicsModelFromReactor.h5m_filename should be a string" + raise TypeError(msg) @property def tet_mesh_filename(self): return self._tet_mesh_filename @@ -132,7 +138,8 @@ def tet_mesh_filename(self, value): if isinstance(value, (str, type(None))): self._tet_mesh_filename = value else: - raise TypeError("NeutronicsModelFromReactor.tet_mesh_filename should be a string") + msg = "NeutronicsModelFromReactor.tet_mesh_filename should be a string" + raise TypeError(msg) @property def source(self): @@ -180,8 +187,7 @@ def mesh_tally_2d(self, value): if value is not None: if not isinstance(value, list): raise TypeError( - "NeutronicsModelFromReactor.mesh_tally_2d should be a\ - list" + "NeutronicsModelFromReactor.mesh_tally_2d should be a list" ) output_options = ( ["heating", "flux", "absorption"] @@ -207,8 +213,7 @@ def mesh_tally_3d(self, value): if value is not None: if not isinstance(value, list): raise TypeError( - "NeutronicsModelFromReactor.mesh_tally_3d should be a\ - list" + "NeutronicsModelFromReactor.mesh_tally_3d should be a list" ) output_options = ( ["heating", "flux", "absorption"] @@ -233,41 +238,10 @@ def materials(self): def materials(self, value): if not isinstance(value, dict): raise TypeError( - "NeutronicsModelFromReactor.materials should be a\ - dictionary" + "NeutronicsModelFromReactor.materials should be a dictionary" ) self._materials = value - # @property - # def simulation_batches(self): - # return self._simulation_batches - - # @simulation_batches.setter - # def simulation_batches(self, value): - # if isinstance(value, float): - # value = int(value) - # if not isinstance(value, int): - # raise TypeError( - # "NeutronicsModelFromReactor.simulation_batches should be an int" - # ) - # if value < 2: - # raise ValueError("The minimum of setting for simulation_batches is 2") - # self._simulation_batches = value - - # @property - # def simulation_particles_per_batch(self): - # return self._simulation_particles_per_batch - - # @simulation_particles_per_batch.setter - # def simulation_particles_per_batch(self, value): - # if isinstance(value, float): - # value = int(value) - # if not isinstance(value, int): - # raise TypeError( - # "NeutronicsModelFromReactor.simulation_particles_per_batch\ - # should be an int" - # ) - # self._simulation_particles_per_batch = value def create_material(self, material_tag: str, material_entry): if isinstance(material_entry, str): @@ -364,8 +338,6 @@ def find_bounding_box(self): (bbox[1][0], bbox[1][1], bbox[1][2]), ) - # def build_csg_graveyard(self): - def export_xml( self, simulation_batches: int, @@ -401,6 +373,12 @@ def export_xml( https://docs.openmc.org/en/latest/usersguide/tallies.html#scores. Defaults to None which uses the NeutronicsModel.mesh_tally_3d attribute. + mesh_tally_tet: the tallies to calculate on the tet mesh, options + include heating and flux , MT numbers and OpenMC standard + scores such as (n,Xa) which is helium production are also supported + https://docs.openmc.org/en/latest/usersguide/tallies.html#scores. + Defaults to None which uses the NeutronicsModel.mesh_tally_tet + attribute. mesh_tally_2d: . the 2D mesh based tallies to calculate, options include heating and flux , MT numbers and OpenMC standard scores such as (n,Xa) which is helium production are also supported @@ -487,7 +465,8 @@ def export_xml( # requires a .cub file export from cubit and mbconvert to h5m format umesh = openmc.UnstructuredMesh(self.tet_mesh_filename, library='moab') else: - raise ValueError('only h5m or exo files are accepted as valid tet_mesh_filename values') + msg = 'only h5m or exo files are accepted as valid tet_mesh_filename values' + raise ValueError(msg) umesh_filter = openmc.MeshFilter(umesh) @@ -722,8 +701,8 @@ def simulate( "The simulation_batches argument must be an int" ) if simulation_batches < 2: - raise ValueError("The minimum of setting for simulation_batches is 2") - + msg = "The minimum of setting for simulation_batches is 2" + raise ValueError(msg) if isinstance(simulation_particles_per_batch, float): simulation_particles_per_batch = int(simulation_particles_per_batch) From b12884a33ff8574d51fc06a63c3b152b76ae3e53 Mon Sep 17 00:00:00 2001 From: autopep8 Date: Sun, 5 Sep 2021 18:33:29 +0000 Subject: [PATCH 6/9] Automated autopep8 fixes --- openmc_dagmc_wrapper/neutronics_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc_dagmc_wrapper/neutronics_model.py b/openmc_dagmc_wrapper/neutronics_model.py index bd2a454..bf38d68 100644 --- a/openmc_dagmc_wrapper/neutronics_model.py +++ b/openmc_dagmc_wrapper/neutronics_model.py @@ -129,6 +129,7 @@ def h5m_filename(self, value): else: msg = "NeutronicsModelFromReactor.h5m_filename should be a string" raise TypeError(msg) + @property def tet_mesh_filename(self): return self._tet_mesh_filename @@ -242,7 +243,6 @@ def materials(self, value): ) self._materials = value - def create_material(self, material_tag: str, material_entry): if isinstance(material_entry, str): openmc_material = nmm.Material.from_library( From 61f95d6d6759ebec3142e9c85dfcfc0b8fe6e881 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 19:37:01 +0100 Subject: [PATCH 7/9] added line at end of file pep8 --- .github/workflows/autopep8.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/autopep8.yml b/.github/workflows/autopep8.yml index 6641dc6..bc55247 100644 --- a/.github/workflows/autopep8.yml +++ b/.github/workflows/autopep8.yml @@ -21,4 +21,4 @@ jobs: git config --global user.name 'autopep8' git config --global user.email 'autopep8@users.noreply.github.com' git commit -am "Automated autopep8 fixes" - git push \ No newline at end of file + git push From caf79d4db49d2d26ead824bcd1ccb64d2c4ba237 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 19:50:33 +0100 Subject: [PATCH 8/9] added url links to docs --- docs/source/index.rst | 9 +++++++-- readthedocs.yml | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index d79e551..6e8c583 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -20,14 +20,14 @@ neutronics simulations of fusion reactors in a reproducible manner. The source code is distributed with a permissive open-source license (MIT) and is available from the GitHub repository -`https://github.com/fusion-energy/paramak-neutronics `_ +`https://github.com/fusion-energy/openmc-dagmc-wrapper `_ Features -------- In general the openmc-dagmc-wrapper takes a DAGMC geometry in the form of a h5m -file and helps all tallies, materials and a source term to be easily added to +file and helps adding tallies, materials and a source term to be easily added to create a complete neutronics model. The package will also post processes the results of the neutronics simulation to allow easy access to the outputs. The simulated results are extracted from the statepoint.h5 file that @@ -51,5 +51,10 @@ The `OpenMC workflow `_ demonstrates the use of this package along side others in a complete neutronics tool chain. +`CAD-to-h5m `_ makes use of the +`Cubit API `_ to convert CAD +files (stp or sat format) into `DAGMC `_ +compatible h5m files for use in DAGMC enabled neutronics codes. + For magnetic confinement fusion simulations you might want to use the parametric-plasma-source `Git repository `_ diff --git a/readthedocs.yml b/readthedocs.yml index 2da9c2c..3867927 100755 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -20,4 +20,4 @@ sphinx: # specify conda environment needed for build conda: - environment: environment.yml \ No newline at end of file + environment: environment.yml From 28ac281feb139a9bde964b76bf7c7c27d7277e80 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 5 Sep 2021 19:53:08 +0100 Subject: [PATCH 9/9] using new docker image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 77e306c..b91af56 100755 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: # test: build: docker: - - image: ghcr.io/fusion-energy/paramak-neutronics:dependencies + - image: ghcr.io/fusion-energy/openmc-dagmc-wrapper:dependencies steps: - checkout - run: