mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 13:45:36 -04:00
Adding docstrings and updated the element, executor, filter, geometry, material,
mesh, and nuclide modules.
This commit is contained in:
parent
f41d7d9b45
commit
7ed1dd17e6
14 changed files with 401 additions and 275 deletions
|
|
@ -6,4 +6,3 @@ Element
|
|||
|
||||
.. automodule:: openmc.element
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Executor
|
|||
|
||||
.. automodule:: openmc.executor
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Filter
|
|||
|
||||
.. automodule:: openmc.filter
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Geometry
|
|||
|
||||
.. automodule:: openmc.geometry
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Materials
|
|||
|
||||
.. automodule:: openmc.material
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Mesh
|
|||
|
||||
.. automodule:: openmc.mesh
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ Nuclide
|
|||
|
||||
.. automodule:: openmc.nuclide
|
||||
:members:
|
||||
:undoc-members:
|
||||
|
|
|
|||
|
|
@ -1,58 +1,63 @@
|
|||
from openmc.checkvalue import *
|
||||
|
||||
class Element(object):
|
||||
"""A natural element used in a material via <element>. Internally, OpenMC will
|
||||
expand the natural element into isotopes based on the known natural
|
||||
abundances.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Chemical symbol of the element, e.g. Pu
|
||||
xs : str
|
||||
Cross section identifier, e.g. 71c
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str
|
||||
Chemical symbol of the element, e.g. Pu
|
||||
xs : str
|
||||
Cross section identifier, e.g. 71c
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name='', xs=None):
|
||||
|
||||
# Initialize class attributes
|
||||
self._name = ''
|
||||
self._xs = None
|
||||
|
||||
# Set the Material class attributes
|
||||
# Set class attributes
|
||||
self.name = name
|
||||
|
||||
if not xs is None:
|
||||
self.xs = xs
|
||||
|
||||
|
||||
def __eq__(self, element2):
|
||||
|
||||
# Check type
|
||||
if not isinstance(element2, Element):
|
||||
return False
|
||||
|
||||
# Check name
|
||||
# Check name and xs
|
||||
if self._name != element2._name:
|
||||
return False
|
||||
|
||||
# Check xs
|
||||
elif self._xs != element2._xs:
|
||||
return False
|
||||
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def __hash__(self):
|
||||
hashable = []
|
||||
hashable.append(self._name)
|
||||
hashable.append(self._xs)
|
||||
return hash(tuple(hashable))
|
||||
|
||||
return hash((self._name, self._xs))
|
||||
|
||||
@property
|
||||
def xs(self):
|
||||
return self._xs
|
||||
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
|
||||
@xs.setter
|
||||
def xs(self, xs):
|
||||
|
||||
if not is_string(xs):
|
||||
msg = 'Unable to set cross-section identifier xs for Element ' \
|
||||
'with a non-string value {0}'.format(xs)
|
||||
|
|
@ -60,10 +65,8 @@ class Element(object):
|
|||
|
||||
self._xs = xs
|
||||
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
|
||||
if not is_string(name):
|
||||
msg = 'Unable to set name for Element with a non-string ' \
|
||||
'value {0}'.format(name)
|
||||
|
|
@ -71,9 +74,7 @@ class Element(object):
|
|||
|
||||
self._name = name
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = 'Element - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
return string
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
|
|
@ -5,37 +6,39 @@ from openmc.checkvalue import *
|
|||
|
||||
|
||||
class Executor(object):
|
||||
"""Control execution of OpenMC
|
||||
|
||||
Attributes
|
||||
----------
|
||||
working_directory : str
|
||||
Path to working directory to run in
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._working_directory = '.'
|
||||
|
||||
|
||||
def _run_openmc(self, command, output):
|
||||
|
||||
# Launch a subprocess to run OpenMC
|
||||
p = subprocess.Popen(command, shell=True,
|
||||
p = subprocess.Popen(command, shell=True,
|
||||
cwd=self._working_directory,
|
||||
stdout=subprocess.PIPE)
|
||||
|
||||
# Capture and re-print OpenMC output in real-time
|
||||
while (True and output):
|
||||
line = p.stdout.readline()
|
||||
print(line),
|
||||
print(line, end='')
|
||||
|
||||
# If OpenMC is finished, break loop
|
||||
if line == '' and p.poll() != None:
|
||||
break
|
||||
|
||||
|
||||
@property
|
||||
def working_directory(self):
|
||||
return self._working_directory
|
||||
|
||||
|
||||
@working_directory.setter
|
||||
def working_directory(self, working_directory):
|
||||
|
||||
if not is_string(working_directory):
|
||||
msg = 'Unable to set Executor\'s working directory to {0} ' \
|
||||
'since it is not a string'.format(working_directory)
|
||||
|
|
@ -48,14 +51,34 @@ class Executor(object):
|
|||
|
||||
self._working_directory = working_directory
|
||||
|
||||
|
||||
def plot_geometry(self, output=True):
|
||||
self._run_openmc('openmc -p', output)
|
||||
"""Run OpenMC in plotting mode"""
|
||||
|
||||
self._run_openmc('openmc -p', output)
|
||||
|
||||
def run_simulation(self, particles=None, threads=None,
|
||||
geometry_debug=False, restart_file=None,
|
||||
tracks=False, mpi_procs=1, output=True):
|
||||
"""Run an OpenMC simulation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
particles : int
|
||||
Number of particles to simulate per generation
|
||||
threads : int
|
||||
Number of OpenMP threads
|
||||
geometry_debug : bool
|
||||
Turn on geometry debugging during simulation
|
||||
restart_file : str
|
||||
Path to restart file to use
|
||||
tracks : bool
|
||||
Write tracks for all particles
|
||||
mpi_procs : int
|
||||
Number of MPI processes
|
||||
output : bool
|
||||
Capture OpenMC output from standard out
|
||||
|
||||
"""
|
||||
|
||||
post_args = ' '
|
||||
pre_args = ''
|
||||
|
|
|
|||
115
openmc/filter.py
115
openmc/filter.py
|
|
@ -6,10 +6,30 @@ from openmc.constants import *
|
|||
|
||||
|
||||
class Filter(object):
|
||||
"""A filter used to constrain a tally to a specific criterion, e.g. only tally
|
||||
events when the particle is in a certain cell and energy range.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
type : str
|
||||
The type of the tally filter. Acceptable values are "universe",
|
||||
"material", "cell", "cellborn", "surface", "mesh", "energy",
|
||||
"energyout", and "distribcell".
|
||||
bins : int or list of int or list of float or ndarray
|
||||
The bins for the filter. This takes on different meaning for different
|
||||
filters.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
type : str
|
||||
The type of the tally filter.
|
||||
bins : int or list of int or list of float or ndarray
|
||||
The bins for the filter
|
||||
|
||||
"""
|
||||
|
||||
# Initialize Filter class attributes
|
||||
def __init__(self, type=None, bins=None):
|
||||
|
||||
self.type = type
|
||||
self._num_bins = 0
|
||||
self.bins = bins
|
||||
|
|
@ -17,9 +37,7 @@ class Filter(object):
|
|||
self._offset = -1
|
||||
self._stride = None
|
||||
|
||||
|
||||
def __eq__(self, filter2):
|
||||
|
||||
# Check type
|
||||
if self._type != filter2._type:
|
||||
return False
|
||||
|
|
@ -37,19 +55,14 @@ class Filter(object):
|
|||
|
||||
|
||||
def __hash__(self):
|
||||
hashable = []
|
||||
hashable.append(self._type)
|
||||
hashable.append(self._bins)
|
||||
return hash(tuple(hashable))
|
||||
return hash((self._type, self._bins))
|
||||
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, create a copy
|
||||
if existing is None:
|
||||
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._type = self._type
|
||||
clone._bins = copy.deepcopy(self._bins, memo)
|
||||
|
|
@ -66,43 +79,34 @@ class Filter(object):
|
|||
else:
|
||||
return existing
|
||||
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
|
||||
@property
|
||||
def bins(self):
|
||||
return self._bins
|
||||
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return self._num_bins
|
||||
|
||||
|
||||
@property
|
||||
def mesh(self):
|
||||
return self._mesh
|
||||
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
return self._offset
|
||||
|
||||
|
||||
@property
|
||||
def stride(self):
|
||||
return self._stride
|
||||
|
||||
|
||||
@type.setter
|
||||
def type(self, type):
|
||||
|
||||
if type is None:
|
||||
self._type = type
|
||||
|
||||
elif not type in FILTER_TYPES.values():
|
||||
msg = 'Unable to set Filter type to "{0}" since it is not one ' \
|
||||
'of the supported types'.format(type)
|
||||
|
|
@ -110,13 +114,10 @@ class Filter(object):
|
|||
|
||||
self._type = type
|
||||
|
||||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
|
||||
if bins is None:
|
||||
self.num_bins = 0
|
||||
|
||||
elif self._type is None:
|
||||
msg = 'Unable to set bins for Filter to "{0}" since ' \
|
||||
'the Filter type has not yet been set'.format(bins)
|
||||
|
|
@ -132,30 +133,23 @@ class Filter(object):
|
|||
|
||||
if self._type in ['cell', 'cellborn', 'surface', 'material',
|
||||
'universe', 'distribcell']:
|
||||
|
||||
for edge in bins:
|
||||
|
||||
if not is_integer(edge):
|
||||
msg = 'Unable to add bin "{0}" to a {1} Filter since ' \
|
||||
'it is a non-integer'.format(edge, self._type)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif edge < 0:
|
||||
msg = 'Unable to add bin "{0}" to a {1} Filter since ' \
|
||||
'it is a negative integer'.format(edge, self._type)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
elif self._type in ['energy', 'energyout']:
|
||||
|
||||
for edge in bins:
|
||||
|
||||
if not is_integer(edge) and not is_float(edge):
|
||||
msg = 'Unable to add bin edge "{0}" to a {1} Filter ' \
|
||||
'since it is a non-integer or floating point ' \
|
||||
'value'.format(edge, self._type)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif edge < 0.:
|
||||
msg = 'Unable to add bin edge "{0}" to a {1} Filter ' \
|
||||
'since it is a negative value'.format(edge, self._type)
|
||||
|
|
@ -163,27 +157,22 @@ class Filter(object):
|
|||
|
||||
# Check that bin edges are monotonically increasing
|
||||
for index in range(len(bins)):
|
||||
|
||||
if index > 0 and bins[index] < bins[index-1]:
|
||||
msg = 'Unable to add bin edges "{0}" to a {1} Filter ' \
|
||||
'since they are not monotonically ' \
|
||||
'increasing'.format(bins, self._type)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
# mesh filters
|
||||
elif self._type == 'mesh':
|
||||
|
||||
if not len(bins) == 1:
|
||||
msg = 'Unable to add bins "{0}" to a mesh Filter since ' \
|
||||
'only a single mesh can be used per tally'.format(bins)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif not is_integer(bins[0]):
|
||||
msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
|
||||
'is a non-integer'.format(bins[0])
|
||||
raise ValueError(msg)
|
||||
|
||||
elif bins[0] < 0:
|
||||
msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
|
||||
'is a negative integer'.format(bins[0])
|
||||
|
|
@ -192,11 +181,9 @@ class Filter(object):
|
|||
# If all error checks passed, add bin edges
|
||||
self._bins = bins
|
||||
|
||||
|
||||
# FIXME
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins):
|
||||
|
||||
if not is_integer(num_bins) or num_bins < 0:
|
||||
msg = 'Unable to set the number of bins "{0}" for a {1} Filter ' \
|
||||
'since it is not a positive ' \
|
||||
|
|
@ -205,10 +192,8 @@ class Filter(object):
|
|||
|
||||
self._num_bins = num_bins
|
||||
|
||||
|
||||
@mesh.setter
|
||||
def mesh(self, mesh):
|
||||
|
||||
if not isinstance(mesh, Mesh):
|
||||
msg = 'Unable to set Mesh to "{0}" for Filter since it is not a ' \
|
||||
'Mesh object'.format(mesh)
|
||||
|
|
@ -218,10 +203,8 @@ class Filter(object):
|
|||
self.type = 'mesh'
|
||||
self.bins = self._mesh._id
|
||||
|
||||
|
||||
@offset.setter
|
||||
def offset(self, offset):
|
||||
|
||||
if not is_integer(offset):
|
||||
msg = 'Unable to set offset "{0}" for a {1} Filter since it is a ' \
|
||||
'non-integer value'.format(offset, self._type)
|
||||
|
|
@ -229,10 +212,8 @@ class Filter(object):
|
|||
|
||||
self._offset = offset
|
||||
|
||||
|
||||
@stride.setter
|
||||
def stride(self, stride):
|
||||
|
||||
if not is_integer(stride):
|
||||
msg = 'Unable to set stride "{0}" for a {1} Filter since it is a ' \
|
||||
'non-integer value'.format(stride, self._type)
|
||||
|
|
@ -247,6 +228,19 @@ class Filter(object):
|
|||
|
||||
|
||||
def can_merge(self, filter):
|
||||
"""Determine if filter can be merged with another.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filter : Filter
|
||||
Filter to compare with
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether the filter can be merged
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(filter, Filter):
|
||||
return False
|
||||
|
|
@ -270,8 +264,20 @@ class Filter(object):
|
|||
else:
|
||||
return True
|
||||
|
||||
|
||||
def merge(self, filter):
|
||||
"""Merge this filter with another.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filter : Filter
|
||||
Filter to merge with
|
||||
|
||||
Returns
|
||||
-------
|
||||
merged_filter : Filter
|
||||
Filter resulting from the merge
|
||||
|
||||
"""
|
||||
|
||||
if not self.can_merge(filter):
|
||||
msg = 'Unable to merge {0} with {1} filters'.format(self._type, filter._type)
|
||||
|
|
@ -287,33 +293,32 @@ class Filter(object):
|
|||
|
||||
return merged_filter
|
||||
|
||||
|
||||
def get_bin_index(self, filter_bin):
|
||||
"""Returns the index in the Filter for some bin.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filter_bin : int, tuple
|
||||
The bin is the integer ID for 'material', 'surface', 'cell',
|
||||
'cellborn', and 'universe' Filters. The bin is an integer for
|
||||
the cell instance ID for 'distribcell' Filters. The bin is
|
||||
a 2-tuple of floats for 'energy' and 'energyout' filters
|
||||
corresponding to the energy boundaries of the bin of interest.
|
||||
The bin is a (x,y,z) 3-tuple for 'mesh' filters corresponding to
|
||||
the mesh cell of interest.
|
||||
|
||||
filter_bin : int or tuple
|
||||
The bin is the integer ID for 'material', 'surface', 'cell',
|
||||
'cellborn', and 'universe' Filters. The bin is an integer for the
|
||||
cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of
|
||||
floats for 'energy' and 'energyout' filters corresponding to the
|
||||
energy boundaries of the bin of interest. The bin is a (x,y,z)
|
||||
3-tuple for 'mesh' filters corresponding to the mesh cell of
|
||||
interest.
|
||||
|
||||
Returns
|
||||
-------
|
||||
filter_index : int
|
||||
The index in the Tally data array for this filter bin.
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
# FIXME: This does not work for distribcells!!!
|
||||
|
||||
try:
|
||||
# Filter bins for a mesh are an (x,y,z) tuple
|
||||
if self.type == 'mesh':
|
||||
|
||||
# Convert (x,y,z) to a single bin -- this is similar to
|
||||
# subroutine mesh_indices_to_bin in openmc/src/mesh.F90.
|
||||
if (len(self.mesh.dimension) == 3):
|
||||
|
|
@ -350,9 +355,7 @@ class Filter(object):
|
|||
|
||||
return filter_index
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = 'Filter\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self._bins)
|
||||
|
|
|
|||
|
|
@ -12,19 +12,24 @@ def reset_auto_ids():
|
|||
|
||||
|
||||
class Geometry(object):
|
||||
"""Geometry representing a collection of surfaces, cells, and universes.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
root_universe : openmc.universe.Universe
|
||||
Root universe which contains all others
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Initialize Geometry class attributes
|
||||
self._root_universe = None
|
||||
self._offsets = {}
|
||||
|
||||
|
||||
@property
|
||||
def root_universe(self):
|
||||
return self._root_universe
|
||||
|
||||
|
||||
@root_universe.setter
|
||||
def root_universe(self, root_universe):
|
||||
|
||||
|
|
@ -34,7 +39,7 @@ class Geometry(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
elif root_universe._id != 0:
|
||||
msg = 'Unable to add root Universe {0} to Geometry since ' \
|
||||
msg = 'Unable to add root Universe {0} to Geometry since ' \
|
||||
'it has ID={1} instead of ' \
|
||||
'ID=0'.format(root_universe, root_universe._id)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -43,22 +48,25 @@ class Geometry(object):
|
|||
|
||||
|
||||
def get_offset(self, path, filter_offset):
|
||||
"""
|
||||
Returns the corresponding location in the results array for a given
|
||||
"""Returns the corresponding location in the results array for a given
|
||||
path and filter number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : list
|
||||
A list of IDs that form the path to the target. It should begin
|
||||
with 0 for the base universe, and should cover every universe,
|
||||
cell, and lattice passed through. For the case of the lattice,
|
||||
a tuple should be provided to indicate which coordinates in the
|
||||
lattice should be entered. This should be in the
|
||||
form: (lat_id, i_x, i_y, i_z)
|
||||
A list of IDs that form the path to the target. It should begin with
|
||||
0 for the base universe, and should cover every universe, cell, and
|
||||
lattice passed through. For the case of the lattice, a tuple should
|
||||
be provided to indicate which coordinates in the lattice should be
|
||||
entered. This should be in the form: (lat_id, i_x, i_y, i_z)
|
||||
|
||||
filter_offset : int
|
||||
An integer that specifies which offset map the filter is using
|
||||
An integer that specifies which offset map the filter is using
|
||||
|
||||
Returns
|
||||
-------
|
||||
offset : int
|
||||
Location in the results array for the path and filter
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -74,16 +82,39 @@ class Geometry(object):
|
|||
# Return the final offset
|
||||
return offset
|
||||
|
||||
|
||||
def get_all_cells(self):
|
||||
"""Return all cells defined
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Cell
|
||||
Cells in the geometry
|
||||
|
||||
"""
|
||||
|
||||
return self._root_universe.get_all_cells()
|
||||
|
||||
|
||||
def get_all_universes(self):
|
||||
"""Return all universes defined
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Universe
|
||||
Universes in the geometry
|
||||
|
||||
"""
|
||||
|
||||
return self._root_universe.get_all_universes()
|
||||
|
||||
|
||||
def get_all_nuclides(self):
|
||||
"""Return all nuclides assigned to a material in the geometry
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.nuclide.Nuclide
|
||||
Nuclides in the geometry
|
||||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
materials = self.get_all_materials()
|
||||
|
|
@ -93,8 +124,15 @@ class Geometry(object):
|
|||
|
||||
return nuclides
|
||||
|
||||
|
||||
def get_all_materials(self):
|
||||
"""Return all materials assigned to a cell
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.material.Material
|
||||
Materials in the geometry
|
||||
|
||||
"""
|
||||
|
||||
material_cells = self.get_all_material_cells()
|
||||
materials = set()
|
||||
|
|
@ -104,9 +142,7 @@ class Geometry(object):
|
|||
|
||||
return list(materials)
|
||||
|
||||
|
||||
def get_all_material_cells(self):
|
||||
|
||||
all_cells = self.get_all_cells()
|
||||
material_cells = set()
|
||||
|
||||
|
|
@ -116,16 +152,21 @@ class Geometry(object):
|
|||
|
||||
return list(material_cells)
|
||||
|
||||
|
||||
def get_all_material_universes(self):
|
||||
"""Return all universes composed of at least one non-fill cell
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Universe
|
||||
Universes with non-fill cells
|
||||
|
||||
"""
|
||||
|
||||
all_universes = self.get_all_universes()
|
||||
material_universes = set()
|
||||
|
||||
for universe_id, universe in all_universes.items():
|
||||
|
||||
cells = universe._cells
|
||||
|
||||
for cell_id, cell in cells.items():
|
||||
if cell._type == 'normal':
|
||||
material_universes.add(universe)
|
||||
|
|
@ -133,24 +174,28 @@ class Geometry(object):
|
|||
return list(material_universes)
|
||||
|
||||
|
||||
|
||||
class GeometryFile(object):
|
||||
"""Geometry file used for an OpenMC simulation. Corresponds directly to the
|
||||
geometry.xml input file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
geometry : Geometry
|
||||
The geometry to be used
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Initialize GeometryFile class attributes
|
||||
self._geometry = None
|
||||
self._geometry_file = ET.Element("geometry")
|
||||
|
||||
|
||||
@property
|
||||
def geometry(self):
|
||||
return self._geometry
|
||||
|
||||
|
||||
@geometry.setter
|
||||
def geometry(self, geometry):
|
||||
|
||||
if not isinstance(geometry, Geometry):
|
||||
msg = 'Unable to set the Geometry to {0} for the GeometryFile ' \
|
||||
'since it is not a Geometry object'.format(geometry)
|
||||
|
|
@ -158,8 +203,10 @@ class GeometryFile(object):
|
|||
|
||||
self._geometry = geometry
|
||||
|
||||
|
||||
def export_to_xml(self):
|
||||
"""Create a geometry.xml file that can be used for a simulation.
|
||||
|
||||
"""
|
||||
|
||||
root_universe = self._geometry._root_universe
|
||||
root_universe.create_xml_subelement(self._geometry_file)
|
||||
|
|
|
|||
|
|
@ -23,20 +23,34 @@ def reset_auto_material_id():
|
|||
# Units for density supported by OpenMC
|
||||
DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/cm3', 'at/b-cm', 'at/cm3', 'sum']
|
||||
|
||||
# ENDF temperatures
|
||||
ENDF_TEMPS = np.array([300, 600, 700, 900, 1200, 1500])
|
||||
|
||||
# ENDF ZAIDs
|
||||
ENDF_ZAIDS = np.array(['70c', '71c', '72c', '73c', '74c'])
|
||||
|
||||
# Constant for density when not needed
|
||||
NO_DENSITY = 99999.
|
||||
|
||||
|
||||
class Material(object):
|
||||
"""A material composed of a collection of nuclides/elements that can be assigned
|
||||
to a region of space.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
material_id : int
|
||||
Unique identifier for the material
|
||||
name : str
|
||||
Name of the material
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
Unique identifier for the material
|
||||
density : float
|
||||
Density of the material (units defined separately)
|
||||
density_units : str
|
||||
Units used for `density`. Can be one of 'g/cm3', 'g/cc', 'kg/cm3',
|
||||
'atom/b-cm', 'atom/cm3', or 'sum'.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, material_id=None, name=''):
|
||||
|
||||
# Initialize class attributes
|
||||
self.id = material_id
|
||||
self.name = name
|
||||
|
|
@ -62,40 +76,32 @@ class Material(object):
|
|||
# If specified, this file will be used instead of composition values
|
||||
self._distrib_otf_file = None
|
||||
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
|
||||
@property
|
||||
def density(self):
|
||||
return self._density
|
||||
|
||||
|
||||
@property
|
||||
def density_units(self):
|
||||
return self._density_units
|
||||
|
||||
|
||||
@property
|
||||
def convert_to_distrib_comps(self):
|
||||
return self._convert_to_distrib_comps
|
||||
|
||||
|
||||
@property
|
||||
def distrib_otf_file(self):
|
||||
return self._distrib_otf_file
|
||||
|
||||
|
||||
@id.setter
|
||||
def id(self, material_id):
|
||||
|
||||
global AUTO_MATERIAL_ID, MATERIAL_IDS
|
||||
|
||||
# If the Material already has an ID, remove it from global list
|
||||
|
|
@ -127,20 +133,26 @@ class Material(object):
|
|||
self._id = material_id
|
||||
MATERIAL_IDS.append(material_id)
|
||||
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
|
||||
if not is_string(name):
|
||||
msg = 'Unable to set name for Material ID={0} with a non-string ' \
|
||||
'value {1}'.format(self._id, name)
|
||||
raise ValueError(msg)
|
||||
|
||||
else:
|
||||
self._name = name
|
||||
|
||||
|
||||
def set_density(self, units, density=NO_DENSITY):
|
||||
"""Set the density of the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
units : str
|
||||
Physical units of density
|
||||
density : float, optional
|
||||
Value of the density
|
||||
|
||||
"""
|
||||
|
||||
if not is_float(density):
|
||||
msg = 'Unable to set the density for Material ID={0} to a ' \
|
||||
|
|
@ -161,10 +173,8 @@ class Material(object):
|
|||
self._density = density
|
||||
self._density_units = units
|
||||
|
||||
|
||||
@distrib_otf_file.setter
|
||||
def distrib_otf_file(self, filename):
|
||||
|
||||
# TODO: remove this when distributed materials are merged
|
||||
warnings.warn('This feature is not yet implemented in a release ' \
|
||||
'version of openmc')
|
||||
|
|
@ -176,10 +186,8 @@ class Material(object):
|
|||
|
||||
self._distrib_otf_file = filename
|
||||
|
||||
|
||||
@convert_to_distrib_comps.setter
|
||||
def convert_to_distrib_comps(self):
|
||||
|
||||
# TODO: remove this when distributed materials are merged
|
||||
warnings.warn('This feature is not yet implemented in a release ' \
|
||||
'version of openmc')
|
||||
|
|
@ -188,6 +196,18 @@ class Material(object):
|
|||
|
||||
|
||||
def add_nuclide(self, nuclide, percent, percent_type='ao'):
|
||||
"""Add a nuclide to the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nuclide : str or openmc.nuclide.Nuclide
|
||||
Nuclide to add
|
||||
percent : float
|
||||
Atom or weight percent
|
||||
percent_type : str
|
||||
'ao' for atom percent and 'wo' for weight percent
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(nuclide, (openmc.Nuclide, str)):
|
||||
msg = 'Unable to add a Nuclide to Material ID={0} with a ' \
|
||||
|
|
@ -215,6 +235,14 @@ class Material(object):
|
|||
|
||||
|
||||
def remove_nuclide(self, nuclide):
|
||||
"""Remove a nuclide from the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nuclide : openmc.nuclide.Nuclide
|
||||
Nuclide to remove
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(nuclide, openmc.Nuclide):
|
||||
msg = 'Unable to remove a Nuclide {0} in Material ID={1} ' \
|
||||
|
|
@ -225,8 +253,19 @@ class Material(object):
|
|||
if nuclide._name in self._nuclides:
|
||||
del self._nuclides[nuclide._name]
|
||||
|
||||
|
||||
def add_element(self, element, percent, percent_type='ao'):
|
||||
"""Add a natural element to the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
element : openmc.element.Element
|
||||
Element to add
|
||||
percent : float
|
||||
Atom or weight percent
|
||||
percent_type : str
|
||||
'ao' for atom percent and 'wo' for weight percent
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(element, openmc.Element):
|
||||
msg = 'Unable to add an Element to Material ID={0} with a ' \
|
||||
|
|
@ -250,6 +289,14 @@ class Material(object):
|
|||
|
||||
|
||||
def remove_element(self, element):
|
||||
"""Remove a natural element from the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
element : openmc.element.Element
|
||||
Element to remove
|
||||
|
||||
"""
|
||||
|
||||
# If the Material contains the Element, delete it
|
||||
if element._name in self._elements:
|
||||
|
|
@ -257,6 +304,16 @@ class Material(object):
|
|||
|
||||
|
||||
def add_s_alpha_beta(self, name, xs):
|
||||
r"""Add an :math:`S(\alpha,\beta)` table to the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of the :math:`S(\alpha,\beta)` table
|
||||
xs : str
|
||||
Cross section identifier, e.g. '71t'
|
||||
|
||||
"""
|
||||
|
||||
if not is_string(name):
|
||||
msg = 'Unable to add an S(a,b) table to Material ID={0} with a ' \
|
||||
|
|
@ -272,6 +329,15 @@ class Material(object):
|
|||
|
||||
|
||||
def get_all_nuclides(self):
|
||||
"""Returns all nuclides in the material
|
||||
|
||||
Returns
|
||||
-------
|
||||
nuclides : dict
|
||||
Dictionary whose keys are nuclide names and values are 2-tuples of
|
||||
(nuclide, density)
|
||||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
|
||||
|
|
@ -282,9 +348,7 @@ class Material(object):
|
|||
|
||||
return nuclides
|
||||
|
||||
|
||||
def _repr__(self):
|
||||
|
||||
string = 'Material\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
|
@ -316,9 +380,7 @@ class Material(object):
|
|||
|
||||
return string
|
||||
|
||||
|
||||
def get_nuclide_xml(self, nuclide, distrib=False):
|
||||
|
||||
def _get_nuclide_xml(self, nuclide, distrib=False):
|
||||
xml_element = ET.Element("nuclide")
|
||||
xml_element.set("name", nuclide[0]._name)
|
||||
|
||||
|
|
@ -333,9 +395,7 @@ class Material(object):
|
|||
|
||||
return xml_element
|
||||
|
||||
|
||||
def get_element_xml(self, element, distrib=False):
|
||||
|
||||
def _get_element_xml(self, element, distrib=False):
|
||||
xml_element = ET.Element("element")
|
||||
xml_element.set("name", str(element[0]._name))
|
||||
|
||||
|
|
@ -347,28 +407,31 @@ class Material(object):
|
|||
|
||||
return xml_element
|
||||
|
||||
|
||||
def get_nuclides_xml(self, nuclides, distrib=False):
|
||||
|
||||
def _get_nuclides_xml(self, nuclides, distrib=False):
|
||||
xml_elements = []
|
||||
|
||||
for nuclide in nuclides.values():
|
||||
xml_elements.append(self.get_nuclide_xml(nuclide, distrib))
|
||||
xml_elements.append(self._get_nuclide_xml(nuclide, distrib))
|
||||
|
||||
return xml_elements
|
||||
|
||||
|
||||
def get_elements_xml(self, elements, distrib=False):
|
||||
|
||||
def _get_elements_xml(self, elements, distrib=False):
|
||||
xml_elements = []
|
||||
|
||||
for element in elements.values():
|
||||
xml_elements.append(self.get_element_xml(element, distrib))
|
||||
xml_elements.append(self._get_element_xml(element, distrib))
|
||||
|
||||
return xml_elements
|
||||
|
||||
|
||||
def get_material_xml(self):
|
||||
"""Return XML representation of the material
|
||||
|
||||
Returns
|
||||
-------
|
||||
element : xml.etree.ElementTree.Element
|
||||
XML element containing material data
|
||||
|
||||
"""
|
||||
|
||||
# Create Material XML element
|
||||
element = ET.Element("material")
|
||||
|
|
@ -384,19 +447,17 @@ class Material(object):
|
|||
subelement.set("units", self._density_units)
|
||||
|
||||
if not self._convert_to_distrib_comps:
|
||||
|
||||
# Create nuclide XML subelements
|
||||
subelements = self.get_nuclides_xml(self._nuclides)
|
||||
subelements = self._get_nuclides_xml(self._nuclides)
|
||||
for subelement in subelements:
|
||||
element.append(subelement)
|
||||
|
||||
# Create element XML subelements
|
||||
subelements = self.get_elements_xml(self._elements)
|
||||
subelements = self._get_elements_xml(self._elements)
|
||||
for subelement in subelements:
|
||||
element.append(subelement)
|
||||
|
||||
else:
|
||||
|
||||
subelement = ET.SubElement(element, "compositions")
|
||||
|
||||
comps = []
|
||||
|
|
@ -409,29 +470,24 @@ class Material(object):
|
|||
raise ValueError(msg)
|
||||
comps.append(per)
|
||||
|
||||
|
||||
if self._distrib_otf_file is None:
|
||||
|
||||
# Create values and units subelements
|
||||
subsubelement = ET.SubElement(subelement, "values")
|
||||
subsubelement.text = ' '.join([str(c) for c in comps])
|
||||
subsubelement = ET.SubElement(subelement, "units")
|
||||
subsubelement.text = dist_per_type
|
||||
|
||||
else:
|
||||
|
||||
# Specify the materials file
|
||||
subsubelement = ET.SubElement(subelement, "otf_file_path")
|
||||
subsubelement.text = self._distrib_otf_file
|
||||
|
||||
|
||||
# Create nuclide XML subelements
|
||||
subelements = self.get_nuclides_xml(self._nuclides, distrib=True)
|
||||
for subelement_nuc in subelements:
|
||||
subelement.append(subelement_nuc)
|
||||
|
||||
# Create element XML subelements
|
||||
subelements = self.get_elements_xml(self._elements, distrib=True)
|
||||
subelements = self._get_elements_xml(self._elements, distrib=True)
|
||||
for subelement_ele in subelements:
|
||||
subelement.append(subelement_ele)
|
||||
|
||||
|
|
@ -445,31 +501,44 @@ class Material(object):
|
|||
|
||||
|
||||
class MaterialsFile(object):
|
||||
"""Materials file used for an OpenMC simulation. Corresponds directly to the
|
||||
materials.xml input file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
default_xs : str
|
||||
The default cross section identifier applied to a nuclide when none is
|
||||
specified
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Initialize MaterialsFile class attributes
|
||||
self._materials = []
|
||||
self._default_xs = None
|
||||
self._materials_file = ET.Element("materials")
|
||||
|
||||
|
||||
@property
|
||||
def default_xs(self):
|
||||
return self._default_xs
|
||||
|
||||
|
||||
@default_xs.setter
|
||||
def default_xs(self, xs):
|
||||
|
||||
if not is_string(xs):
|
||||
msg = 'Unable to set default xs to a non-string value'.format(xs)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._default_xs = xs
|
||||
|
||||
|
||||
def add_material(self, material):
|
||||
"""Add a material to the file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
material : Material
|
||||
Material to add
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(material, Material):
|
||||
msg = 'Unable to add a non-Material {0} to the ' \
|
||||
|
|
@ -480,6 +549,14 @@ class MaterialsFile(object):
|
|||
|
||||
|
||||
def add_materials(self, materials):
|
||||
"""Add multiple materials to the file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
materials : tuple or list of Material
|
||||
Materials to add
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(materials, (tuple, list, MappingView)):
|
||||
msg = 'Unable to create OpenMC materials.xml file from {0} which ' \
|
||||
|
|
@ -489,8 +566,15 @@ class MaterialsFile(object):
|
|||
for material in materials:
|
||||
self.add_material(material)
|
||||
|
||||
def remove_material(self, material):
|
||||
"""Remove a material from the file
|
||||
|
||||
def remove_materials(self, material):
|
||||
Parameters
|
||||
----------
|
||||
material : Material
|
||||
Material to remove
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(material, Material):
|
||||
msg = 'Unable to remove a non-Material {0} from the ' \
|
||||
|
|
@ -499,9 +583,7 @@ class MaterialsFile(object):
|
|||
|
||||
self._materials.remove(material)
|
||||
|
||||
|
||||
def create_material_subelements(self):
|
||||
|
||||
def _create_material_subelements(self):
|
||||
subelement = ET.SubElement(self._materials_file, "default_xs")
|
||||
|
||||
if not self._default_xs is None:
|
||||
|
|
@ -511,10 +593,12 @@ class MaterialsFile(object):
|
|||
xml_element = material.get_material_xml()
|
||||
self._materials_file.append(xml_element)
|
||||
|
||||
|
||||
def export_to_xml(self):
|
||||
"""Create a materials.xml file that can be used for a simulation.
|
||||
|
||||
self.create_material_subelements()
|
||||
"""
|
||||
|
||||
self._create_material_subelements()
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
sort_xml_elements(self._materials_file)
|
||||
|
|
|
|||
122
openmc/mesh.py
122
openmc/mesh.py
|
|
@ -14,9 +14,37 @@ def reset_auto_mesh_id():
|
|||
|
||||
|
||||
class Mesh(object):
|
||||
"""A structured Cartesian mesh in two or three dimensions
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_id : int
|
||||
Unique identifier for the mesh
|
||||
name : str
|
||||
Name of the mesh
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
Unique identifier for the mesh
|
||||
name : str
|
||||
Name of the mesh
|
||||
type : str
|
||||
Type of the mesh
|
||||
dimension : tuple or list or ndarray
|
||||
The number of mesh cells in each direction.
|
||||
lower_left : tuple or list or ndarray
|
||||
The lower-left corner of the structured mesh. If only two coordinate are
|
||||
given, it is assumed that the mesh is an x-y mesh.
|
||||
upper_right : tuple or list or ndarray
|
||||
The upper-right corner of the structrued mesh. If only two coordinate
|
||||
are given, it is assumed that the mesh is an x-y mesh.
|
||||
width : tuple or list or ndarray
|
||||
The width of mesh cells in each direction.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, mesh_id=None, name=''):
|
||||
|
||||
# Initialize Mesh class attributes
|
||||
self.id = mesh_id
|
||||
self.name = name
|
||||
|
|
@ -26,9 +54,7 @@ class Mesh(object):
|
|||
self._upper_right = None
|
||||
self._width = None
|
||||
|
||||
|
||||
def __eq__(self, mesh2):
|
||||
|
||||
# Check type
|
||||
if self._type != mesh2._type:
|
||||
return False
|
||||
|
|
@ -49,14 +75,11 @@ class Mesh(object):
|
|||
else:
|
||||
return True
|
||||
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, create a copy
|
||||
if existing is None:
|
||||
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._id = self._id
|
||||
clone._name = self._name
|
||||
|
|
@ -74,50 +97,40 @@ class Mesh(object):
|
|||
else:
|
||||
return existing
|
||||
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
|
||||
@property
|
||||
def dimension(self):
|
||||
return self._dimension
|
||||
|
||||
|
||||
@property
|
||||
def lower_left(self):
|
||||
return self._lower_left
|
||||
|
||||
|
||||
@property
|
||||
def upper_right(self):
|
||||
return self._upper_right
|
||||
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
return self._width
|
||||
|
||||
|
||||
@property
|
||||
def num_mesh_cells(self):
|
||||
return np.prod(self._dimension)
|
||||
|
||||
|
||||
@id.setter
|
||||
def id(self, mesh_id):
|
||||
|
||||
if mesh_id is None:
|
||||
global AUTO_MESH_ID
|
||||
self._id = AUTO_MESH_ID
|
||||
|
|
@ -136,27 +149,21 @@ class Mesh(object):
|
|||
else:
|
||||
self._id = mesh_id
|
||||
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
|
||||
if not is_string(name):
|
||||
msg = 'Unable to set name for Mesh ID={0} with a non-string ' \
|
||||
'value {1}'.format(self._id, name)
|
||||
raise ValueError(msg)
|
||||
|
||||
else:
|
||||
self._name = name
|
||||
|
||||
|
||||
@type.setter
|
||||
def type(self, type):
|
||||
|
||||
if not is_string(type):
|
||||
msg = 'Unable to set Mesh ID={0} for type {1} which is not ' \
|
||||
'a string'.format(self._id, type)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif not type in ['rectangular', 'hexagonal']:
|
||||
msg = 'Unable to set Mesh ID={0} for type {1} which since ' \
|
||||
'only rectangular and hexagonal meshes are ' \
|
||||
|
|
@ -165,23 +172,19 @@ class Mesh(object):
|
|||
|
||||
self._type = type
|
||||
|
||||
|
||||
@dimension.setter
|
||||
def dimension(self, dimension):
|
||||
|
||||
if not isinstance(dimension, (tuple, list, np.ndarray)):
|
||||
msg = 'Unable to set Mesh ID={0} with dimension {1} which is ' \
|
||||
'not a Python list, tuple or NumPy ' \
|
||||
'array'.format(self._id, dimension)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif len(dimension) != 2 and len(dimension) != 3:
|
||||
msg = 'Unable to set Mesh ID={0} with dimension {1} since it ' \
|
||||
'must include 2 or 3 dimensions'.format(self._id, dimension)
|
||||
raise ValueError(msg)
|
||||
|
||||
for dim in dimension:
|
||||
|
||||
if not is_integer(dim):
|
||||
msg = 'Unable to set Mesh ID={0} with dimension {1} which ' \
|
||||
'is a non-integer'.format(self._id, dim)
|
||||
|
|
@ -189,10 +192,8 @@ class Mesh(object):
|
|||
|
||||
self._dimension = dimension
|
||||
|
||||
|
||||
@lower_left.setter
|
||||
def lower_left(self, lower_left):
|
||||
|
||||
if not isinstance(lower_left, (tuple, list, np.ndarray)):
|
||||
msg = 'Unable to set Mesh ID={0} with lower_left {1} which is ' \
|
||||
'not a Python list, tuple or NumPy ' \
|
||||
|
|
@ -205,7 +206,6 @@ class Mesh(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
for coord in lower_left:
|
||||
|
||||
if not is_integer(coord) and not is_float(coord):
|
||||
msg = 'Unable to set Mesh ID={0} with lower_left {1} which ' \
|
||||
'is neither neither an integer nor a floating point ' \
|
||||
|
|
@ -214,10 +214,8 @@ class Mesh(object):
|
|||
|
||||
self._lower_left = lower_left
|
||||
|
||||
|
||||
@upper_right.setter
|
||||
def upper_right(self, upper_right):
|
||||
|
||||
if not isinstance(upper_right, (tuple, list, np.ndarray)):
|
||||
msg = 'Unable to set Mesh ID={0} with upper_right {1} which ' \
|
||||
'is not a Python list, tuple or NumPy ' \
|
||||
|
|
@ -230,7 +228,6 @@ class Mesh(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
for coord in upper_right:
|
||||
|
||||
if not is_integer(coord) and not is_float(coord):
|
||||
msg = 'Unable to set Mesh ID={0} with upper_right {1} which ' \
|
||||
'is neither an integer nor a floating point ' \
|
||||
|
|
@ -239,12 +236,9 @@ class Mesh(object):
|
|||
|
||||
self._upper_right = upper_right
|
||||
|
||||
|
||||
@width.setter
|
||||
def width(self, width):
|
||||
|
||||
if not width is None:
|
||||
|
||||
if not isinstance(width, (tuple, list, np.ndarray)):
|
||||
msg = 'Unable to set Mesh ID={0} with width {1} which ' \
|
||||
'is not a Python list, tuple or NumPy ' \
|
||||
|
|
@ -257,7 +251,6 @@ class Mesh(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
for dim in width:
|
||||
|
||||
if not is_integer(dim) and not is_float(dim):
|
||||
msg = 'Unable to set Mesh ID={0} with width {1} which is ' \
|
||||
'neither an integer nor a floating point ' \
|
||||
|
|
@ -266,9 +259,7 @@ class Mesh(object):
|
|||
|
||||
self._width = width
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = 'Mesh\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
|
@ -279,53 +270,32 @@ class Mesh(object):
|
|||
string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._width)
|
||||
return string
|
||||
|
||||
|
||||
def get_mesh_xml(self):
|
||||
"""Return XML representation of the mesh
|
||||
|
||||
Returns
|
||||
-------
|
||||
element : xml.etree.ElementTree.Element
|
||||
XML element containing mesh data
|
||||
|
||||
"""
|
||||
|
||||
element = ET.Element("mesh")
|
||||
element.set("id", str(self._id))
|
||||
element.set("type", self._type)
|
||||
|
||||
if len(self._dimension) == 2:
|
||||
subelement = ET.SubElement(element, "dimension")
|
||||
subelement.text = '{0} {1}'.format(self._dimension[0],
|
||||
self._dimension[1])
|
||||
else:
|
||||
subelement = ET.SubElement(element, "dimension")
|
||||
subelement.text = '{0} {1} {2}'.format(self._dimension[0],
|
||||
self._dimension[1],
|
||||
self._dimension[2])
|
||||
subelement = ET.SubElement(element, "dimension")
|
||||
subelement.text = ' '.join(map(str, self._dimension))
|
||||
|
||||
if len(self._lower_left) == 2:
|
||||
subelement = ET.SubElement(element, "lower_left")
|
||||
subelement.text = '{0} {1}'.format(self._lower_left[0],
|
||||
self._lower_left[1])
|
||||
else:
|
||||
subelement = ET.SubElement(element, "lower_left")
|
||||
subelement.text = '{0} {1} {2}'.format(self._lower_left[0],
|
||||
self._lower_left[1],
|
||||
self._lower_left[2])
|
||||
subelement = ET.SubElement(element, "lower_left")
|
||||
subelement.text = ' '.join(map(str, self._lower_left))
|
||||
|
||||
if not self._upper_right is None:
|
||||
if len(self._upper_right) == 2:
|
||||
subelement = ET.SubElement(element, "upper_right")
|
||||
subelement.text = '{0} {1}'.format(self._upper_right[0],
|
||||
self._upper_right[1])
|
||||
else:
|
||||
subelement = ET.SubElement(element, "upper_right")
|
||||
subelement.text = '{0} {1} {2}'.format(self._upper_right[0],
|
||||
self._upper_right[1],
|
||||
self._upper_right[2])
|
||||
subelement = ET.SubElement(element, "upper_right")
|
||||
subelement.text = ' '.join(map(str, self._upper_right))
|
||||
|
||||
if not self._width is None:
|
||||
if len(self._width) == 2:
|
||||
subelement = ET.SubElement(element, "width")
|
||||
subelement.text = '{0} {1}'.format(self._width[0],
|
||||
self._width[1])
|
||||
else:
|
||||
subelement = ET.SubElement(element, "width")
|
||||
subelement.text = '{0} {1} {2}'.format(self._width[0],
|
||||
self._width[1],
|
||||
self._width[2])
|
||||
subelement = ET.SubElement(element, "width")
|
||||
subelement.text = ' '.join(map(str, self._width))
|
||||
|
||||
return element
|
||||
return element
|
||||
|
|
|
|||
|
|
@ -2,9 +2,28 @@ from openmc.checkvalue import *
|
|||
|
||||
|
||||
class Nuclide(object):
|
||||
"""A nuclide that can be used in a material.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of the nuclide, e.g. U-235
|
||||
xs : str
|
||||
Cross section identifier, e.g. 71c
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str
|
||||
Name of the nuclide, e.g. U-235
|
||||
xs : str
|
||||
Cross section identifier, e.g. 71c
|
||||
zaid : int
|
||||
1000*(atomic number) + mass number. As an example, the zaid of U-235
|
||||
would be 92235.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name='', xs=None):
|
||||
|
||||
# Initialize class attributes
|
||||
self._name = ''
|
||||
self._xs = None
|
||||
|
|
@ -16,9 +35,7 @@ class Nuclide(object):
|
|||
if not xs is None:
|
||||
self.xs = xs
|
||||
|
||||
|
||||
def __eq__(self, nuclide2):
|
||||
|
||||
# Check type
|
||||
if not isinstance(nuclide2, Nuclide):
|
||||
return False
|
||||
|
|
@ -34,29 +51,23 @@ class Nuclide(object):
|
|||
else:
|
||||
return True
|
||||
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._name, self._xs))
|
||||
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
|
||||
@property
|
||||
def xs(self):
|
||||
return self._xs
|
||||
|
||||
|
||||
@property
|
||||
def zaid(self):
|
||||
return self._zaid
|
||||
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
|
||||
if not is_string(name):
|
||||
msg = 'Unable to set name for Nuclide with a non-string ' \
|
||||
'value {0}'.format(name)
|
||||
|
|
@ -64,10 +75,8 @@ class Nuclide(object):
|
|||
|
||||
self._name = name
|
||||
|
||||
|
||||
@xs.setter
|
||||
def xs(self, xs):
|
||||
|
||||
if not is_string(xs):
|
||||
msg = 'Unable to set cross-section identifier xs for Nuclide ' \
|
||||
'with a non-string value {0}'.format(xs)
|
||||
|
|
@ -75,10 +84,8 @@ class Nuclide(object):
|
|||
|
||||
self._xs = xs
|
||||
|
||||
|
||||
@zaid.setter
|
||||
def zaid(self, zaid):
|
||||
|
||||
if not is_integer(zaid):
|
||||
msg = 'Unable to set zaid for Nuclide ' \
|
||||
'with a non-integer {0}'.format(zaid)
|
||||
|
|
@ -86,11 +93,9 @@ class Nuclide(object):
|
|||
|
||||
self._zaid = zaid
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = 'Nuclide - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
if self._zaid is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self._zaid)
|
||||
return string
|
||||
return string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue