Refactored Trigger, Mesh and Filter classes into new Python API files

This commit is contained in:
Will Boyd 2015-05-11 17:00:23 -04:00
parent 2fa7b44175
commit da83d8bb5c
5 changed files with 695 additions and 679 deletions

View file

@ -6,10 +6,12 @@ from openmc.plots import *
from openmc.settings import *
from openmc.surface import *
from openmc.universe import *
from openmc.mesh import *
from openmc.filter import *
from openmc.trigger import *
from openmc.tallies import *
from openmc.cmfd import *
from openmc.executor import *
#from statepoint import *
try:
from openmc.opencg_compatible import *

267
src/utils/openmc/filter.py Normal file
View file

@ -0,0 +1,267 @@
import copy
from openmc import Mesh
from openmc.checkvalue import *
from openmc.constants import *
class Filter(object):
# Initialize Filter class attributes
def __init__(self, type=None, bins=None):
self.type = type
self.bins = bins
self._mesh = None
self._offset = -1
self._stride = None
def __eq__(self, filter2):
# Check type
if self._type != filter2._type:
return False
# Check number of bins
elif len(self._bins) != len(filter2._bins):
return False
# Check bin edges
elif not np.allclose(self._bins, filter2._bins):
return False
else:
return True
def __hash__(self):
hashable = []
hashable.append(self._type)
hashable.append(self._bins)
return hash(tuple(hashable))
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)
clone._num_bins = self._num_bins
clone._mesh = copy.deepcopy(self._mesh, memo)
clone._offset = self._offset
clone._stride = self._stride
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
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)
raise ValueError(msg)
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)
raise ValueError(msg)
# If the bin edge is a single value, it is a Cell, Material, etc. ID
if not isinstance(bins, (tuple, list, np.ndarray)):
bins = [bins]
# If the bins are in a collection, convert it to a list
else:
bins = list(bins)
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 {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 {1} Filter since it ' \
'is a negative value'.format(edge, self._type)
raise ValueError(msg)
# 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 {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])
raise ValueError(msg)
# 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 ' \
'integer'.format(num_bins, self._type)
raise ValueError(msg)
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)
raise ValueError(msg)
self._mesh = mesh
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)
raise ValueError(msg)
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)
raise ValueError(msg)
if stride < 0:
msg = 'Unable to set stride {0} for a {1} Filter since it is a ' \
'negative value'.format(stride, self._type)
raise ValueError(msg)
self._stride = stride
def get_bin_index(self, bin):
try:
index = self._bins.index(bin)
except ValueError:
msg = 'Unable to get the bin index for Filter since {0} ' \
'is not one of the bins'.format(bin)
raise ValueError(msg)
return 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)
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offset)
return string

308
src/utils/openmc/mesh.py Normal file
View file

@ -0,0 +1,308 @@
import copy
from xml.etree import ElementTree as ET
from openmc.checkvalue import *
# "Static" variable for auto-generated and Mesh IDs
AUTO_MESH_ID = 10000
def reset_auto_mesh_id():
global AUTO_MESH_ID
AUTO_MESH_ID = 10000
class Mesh(object):
def __init__(self, mesh_id=None, name=''):
# Initialize Mesh class attributes
self.id = mesh_id
self.name = name
self._type = 'rectangular'
self._dimension = None
self._lower_left = None
self._upper_right = None
self._width = None
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
clone._type = self._type
clone._dimension = copy.deepcopy(self._dimension, memo)
clone._lower_left = copy.deepcopy(self._lower_left, memo)
clone._upper_right = copy.deepcopy(self._upper_right, memo)
clone._width = copy.deepcopy(self._width, memo)
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
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
AUTO_MESH_ID += 1
# Check that the ID is an integer and wasn't already used
elif not is_integer(mesh_id):
msg = 'Unable to set a non-integer Mesh ID {0}'.format(mesh_id)
raise ValueError(msg)
elif mesh_id < 0:
msg = 'Unable to set Mesh ID to {0} since it must be a ' \
'non-negative integer'.format(mesh_id)
raise ValueError(msg)
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 ' \
'supported '.format(self._id, type)
raise ValueError(msg)
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)
raise ValueError(msg)
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 ' \
'array'.format(self._id, lower_left)
raise ValueError(msg)
elif len(lower_left) != 2 and len(lower_left) != 3:
msg = 'Unable to set Mesh ID={0} with lower_left {1} since it ' \
'must include 2 or 3 dimensions'.format(self._id, lower_left)
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 ' \
'value'.format(self._id, coord)
raise ValueError(msg)
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 ' \
'array'.format(self._id, upper_right)
raise ValueError(msg)
if len(upper_right) != 2 and len(upper_right) != 3:
msg = 'Unable to set Mesh ID={0} with upper_right {1} since it ' \
'must include 2 or 3 dimensions'.format(self._id, upper_right)
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 ' \
'value'.format(self._id, coord)
raise ValueError(msg)
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 ' \
'array'.format(self._id, width)
raise ValueError(msg)
if len(width) != 2 and len(width) != 3:
msg = 'Unable to set Mesh ID={0} with width {1} since it must ' \
'include 2 or 3 dimensions'.format(self._id, width)
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 ' \
'value'.format(self._id, width)
raise ValueError(msg)
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)
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
string += '{0: <16}{1}{2}\n'.format('\tBasis', '=\t', self._dimension)
string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._lower_left)
string += '{0: <16}{1}{2}\n'.format('\tOrigin', '=\t', self._upper_right)
string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._width)
return string
def get_mesh_xml(self):
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])
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])
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])
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])
return element

