Merge pull request #800 from paulromano/volume

Change how volume is handled
This commit is contained in:
Will Boyd 2017-03-02 09:06:44 -05:00 committed by GitHub
commit b1fbef35e9
17 changed files with 385 additions and 271 deletions

View file

@ -146,7 +146,7 @@ The current version of the statepoint file format is 16.0.
All values are given in seconds and are measured on the master process.
:Datasets: - **total initialization** (*double*) -- Time spent reading inputs,
allocating arrays, etc.
allocating arrays, etc.
- **reading cross sections** (*double*) -- Time spent loading cross
section libraries (this is a subset of initialization).
- **simulation** (*double*) -- Time spent between initialization and

View file

@ -57,6 +57,7 @@ Simulation Settings
openmc.Source
openmc.ResonanceScattering
openmc.VolumeCalculation
openmc.Settings
Material Specification
@ -185,6 +186,7 @@ Running OpenMC
:template: myfunction.rst
openmc.run
openmc.calculate_volumes
openmc.plot_geometry
Post-processing
@ -286,17 +288,11 @@ Multi-group Cross Sections
openmc.mgxs.AbsorptionXS
openmc.mgxs.CaptureXS
openmc.mgxs.Chi
openmc.mgxs.ChiPrompt
openmc.mgxs.FissionXS
openmc.mgxs.InverseVelocity
openmc.mgxs.KappaFissionXS
openmc.mgxs.MultiplicityMatrixXS
openmc.mgxs.NuFissionXS
openmc.mgxs.NuFissionMatrixXS
openmc.mgxs.NuScatterXS
openmc.mgxs.NuScatterMatrixXS
openmc.mgxs.PromptNuFissionXS
openmc.mgxs.PromptNuFissionMatrixXS
openmc.mgxs.ScatterXS
openmc.mgxs.ScatterMatrixXS
openmc.mgxs.TotalXS

View file

@ -13,9 +13,12 @@ It is assumed that if no
is specified, the XML input files are present in the current directory.
.SH OPTIONS
.TP
.B "\-c\fR, \fP\-\-volume"
Run in stochastic volume calculation mode
.TP
.B "\-g\fR, \fP\-\-geometry-debug"
Run in geometry debugging mode, where cell overlaps are checked for after each
move of a particle
Run with geometry debugging turned on, where cell overlaps are checked for after
each move of a particle
.TP
.B "\-p\fR, \fP\-\-plot"
Run in plotting mode

View file

@ -86,9 +86,9 @@ class Cell(object):
distribcell_paths : list of str
The paths traversed through the CSG tree to reach each distribcell
instance
volume_information : dict
Estimate of the volume and total number of atoms of each nuclide from a
stochastic volume calculation. This information is set with the
volume : float
Volume of the cell in cm^3. This can either be set manually or
calculated in a stochastic volume calculation and added via the
:meth:`Cell.add_volume_information` method.
"""
@ -106,7 +106,8 @@ class Cell(object):
self._offsets = None
self._distribcell_index = None
self._distribcell_paths = None
self._volume_information = None
self._volume = None
self._atoms = None
def __contains__(self, point):
if self.region is None:
@ -224,8 +225,8 @@ class Cell(object):
return self._distribcell_paths
@property
def volume_information(self):
return self._volume_information
def volume(self):
return self._volume
@id.setter
def id(self, cell_id):
@ -326,6 +327,12 @@ class Cell(object):
cv.check_type('cell region', region, Region)
self._region = region
@volume.setter
def volume(self, volume):
if volume is not None:
cv.check_type('cell volume', volume, Real)
self._volume = volume
@distribcell_index.setter
def distribcell_index(self, ind):
cv.check_type('distribcell index', ind, Integral)
@ -391,10 +398,9 @@ class Cell(object):
"""
if volume_calc.domain_type == 'cell':
for cell_id in volume_calc.results:
if cell_id == self.id:
self._volume_information = volume_calc.results[cell_id]
break
if self.id in volume_calc.volumes:
self._volume = volume_calc.volumes[self.id][0]
self._atoms = volume_calc.atoms[self.id]
else:
raise ValueError('No volume information found for this cell.')
else:
@ -446,9 +452,9 @@ class Cell(object):
elif self.fill_type == 'void':
pass
else:
if self.volume_information is not None:
volume = self.volume_information['volume'][0]
for name, atoms in self.volume_information['atoms']:
if self._atoms is not None:
volume = self.volume
for name, atoms in self._atoms.items():
nuclide = openmc.Nuclide(name)
density = 1.0e-24 * atoms[0]/volume # density in atoms/b-cm
nuclides[name] = (nuclide, density)

View file

@ -1,16 +1,17 @@
from __future__ import print_function
import subprocess
from numbers import Integral
import sys
from six import string_types
from openmc import VolumeCalculation
_summary_indicator = "TIMING STATISTICS"
def _run(command, output, cwd):
def _run(args, output, cwd):
# Launch a subprocess
p = subprocess.Popen(command, shell=True, cwd=cwd, stdout=subprocess.PIPE,
p = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, universal_newlines=True)
storage_flag = False
@ -51,8 +52,59 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
Path to working directory to run in. Defaults to the current working directory.
"""
if output:
output = 'full'
return _run([openmc_exec, '-p'], output, cwd)
return _run(openmc_exec + ' -p', output, cwd)
def calculate_volumes(threads=None, output=True, cwd='.',
openmc_exec='openmc', mpi_args=None):
"""Run stochastic volume calculations in OpenMC.
This function runs OpenMC in stochastic volume calculation mode. To specify
the parameters of a volume calculation, one must first create a
:class:`openmc.VolumeCalculation` instance and assign it to
:attr:`openmc.Settings.volume_calculations`. For example:
>>> vol = openmc.VolumeCalculation(domains=[cell1, cell2], samples=100000)
>>> settings = openmc.Settings()
>>> settings.volume_calculations = [vol]
>>> settings.export_to_xml()
>>> openmc.calculate_volumes()
Parameters
----------
threads : int, optional
Number of OpenMP threads. If OpenMC is compiled with OpenMP threading
enabled, the default is implementation-dependent but is usually equal to
the number of hardware threads available (or a value set by the
:envvar:`OMP_NUM_THREADS` environment variable).
output : bool, optional
Capture OpenMC output from standard out
openmc_exec : str, optional
Path to OpenMC executable. Defaults to 'openmc'.
mpi_args : list of str, optional
MPI execute command and any additional MPI arguments to pass,
e.g. ['mpiexec', '-n', '8'].
cwd : str, optional
Path to working directory to run in. Defaults to the current working
directory.
See Also
--------
openmc.VolumeCalculation
"""
args = [openmc_exec, '--volume']
if isinstance(threads, Integral) and threads > 0:
args += ['-s', str(threads)]
if mpi_args is not None:
args = mpi_args + args
if output:
output = 'full'
return _run(args, output, cwd)
def run(particles=None, threads=None, geometry_debug=False,
@ -90,27 +142,24 @@ def run(particles=None, threads=None, geometry_debug=False,
"""
post_args = ' '
pre_args = ''
args = [openmc_exec]
if isinstance(particles, Integral) and particles > 0:
post_args += '-n {0} '.format(particles)
args += ['-n', str(particles)]
if isinstance(threads, Integral) and threads > 0:
post_args += '-s {0} '.format(threads)
args += ['-s', str(threads)]
if geometry_debug:
post_args += '-g '
args.append('-g')
if isinstance(restart_file, string_types):
post_args += '-r {0} '.format(restart_file)
args += ['-r', restart_file]
if tracks:
post_args += '-t'
args.append('-t')
if mpi_args is not None:
pre_args = ' '.join(mpi_args) + ' '
args = mpi_args + args
command = pre_args + openmc_exec + ' ' + post_args
return _run(command, output, cwd)
return _run(args, output, cwd)

View file

