Merge pull request #1231 from amandalund/settings_from_xml

Add Settings.from_xml method
This commit is contained in:
Paul Romano 2019-05-23 07:34:19 -05:00 committed by GitHub
commit e252ff8e21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 821 additions and 37 deletions

View file

@ -7,6 +7,7 @@ import numpy as np
import openmc.checkvalue as cv
import openmc
from openmc._xml import get_text
from openmc.mixin import EqualityMixin, IDManagerMixin
@ -230,8 +231,9 @@ class Mesh(IDManagerMixin):
element.set("id", str(self._id))
element.set("type", self._type)
subelement = ET.SubElement(element, "dimension")
subelement.text = ' '.join(map(str, self._dimension))
if self._dimension is not None:
subelement = ET.SubElement(element, "dimension")
subelement.text = ' '.join(map(str, self._dimension))
subelement = ET.SubElement(element, "lower_left")
subelement.text = ' '.join(map(str, self._lower_left))
@ -246,6 +248,46 @@ class Mesh(IDManagerMixin):
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate mesh from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.Mesh
Mesh generated from XML element
"""
mesh_id = int(get_text(elem, 'id'))
mesh = cls(mesh_id)
mesh_type = get_text(elem, 'type')
if mesh_type is not None:
mesh.type = mesh_type
dimension = get_text(elem, 'dimension')
if dimension is not None:
mesh.dimension = [int(x) for x in dimension.split()]
lower_left = get_text(elem, 'lower_left')
if lower_left is not None:
mesh.lower_left = [float(x) for x in lower_left.split()]
upper_right = get_text(elem, 'upper_right')
if upper_right is not None:
mesh.upper_right = [float(x) for x in upper_right.split()]
width = get_text(elem, 'width')
if width is not None:
mesh.width = [float(x) for x in width.split()]
return mesh
def build_cells(self, bc=['reflective'] * 6):
"""Generates a lattice of universes with the same dimensionality
as the mesh object. The individual cells/universes produced

View file