View file

@ -2,15 +2,13 @@ import copy
import os
from xml.etree import ElementTree as ET
from openmc import Nuclide
from openmc import Mesh, Filter, Trigger, Nuclide
from openmc.clean_xml import *
from openmc.checkvalue import *
from openmc.constants import *
# "Static" variables for auto-generated Tally and Mesh IDs
# "Static" variable for auto-generated Tally IDs
AUTO_TALLY_ID = 10000
AUTO_MESH_ID = 10000
def reset_auto_tally_id():
@ -18,680 +16,6 @@ def reset_auto_tally_id():
AUTO_TALLY_ID = 10000
def reset_auto_mesh_id():
global AUTO_MESH_ID
AUTO_MESH_ID = 10000
class Filter(object):
# Initialize Filter class attributes
def __init__(self, type=None, bins=None):
self.type = type
self.bins = bins
self._mesh = None
self._offset = -1
self._stride = None
def __eq__(self, filter2):
# Check type
if self._type != filter2._type:
return False
# Check number of bins
elif len(self._bins) != len(filter2._bins):
return False
# Check bin edges
elif not np.allclose(self._bins, filter2._bins):
return False
else:
return True
def __hash__(self):
hashable = []
hashable.append(self._type)
hashable.append(self._bins)
return hash(tuple(hashable))
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)
clone._num_bins = self._num_bins
clone._mesh = copy.deepcopy(self._mesh, memo)
clone._offset = self._offset
clone._stride = self._stride
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
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)
raise ValueError(msg)
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)
raise ValueError(msg)
# If the bin edge is a single value, it is a Cell, Material, etc. ID
if not isinstance(bins, (tuple, list, np.ndarray)):
bins = [bins]
# If the bins are in a collection, convert it to a list
else:
bins = list(bins)
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 {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 {1} Filter since it ' \
'is a negative value'.format(edge, self._type)
raise ValueError(msg)
# 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 {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])
raise ValueError(msg)
# 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 ' \
'integer'.format(num_bins, self._type)
raise ValueError(msg)
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)
raise ValueError(msg)
self._mesh = mesh
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)
raise ValueError(msg)
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)
raise ValueError(msg)
if stride < 0:
msg = 'Unable to set stride {0} for a {1} Filter since it is a ' \
'negative value'.format(stride, self._type)
raise ValueError(msg)
self._stride = stride
def get_bin_index(self, bin):
try:
index = self._bins.index(bin)
except ValueError:
msg = 'Unable to get the bin index for Filter since {0} ' \
'is not one of the bins'.format(bin)
raise ValueError(msg)
return 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)
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offset)
return string
class Mesh(object):
def __init__(self, mesh_id=None, name=''):
# Initialize Mesh class attributes
self.id = mesh_id
self.name = name
self._type = 'rectangular'
self._dimension = None
self._lower_left = None
self._upper_right = None
self._width = None
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
clone._type = self._type
clone._dimension = copy.deepcopy(self._dimension, memo)
clone._lower_left = copy.deepcopy(self._lower_left, memo)
clone._upper_right = copy.deepcopy(self._upper_right, memo)
clone._width = copy.deepcopy(self._width, memo)
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
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
AUTO_MESH_ID += 1
# Check that the ID is an integer and wasn't already used
elif not is_integer(mesh_id):
msg = 'Unable to set a non-integer Mesh ID {0}'.format(mesh_id)
raise ValueError(msg)
elif mesh_id < 0:
msg = 'Unable to set Mesh ID to {0} since it must be a ' \
'non-negative integer'.format(mesh_id)
raise ValueError(msg)
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 ' \
'supported '.format(self._id, type)
raise ValueError(msg)
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)
raise ValueError(msg)
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 ' \
'array'.format(self._id, lower_left)
raise ValueError(msg)
elif len(lower_left) != 2 and len(lower_left) != 3:
msg = 'Unable to set Mesh ID={0} with lower_left {1} since it ' \
'must include 2 or 3 dimensions'.format(self._id, lower_left)
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 ' \
'value'.format(self._id, coord)
raise ValueError(msg)
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 ' \
'array'.format(self._id, upper_right)
raise ValueError(msg)
if len(upper_right) != 2 and len(upper_right) != 3:
msg = 'Unable to set Mesh ID={0} with upper_right {1} since it ' \
'must include 2 or 3 dimensions'.format(self._id, upper_right)
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 ' \
'value'.format(self._id, coord)
raise ValueError(msg)
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 ' \
'array'.format(self._id, width)
raise ValueError(msg)
if len(width) != 2 and len(width) != 3:
msg = 'Unable to set Mesh ID={0} with width {1} since it must ' \
'include 2 or 3 dimensions'.format(self._id, width)
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 ' \
'value'.format(self._id, width)
raise ValueError(msg)
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)
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
string += '{0: <16}{1}{2}\n'.format('\tBasis', '=\t', self._dimension)
string += '{0: <16}{1}{2}\n'.format('\tWidth', '=\t', self._lower_left)
string += '{0: <16}{1}{2}\n'.format('\tOrigin', '=\t', self._upper_right)
string += '{0: <16}{1}{2}\n'.format('\tPixels', '=\t', self._width)
return string
def get_mesh_xml(self):
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])
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])
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])
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])
return element
class Trigger(object):
def __init__(self, trigger_type, threshold):
# Initialize Mesh class attributes
self.trigger_type = trigger_type
self.threshold = threshold
self._scores = []
def __deepcopy__(self, memo):
existing = memo.get(id(self))
# If this is first time we have tried to copy this object, create a copy
if existing is None:
clone = type(self).__new__(type(self))
clone._trigger_type = self._trigger_type
clone._threshold = self._threshold
clone._scores = []
for score in self._scores:
clone.add_score(score)
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
else:
return existing
@property
def trigger_type(self):
return self._trigger_type
@property
def threshold(self):
return self._threshold
@property
def scores(self):
return self._scores
@trigger_type.setter
def trigger_type(self, trigger_type):
if not trigger_type in ['variance', 'std_dev', 'rel_err']:
msg = 'Unable to create a tally trigger with ' \
'type {0}'.format(trigger_type)
raise ValueError(msg)
self._trigger_type = trigger_type
@threshold.setter
def threshold(self, threshold):
if not is_float(threshold):
msg = 'Unable to set a tally trigger threshold with ' \
'threshold {0}'.format(threshold)
raise ValueError(msg)
self._threshold = threshold
def add_score(self, score):
if not is_string(score):
msg = 'Unable to add score {0} to tally trigger since ' \
'it is not a string'.format(score)
raise ValueError(msg)
# If the score is already in the Tally, don't add it again
if score in self._scores:
return
else:
self._scores.append(score)
def __repr__(self):
string = 'Trigger\n'
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
return string
def get_trigger_xml(self, element):
subelement = ET.SubElement(element, "trigger")
subelement.set("type", self._trigger_type)
subelement.set("threshold", str(self._threshold))
# Scores
if len(self._scores) != 0:
scores = ''
for score in self._scores:
scores += '{0} '.format(score)
scores.rstrip(' ')
subelement.set("scores", scores)
class Tally(object):
def __init__(self, tally_id=None, name=''):