@ -61,8 +61,16 @@ class Geometry(object):
"""
if volume_calc.domain_type == 'cell':
for cell in self.get_all_cells():
if cell.id in volume_calc.results:
if cell.id in volume_calc.volumes:
cell.add_volume_information(volume_calc)
elif volume_calc.domain_type == 'material':
for material in self.get_all_materials():
if material.id in volume_calc.volumes:
material.add_volume_information(volume_calc)
elif volume_calc.domain_type == 'universe':
for universe in self.get_all_universes():
if universe.id in volume_calc.volumes:
universe.add_volume_information(volume_calc)
def export_to_xml(self, path='geometry.xml'):
"""Export geometry to an XML file.

View file

@ -71,6 +71,10 @@ class Material(object):
The average molar mass of nuclides in the material in units of grams per
mol. For example, UO2 with 3 nuclides will have an average molar mass
of 270 / 3 = 90 g / mol.
volume : float
Volume of the material in cm^3. This can either be set manually or
calculated in a stochastic volume calculation and added via the
:meth:`Material.add_volume_information` method.
"""
@ -82,6 +86,8 @@ class Material(object):
self._density = None
self._density_units = ''
self._depletable = False
self._volume = None
self._atoms = {}
# A list of tuples (nuclide, percent, percent type)
self._nuclides = []
@ -226,6 +232,10 @@ class Material(object):
# Compute and return the molar mass
return mass / moles
@property
def volume(self):
return self._volume
@id.setter
def id(self, material_id):
@ -259,6 +269,12 @@ class Material(object):
depletable, bool)
self._depletable = depletable
@volume.setter
def volume(self, volume):
if volume is not None:
cv.check_type('material volume', volume, Real)
self._volume = volume
@classmethod
def from_hdf5(cls, group):
"""Create material from HDF5 group
@ -302,6 +318,24 @@ class Material(object):
return material
def add_volume_information(self, volume_calc):
"""Add volume information to a material.
Parameters
----------
volume_calc : openmc.VolumeCalculation
Results from a stochastic volume calculation
"""
if volume_calc.domain_type == 'material':
if self.id in volume_calc.volumes:
self._volume = volume_calc.volumes[self.id]
self._atoms = volume_calc.atoms[self.id]
else:
raise ValueError('No volume information found for this material.')
else:
raise ValueError('No volume information found for this material.')
def set_density(self, units, density=None):
"""Set the density of the material

View file

@ -58,7 +58,7 @@ _DOMAINS = (openmc.Cell,
openmc.Material,
openmc.Mesh)
# Supported ScatterMatrixXS and NuScatterMatrixXS angular distribution types
# Supported ScatterMatrixXS angular distribution types
MU_TREATMENTS = ('legendre', 'histogram')
# Maximum Legendre order supported by OpenMC

View file

@ -1563,19 +1563,17 @@ class XSdata(object):
temperature=294., nuclide='total',
xs_type='macro', subdomain=None):
"""This method allows for either the direct use of only an
openmc.mgxs.MultiplicityMatrixXS OR
an openmc.mgxs.NuScatterMatrixXS and
openmc.mgxs.MultiplicityMatrixXS or an openmc.mgxs.ScatterMatrixXS and
openmc.mgxs.ScatterMatrixXS to be used to set the scattering
multiplicity for this XSdata object. Multiplicity,
in OpenMC parlance, is a factor used to account for the production
of neutrons introduced by scattering multiplication reactions, i.e.,
(n,xn) events. In this sense, the multiplication matrix is simply
defined as the ratio of the nu-scatter and scatter matrices.
multiplicity for this XSdata object. Multiplicity, in OpenMC parlance,
is a factor used to account for the production of neutrons introduced by
scattering multiplication reactions, i.e., (n,xn) events. In this sense,
the multiplication matrix is simply defined as the ratio of the
nu-scatter and scatter matrices.
Parameters
----------
nuscatter: {openmc.mgxs.NuScatterMatrixXS,
openmc.mgxs.MultiplicityMatrixXS}
nuscatter: openmc.mgxs.ScatterMatrixXS or openmc.mgxs.MultiplicityMatrixXS
MGXS Object containing the matrix cross section for the domain
of interest.
scatter: openmc.mgxs.ScatterMatrixXS
@ -1701,19 +1699,21 @@ class XSdata(object):
Representation of the MGXS (isotropic or angle-dependent flux
weighting).
num_polar : int, optional
Number of equal width angular bins that the polar angular
domain is subdivided into. This is required when
:param:`target_representation` is "angle".
Number of equal width angular bins that the polar angular domain is
subdivided into. This is required when `target_representation` is
"angle".
num_azimuthal : int, optional
Number of equal width angular bins that the azimuthal angular
domain is subdivided into. This is required when
:param:`target_representation` is "angle".
Number of equal width angular bins that the azimuthal angular domain
is subdivided into. This is required when `target_representation` is
"angle".
Returns
-------
openmc.XSdata
Multi-group cross section data with the same data as self, but
represented as specified in :param:`target_representation`.
represented as specified in `target_representation`.
"""
@ -1798,7 +1798,7 @@ class XSdata(object):
-------
openmc.XSdata
Multi-group cross section data with the same data as in self, but
represented as specified in :param:`target_format`.
represented as specified in `target_format`.
"""
@ -2447,19 +2447,19 @@ class MGXSLibrary(object):
Representation of the MGXS (isotropic or angle-dependent flux
weighting).
num_polar : int, optional
Number of equal width angular bins that the polar angular
domain is subdivided into. This is required when
:param:`target_representation` is "angle".
Number of equal width angular bins that the polar angular domain is
subdivided into. This is required when `target_representation` is
"angle".
num_azimuthal : int, optional
Number of equal width angular bins that the azimuthal angular
domain is subdivided into. This is required when
:param:`target_representation` is "angle".
Number of equal width angular bins that the azimuthal angular domain
is subdivided into. This is required when `target_representation` is
"angle".
Returns
-------
openmc.MGXSLibrary
Multi-group Library with the same data as self, but represented as
specified in :param:`target_representation`.
specified in `target_representation`.
"""
@ -2486,9 +2486,9 @@ class MGXSLibrary(object):
Returns
-------
openmc.MGXSLibrary
Multi-group Library with the same data as self, but with the
scatter format represented as specified in :param:`target_format`
and :param:`target_order`.
Multi-group Library with the same data as self, but with the scatter
format represented as specified in `target_format` and
`target_order`.
"""