@ -7,7 +7,7 @@ import sys
import numpy as np
from openmc._xml import clean_indentation
from openmc._xml import clean_indentation, get_text
import openmc.checkvalue as cv
from openmc import VolumeCalculation, Source, Mesh
@ -174,7 +174,6 @@ class Settings(object):
self._source = cv.CheckedList(Source, 'source distributions')
self._confidence_intervals = None
self._cross_sections = None
self._electron_treatment = None
self._photon_transport = None
self._ptables = None
@ -552,7 +551,8 @@ class Settings(object):
@entropy_mesh.setter
def entropy_mesh(self, entropy):
cv.check_type('entropy mesh', entropy, Mesh)
cv.check_length('entropy mesh dimension', entropy.dimension, 3)
if entropy.dimension:
cv.check_length('entropy mesh dimension', entropy.dimension, 3)
cv.check_length('entropy mesh lower-left corner', entropy.lower_left, 3)
cv.check_length('entropy mesh upper-right corner', entropy.upper_right, 3)
self._entropy_mesh = entropy
@ -693,29 +693,29 @@ class Settings(object):
elem = ET.SubElement(root, "run_mode")
elem.text = self._run_mode
def _create_batches_subelement(self, run_mode_element):
def _create_batches_subelement(self, root):
if self._batches is not None:
element = ET.SubElement(run_mode_element, "batches")
element = ET.SubElement(root, "batches")
element.text = str(self._batches)
def _create_generations_per_batch_subelement(self, run_mode_element):
def _create_generations_per_batch_subelement(self, root):
if self._generations_per_batch is not None:
element = ET.SubElement(run_mode_element, "generations_per_batch")
element = ET.SubElement(root, "generations_per_batch")
element.text = str(self._generations_per_batch)
def _create_inactive_subelement(self, run_mode_element):
def _create_inactive_subelement(self, root):
if self._inactive is not None:
element = ET.SubElement(run_mode_element, "inactive")
element = ET.SubElement(root, "inactive")
element.text = str(self._inactive)
def _create_particles_subelement(self, run_mode_element):
def _create_particles_subelement(self, root):
if self._particles is not None:
element = ET.SubElement(run_mode_element, "particles")
element = ET.SubElement(root, "particles")
element.text = str(self._particles)
def _create_keff_trigger_subelement(self, run_mode_element):
def _create_keff_trigger_subelement(self, root):
if self._keff_trigger is not None:
element = ET.SubElement(run_mode_element, "keff_trigger")
element = ET.SubElement(root, "keff_trigger")
for key in self._keff_trigger:
subelement = ET.SubElement(element, key)
@ -927,6 +927,237 @@ class Settings(object):
elem = ET.SubElement(root, "dagmc")
elem.text = str(self._dagmc).lower()
def _eigenvalue_from_xml_element(self, root):
elem = root.find('eigenvalue')
if elem is not None:
self._run_mode_from_xml_element(elem)
self._particles_from_xml_element(elem)
self._batches_from_xml_element(elem)
self._inactive_from_xml_element(elem)
self._generations_per_batch_from_xml_element(elem)
def _run_mode_from_xml_element(self, root):
text = get_text(root, 'run_mode')
if text is not None:
self.run_mode = text
def _particles_from_xml_element(self, root):
text = get_text(root, 'particles')
if text is not None:
self.particles = int(text)
def _batches_from_xml_element(self, root):
text = get_text(root, 'batches')
if text is not None:
self.batches = int(text)
def _inactive_from_xml_element(self, root):
text = get_text(root, 'inactive')
if text is not None:
self.inactive = int(text)
def _generations_per_batch_from_xml_element(self, root):
text = get_text(root, 'generations_per_batch')
if text is not None:
self.generations_per_batch = int(text)
def _keff_trigger_from_xml_element(self, root):
elem = root.find('keff_trigger')
if elem is not None:
trigger = get_text(elem, 'type')
threshold = float(get_text(elem, 'threshold'))
self.keff_trigger = {'type': trigger, 'threshold': threshold}
def _source_from_xml_element(self, root):
for elem in root.findall('source'):
self.source.append(Source.from_xml_element(elem))
def _output_from_xml_element(self, root):
elem = root.find('output')
if elem is not None:
self.output = {}
for key in ('summary', 'tallies', 'path'):
value = get_text(elem, key)
if value is not None:
if key in ('summary', 'tallies'):
value = value in ('true', '1')
self.output[key] = value
def _statepoint_from_xml_element(self, root):
elem = root.find('state_point')
if elem is not None:
text = get_text(elem, 'batches')
if text is not None:
self.statepoint['batches'] = [int(x) for x in text.split()]
def _sourcepoint_from_xml_element(self, root):
elem = root.find('source_point')
if elem is not None:
for key in ('separate', 'write', 'overwrite_latest', 'batches'):
value = get_text(elem, key)
if value is not None:
if key in ('separate', 'write'):
value = value in ('true', '1')
elif key == 'overwrite_latest':
value = value in ('true', '1')
key = 'overwrite'
else:
value = [int(x) for x in value.split()]
self.sourcepoint[key] = value
def _confidence_intervals_from_xml_element(self, root):
text = get_text(root, 'confidence_intervals')
if text is not None:
self.confidence_intervals = text in ('true', '1')
def _electron_treatment_from_xml_element(self, root):
text = get_text(root, 'electron_treatment')
if text is not None:
self.electron_treatment = text
def _energy_mode_from_xml_element(self, root):
text = get_text(root, 'energy_mode')
if text is not None:
self.energy_mode = text
def _max_order_from_xml_element(self, root):
text = get_text(root, 'max_order')
if text is not None:
self.max_order = int(text)
def _photon_transport_from_xml_element(self, root):
text = get_text(root, 'photon_transport')
if text is not None:
self.photon_transport = text in ('true', '1')
def _ptables_from_xml_element(self, root):
text = get_text(root, 'ptables')
if text is not None:
self.ptables = text in ('true', '1')
def _seed_from_xml_element(self, root):
text = get_text(root, 'seed')
if text is not None:
self.seed = int(text)
def _survival_biasing_from_xml_element(self, root):
text = get_text(root, 'survival_biasing')
if text is not None:
self.survival_biasing = text in ('true', '1')
def _cutoff_from_xml_element(self, root):
elem = root.find('cutoff')
if elem is not None:
self.cutoff = {}
for key in ('energy_neutron', 'energy_photon', 'energy_electron',
'energy_positron', 'weight', 'weight_avg'):
value = get_text(elem, key)
if value is not None:
self.cutoff[key] = float(value)
def _entropy_mesh_from_xml_element(self, root):
text = get_text(root, 'entropy_mesh')
if text is not None:
path = "./mesh[@id='{}']".format(int(text))
elem = root.find(path)
if elem is not None:
self.entropy_mesh = Mesh.from_xml_element(elem)
def _trigger_from_xml_element(self, root):
elem = root.find('trigger')
if elem is not None:
self.trigger_active = get_text(elem, 'active') in ('true', '1')
text = get_text(elem, 'max_batches')
if text is not None:
self.trigger_max_batches = int(text)
text = get_text(elem, 'batch_interval')
if text is not None:
self.trigger_batch_interval = int(text)
def _no_reduce_from_xml_element(self, root):
text = get_text(root, 'no_reduce')
if text is not None:
self.no_reduce = text in ('true', '1')
def _verbosity_from_xml_element(self, root):
text = get_text(root, 'verbosity')
if text is not None:
self.verbosity = int(text)
def _tabular_legendre_from_xml_element(self, root):
elem = root.find('tabular_legendre')
if elem is not None:
text = get_text(elem, 'enable')
self.tabular_legendre['enable'] = text in ('true', '1')
text = get_text(elem, 'num_points')
if text is not None:
self.tabular_legendre['num_points'] = int(text)
def _temperature_from_xml_element(self, root):
text = get_text(root, 'temperature_default')
if text is not None:
self.temperature['default'] = float(text)
text = get_text(root, 'temperature_tolerance')
if text is not None:
self.temperature['tolerance'] = float(text)
text = get_text(root, 'temperature_method')
if text is not None:
self.temperature['method'] = text
text = get_text(root, 'temperature_range')
if text is not None:
self.temperature['range'] = [float(x) for x in text.split()]
text = get_text(root, 'temperature_multipole')
if text is not None:
self.temperature['multipole'] = text in ('true', '1')
def _trace_from_xml_element(self, root):
text = get_text(root, 'trace')
if text is not None:
self.trace = [int(x) for x in text.split()]
def _track_from_xml_element(self, root):
text = get_text(root, 'track')
if text is not None:
self.track = [int(x) for x in text.split()]
def _ufs_mesh_from_xml_element(self, root):
text = get_text(root, 'ufs_mesh')
if text is not None:
path = "./mesh[@id='{}']".format(int(text))
elem = root.find(path)
if elem is not None:
self.ufs_mesh = Mesh.from_xml_element(elem)
def _resonance_scattering_from_xml_element(self, root):
elem = root.find('resonance_scattering')
if elem is not None:
keys = ('enable', 'method', 'energy_min', 'energy_max', 'nuclides')
for key in keys:
value = get_text(elem, key)
if value is not None:
if key == 'enable':
value = value in ('true', '1')
elif key in ('energy_min', 'energy_max'):
value = float(value)
elif key == 'nuclides':
value = value.split()
self.resonance_scattering[key] = value
def _create_fission_neutrons_from_xml_element(self, root):
text = get_text(root, 'create_fission_neutrons')
if text is not None:
self.create_fission_neutrons = text in ('true', '1')
def _log_grid_bins_from_xml_element(self, root):
text = get_text(root, 'log_grid_bins')
if text is not None:
self.log_grid_bins = int(text)
def _dagmc_from_xml_element(self, root):
text = get_text(root, 'dagmc')
if text is not None:
self.dagmc = text in ('true', '1')
def export_to_xml(self, path='settings.xml'):
"""Export simulation settings to an XML file.
@ -985,3 +1216,60 @@ class Settings(object):
# Write the XML Tree to the settings.xml file
tree = ET.ElementTree(root_element)
tree.write(str(p), xml_declaration=True, encoding='utf-8')
@classmethod
def from_xml(cls, path='settings.xml'):
"""Generate settings from XML file
Parameters
----------
path : str, optional
Path to settings XML file
Returns
-------
openmc.Settings
Settings object
"""
tree = ET.parse(path)
root = tree.getroot()
settings = cls()
settings._eigenvalue_from_xml_element(root)
settings._run_mode_from_xml_element(root)
settings._particles_from_xml_element(root)
settings._batches_from_xml_element(root)
settings._inactive_from_xml_element(root)
settings._generations_per_batch_from_xml_element(root)
settings._keff_trigger_from_xml_element(root)
settings._source_from_xml_element(root)
settings._output_from_xml_element(root)
settings._statepoint_from_xml_element(root)
settings._sourcepoint_from_xml_element(root)
settings._confidence_intervals_from_xml_element(root)
settings._electron_treatment_from_xml_element(root)
settings._energy_mode_from_xml_element(root)
settings._max_order_from_xml_element(root)
settings._photon_transport_from_xml_element(root)
settings._ptables_from_xml_element(root)
settings._seed_from_xml_element(root)
settings._survival_biasing_from_xml_element(root)
settings._cutoff_from_xml_element(root)
settings._entropy_mesh_from_xml_element(root)
settings._trigger_from_xml_element(root)
settings._no_reduce_from_xml_element(root)
settings._verbosity_from_xml_element(root)
settings._tabular_legendre_from_xml_element(root)
settings._temperature_from_xml_element(root)
settings._trace_from_xml_element(root)
settings._track_from_xml_element(root)
settings._ufs_mesh_from_xml_element(root)
settings._resonance_scattering_from_xml_element(root)
settings._create_fission_neutrons_from_xml_element(root)
settings._log_grid_bins_from_xml_element(root)
settings._dagmc_from_xml_element(root)
# TODO: Get volume calculations
return settings

View file

@ -2,6 +2,7 @@ from numbers import Real
import sys
from xml.etree import ElementTree as ET
from openmc._xml import get_text
from openmc.stats.univariate import Univariate
from openmc.stats.multivariate import UnitSphere, Spatial
import openmc.checkvalue as cv
@ -137,3 +138,46 @@ class Source(object):
if self.energy is not None:
element.append(self.energy.to_xml_element('energy'))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate source from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.Source
Source generated from XML element
"""
source = cls()
strength = get_text(elem, 'strength')
if strength is not None:
source.strength = float(strength)
particle = get_text(elem, 'particle')
if particle is not None:
source.particle = particle
filename = get_text(elem, 'file')
if filename is not None:
source.file = filename
space = elem.find('space')
if space is not None:
source.space = Spatial.from_xml_element(space)
angle = elem.find('angle')
if angle is not None:
source.angle = UnitSphere.from_xml_element(angle)
energy = elem.find('energy')
if energy is not None:
source.energy = Univariate.from_xml_element(energy)
return source