115
src/utils/openmc/trigger.py Normal file
View file

@ -0,0 +1,115 @@
from xml.etree import ElementTree as ET
from openmc.checkvalue import *
class Trigger(object):
def __init__(self, trigger_type, threshold):
# Initialize Mesh class attributes
self.trigger_type = trigger_type
self.threshold = threshold
self._scores = []
def __deepcopy__(self, memo):
existing = memo.get(id(self))
# If this is first time we have tried to copy this object, create a copy
if existing is None:
clone = type(self).__new__(type(self))
clone._trigger_type = self._trigger_type
clone._threshold = self._threshold
clone._scores = []
for score in self._scores:
clone.add_score(score)
memo[id(self)] = clone
return clone
# If this object has been copied before, return the first copy made
else:
return existing
@property
def trigger_type(self):
return self._trigger_type
@property
def threshold(self):
return self._threshold
@property
def scores(self):
return self._scores
@trigger_type.setter
def trigger_type(self, trigger_type):
if not trigger_type in ['variance', 'std_dev', 'rel_err']:
msg = 'Unable to create a tally trigger with ' \
'type {0}'.format(trigger_type)
raise ValueError(msg)
self._trigger_type = trigger_type
@threshold.setter
def threshold(self, threshold):
if not is_float(threshold):
msg = 'Unable to set a tally trigger threshold with ' \
'threshold {0}'.format(threshold)
raise ValueError(msg)
self._threshold = threshold
def add_score(self, score):
if not is_string(score):
msg = 'Unable to add score {0} to tally trigger since ' \
'it is not a string'.format(score)
raise ValueError(msg)
# If the score is already in the Tally, don't add it again
if score in self._scores:
return
else:
self._scores.append(score)
def __repr__(self):
string = 'Trigger\n'
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
return string
def get_trigger_xml(self, element):
subelement = ET.SubElement(element, "trigger")
subelement.set("type", self._trigger_type)
subelement.set("threshold", str(self._threshold))
# Scores
if len(self._scores) != 0:
scores = ''
for score in self._scores:
scores += '{0} '.format(score)
scores.rstrip(' ')
subelement.set("scores", scores)
__author__ = 'wboyd'