View file

@ -1,5 +1,5 @@
from collections import OrderedDict, Iterable
from numbers import Integral
from numbers import Integral, Real
import random
import sys
@ -42,6 +42,10 @@ class Universe(object):
cells : collections.OrderedDict
Dictionary whose keys are cell IDs and values are :class:`Cell`
instances
volume : float
Volume of the universe in cm^3. This can either be set manually or
calculated in a stochastic volume calculation and added via the
:meth:`Universe.add_volume_information` method.
"""
@ -49,6 +53,8 @@ class Universe(object):
# Initialize Cell class attributes
self.id = universe_id
self.name = name
self._volume = None
self._atoms = {}
# Keys - Cell IDs
# Values - Cells
@ -99,6 +105,10 @@ class Universe(object):
def cells(self):
return self._cells
@property
def volume(self):
return self._volume
@id.setter
def id(self, universe_id):
if universe_id is None:
@ -118,6 +128,12 @@ class Universe(object):
else:
self._name = ''
@volume.setter
def volume(self, volume):
if volume is not None:
cv.check_type('universe volume', volume, Real)
self._volume = volume
@classmethod
def from_hdf5(cls, group, cells):
"""Create universe from HDF5 group
@ -147,6 +163,24 @@ class Universe(object):
return universe
def add_volume_information(self, volume_calc):
"""Add volume information to a universe.
Parameters
----------
volume_calc : openmc.VolumeCalculation
Results from a stochastic volume calculation
"""
if volume_calc.domain_type == 'cell':
if self.id in volume_calc.volumes:
self._volume = volume_calc.volumes[self.id]
self._atoms = volume_calc.atoms[self.id]
else:
raise ValueError('No volume information found for this universe.')
else:
raise ValueError('No volume information found for this universe.')
def find(self, point):
"""Find cells/universes/lattices which contain a given point

View file

@ -1,4 +1,4 @@
from collections import Iterable, Mapping
from collections import Iterable, Mapping, OrderedDict
from numbers import Real, Integral
from xml.etree import ElementTree as ET
from warnings import warn
@ -43,21 +43,21 @@ class VolumeCalculation(object):
Lower-left coordinates of bounding box used to sample points
upper_right : Iterable of float
Upper-right coordinates of bounding box used to sample points
results : dict
Dictionary whose keys are unique IDs of domains and values are
dictionaries with calculated volumes and total number of atoms for each
nuclide present in the domain.
volumes : dict
Dictionary whose keys are unique IDs of domains and values are the
estimated volumes
atoms : dict
Dictionary mapping unique IDs of domains to a mapping of nuclides to
total number of atoms for each nuclide present in the domain. For
example, {10: {'U235': 1.0e22, 'U238': 5.0e22, ...}}.
atoms_dataframe : pandas.DataFrame
DataFrame showing the estimated number of atoms for each nuclide present
in each domain specified.
volumes : dict
Dictionary mapping unique IDs of domains to estimated volumes in cm^3.
"""
def __init__(self, domains, samples, lower_left=None,
upper_right=None):
self._results = None
self._atoms = {}
self._volumes = {}
cv.check_type('domains', domains, Iterable,
(openmc.Cell, openmc.Material, openmc.Universe))
@ -122,25 +122,25 @@ class VolumeCalculation(object):
def upper_right(self):
return self._upper_right
@property
def results(self):
return self._results
@property
def domain_type(self):
return self._domain_type
@property
def atoms(self):
return self._atoms
@property
def volumes(self):
return {uid: results['volume'] for uid, results in self.results.items()}
return self._volumes
@property
def atoms_dataframe(self):
items = []
columns = [self.domain_type.capitalize(), 'Nuclide', 'Atoms',
'Uncertainty']
for uid, results in self.results.items():
for name, atoms in results['atoms']:
for uid, atoms_dict in self.atoms.items():
for name, atoms in atoms_dict.items():
items.append((uid, name, atoms[0], atoms[1]))
return pd.DataFrame.from_records(items, columns=columns)
@ -170,10 +170,15 @@ class VolumeCalculation(object):
cv.check_length(name, upper_right, 3)
self._upper_right = upper_right
@results.setter
def results(self, results):
cv.check_type('results', results, Mapping)
self._results = results
@volumes.setter
def volumes(self, volumes):
cv.check_type('volumes', volumes, Mapping)
self._volumes = volumes
@atoms.setter
def atoms(self, atoms):
cv.check_type('atoms', atoms, Mapping)
self._atoms = atoms
@classmethod
def from_hdf5(cls, filename):
@ -198,7 +203,8 @@ class VolumeCalculation(object):
lower_left = f.attrs['lower_left']
upper_right = f.attrs['upper_right']
results = {}
volumes = {}
atoms = {}
ids = []
for obj_name in f:
if obj_name.startswith('domain_'):
@ -207,12 +213,13 @@ class VolumeCalculation(object):
group = f[obj_name]
volume = tuple(group['volume'].value)
nucnames = group['nuclides'].value
atoms = group['atoms'].value
atoms_ = group['atoms'].value
atom_list = []
for name_i, atoms_i in zip(nucnames, atoms):
atom_list.append((name_i.decode(), tuple(atoms_i)))
results[domain_id] = {'volume': volume, 'atoms': atom_list}
atom_dict = OrderedDict()
for name_i, atoms_i in zip(nucnames, atoms_):
atom_dict[name_i.decode()] = tuple(atoms_i)
volumes[domain_id] = volume
atoms[domain_id] = atom_dict
# Instantiate some throw-away domains that are used by the constructor
# to assign IDs
@ -225,9 +232,30 @@ class VolumeCalculation(object):
# Instantiate the class and assign results
vol = cls(domains, samples, lower_left, upper_right)
vol.results = results
vol.volumes = volumes
vol.atoms = atoms
return vol
def load_results(self, filename):
"""Load stochastic volume calculation results from an HDF5 file.
Parameters
----------
filename : str
Path to volume.h5 file
"""
results = type(self).from_hdf5(filename)
# Make sure properties match
assert self.domains == results.domains
assert self.lower_left == results.lower_left
assert self.upper_right == results.upper_right
# Copy results
self.volumes = results.volumes
self.atoms = results.atoms
def to_xml_element(self):
"""Return XML representation of the volume calculation

View file

@ -365,6 +365,9 @@ contains
case ('-g', '-geometry-debug', '--geometry-debug')
check_overlaps = .true.
case ('-c', '--volume')
run_mode = MODE_VOLUME
case ('-s', '--threads')
! Read number of threads
i = i + 1

View file

@ -194,7 +194,8 @@ contains
write(OUTPUT_UNIT,*) 'Usage: openmc [options] [directory]'
write(OUTPUT_UNIT,*)
write(OUTPUT_UNIT,*) 'Options:'
write(OUTPUT_UNIT,*) ' -g, --geometry-debug Run in geometry debugging mode'
write(OUTPUT_UNIT,*) ' -c, --volume Run in stochastic volume calculation mode'
write(OUTPUT_UNIT,*) ' -g, --geometry-debug Run with geometry debugging on'
write(OUTPUT_UNIT,*) ' -n, --particles Number of particles per generation'
write(OUTPUT_UNIT,*) ' -p, --plot Run in plotting mode'
write(OUTPUT_UNIT,*) ' -r, --restart Restart a previous run from a state point'

View file

@ -27,23 +27,12 @@ element materials {
attribute name { xsd:string })
}* &
element element {
(element name { xsd:string { maxLength = "2" } } |
attribute name { xsd:string { maxLength = "2" } }) &
(element scattering { ( "data" | "iso-in-lab" ) } |
attribute scattering { ( "data" | "iso-in-lab" ) })? &
(
(element ao { xsd:double } | attribute ao { xsd:double }) |
(element wo { xsd:double } | attribute wo { xsd:double })
)
}* &
element sab {
(element name { xsd:string } | attribute name { xsd:string })
}*
}+
}+ &
element cross_sections { xsd:string { maxLength = "255" } }? &
element multipole_library { xsd:string { maxLength = "255" } }? &
element multipole_library { xsd:string { maxLength = "255" } }?
}

View file

@ -1,64 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<element name="materials" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<oneOrMore>
<element name="material">
<interleave>
<choice>
<element name="id">
<data type="int"/>
</element>
<attribute name="id">
<data type="int"/>
</attribute>
</choice>
<optional>
<interleave>
<oneOrMore>
<element name="material">
<interleave>
<choice>
<element name="name">
<data type="string">
<param name="maxLength">52</param>
</data>
<element name="id">
<data type="int"/>
</element>
<attribute name="name">
<data type="string">
<param name="maxLength">52</param>
</data>
<attribute name="id">
<data type="int"/>
</attribute>
</choice>
</optional>
<optional>
<element name="temperature">
<data type="double"/>
</element>
</optional>
<element name="density">
<interleave>
<optional>
<choice>
<element name="value">
<data type="double"/>
</element>
<attribute name="value">
<data type="double"/>
</attribute>
</choice>
</optional>
<optional>
<choice>
<element name="units">
<element name="name">
<data type="string">
<param name="maxLength">10</param>
<param name="maxLength">52</param>
</data>
</element>
<attribute name="units">
<attribute name="name">
<data type="string">
<param name="maxLength">10</param>
<param name="maxLength">52</param>
</data>
</attribute>
</choice>
</interleave>
</element>
<zeroOrMore>
<element name="nuclide">
</optional>
<optional>
<element name="temperature">
<data type="double"/>
</element>
</optional>
<element name="density">
<interleave>
<optional>
<choice>
<element name="value">
<data type="double"/>
</element>
<attribute name="value">
<data type="double"/>
</attribute>
</choice>
</optional>
<choice>
<element name="units">
<data type="string">
<param name="maxLength">10</param>
</data>
</element>
<attribute name="units">
<data type="string">
<param name="maxLength">10</param>
</data>
</attribute>
</choice>
</interleave>
</element>
<zeroOrMore>
<element name="nuclide">
<interleave>
<choice>
<element name="name">
<data type="string"/>
</element>
<attribute name="name">
<data type="string"/>
</attribute>
</choice>
<optional>
<choice>
<element name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</element>
<attribute name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</attribute>
</choice>
</optional>
<choice>
<choice>
<element name="ao">
<data type="double"/>
</element>
<attribute name="ao">
<data type="double"/>
</attribute>
</choice>
<choice>
<element name="wo">
<data type="double"/>
</element>
<attribute name="wo">
<data type="double"/>
</attribute>
</choice>
</choice>
</interleave>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="macroscopic">
<choice>
<element name="name">
<data type="string"/>
@ -67,120 +115,36 @@
<data type="string"/>
</attribute>
</choice>
<optional>
<choice>
<element name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</element>
<attribute name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</attribute>
</choice>
</optional>
<choice>
<choice>
<element name="ao">
<data type="double"/>
</element>
<attribute name="ao">
<data type="double"/>
</attribute>
</choice>
<choice>
<element name="wo">
<data type="double"/>
</element>
<attribute name="wo">
<data type="double"/>
</attribute>
</choice>
</choice>
</interleave>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="macroscopic">
<choice>
<element name="name">
<data type="string"/>
</element>
<attribute name="name">
<data type="string"/>
</attribute>
</choice>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="element">
<interleave>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="sab">
<choice>
<element name="name">
<data type="string">
<param name="maxLength">2</param>
</data>
<data type="string"/>
</element>
<attribute name="name">
<data type="string">
<param name="maxLength">2</param>
</data>
<data type="string"/>
</attribute>
</choice>
<optional>
<choice>
<element name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</element>
<attribute name="scattering">
<choice>
<value>data</value>
<value>iso-in-lab</value>
</choice>
</attribute>
</choice>
</optional>
<choice>
<choice>
<element name="ao">
<data type="double"/>
</element>
<attribute name="ao">
<data type="double"/>
</attribute>
</choice>
<choice>
<element name="wo">
<data type="double"/>
</element>
<attribute name="wo">
<data type="double"/>
</attribute>
</choice>
</choice>
</interleave>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="sab">
<choice>
<element name="name">
<data type="string"/>
</element>
<attribute name="name">
<data type="string"/>
</attribute>
</choice>
</element>
</zeroOrMore>
</interleave>
</element>
</oneOrMore>
</element>
</zeroOrMore>
</interleave>
</element>
</oneOrMore>
<optional>
<element name="cross_sections">
<data type="string">
<param name="maxLength">255</param>
</data>
</element>
</optional>
<optional>
<element name="multipole_library">
<data type="string">
<param name="maxLength">255</param>
</data>
</element>
</optional>
</interleave>
</element>

View file

@ -7,5 +7,5 @@ from testing_harness import ParticleRestartTestHarness
if __name__ == '__main__':
harness = ParticleRestartTestHarness('particle_10_1030.*')
harness = ParticleRestartTestHarness('particle_10_1030.h5')
harness.main()

View file

@ -38,8 +38,7 @@ class VolumeTest(PyAPITestHarness):
bottom_hemisphere = openmc.Cell(3, fill=water, region=-bottom_sphere & -top_plane)
root = openmc.Universe(0, cells=(inside_cyl, top_hemisphere, bottom_hemisphere))
geometry = openmc.Geometry()
geometry.root_universe = root
geometry = openmc.Geometry(root)
geometry.export_to_xml()
# Set up stochastic volume calculation
@ -63,13 +62,13 @@ class VolumeTest(PyAPITestHarness):
outstr += 'Volume calculation {}\n'.format(i)
# Read volume calculation results
vol = openmc.VolumeCalculation.from_hdf5(filename)
volume_calc = openmc.VolumeCalculation.from_hdf5(filename)
# Write cell volumes and total # of atoms for each nuclide
for uid, results in sorted(vol.results.items()):
for uid, volume in sorted(volume_calc.volumes.items()):
outstr += 'Domain {0}: {1[0]:.4f} +/- {1[1]:.4f} cm^3\n'.format(
uid, results['volume'])
outstr += str(vol.atoms_dataframe) + '\n'
uid, volume)
outstr += str(volume_calc.atoms_dataframe) + '\n'
return outstr