View file

@ -8,6 +8,7 @@ from xml.etree import ElementTree as ET
import numpy as np
import openmc.checkvalue as cv
from openmc._xml import get_text
from openmc.stats.univariate import Univariate, Uniform
@ -47,6 +48,17 @@ class UnitSphere(metaclass=ABCMeta):
def to_xml_element(self):
return ''
@classmethod
@abstractmethod
def from_xml_element(cls, elem):
distribution = get_text(elem, 'type')
if distribution == 'mu-phi':
return PolarAzimuthal.from_xml_element(elem)
elif distribution == 'isotropic':
return Isotropic.from_xml_element(elem)
elif distribution == 'monodirectional':
return Monodirectional.from_xml_element(elem)
class PolarAzimuthal(UnitSphere):
"""Angular distribution represented by polar and azimuthal angles
@ -121,6 +133,29 @@ class PolarAzimuthal(UnitSphere):
element.append(self.phi.to_xml_element('phi'))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate angular distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.PolarAzimuthal
Angular distribution generated from XML element
"""
mu_phi = cls()
params = get_text(elem, 'parameters')
if params is not None:
mu_phi.reference_uvw = [float(x) for x in params.split()]
mu_phi.mu = Univariate.from_xml_element(elem.find('mu'))
mu_phi.phi = Univariate.from_xml_element(elem.find('phi'))
return mu_phi
class Isotropic(UnitSphere):
"""Isotropic angular distribution.
@ -143,6 +178,23 @@ class Isotropic(UnitSphere):
element.set("type", "isotropic")
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate isotropic distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Isotropic
Isotropic distribution generated from XML element
"""
return cls()
class Monodirectional(UnitSphere):
"""Monodirectional angular distribution.
@ -178,6 +230,27 @@ class Monodirectional(UnitSphere):
element.set("reference_uvw", ' '.join(map(str, self.reference_uvw)))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate monodirectional distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Monodirectional
Monodirectional distribution generated from XML element
"""
monodirectional = cls()
params = get_text(elem, 'parameters')
if params is not None:
monodirectional.reference_uvw = [float(x) for x in params.split()]
return monodirectional
class Spatial(metaclass=ABCMeta):
"""Distribution of locations in three-dimensional Euclidean space.
@ -193,6 +266,17 @@ class Spatial(metaclass=ABCMeta):
def to_xml_element(self):
return ''
@classmethod
@abstractmethod
def from_xml_element(cls, elem):
distribution = get_text(elem, 'type')
if distribution == 'cartesian':
return CartesianIndependent.from_xml_element(elem)
elif distribution == 'box' or distribution == 'fission':
return Box.from_xml_element(elem)
elif distribution == 'point':
return Point.from_xml_element(elem)
class CartesianIndependent(Spatial):
"""Spatial distribution with independent x, y, and z distributions.
@ -270,6 +354,26 @@ class CartesianIndependent(Spatial):
element.append(self.z.to_xml_element('z'))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate spatial distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.CartesianIndependent
Spatial distribution generated from XML element
"""
x = Univariate.from_xml_element(elem.find('x'))
y = Univariate.from_xml_element(elem.find('y'))
z = Univariate.from_xml_element(elem.find('z'))
return cls(x, y, z)
class Box(Spatial):
"""Uniform distribution of coordinates in a rectangular cuboid.
@ -351,6 +455,27 @@ class Box(Spatial):
' '.join(map(str, self.upper_right))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate box distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Box
Box distribution generated from XML element
"""
only_fissionable = get_text(elem, 'type') == 'fission'
params = [float(x) for x in get_text(elem, 'parameters').split()]
lower_left = params[:len(params)//2]
upper_right = params[len(params)//2:]
return cls(lower_left, upper_right, only_fissionable)
class Point(Spatial):
"""Delta function in three dimensions.
@ -398,3 +523,21 @@ class Point(Spatial):
params = ET.SubElement(element, "parameters")
params.text = ' '.join(map(str, self.xyz))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate point distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Point
Point distribution generated from XML element
"""
xyz = [float(x) for x in get_text(elem, 'parameters').split()]
return cls(xyz)

View file

@ -7,6 +7,7 @@ from xml.etree import ElementTree as ET
import numpy as np
import openmc.checkvalue as cv
from openmc._xml import get_text
from openmc.mixin import EqualityMixin
@ -32,6 +33,29 @@ class Univariate(EqualityMixin, metaclass=ABCMeta):
def __len__(self):
return 0
@classmethod
@abstractmethod
def from_xml_element(cls, elem):
distribution = get_text(elem, 'type')
if distribution == 'discrete':
return Discrete.from_xml_element(elem)
elif distribution == 'uniform':
return Uniform.from_xml_element(elem)
elif distribution == 'maxwell':
return Maxwell.from_xml_element(elem)
elif distribution == 'watt':
return Watt.from_xml_element(elem)
elif distribution == 'normal':
return Normal.from_xml_element(elem)
elif distribution == 'muir':
return Muir.from_xml_element(elem)
elif distribution == 'tabular':
return Tabular.from_xml_element(elem)
elif distribution == 'legendre':
return Legendre.from_xml_element(elem)
elif distribution == 'mixture':
return Mixture.from_xml_element(elem)
class Discrete(Univariate):
"""Distribution characterized by a probability mass function.
@ -110,6 +134,26 @@ class Discrete(Univariate):
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate discrete distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Discrete
Discrete distribution generated from XML element
"""
params = [float(x) for x in get_text(elem, 'parameters').split()]
x = params[:len(params)//2]
p = params[len(params)//2:]
return cls(x, p)
class Uniform(Univariate):
"""Distribution with constant probability over a finite interval [a,b]
@ -181,6 +225,24 @@ class Uniform(Univariate):
element.set("parameters", '{} {}'.format(self.a, self.b))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate uniform distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Uniform
Uniform distribution generated from XML element
"""
params = get_text(elem, 'parameters').split()
return cls(*map(float, params))
class Maxwell(Univariate):
"""Maxwellian distribution in energy.
@ -237,6 +299,24 @@ class Maxwell(Univariate):
element.set("parameters", str(self.theta))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate Maxwellian distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Maxwell
Maxwellian distribution generated from XML element
"""
theta = float(get_text(elem, 'parameters'))
return cls(theta)
class Watt(Univariate):
r"""Watt fission energy spectrum.
@ -308,6 +388,25 @@ class Watt(Univariate):
element.set("parameters", '{} {}'.format(self.a, self.b))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate Watt distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Watt
Watt distribution generated from XML element
"""
params = get_text(elem, 'parameters').split()
return cls(*map(float, params))
class Normal(Univariate):
r"""Normally distributed sampling.
@ -377,6 +476,25 @@ class Normal(Univariate):
element.set("parameters", '{} {}'.format(self.mean_value, self.std_dev))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate Normal distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Normal
Normal distribution generated from XML element
"""
params = get_text(elem, 'parameters').split()
return cls(*map(float, params))
class Muir(Univariate):
"""Muir energy spectrum.
@ -465,6 +583,24 @@ class Muir(Univariate):
element.set("parameters", '{} {} {}'.format(self._e0, self._m_rat, self._kt))
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate Muir distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Muir
Muir distribution generated from XML element
"""
params = get_text(elem, 'parameters').split()
return cls(*map(float, params))
class Tabular(Univariate):
"""Piecewise continuous probability distribution.
@ -561,6 +697,27 @@ class Tabular(Univariate):
return element
@classmethod
def from_xml_element(cls, elem):
"""Generate tabular distribution from an XML element
Parameters
----------
elem : xml.etree.ElementTree.Element
XML element
Returns
-------
openmc.stats.Tabular
Tabular distribution generated from XML element
"""
interpolation = get_text(elem, 'interpolation')
params = [float(x) for x in get_text(elem, 'parameters').split()]
x = params[:len(params)//2]
p = params[len(params)//2:]
return cls(x, p, interpolation)
class Legendre(Univariate):
r"""Probability density given by a Legendre polynomial expansion
@ -607,6 +764,10 @@ class Legendre(Univariate):
def to_xml_element(self, element_name):
raise NotImplementedError
@classmethod
def from_xml_element(cls, elem):
raise NotImplementedError
class Mixture(Univariate):
"""Probability distribution characterized by a mixture of random variables.
@ -660,3 +821,7 @@ class Mixture(Univariate):
def to_xml_element(self, element_name):
raise NotImplementedError
@classmethod
def from_xml_element(cls, elem):
raise NotImplementedError

View file

@ -19,11 +19,12 @@ def test_export_to_xml(run_in_tmpdir):
'write': True, 'overwrite': True}
s.statepoint = {'batches': [50, 150, 500, 1000]}
s.confidence_intervals = True
s.cross_sections = '/path/to/cross_sections.xml'
s.ptables = True
s.seed = 17
s.survival_biasing = True
s.cutoff = {'weight': 0.25, 'weight_avg': 0.5, 'energy': 1.0e-5}
s.cutoff = {'weight': 0.25, 'weight_avg': 0.5, 'energy_neutron': 1.0e-5,
'energy_photon': 1000.0, 'energy_electron': 1.0e-5,
'energy_positron': 1.0e-5}
mesh = openmc.Mesh()
mesh.lower_left = (-10., -10., -10.)
mesh.upper_right = (10., 10., 10.)
@ -47,6 +48,59 @@ def test_export_to_xml(run_in_tmpdir):
upper_right = (10., 10., 10.))
s.create_fission_neutrons = True
s.log_grid_bins = 2000
s.photon_transport = False
s.electron_treatment = 'led'
s.dagmc = False
# Make sure exporting XML works
s.export_to_xml()
# Generate settings from XML
s = openmc.Settings.from_xml()
assert s.run_mode == 'fixed source'
assert s.batches == 1000
assert s.generations_per_batch == 10
assert s.inactive == 100
assert s.particles == 1000000
assert s.keff_trigger == {'type': 'std_dev', 'threshold': 0.001}
assert s.energy_mode == 'continuous-energy'
assert s.max_order == 5
assert isinstance(s.source[0], openmc.Source)
assert isinstance(s.source[0].space, openmc.stats.Point)
assert s.output == {'summary': True, 'tallies': False, 'path': 'here'}
assert s.verbosity == 7
assert s.sourcepoint == {'batches': [50, 150, 500, 1000], 'separate': True,
'write': True, 'overwrite': True}
assert s.statepoint == {'batches': [50, 150, 500, 1000]}
assert s.confidence_intervals
assert s.ptables
assert s.seed == 17
assert s.survival_biasing
assert s.cutoff == {'weight': 0.25, 'weight_avg': 0.5,
'energy_neutron': 1.0e-5, 'energy_photon': 1000.0,
'energy_electron': 1.0e-5, 'energy_positron': 1.0e-5}
assert isinstance(s.entropy_mesh, openmc.Mesh)
assert s.entropy_mesh.lower_left == [-10., -10., -10.]
assert s.entropy_mesh.upper_right == [10., 10., 10.]
assert s.entropy_mesh.dimension == [5, 5, 5]
assert s.trigger_active
assert s.trigger_max_batches == 10000
assert s.trigger_batch_interval == 50
assert not s.no_reduce
assert s.tabular_legendre == {'enable': True, 'num_points': 50}
assert s.temperature == {'default': 293.6, 'method': 'interpolation',
'multipole': True, 'range': [200., 1000.]}
assert s.trace == [10, 1, 20]
assert s.track == [1, 1, 1, 2, 1, 1]
assert isinstance(s.ufs_mesh, openmc.Mesh)
assert s.ufs_mesh.lower_left == [-10., -10., -10.]
assert s.ufs_mesh.upper_right == [10., 10., 10.]
assert s.ufs_mesh.dimension == [5, 5, 5]
assert s.resonance_scattering == {'enable': True, 'method': 'rvs',
'energy_min': 1.0, 'energy_max': 1000.0,
'nuclides': ['U235', 'U238', 'Pu239']}
assert s.create_fission_neutrons
assert s.log_grid_bins == 2000
assert not s.photon_transport
assert s.electron_treatment == 'led'
assert not s.dagmc

View file

@ -11,7 +11,6 @@ def test_source():
assert src.space == space
assert src.angle == angle
assert src.energy == energy
assert src.strength == 1.0
elem = src.to_xml_element()
assert 'strength' in elem.attrib
@ -19,6 +18,13 @@ def test_source():
assert elem.find('angle') is not None
assert elem.find('energy') is not None
src = openmc.Source.from_xml_element(elem)
assert isinstance(src.angle, openmc.stats.Isotropic)
assert src.space.xyz == [0.0, 0.0, 0.0]
assert src.energy.x == [1.0e6]
assert src.energy.p == [1.0]
assert src.strength == 1.0
def test_source_file():
filename = 'source.h5'

View file

@ -10,10 +10,15 @@ def test_discrete():
x = [0.0, 1.0, 10.0]
p = [0.3, 0.2, 0.5]
d = openmc.stats.Discrete(x, p)
elem = d.to_xml_element('distribution')
d = openmc.stats.Discrete.from_xml_element(elem)
assert d.x == x
assert d.p == p
assert len(d) == len(x)
d.to_xml_element('distribution')
d = openmc.stats.Univariate.from_xml_element(elem)
assert isinstance(d, openmc.stats.Discrete)
# Single point
d2 = openmc.stats.Discrete(1e6, 1.0)
@ -25,6 +30,9 @@ def test_discrete():
def test_uniform():
a, b = 10.0, 20.0
d = openmc.stats.Uniform(a, b)
elem = d.to_xml_element('distribution')
d = openmc.stats.Uniform.from_xml_element(elem)
assert d.a == a
assert d.b == b
assert len(d) == 2
@ -34,35 +42,39 @@ def test_uniform():
assert t.p == [1/(b-a), 1/(b-a)]
assert t.interpolation == 'histogram'
d.to_xml_element('distribution')
def test_maxwell():
theta = 1.2895e6
d = openmc.stats.Maxwell(theta)
elem = d.to_xml_element('distribution')
d = openmc.stats.Maxwell.from_xml_element(elem)
assert d.theta == theta
assert len(d) == 1
d.to_xml_element('distribution')
def test_watt():
a, b = 0.965e6, 2.29e-6
d = openmc.stats.Watt(a, b)
elem = d.to_xml_element('distribution')
d = openmc.stats.Watt.from_xml_element(elem)
assert d.a == a
assert d.b == b
assert len(d) == 2
d.to_xml_element('distribution')
def test_tabular():
x = [0.0, 5.0, 7.0]
p = [0.1, 0.2, 0.05]
d = openmc.stats.Tabular(x, p, 'linear-linear')
elem = d.to_xml_element('distribution')
d = openmc.stats.Tabular.from_xml_element(elem)
assert d.x == x
assert d.p == p
assert d.interpolation == 'linear-linear'
assert len(d) == len(x)
d.to_xml_element('distribution')
def test_legendre():
@ -115,6 +127,15 @@ def test_polar_azimuthal():
assert elem.find('mu') is not None
assert elem.find('phi') is not None
d = openmc.stats.PolarAzimuthal.from_xml_element(elem)
assert d.mu.x == [1.]
assert d.mu.p == [1.]
assert d.phi.x == [0.]
assert d.phi.p == [1.]
d = openmc.stats.UnitSphere.from_xml_element(elem)
assert isinstance(d, openmc.stats.PolarAzimuthal)
def test_isotropic():
d = openmc.stats.Isotropic()
@ -122,24 +143,25 @@ def test_isotropic():
assert elem.tag == 'angle'
assert elem.attrib['type'] == 'isotropic'
d = openmc.stats.Isotropic.from_xml_element(elem)
assert isinstance(d, openmc.stats.Isotropic)
def test_monodirectional():
d = openmc.stats.Monodirectional((1., 0., 0.))
assert d.reference_uvw == pytest.approx((1., 0., 0.))
elem = d.to_xml_element()
assert elem.tag == 'angle'
assert elem.attrib['type'] == 'monodirectional'
d = openmc.stats.Monodirectional.from_xml_element(elem)
assert d.reference_uvw == pytest.approx((1., 0., 0.))
def test_cartesian():
x = openmc.stats.Uniform(-10., 10.)
y = openmc.stats.Uniform(-10., 10.)
z = openmc.stats.Uniform(0., 20.)
d = openmc.stats.CartesianIndependent(x, y, z)
assert d.x == x
assert d.y == y
assert d.z == z
elem = d.to_xml_element()
assert elem.tag == 'space'
@ -147,55 +169,75 @@ def test_cartesian():
assert elem.find('x') is not None
assert elem.find('y') is not None
d = openmc.stats.CartesianIndependent.from_xml_element(elem)
assert d.x == x
assert d.y == y
assert d.z == z
d = openmc.stats.Spatial.from_xml_element(elem)
assert isinstance(d, openmc.stats.CartesianIndependent)
def test_box():
lower_left = (-10., -10., -10.)
upper_right = (10., 10., 10.)
d = openmc.stats.Box(lower_left, upper_right)
assert d.lower_left == pytest.approx(lower_left)
assert d.upper_right == pytest.approx(upper_right)
assert not d.only_fissionable
elem = d.to_xml_element()
assert elem.tag == 'space'
assert elem.attrib['type'] == 'box'
assert elem.find('parameters') is not None
d = openmc.stats.Box.from_xml_element(elem)
assert d.lower_left == pytest.approx(lower_left)
assert d.upper_right == pytest.approx(upper_right)
assert not d.only_fissionable
# only fissionable parameter
d2 = openmc.stats.Box(lower_left, upper_right, True)
assert d2.only_fissionable
elem = d2.to_xml_element()
assert elem.attrib['type'] == 'fission'
d = openmc.stats.Spatial.from_xml_element(elem)
assert isinstance(d, openmc.stats.Box)
def test_point():
p = (-4., 2., 10.)
d = openmc.stats.Point(p)
assert d.xyz == pytest.approx(p)
elem = d.to_xml_element()
assert elem.tag == 'space'
assert elem.attrib['type'] == 'point'
assert elem.find('parameters') is not None
d = openmc.stats.Point.from_xml_element(elem)
assert d.xyz == pytest.approx(p)
def test_normal():
mean = 10.0
std_dev = 2.0
d = openmc.stats.Normal(mean,std_dev)
elem = d.to_xml_element('distribution')
assert elem.attrib['type'] == 'normal'
d = openmc.stats.Normal.from_xml_element(elem)
assert d.mean_value == pytest.approx(mean)
assert d.std_dev == pytest.approx(std_dev)
assert len(d) == 2
elem = d.to_xml_element('distribution')
assert elem.attrib['type'] == 'normal'
def test_muir():
mean = 10.0
mass = 5.0
temp = 20000.
d = openmc.stats.Muir(mean,mass,temp)
elem = d.to_xml_element('energy')
assert elem.attrib['type'] == 'muir'
d = openmc.stats.Muir.from_xml_element(elem)
assert d.e0 == pytest.approx(mean)
assert d.m_rat == pytest.approx(mass)
assert d.kt == pytest.approx(temp)
assert len(d) == 3
elem = d.to_xml_element('energy')
assert elem.attrib['type'] == 'muir'