mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 14:35:27 -04:00
removed old command line scripts (#3300)
Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
This commit is contained in:
parent
be4396c12b
commit
11587786e0
16 changed files with 23 additions and 1284 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
|
|
@ -71,9 +71,9 @@ sub-elements:
|
|||
the PNG file format. The "voxel" plot type produces a binary datafile
|
||||
containing voxel grid positioning and the cell or material (specified by the
|
||||
``color`` tag) at the center of each voxel. Voxel plot files can be
|
||||
processed into VTK files using the :ref:`scripts_voxel` script provided with
|
||||
OpenMC and subsequently viewed with a 3D viewer such as VISIT or Paraview.
|
||||
See the :ref:`io_voxel` for information about the datafile structure.
|
||||
processed into VTK files using the :func:`openmc.voxel_to_vtk` function and
|
||||
subsequently viewed with a 3D viewer such as VISIT or Paraview. See the
|
||||
:ref:`io_voxel` for information about the datafile structure.
|
||||
|
||||
.. note:: High-resolution voxel files produced by OpenMC can be quite large,
|
||||
but the equivalent VTK files will be significantly smaller.
|
||||
|
|
@ -152,17 +152,17 @@ attributes or sub-elements. These are not used in "voxel" plots:
|
|||
*Default*: 255 255 255 (white)
|
||||
|
||||
:show_overlaps:
|
||||
Indicates whether overlapping regions of different cells are shown.
|
||||
Indicates whether overlapping regions of different cells are shown.
|
||||
|
||||
*Default*: None
|
||||
|
||||
:overlap_color:
|
||||
Specifies the RGB color of overlapping regions of different cells. Does not
|
||||
do anything if ``show_overlaps`` is "false" or not specified. Should be 3
|
||||
Specifies the RGB color of overlapping regions of different cells. Does not
|
||||
do anything if ``show_overlaps`` is "false" or not specified. Should be 3
|
||||
integers separated by spaces.
|
||||
|
||||
*Default*: 255 0 0 (red)
|
||||
|
||||
|
||||
:meshlines:
|
||||
The ``meshlines`` sub-element allows for plotting the boundaries of a
|
||||
regular mesh on top of a plot. Only one ``meshlines`` element is allowed per
|
||||
|
|
|
|||
|
|
@ -111,11 +111,11 @@ The voxel plot data is written to an :ref:`HDF5 file <io_voxel>`. The voxel file
|
|||
can subsequently be converted into a standard mesh format that can be viewed in
|
||||
`ParaView <https://www.paraview.org/>`_, `VisIt
|
||||
<https://wci.llnl.gov/simulation/computer-codes/visit>`_, etc. This typically
|
||||
will compress the size of the file significantly. The provided
|
||||
:ref:`scripts_voxel` script can convert the HDF5 voxel file to VTK formats. Once
|
||||
processed into a standard 3D file format, colors and masks can be defined using
|
||||
the stored ID numbers to better explore the geometry. The process for doing this
|
||||
will depend on the 3D viewer, but should be straightforward.
|
||||
will compress the size of the file significantly. The
|
||||
:func:`openmc.voxel_to_vtk` function can convert the HDF5 voxel file to VTK
|
||||
formats. Once processed into a standard 3D file format, colors and masks can be
|
||||
defined using the stored ID numbers to better explore the geometry. The process
|
||||
for doing this will depend on the 3D viewer, but should be straightforward.
|
||||
|
||||
.. note:: 3D voxel plotting can be very computer intensive for the viewing
|
||||
program (Visit, ParaView, etc.) if the number of voxels is large (>10
|
||||
|
|
|
|||
|
|
@ -41,12 +41,9 @@ Plotting in 2D
|
|||
--------------
|
||||
|
||||
The `example notebook`_ also demonstrates how to plot a structured mesh tally in
|
||||
two dimensions using the Python API. One can also use the :ref:`scripts_plot`
|
||||
script which provides an interactive GUI to explore and plot structured mesh
|
||||
tallies for any scores and filter bins.
|
||||
|
||||
.. image:: ../_images/plotmeshtally.png
|
||||
:width: 400px
|
||||
two dimensions using the Python API. One can also use the `openmc-plotter
|
||||
<https://github.com/openmc-dev/plotter/>`_ application that provides an
|
||||
interactive GUI to explore and plot a much wider variety of tallies.
|
||||
|
||||
.. _usersguide_track:
|
||||
|
||||
|
|
@ -81,7 +78,7 @@ of three, e.g., if we wanted particles 3 and 4 from batch 1 and generation 2::
|
|||
After running OpenMC, the working directory will contain a file of the form
|
||||
"track_(batch #)_(generation #)_(particle #).h5" for each particle tracked.
|
||||
These track files can be converted into VTK poly data files with the
|
||||
:ref:`scripts_track` script.
|
||||
:class:`openmc.Tracks` class.
|
||||
|
||||
----------------------
|
||||
Source Site Processing
|
||||
|
|
|
|||
|
|
@ -53,142 +53,3 @@ flags:
|
|||
|
||||
.. note:: If you're using the Python API, :func:`openmc.run` is equivalent to
|
||||
running ``openmc`` from the command line.
|
||||
|
||||
.. _scripts_ace:
|
||||
|
||||
----------------------
|
||||
``openmc-ace-to-hdf5``
|
||||
----------------------
|
||||
|
||||
This script can be used to create HDF5 nuclear data libraries used by OpenMC if
|
||||
you have existing ACE files. There are four different ways you can specify ACE
|
||||
libraries that are to be converted:
|
||||
|
||||
1. List each ACE library as a positional argument. This is very useful in
|
||||
conjunction with the usual shell utilities (``ls``, ``find``, etc.).
|
||||
2. Use the ``--xml`` option to specify a pre-v0.9 cross_sections.xml file.
|
||||
3. Use the ``--xsdir`` option to specify a MCNP xsdir file.
|
||||
4. Use the ``--xsdata`` option to specify a Serpent xsdata file.
|
||||
|
||||
The script does not use any extra information from cross_sections.xml/ xsdir/
|
||||
xsdata files to determine whether the nuclide is metastable. Instead, the
|
||||
``--metastable`` argument can be used to specify whether the ZAID naming convention
|
||||
follows the NNDC data convention (1000*Z + A + 300 + 100*m), or the MCNP data
|
||||
convention (essentially the same as NNDC, except that the first metastable state
|
||||
of Am242 is 95242 and the ground state is 95642).
|
||||
|
||||
The optional ``--fission_energy_release`` argument will accept an HDF5 file
|
||||
containing a library of fission energy release (ENDF MF=1 MT=458) data. A
|
||||
library built from ENDF/B-VII.1 data is released with OpenMC and can be found at
|
||||
openmc/data/fission_Q_data_endb71.h5. This data is necessary for
|
||||
'fission-q-prompt' and 'fission-q-recoverable' tallies, but is not needed
|
||||
otherwise.
|
||||
|
||||
-h, --help show help message and exit
|
||||
|
||||
-d DESTINATION, --destination DESTINATION
|
||||
Directory to create new library in
|
||||
|
||||
-m META, --metastable META
|
||||
How to interpret ZAIDs for metastable nuclides. META
|
||||
can be either 'nndc' or 'mcnp'. (default: nndc)
|
||||
|
||||
--xml XML Old-style cross_sections.xml that lists ACE libraries
|
||||
|
||||
--xsdir XSDIR MCNP xsdir file that lists ACE libraries
|
||||
|
||||
--xsdata XSDATA Serpent xsdata file that lists ACE libraries
|
||||
|
||||
--fission_energy_release FISSION_ENERGY_RELEASE
|
||||
HDF5 file containing fission energy release data
|
||||
|
||||
.. _scripts_plot:
|
||||
|
||||
--------------------------
|
||||
``openmc-plot-mesh-tally``
|
||||
--------------------------
|
||||
|
||||
``openmc-plot-mesh-tally`` provides a graphical user interface for plotting mesh
|
||||
tallies. The path to the statepoint file can be provided as an optional arugment
|
||||
(if omitted, a file dialog will be presented).
|
||||
|
||||
.. _scripts_track_combine:
|
||||
|
||||
------------------------
|
||||
``openmc-track-combine``
|
||||
------------------------
|
||||
|
||||
This script combines multiple HDF5 :ref:`particle track files
|
||||
<usersguide_track>` into a single HDF5 particle track file. The filenames of the
|
||||
particle track files should be given as posititional arguments. The output
|
||||
filename can also be changed with the ``-o`` flag:
|
||||
|
||||
-o OUT, --out OUT Output HDF5 particle track file
|
||||
|
||||
.. _scripts_track:
|
||||
|
||||
-----------------------
|
||||
``openmc-track-to-vtk``
|
||||
-----------------------
|
||||
|
||||
This script converts HDF5 :ref:`particle track files <usersguide_track>` to VTK
|
||||
poly data that can be viewed with ParaView or VisIt. The filenames of the
|
||||
particle track files should be given as posititional arguments. The output
|
||||
filename can also be changed with the ``-o`` flag:
|
||||
|
||||
-o OUT, --out OUT Output VTK poly filename
|
||||
|
||||
------------------------
|
||||
``openmc-update-inputs``
|
||||
------------------------
|
||||
|
||||
If you have existing XML files that worked in a previous version of OpenMC that
|
||||
no longer work with the current version, you can try to update these files using
|
||||
``openmc-update-inputs``. If any of the given files do not match the most
|
||||
up-to-date formatting, then they will be automatically rewritten. The old
|
||||
out-of-date files will not be deleted; they will be moved to a new file with
|
||||
'.original' appended to their name.
|
||||
|
||||
Formatting changes that will be made:
|
||||
|
||||
geometry.xml
|
||||
Lattices containing 'outside' attributes/tags will be replaced with lattices
|
||||
containing 'outer' attributes, and the appropriate cells/universes will be
|
||||
added. Any 'surfaces' attributes/elements on a cell will be renamed 'region'.
|
||||
|
||||
materials.xml
|
||||
Nuclide names will be changed from ACE aliases (e.g., Am-242m) to HDF5/GNDS
|
||||
names (e.g., Am242_m1). Thermal scattering table names will be changed from
|
||||
ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O).
|
||||
|
||||
----------------------
|
||||
``openmc-update-mgxs``
|
||||
----------------------
|
||||
|
||||
This script updates OpenMC's deprecated multi-group cross section XML files to
|
||||
the latest HDF5-based format.
|
||||
|
||||
-i IN, --input IN Input XML file
|
||||
-o OUT, --output OUT Output file in HDF5 format
|
||||
|
||||
.. _scripts_voxel:
|
||||
|
||||
---------------------------
|
||||
``openmc-voxel-to-vtk``
|
||||
---------------------------
|
||||
|
||||
When OpenMC generates :ref:`voxel plots <usersguide_voxel>`, they are in an
|
||||
:ref:`HDF5 format <io_voxel>` that is not terribly useful by itself. The
|
||||
``openmc-voxel-to-vtk`` script converts a voxel HDF5 file to a `VTK
|
||||
<https://vtk.org/>`_ file. To run this script, you will need to have the VTK
|
||||
Python bindings installed. To convert a voxel file, simply provide the path to
|
||||
the file:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
openmc-voxel-to-vtk voxel_1.h5
|
||||
|
||||
The ``openmc-voxel-to-vtk`` script also takes the following optional
|
||||
command-line arguments:
|
||||
|
||||
-o, --output Path to output VTK file
|
||||
|
|
|
|||
|
|
@ -751,11 +751,10 @@ instance, whereas the :meth:`openmc.Track.filter` method returns a new
|
|||
with more than one process, a separate track file will be written for
|
||||
each MPI process with the filename ``tracks_p#.h5`` where # is the
|
||||
rank of the corresponding process. Multiple track files can be
|
||||
combined with the :ref:`scripts_track_combine` script:
|
||||
combined with the :meth:`openmc.Tracks.combine` method::
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
openmc-track-combine tracks_p*.h5 --out tracks.h5
|
||||
track_files = [f"tracks_p{rank}.h5" for rank in range(32)]
|
||||
openmc.Tracks.combine(track_files, "tracks.h5")
|
||||
|
||||
-----------------------
|
||||
Restarting a Simulation
|
||||
|
|
|
|||
|
|
@ -59,19 +59,10 @@ Repository = "https://github.com/openmc-dev/openmc"
|
|||
Issues = "https://github.com/openmc-dev/openmc/issues"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ['openmc*', 'scripts*']
|
||||
include = ['openmc*']
|
||||
exclude = ['tests*']
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"openmc.data.effective_dose" = ["**/*.txt"]
|
||||
"openmc.data" = ["*.txt", "*.DAT", "*.json", "*.h5"]
|
||||
"openmc.lib" = ["libopenmc.dylib", "libopenmc.so"]
|
||||
|
||||
[project.scripts]
|
||||
openmc-ace-to-hdf5 = "scripts.openmc_ace_to_hdf5:main"
|
||||
openmc-plot-mesh-tally = "scripts.openmc_plot_mesh_tally:main"
|
||||
openmc-track-combine = "scripts.openmc_track_combine:main"
|
||||
openmc-track-to-vtk = "scripts.openmc_track_to_vtk:main"
|
||||
openmc-update-inputs = "scripts.openmc_update_inputs:main"
|
||||
openmc-update-mgxs = "scripts.openmc_update_mgxs:main"
|
||||
openmc-voxel-to-vtk = "scripts.openmc_voxel_to_vtk:main"
|
||||
|
|
|
|||
|
|
@ -1,156 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""This script can be used to create HDF5 nuclear data libraries used by
|
||||
OpenMC. There are four different ways you can specify ACE libraries that are to
|
||||
be converted:
|
||||
|
||||
1. List each ACE library as a positional argument. This is very useful in
|
||||
conjunction with the usual shell utilities (ls, find, etc.).
|
||||
2. Use the --xsdir option to specify a MCNP xsdir file.
|
||||
3. Use the --xsdata option to specify a Serpent xsdata file.
|
||||
|
||||
The script does not use any extra information from xsdir/xsdata files to
|
||||
determine whether the nuclide is metastable. Instead, the --metastable argument
|
||||
can be used to specify whether the ZAID naming convention follows the NNDC data
|
||||
convention (1000*Z + A + 300 + 100*m), or the MCNP data convention (essentially
|
||||
the same as NNDC, except that the first metastable state of Am242 is 95242 and
|
||||
the ground state is 95642).
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from functools import partial
|
||||
import os
|
||||
from pathlib import Path
|
||||
import warnings
|
||||
|
||||
import openmc.data
|
||||
from openmc.data.ace import TableType
|
||||
|
||||
|
||||
def ace_to_hdf5(destination, xsdir, xsdata, libraries, metastable, libver):
|
||||
|
||||
if not destination.is_dir():
|
||||
destination.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
ace_libraries = []
|
||||
if xsdir is not None:
|
||||
ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdir(xsdir))
|
||||
elif xsdata is not None:
|
||||
ace_libraries.extend(openmc.data.ace.get_libraries_from_xsdata(xsdata))
|
||||
else:
|
||||
ace_libraries = [Path(lib) for lib in libraries]
|
||||
|
||||
converted = {}
|
||||
library = openmc.data.DataLibrary()
|
||||
|
||||
for path in ace_libraries:
|
||||
# Check that ACE library exists
|
||||
if not os.path.exists(path):
|
||||
warnings.warn(f"ACE library '{path}' does not exist.")
|
||||
continue
|
||||
|
||||
lib = openmc.data.ace.Library(path)
|
||||
for table in lib.tables:
|
||||
# Check type of the ACE table and determine appropriate class /
|
||||
# conversion function
|
||||
if table.data_type == TableType.NEUTRON_CONTINUOUS:
|
||||
name = table.zaid
|
||||
cls = openmc.data.IncidentNeutron
|
||||
converter = partial(cls.from_ace, metastable_scheme=metastable)
|
||||
elif table.data_type == TableType.THERMAL_SCATTERING:
|
||||
# Adjust name to be the new thermal scattering name
|
||||
name = openmc.data.get_thermal_name(table.zaid)
|
||||
cls = openmc.data.ThermalScattering
|
||||
converter = cls.from_ace
|
||||
else:
|
||||
print(f"Can't convert ACE table {table.name}")
|
||||
continue
|
||||
|
||||
if name not in converted:
|
||||
try:
|
||||
data = converter(table)
|
||||
except Exception as e:
|
||||
print(f"Failed to convert {table.name}: {e}")
|
||||
continue
|
||||
|
||||
print(f"Converting {table.name} (ACE) to {data.name} (HDF5)")
|
||||
|
||||
# Determine output filename
|
||||
outfile = destination / (data.name.replace(".", "_") + ".h5")
|
||||
data.export_to_hdf5(outfile, "w", libver=libver)
|
||||
|
||||
# Register with library
|
||||
library.register_file(outfile)
|
||||
|
||||
# Add nuclide to list
|
||||
converted[name] = outfile
|
||||
else:
|
||||
# Read existing HDF5 file
|
||||
data = cls.from_hdf5(converted[name])
|
||||
|
||||
# Add data for new temperature
|
||||
try:
|
||||
print(f"Converting {table.name} (ACE) to {data.name} (HDF5)")
|
||||
if table.data_type == TableType.NEUTRON_CONTINUOUS:
|
||||
data.add_temperature_from_ace(table, metastable)
|
||||
else:
|
||||
data.add_temperature_from_ace(table)
|
||||
except Exception as e:
|
||||
print(f"Failed to convert {table.name}: {e}")
|
||||
continue
|
||||
|
||||
# Re-export
|
||||
data.export_to_hdf5(converted[name], "w", libver=libver)
|
||||
|
||||
# Write cross_sections.xml
|
||||
library.export_to_xml(destination / "cross_sections.xml")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
class CustomFormatter(
|
||||
argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter
|
||||
):
|
||||
pass
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=CustomFormatter
|
||||
)
|
||||
parser.add_argument("libraries", nargs="*", help="ACE libraries to convert to HDF5")
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--destination",
|
||||
type=Path,
|
||||
default=Path.cwd(),
|
||||
help="Directory to create new library in",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--metastable",
|
||||
choices=["mcnp", "nndc"],
|
||||
default="nndc",
|
||||
help="How to interpret ZAIDs for metastable nuclides",
|
||||
)
|
||||
parser.add_argument("--xsdir", help="MCNP xsdir file that lists " "ACE libraries")
|
||||
parser.add_argument(
|
||||
"--xsdata", help="Serpent xsdata file that lists " "ACE libraries"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--libver",
|
||||
choices=["earliest", "latest"],
|
||||
default="earliest",
|
||||
help="Output HDF5 versioning. Use "
|
||||
"'earliest' for backwards compatibility or 'latest' "
|
||||
"for performance",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
ace_to_hdf5(
|
||||
destination=args.destination,
|
||||
xsdir=args.xsdir,
|
||||
xsdata=args.xsdata,
|
||||
libraries=args.libraries,
|
||||
metastable=args.metastable,
|
||||
libver=args.libver,
|
||||
)
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""Python script to plot tally data generated by OpenMC."""
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import tkinter as tk
|
||||
import tkinter.filedialog as filedialog
|
||||
import tkinter.font as font
|
||||
import tkinter.messagebox as messagebox
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use("TkAgg")
|
||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk
|
||||
from matplotlib.figure import Figure
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from openmc import StatePoint, MeshFilter, UnstructuredMesh
|
||||
|
||||
_COMBOBOX_SELECTED = '<<ComboboxSelected>>'
|
||||
|
||||
|
||||
def mesh_filter_check(filter):
|
||||
"""
|
||||
Check that the filter is a usable mesh filter
|
||||
"""
|
||||
return isinstance(filter, MeshFilter) and not isinstance(filter.mesh, UnstructuredMesh)
|
||||
|
||||
|
||||
class MeshPlotter(tk.Frame):
|
||||
def __init__(self, parent, filename):
|
||||
super().__init__(parent)
|
||||
|
||||
self.labels = {
|
||||
'Cell': 'Cell:',
|
||||
'Cellborn': 'Cell born:',
|
||||
'Surface': 'Surface:',
|
||||
'Material': 'Material:',
|
||||
'Universe': 'Universe:',
|
||||
'Energy': 'Energy in:',
|
||||
'Energyout': 'Energy out:'
|
||||
}
|
||||
|
||||
self.filterBoxes = {}
|
||||
|
||||
# Read data from source or leakage fraction file
|
||||
self.get_file_data(filename)
|
||||
|
||||
# Set up top-level window
|
||||
top = self.winfo_toplevel()
|
||||
top.title('Mesh Tally Plotter: ' + filename)
|
||||
top.rowconfigure(0, weight=1)
|
||||
top.columnconfigure(0, weight=1)
|
||||
self.grid(sticky=tk.W+tk.N)
|
||||
|
||||
# Create widgets and draw to screen
|
||||
self.create_widgets()
|
||||
self.update()
|
||||
|
||||
def create_widgets(self):
|
||||
figureFrame = tk.Frame(self)
|
||||
figureFrame.grid(row=0, column=0)
|
||||
|
||||
# Create the Figure and Canvas
|
||||
self.dpi = 100
|
||||
self.fig = Figure((5.0, 5.0), dpi=self.dpi)
|
||||
self.canvas = FigureCanvasTkAgg(self.fig, master=figureFrame)
|
||||
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
|
||||
|
||||
# Create the navigation toolbar, tied to the canvas
|
||||
self.mpl_toolbar = NavigationToolbar2Tk(self.canvas, figureFrame)
|
||||
self.mpl_toolbar.update()
|
||||
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
|
||||
|
||||
# Create frame for comboboxes
|
||||
self.selectFrame = tk.Frame(self)
|
||||
self.selectFrame.grid(row=1, column=0, sticky=tk.W+tk.E)
|
||||
|
||||
# Tally selection
|
||||
labelTally = tk.Label(self.selectFrame, text='Tally:')
|
||||
labelTally.grid(row=0, column=0, sticky=tk.W)
|
||||
self.tallyBox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.tallyBox['values'] = [self.datafile.tallies[i].id
|
||||
for i in self.meshTallies]
|
||||
self.tallyBox.current(0)
|
||||
self.tallyBox.grid(row=0, column=1, sticky=tk.W+tk.E)
|
||||
self.tallyBox.bind(_COMBOBOX_SELECTED, self.update)
|
||||
|
||||
# Planar basis selection
|
||||
labelBasis = tk.Label(self.selectFrame, text='Basis:')
|
||||
labelBasis.grid(row=1, column=0, sticky=tk.W)
|
||||
self.basisBox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.basisBox['values'] = ('xy', 'yz', 'xz')
|
||||
self.basisBox.current(0)
|
||||
self.basisBox.grid(row=1, column=1, sticky=tk.W+tk.E)
|
||||
self.basisBox.bind(_COMBOBOX_SELECTED, self.update)
|
||||
|
||||
# Axial level
|
||||
labelAxial = tk.Label(self.selectFrame, text='Axial level:')
|
||||
labelAxial.grid(row=2, column=0, sticky=tk.W)
|
||||
self.axialBox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.axialBox.grid(row=2, column=1, sticky=tk.W+tk.E)
|
||||
self.axialBox.bind(_COMBOBOX_SELECTED, self.redraw)
|
||||
|
||||
# Option for mean/uncertainty
|
||||
labelMean = tk.Label(self.selectFrame, text='Mean/Uncertainty:')
|
||||
labelMean.grid(row=3, column=0, sticky=tk.W)
|
||||
self.meanBox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.meanBox['values'] = ('Mean', 'Absolute uncertainty',
|
||||
'Relative uncertainty')
|
||||
self.meanBox.current(0)
|
||||
self.meanBox.grid(row=3, column=1, sticky=tk.W+tk.E)
|
||||
self.meanBox.bind(_COMBOBOX_SELECTED, self.update)
|
||||
|
||||
# Scores
|
||||
labelScore = tk.Label(self.selectFrame, text='Score:')
|
||||
labelScore.grid(row=4, column=0, sticky=tk.W)
|
||||
self.scoreBox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.scoreBox.grid(row=4, column=1, sticky=tk.W+tk.E)
|
||||
self.scoreBox.bind(_COMBOBOX_SELECTED, self.redraw)
|
||||
|
||||
# Filter label
|
||||
boldfont = font.Font(weight='bold')
|
||||
labelFilters = tk.Label(self.selectFrame, text='Filters:',
|
||||
font=boldfont)
|
||||
labelFilters.grid(row=5, column=0, sticky=tk.W)
|
||||
|
||||
def update(self, event=None):
|
||||
widget = event.widget if event else None
|
||||
|
||||
tally_id = self.meshTallies[self.tallyBox.current()]
|
||||
selectedTally = self.datafile.tallies[tally_id]
|
||||
|
||||
# Get mesh for selected tally
|
||||
self.mesh = selectedTally.find_filter(MeshFilter).mesh
|
||||
|
||||
# Get mesh dimensions
|
||||
if len(self.mesh.dimension) == 2:
|
||||
self.nx, self.ny = self.mesh.dimension
|
||||
self.nz = 1
|
||||
else:
|
||||
self.nx, self.ny, self.nz = self.mesh.dimension
|
||||
|
||||
# Repopulate comboboxes baesd on current basis selection
|
||||
text = self.basisBox.get()
|
||||
if text == 'xy':
|
||||
self.axialBox['values'] = [str(i+1) for i in range(self.nz)]
|
||||
elif text == 'yz':
|
||||
self.axialBox['values'] = [str(i+1) for i in range(self.nx)]
|
||||
else:
|
||||
self.axialBox['values'] = [str(i+1) for i in range(self.ny)]
|
||||
self.axialBox.current(0)
|
||||
|
||||
# If update() was called by a change in the basis combobox, we don't
|
||||
# need to repopulate the filters
|
||||
if widget == self.basisBox:
|
||||
self.redraw()
|
||||
return
|
||||
|
||||
# Update scores
|
||||
self.scoreBox['values'] = selectedTally.scores
|
||||
self.scoreBox.current(0)
|
||||
|
||||
# Remove any filter labels/comboboxes that exist
|
||||
for row in range(6, self.selectFrame.grid_size()[1]):
|
||||
for w in self.selectFrame.grid_slaves(row=row):
|
||||
w.grid_forget()
|
||||
w.destroy()
|
||||
|
||||
# create a label/combobox for each filter in selected tally
|
||||
count = 0
|
||||
for f in selectedTally.filters:
|
||||
filterType = f.short_name
|
||||
if filterType == 'Mesh':
|
||||
continue
|
||||
count += 1
|
||||
|
||||
# Create label and combobox for this filter
|
||||
label = tk.Label(self.selectFrame, text=self.labels[filterType])
|
||||
label.grid(row=count+6, column=0, sticky=tk.W)
|
||||
combobox = ttk.Combobox(self.selectFrame, state='readonly')
|
||||
self.filterBoxes[filterType] = combobox
|
||||
|
||||
# Set combobox items
|
||||
if filterType in ['Energy', 'Energyout']:
|
||||
combobox['values'] = ['{} to {}'.format(*ebin)
|
||||
for ebin in f.bins]
|
||||
else:
|
||||
combobox['values'] = [str(i) for i in f.bins]
|
||||
|
||||
combobox.current(0)
|
||||
combobox.grid(row=count+6, column=1, sticky=tk.W+tk.E)
|
||||
combobox.bind(_COMBOBOX_SELECTED, self.redraw)
|
||||
|
||||
# If There are no filters, leave a 'None available' message
|
||||
if count == 0:
|
||||
count += 1
|
||||
label = tk.Label(self.selectFrame, text="None Available")
|
||||
label.grid(row=count+6, column=0, sticky=tk.W)
|
||||
|
||||
self.redraw()
|
||||
|
||||
def redraw(self, event=None):
|
||||
basis = self.basisBox.current() + 1
|
||||
axial_level = self.axialBox.current() + 1
|
||||
mbvalue = self.meanBox.get()
|
||||
|
||||
# Get selected tally
|
||||
tally_id = self.meshTallies[self.tallyBox.current()]
|
||||
selectedTally = self.datafile.tallies[tally_id]
|
||||
|
||||
# Create spec_list
|
||||
spec_list = []
|
||||
for f in selectedTally.filters:
|
||||
if f.short_name == 'Mesh':
|
||||
mesh_filter = f
|
||||
continue
|
||||
elif f.short_name in ['Energy', 'Energyout']:
|
||||
index = self.filterBoxes[f.short_name].current()
|
||||
ebin = f.bins[index]
|
||||
spec_list.append((type(f), (ebin,)))
|
||||
else:
|
||||
index = self.filterBoxes[f.short_name].current()
|
||||
spec_list.append((type(f), (index,)))
|
||||
|
||||
dims = (self.nx, self.ny, self.nz)
|
||||
|
||||
text = self.basisBox.get()
|
||||
if text == 'xy':
|
||||
h_ind = 0
|
||||
v_ind = 1
|
||||
elif text == 'yz':
|
||||
h_ind = 1
|
||||
v_ind = 2
|
||||
else:
|
||||
h_ind = 0
|
||||
v_ind = 2
|
||||
|
||||
axial_ind = 3 - (h_ind + v_ind)
|
||||
dims = (dims[h_ind], dims[v_ind])
|
||||
|
||||
mesh_dim = len(self.mesh.dimension)
|
||||
if mesh_dim == 3:
|
||||
mesh_indices = [0,0,0]
|
||||
else:
|
||||
mesh_indices = [0,0]
|
||||
|
||||
matrix = np.zeros(dims)
|
||||
for i in range(dims[0]):
|
||||
for j in range(dims[1]):
|
||||
if mesh_dim == 3:
|
||||
mesh_indices[h_ind] = i + 1
|
||||
mesh_indices[v_ind] = j + 1
|
||||
mesh_indices[axial_ind] = axial_level
|
||||
else:
|
||||
mesh_indices[0] = i + 1
|
||||
mesh_indices[1] = j + 1
|
||||
filters, filter_bins = zip(*spec_list + [
|
||||
(type(mesh_filter), (tuple(mesh_indices),))])
|
||||
mean = selectedTally.get_values(
|
||||
[self.scoreBox.get()], filters, filter_bins)
|
||||
stdev = selectedTally.get_values(
|
||||
[self.scoreBox.get()], filters, filter_bins,
|
||||
value='std_dev')
|
||||
if mbvalue == 'Mean':
|
||||
matrix[i, j] = mean
|
||||
elif mbvalue == 'Absolute uncertainty':
|
||||
matrix[i, j] = stdev
|
||||
else:
|
||||
if mean > 0.:
|
||||
matrix[i, j] = stdev/mean
|
||||
else:
|
||||
matrix[i, j] = 0.
|
||||
|
||||
# Clear the figure
|
||||
self.fig.clear()
|
||||
|
||||
# Make figure, set up color bar
|
||||
self.axes = self.fig.add_subplot(111)
|
||||
cax = self.axes.imshow(matrix.transpose(), vmin=0.0, vmax=matrix.max(),
|
||||
interpolation='none', origin='lower')
|
||||
self.fig.colorbar(cax)
|
||||
|
||||
self.axes.set_xticks([])
|
||||
self.axes.set_yticks([])
|
||||
self.axes.set_aspect('equal')
|
||||
|
||||
# Draw canvas
|
||||
self.canvas.draw()
|
||||
|
||||
def get_file_data(self, filename):
|
||||
# Create StatePoint object and read in data
|
||||
self.datafile = StatePoint(filename)
|
||||
|
||||
meshes = self.datafile.meshes
|
||||
if any(isinstance(m, UnstructuredMesh) for m in meshes.values()):
|
||||
warn_msg = "Unstructured meshes are present in the" \
|
||||
" statepoint file but are not currently" \
|
||||
" supported by this script"
|
||||
messagebox.showwarning("Unstructured Meshes", message=warn_msg)
|
||||
|
||||
# Find which tallies are mesh tallies
|
||||
self.meshTallies = []
|
||||
for itally, tally in self.datafile.tallies.items():
|
||||
if any([mesh_filter_check(f) for f in tally.filters]):
|
||||
self.meshTallies.append(itally)
|
||||
|
||||
if not self.meshTallies:
|
||||
messagebox.showerror("Invalid StatePoint File",
|
||||
"File does not contain mesh tallies!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('statepoint', nargs='?', help='Statepoint file')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Hide root window
|
||||
root = tk.Tk()
|
||||
root.withdraw()
|
||||
|
||||
# If no filename given as command-line argument, open file dialog
|
||||
if args.statepoint is None:
|
||||
filename = filedialog.askopenfilename(title='Select statepoint file',
|
||||
initialdir='.')
|
||||
else:
|
||||
filename = args.statepoint
|
||||
|
||||
if filename:
|
||||
# Check to make sure file exists
|
||||
if not os.path.isfile(filename):
|
||||
messagebox.showerror("File not found",
|
||||
"Could not find regular file: " + filename)
|
||||
sys.exit(1)
|
||||
|
||||
app = MeshPlotter(root, filename)
|
||||
root.deiconify()
|
||||
root.mainloop()
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""Combine multiple HDF5 particle track files."""
|
||||
|
||||
import argparse
|
||||
|
||||
import openmc
|
||||
|
||||
|
||||
def main():
|
||||
# Parse command-line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Combine particle track files into a single .h5 file.')
|
||||
parser.add_argument('input', metavar='IN', nargs='+',
|
||||
help='Input HDF5 particle track filename(s).')
|
||||
parser.add_argument('-o', '--out', metavar='OUT', default='tracks.h5',
|
||||
help='Output HDF5 particle track file.')
|
||||
|
||||
args = parser.parse_args()
|
||||
openmc.Tracks.combine(args.input, args.out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""Convert HDF5 particle track to VTK poly data.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
|
||||
import openmc
|
||||
import vtk
|
||||
|
||||
|
||||
def _parse_args():
|
||||
# Create argument parser.
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Convert particle track file(s) to a .pvtp file.')
|
||||
parser.add_argument('input', metavar='IN', type=str,
|
||||
help='Input particle track data filename.')
|
||||
parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out',
|
||||
help='Output VTK poly data filename.')
|
||||
|
||||
# Parse and return commandline arguments.
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
# Parse commandline arguments.
|
||||
args = _parse_args()
|
||||
|
||||
# Make sure that the output filename ends with '.pvtp'.
|
||||
if not args.out:
|
||||
args.out = 'tracks.pvtp'
|
||||
elif not args.out.endswith('.pvtp'):
|
||||
args.out += '.pvtp'
|
||||
|
||||
# Write coordinate values to points array.
|
||||
track_file = openmc.Tracks(args.input)
|
||||
track_file.write_to_vtk(args.out)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Update OpenMC's input XML files to the latest format."""
|
||||
|
||||
import argparse
|
||||
from itertools import chain
|
||||
from random import randint
|
||||
from shutil import move
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import openmc.data
|
||||
|
||||
|
||||
description = "Update OpenMC's input XML files to the latest format."
|
||||
epilog = """\
|
||||
If any of the given files do not match the most up-to-date formatting, then they
|
||||
will be automatically rewritten. The old out-of-date files will not be deleted;
|
||||
they will be moved to a new file with '.original' appended to their name.
|
||||
|
||||
Formatting changes that will be made:
|
||||
|
||||
geometry.xml: Lattices containing 'outside' attributes/tags will be replaced
|
||||
with lattices containing 'outer' attributes, and the appropriate
|
||||
cells/universes will be added. Any 'surfaces' attributes/elements on a cell
|
||||
will be renamed 'region'.
|
||||
|
||||
materials.xml: Nuclide names will be changed from ACE aliases (e.g., Am-242m) to
|
||||
HDF5/GNDS names (e.g., Am242_m1). Thermal scattering table names will be
|
||||
changed from ACE aliases (e.g., HH2O) to HDF5/GNDS names (e.g., c_H_in_H2O).
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Read the input files from the commandline."""
|
||||
# Create argument parser.
|
||||
parser = argparse.ArgumentParser(
|
||||
description=description,
|
||||
epilog=epilog,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('input', metavar='IN', type=str, nargs='+',
|
||||
help='Input XML file(s).')
|
||||
|
||||
# Parse and return commandline arguments.
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def get_universe_ids(geometry_root):
|
||||
"""Return a set of universe id numbers."""
|
||||
root = geometry_root
|
||||
out = set()
|
||||
|
||||
# Get the ids of universes defined by cells.
|
||||
for cell in root.iter('cell'):
|
||||
# Get universe attributes/elements
|
||||
if 'universe' in cell.attrib:
|
||||
uid = cell.attrib['universe']
|
||||
out.add(int(uid))
|
||||
elif cell.find('universe') is not None:
|
||||
elem = cell.find('universe')
|
||||
uid = elem.text
|
||||
out.add(int(uid))
|
||||
else:
|
||||
# Default to universe 0
|
||||
out.add(0)
|
||||
|
||||
# Get the ids of universes defined by lattices.
|
||||
for lat in root.iter('lattice'):
|
||||
# Get id attributes.
|
||||
if 'id' in lat.attrib:
|
||||
uid = lat.attrib['id']
|
||||
out.add(int(uid))
|
||||
|
||||
# Get id elements.
|
||||
elif lat.find('id') is not None:
|
||||
elem = lat.find('id')
|
||||
uid = elem.text
|
||||
out.add(int(uid))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_cell_ids(geometry_root):
|
||||
"""Return a set of cell id numbers."""
|
||||
root = geometry_root
|
||||
out = set()
|
||||
|
||||
# Get the ids of universes defined by cells.
|
||||
for cell in root.iter('cell'):
|
||||
# Get id attributes.
|
||||
if 'id' in cell.attrib:
|
||||
cid = cell.attrib['id']
|
||||
out.add(int(cid))
|
||||
|
||||
# Get id elements.
|
||||
elif cell.find('id') is not None:
|
||||
elem = cell.find('id')
|
||||
cid = elem.text
|
||||
out.add(int(cid))
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def find_new_id(current_ids, preferred=None):
|
||||
"""Return a new id that is not already present in current_ids."""
|
||||
distance_from_preferred = 21
|
||||
max_random_attempts = 10000
|
||||
|
||||
# First, try to find an id near the preferred number.
|
||||
if preferred is not None:
|
||||
assert isinstance(preferred, int)
|
||||
for i in range(1, distance_from_preferred):
|
||||
if (preferred - i not in current_ids) and (preferred - i > 0):
|
||||
return preferred - i
|
||||
if (preferred + i not in current_ids) and (preferred + i > 0):
|
||||
return preferred + i
|
||||
|
||||
# If that was unsuccessful, attempt to randomly guess a new id number.
|
||||
for i in range(max_random_attempts):
|
||||
num = randint(1, 2147483647)
|
||||
if num not in current_inds:
|
||||
return num
|
||||
|
||||
# Raise an error if an id was not found.
|
||||
raise RuntimeError('Could not find a unique id number for a new universe.')
|
||||
|
||||
|
||||
def get_lat_id(lattice_element):
|
||||
"""Return the id integer of the lattice_element."""
|
||||
assert isinstance(lattice_element, ET.Element)
|
||||
if 'id' in lattice_element.attrib:
|
||||
return int(lattice_element.attrib['id'].strip())
|
||||
elif any([child.tag == 'id' for child in lattice_element]):
|
||||
elem = lattice_element.find('id')
|
||||
return int(elem.text.strip())
|
||||
else:
|
||||
raise RuntimeError('Could not find the id for a lattice.')
|
||||
|
||||
|
||||
def pop_lat_outside(lattice_element):
|
||||
"""Return lattice's outside material and remove from attributes/elements."""
|
||||
assert isinstance(lattice_element, ET.Element)
|
||||
|
||||
# Check attributes.
|
||||
if 'outside' in lattice_element.attrib:
|
||||
material = lattice_element.attrib['outside'].strip()
|
||||
del lattice_element.attrib['outside']
|
||||
|
||||
# Check subelements.
|
||||
elif any([child.tag == 'outside' for child in lattice_element]):
|
||||
elem = lattice_element.find('outside')
|
||||
material = elem.text.strip()
|
||||
lattice_element.remove(elem)
|
||||
|
||||
# No 'outside' specified. This means the outside is a void.
|
||||
else:
|
||||
material = 'void'
|
||||
|
||||
return material
|
||||
|
||||
|
||||
def update_geometry(geometry_root):
|
||||
"""Update the given XML geometry tree. Return True if changes were made."""
|
||||
root = geometry_root
|
||||
was_updated = False
|
||||
|
||||
# Get a set of already-used universe and cell ids.
|
||||
uids = get_universe_ids(root)
|
||||
cids = get_cell_ids(root)
|
||||
taken_ids = uids.union(cids)
|
||||
|
||||
# Replace 'outside' with 'outer' in lattices.
|
||||
for lat in chain(root.iter('lattice'), root.iter('hex_lattice')):
|
||||
# Get the lattice's id.
|
||||
lat_id = get_lat_id(lat)
|
||||
|
||||
# Ignore lattices that have 'outer' specified.
|
||||
if any([child.tag == 'outer' for child in lat]): continue
|
||||
if 'outer' in lat.attrib: continue
|
||||
|
||||
# Pop the 'outside' material.
|
||||
material = pop_lat_outside(lat)
|
||||
|
||||
# Get an id number for a new outer universe. Ideally, the id should
|
||||
# be close to the lattice's id.
|
||||
new_uid = find_new_id(taken_ids, preferred=lat_id)
|
||||
assert new_uid not in taken_ids
|
||||
|
||||
# Add the new universe filled with the old 'outside' material to the
|
||||
# geometry.
|
||||
new_cell = ET.Element('cell')
|
||||
new_cell.attrib['id'] = str(new_uid)
|
||||
new_cell.attrib['universe'] = str(new_uid)
|
||||
new_cell.attrib['material'] = material
|
||||
root.append(new_cell)
|
||||
taken_ids.add(new_uid)
|
||||
|
||||
# Add the new universe to the lattice's 'outer' attribute.
|
||||
lat.attrib['outer'] = str(new_uid)
|
||||
|
||||
was_updated = True
|
||||
|
||||
for surface in root.findall('surface'):
|
||||
for attribute in ['type', 'coeffs', 'boundary']:
|
||||
if surface.find(attribute) is not None:
|
||||
value = surface.find(attribute).text
|
||||
surface.attrib[attribute] = value
|
||||
|
||||
child_element = surface.find(attribute)
|
||||
surface.remove(child_element)
|
||||
was_updated = True
|
||||
|
||||
# Remove 'type' from lattice definitions.
|
||||
for lat in root.iter('lattice'):
|
||||
elem = lat.find('type')
|
||||
if elem is not None:
|
||||
lat.remove(elem)
|
||||
was_updated = True
|
||||
if 'type' in lat.attrib:
|
||||
del lat.attrib['type']
|
||||
was_updated = True
|
||||
|
||||
# Change 'width' to 'pitch' in lattice definitions.
|
||||
for lat in root.iter('lattice'):
|
||||
elem = lat.find('width')
|
||||
if elem is not None:
|
||||
elem.tag = 'pitch'
|
||||
was_updated = True
|
||||
if 'width' in lat.attrib:
|
||||
lat.attrib['pitch'] = lat.attrib['width']
|
||||
del lat.attrib['width']
|
||||
was_updated = True
|
||||
|
||||
# Change 'surfaces' to 'region' in cell definitions
|
||||
for cell in root.iter('cell'):
|
||||
elem = cell.find('surfaces')
|
||||
if elem is not None:
|
||||
elem.tag = 'region'
|
||||
was_updated = True
|
||||
if 'surfaces' in cell.attrib:
|
||||
cell.attrib['region'] = cell.attrib['surfaces']
|
||||
del cell.attrib['surfaces']
|
||||
was_updated = True
|
||||
|
||||
return was_updated
|
||||
|
||||
def update_materials(root):
|
||||
"""Update the given XML materials tree. Return True if changes were made."""
|
||||
was_updated = False
|
||||
|
||||
for material in root.findall('material'):
|
||||
for nuclide in material.findall('nuclide'):
|
||||
if 'name' in nuclide.attrib:
|
||||
nucname = nuclide.attrib['name'].replace('-', '')
|
||||
# If a nuclide name is in the ZAID notation (e.g., a number),
|
||||
# convert it to the proper nuclide name.
|
||||
if nucname.strip().isnumeric():
|
||||
nucname = openmc.data.ace.get_metadata(int(nucname))[0]
|
||||
nucname = nucname.replace('Nat', '0')
|
||||
if nucname.endswith('m'):
|
||||
nucname = nucname[:-1] + '_m1'
|
||||
nuclide.set('name', nucname)
|
||||
was_updated = True
|
||||
|
||||
elif nuclide.find('name') is not None:
|
||||
name_elem = nuclide.find('name')
|
||||
nucname = name_elem.text
|
||||
nucname = nucname.replace('-', '')
|
||||
nucname = nucname.replace('Nat', '0')
|
||||
if nucname.endswith('m'):
|
||||
nucname = nucname[:-1] + '_m1'
|
||||
name_elem.text = nucname
|
||||
was_updated = True
|
||||
|
||||
for sab in material.findall('sab'):
|
||||
if 'name' in sab.attrib:
|
||||
sabname = sab.attrib['name']
|
||||
sab.set('name', openmc.data.get_thermal_name(sabname))
|
||||
was_updated = True
|
||||
|
||||
elif sab.find('name') is not None:
|
||||
name_elem = sab.find('name')
|
||||
sabname = name_elem.text
|
||||
name_elem.text = openmc.data.get_thermal_name(sabname)
|
||||
was_updated = True
|
||||
|
||||
return was_updated
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parse_args()
|
||||
for fname in args.input:
|
||||
# Parse the XML data.
|
||||
tree = ET.parse(fname)
|
||||
root = tree.getroot()
|
||||
was_updated = False
|
||||
|
||||
if root.tag == 'geometry':
|
||||
was_updated = update_geometry(root)
|
||||
elif root.tag == 'materials':
|
||||
was_updated = update_materials(root)
|
||||
|
||||
if was_updated:
|
||||
# Move the original geometry file to preserve it.
|
||||
move(fname, fname + '.original')
|
||||
|
||||
# Write a new geometry file.
|
||||
tree.write(fname, xml_declaration=True)
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Update OpenMC's deprecated multi-group cross section XML files to the latest
|
||||
HDF5-based format.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import warnings
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import argparse
|
||||
import numpy as np
|
||||
|
||||
import openmc.mgxs_library
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Read the input files from the commandline."""
|
||||
# Create argument parser
|
||||
parser = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('-i', '--input', type=argparse.FileType('r'),
|
||||
help='input XML file')
|
||||
parser.add_argument('-o', '--output', nargs='?', default='',
|
||||
help='output file, in HDF5 format')
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
if args['output'] == '':
|
||||
filename = args['input'].name
|
||||
extension = os.path.splitext(filename)
|
||||
if extension == '.xml':
|
||||
filename = filename[:filename.rfind('.')] + '.h5'
|
||||
args['output'] = filename
|
||||
|
||||
# Parse and return commandline arguments.
|
||||
return args
|
||||
|
||||
|
||||
def get_data(element, entry):
|
||||
value = element.find(entry)
|
||||
if value is not None:
|
||||
value = value.text.strip()
|
||||
elif entry in element.attrib:
|
||||
value = element.attrib[entry].strip()
|
||||
else:
|
||||
value = None
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
# Parse the XML data.
|
||||
tree = ET.parse(args['input'])
|
||||
root = tree.getroot()
|
||||
|
||||
# Get old metadata
|
||||
group_structure = tree.find('group_structure').text.strip()
|
||||
group_structure = np.array(group_structure.split(), dtype=float)
|
||||
# Convert from MeV to eV
|
||||
group_structure *= 1.e6
|
||||
energy_groups = openmc.mgxs.EnergyGroups(group_structure)
|
||||
|
||||
inverse_velocity = tree.find('inverse-velocity')
|
||||
if inverse_velocity is not None:
|
||||
inverse_velocity = inverse_velocity.text.split()
|
||||
inverse_velocity = np.array(inverse_velocity, dtype=float)
|
||||
else:
|
||||
inverse_velocity = None
|
||||
|
||||
xsd = []
|
||||
names = []
|
||||
|
||||
# Now move on to the cross section data itself
|
||||
for xsdata_elem in root.iter('xsdata'):
|
||||
name = get_data(xsdata_elem, 'name')
|
||||
|
||||
temperature = get_data(xsdata_elem, 'kT')
|
||||
if temperature is not None:
|
||||
temperature = float(temperature) / openmc.data.K_BOLTZMANN * 1.E6
|
||||
else:
|
||||
temperature = 294.
|
||||
temperatures = [temperature]
|
||||
|
||||
awr = get_data(xsdata_elem, 'awr')
|
||||
if awr is not None:
|
||||
awr = float(awr)
|
||||
|
||||
representation = get_data(xsdata_elem, 'representation')
|
||||
if representation is None:
|
||||
representation = 'isotropic'
|
||||
if representation == 'angle':
|
||||
n_azi = int(get_data(xsdata_elem, 'num_azimuthal'))
|
||||
n_pol = int(get_data(xsdata_elem, 'num_polar'))
|
||||
|
||||
scatter_format = get_data(xsdata_elem, 'scatt_type')
|
||||
if scatter_format is None:
|
||||
scatter_format = 'legendre'
|
||||
|
||||
order = int(get_data(xsdata_elem, 'order'))
|
||||
|
||||
tab_leg = get_data(xsdata_elem, 'tabular_legendre')
|
||||
if tab_leg is not None:
|
||||
warnings.warn('The tabular_legendre option has moved to the '
|
||||
'settings.xml file and must be added manually')
|
||||
|
||||
# Either add the data to a previously existing xsdata (if it is
|
||||
# for the same 'name' but a different temperature), or create a
|
||||
# new one.
|
||||
try:
|
||||
# It is in our list, so store that entry
|
||||
i = names.index(name)
|
||||
except ValueError:
|
||||
# It is not in our list, so add it
|
||||
i = -1
|
||||
xsd.append(openmc.XSdata(name, energy_groups,
|
||||
temperatures=temperatures,
|
||||
representation=representation))
|
||||
if awr is not None:
|
||||
xsd[-1].atomic_weight_ratio = awr
|
||||
if representation == 'angle':
|
||||
xsd[-1].num_azimuthal = n_azi
|
||||
xsd[-1].num_polar = n_pol
|
||||
xsd[-1].scatter_format = scatter_format
|
||||
xsd[-1].order = order
|
||||
names.append(name)
|
||||
|
||||
if scatter_format == 'legendre':
|
||||
order_dim = order + 1
|
||||
else:
|
||||
order_dim = order
|
||||
|
||||
if i != -1:
|
||||
xsd[i].add_temperature(temperature)
|
||||
|
||||
total = get_data(xsdata_elem, 'total')
|
||||
if total is not None:
|
||||
total = np.array(total.split(), dtype=float)
|
||||
total.shape = xsd[i].xs_shapes['[G]']
|
||||
xsd[i].set_total(total, temperature)
|
||||
|
||||
if inverse_velocity is not None:
|
||||
xsd[i].set_inverse_velocity(inverse_velocity, temperature)
|
||||
|
||||
absorption = get_data(xsdata_elem, 'absorption')
|
||||
absorption = np.array(absorption.split(), dtype=float)
|
||||
absorption.shape = xsd[i].xs_shapes['[G]']
|
||||
xsd[i].set_absorption(absorption, temperature)
|
||||
|
||||
scatter = get_data(xsdata_elem, 'scatter')
|
||||
scatter = np.array(scatter.split(), dtype=float)
|
||||
# This is now a flattened-array of something that started with a
|
||||
# shape of [Order][G][G']; we need to unflatten and then switch the
|
||||
# ordering
|
||||
in_shape = (order_dim, energy_groups.num_groups,
|
||||
energy_groups.num_groups)
|
||||
if representation == 'angle':
|
||||
in_shape = (n_pol, n_azi) + in_shape
|
||||
scatter.shape = in_shape
|
||||
scatter = np.swapaxes(scatter, 2, 3)
|
||||
scatter = np.swapaxes(scatter, 3, 4)
|
||||
else:
|
||||
scatter.shape = in_shape
|
||||
scatter = np.swapaxes(scatter, 0, 1)
|
||||
scatter = np.swapaxes(scatter, 1, 2)
|
||||
|
||||
xsd[i].set_scatter_matrix(scatter, temperature)
|
||||
|
||||
multiplicity = get_data(xsdata_elem, 'multiplicity')
|
||||
if multiplicity is not None:
|
||||
multiplicity = np.array(multiplicity.split(), dtype=float)
|
||||
multiplicity.shape = xsd[i].xs_shapes["[G][G']"]
|
||||
xsd[i].set_multiplicity_matrix(multiplicity, temperature)
|
||||
|
||||
fission = get_data(xsdata_elem, 'fission')
|
||||
if fission is not None:
|
||||
fission = np.array(fission.split(), dtype=float)
|
||||
fission.shape = xsd[i].xs_shapes['[G]']
|
||||
xsd[i].set_fission(fission, temperature)
|
||||
|
||||
kappa_fission = get_data(xsdata_elem, 'kappa_fission')
|
||||
if kappa_fission is not None:
|
||||
kappa_fission = np.array(kappa_fission.split(), dtype=float)
|
||||
kappa_fission.shape = xsd[i].xs_shapes['[G]']
|
||||
xsd[i].set_kappa_fission(kappa_fission, temperature)
|
||||
|
||||
chi = get_data(xsdata_elem, 'chi')
|
||||
if chi is not None:
|
||||
chi = np.array(chi.split(), dtype=float)
|
||||
chi.shape = xsd[i].xs_shapes['[G]']
|
||||
xsd[i].set_chi(chi, temperature)
|
||||
else:
|
||||
chi = None
|
||||
|
||||
nu_fission = get_data(xsdata_elem, 'nu_fission')
|
||||
if nu_fission is not None:
|
||||
nu_fission = np.array(nu_fission.split(), dtype=float)
|
||||
if chi is not None:
|
||||
nu_fission.shape = xsd[i].xs_shapes['[G]']
|
||||
else:
|
||||
nu_fission.shape = xsd[i].xs_shapes["[G][G']"]
|
||||
xsd[i].set_nu_fission(nu_fission, temperature)
|
||||
|
||||
# Build library as we go, but first we have enough to initialize it
|
||||
lib = openmc.MGXSLibrary(energy_groups)
|
||||
lib.add_xsdatas(xsd)
|
||||
lib.export_to_hdf5(args['output'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import openmc
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Process command line arguments
|
||||
parser = ArgumentParser('Converts a voxel HDF5 file to a VTK file')
|
||||
parser.add_argument("voxel_file", help="Path to voxel h5 file")
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
action="store",
|
||||
default="plot",
|
||||
help="Path to output VTK file.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
print("Reading and translating data...")
|
||||
openmc.voxel_to_vtk(args.voxel_file, args.output)
|
||||
print(f"Written VTK file {args.output}...")
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
from subprocess import call
|
||||
|
||||
import numpy as np
|
||||
import openmc
|
||||
|
|
@ -26,8 +25,8 @@ class TrackTestHarness(TestHarness):
|
|||
|
||||
# For MPI mode, combine track files
|
||||
if config['mpi']:
|
||||
call(['../../../scripts/openmc-track-combine', '-o', 'tracks.h5'] +
|
||||
glob.glob('tracks_p*.h5'))
|
||||
track_files = list(glob.glob('tracks_p*.h5'))
|
||||
openmc.Tracks.combine(track_files, 'tracks.h5')
|
||||
|
||||
# Get string of track file information
|
||||
outstr = ''
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from difflib import unified_diff
|
||||
from subprocess import check_call
|
||||
import filecmp
|
||||
import glob
|
||||
import h5py
|
||||
|
|
@ -487,8 +486,7 @@ class PlotTestHarness(TestHarness):
|
|||
|
||||
# Check that voxel h5 can be converted to vtk
|
||||
for voxel_h5_filename in self._voxel_convert_checks:
|
||||
check_call(['../../../scripts/openmc-voxel-to-vtk'] +
|
||||
glob.glob(voxel_h5_filename))
|
||||
openmc.voxel_to_vtk(voxel_h5_filename)
|
||||
|
||||
def _test_output_created(self):
|
||||
"""Make sure *.png has been created."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue