mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 21:55:41 -04:00
Add VolumeCalculation object. Update settings.xml RELAX NG schema
This commit is contained in:
parent
6ef6740ebc
commit
cac6ac6f66
5 changed files with 392 additions and 94 deletions
|
|
@ -6,6 +6,9 @@ from openmc.nuclide import *
|
|||
from openmc.macroscopic import *
|
||||
from openmc.material import *
|
||||
from openmc.plots import *
|
||||
from openmc.region import *
|
||||
from openmc.volume import *
|
||||
from openmc.source import *
|
||||
from openmc.settings import *
|
||||
from openmc.surface import *
|
||||
from openmc.universe import *
|
||||
|
|
@ -18,8 +21,6 @@ from openmc.cmfd import *
|
|||
from openmc.executor import *
|
||||
from openmc.statepoint import *
|
||||
from openmc.summary import *
|
||||
from openmc.region import *
|
||||
from openmc.source import *
|
||||
from openmc.particle_restart import *
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections import Iterable, MutableSequence
|
||||
from numbers import Real, Integral
|
||||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
|
@ -7,10 +7,8 @@ import sys
|
|||
import numpy as np
|
||||
|
||||
from openmc.clean_xml import clean_xml_indentation
|
||||
from openmc.checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than, check_less_than)
|
||||
from openmc import Nuclide
|
||||
from openmc.source import Source
|
||||
import openmc.checkvalue as cv
|
||||
from openmc import Nuclide, VolumeCalculation, Source
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
|
@ -137,6 +135,8 @@ class Settings(object):
|
|||
resonance cross sections.
|
||||
resonance_scattering : ResonanceScattering or iterable of ResonanceScattering
|
||||
The elastic scattering model to use for resonant isotopes
|
||||
volume_calculations : VolumeCalculation or iterable of VolumeCalculation
|
||||
Stochastic volume calculation specifications
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -220,6 +220,8 @@ class Settings(object):
|
|||
self._multipole_active = None
|
||||
|
||||
self._resonance_scattering = None
|
||||
self._volume_calculations = cv.CheckedList(VolumeCalculation,
|
||||
'volume calculations')
|
||||
|
||||
@property
|
||||
def run_mode(self):
|
||||
|
|
@ -421,6 +423,10 @@ class Settings(object):
|
|||
def resonance_scattering(self):
|
||||
return self._resonance_scattering
|
||||
|
||||
@property
|
||||
def volume_calculations(self):
|
||||
return self._volume_calculations
|
||||
|
||||
@run_mode.setter
|
||||
def run_mode(self, run_mode):
|
||||
if run_mode not in ['eigenvalue', 'fixed source']:
|
||||
|
|
@ -431,26 +437,26 @@ class Settings(object):
|
|||
|
||||
@batches.setter
|
||||
def batches(self, batches):
|
||||
check_type('batches', batches, Integral)
|
||||
check_greater_than('batches', batches, 0)
|
||||
cv.check_type('batches', batches, Integral)
|
||||
cv.check_greater_than('batches', batches, 0)
|
||||
self._batches = batches
|
||||
|
||||
@generations_per_batch.setter
|
||||
def generations_per_batch(self, generations_per_batch):
|
||||
check_type('generations per patch', generations_per_batch, Integral)
|
||||
check_greater_than('generations per batch', generations_per_batch, 0)
|
||||
cv.check_type('generations per patch', generations_per_batch, Integral)
|
||||
cv.check_greater_than('generations per batch', generations_per_batch, 0)
|
||||
self._generations_per_batch = generations_per_batch
|
||||
|
||||
@inactive.setter
|
||||
def inactive(self, inactive):
|
||||
check_type('inactive batches', inactive, Integral)
|
||||
check_greater_than('inactive batches', inactive, 0, True)
|
||||
cv.check_type('inactive batches', inactive, Integral)
|
||||
cv.check_greater_than('inactive batches', inactive, 0, True)
|
||||
self._inactive = inactive
|
||||
|
||||
@particles.setter
|
||||
def particles(self, particles):
|
||||
check_type('particles', particles, Integral)
|
||||
check_greater_than('particles', particles, 0)
|
||||
cv.check_type('particles', particles, Integral)
|
||||
cv.check_greater_than('particles', particles, 0)
|
||||
self._particles = particles
|
||||
|
||||
@keff_trigger.setter
|
||||
|
|
@ -484,14 +490,14 @@ class Settings(object):
|
|||
|
||||
@energy_mode.setter
|
||||
def energy_mode(self, energy_mode):
|
||||
check_value('energy mode', energy_mode,
|
||||
cv.check_value('energy mode', energy_mode,
|
||||
['continuous-energy', 'multi-group'])
|
||||
self._energy_mode = energy_mode
|
||||
|
||||
@max_order.setter
|
||||
def max_order(self, max_order):
|
||||
check_type('maximum scattering order', max_order, Integral)
|
||||
check_greater_than('maximum scattering order', max_order, 0, True)
|
||||
cv.check_type('maximum scattering order', max_order, Integral)
|
||||
cv.check_greater_than('maximum scattering order', max_order, 0, True)
|
||||
self._max_order = max_order
|
||||
|
||||
@source.setter
|
||||
|
|
@ -499,7 +505,7 @@ class Settings(object):
|
|||
if isinstance(source, Source):
|
||||
self._source = [source,]
|
||||
else:
|
||||
check_type('source distribution', source, Iterable, Source)
|
||||
cv.check_type('source distribution', source, Iterable, Source)
|
||||
self._source = source
|
||||
|
||||
@output.setter
|
||||
|
|
@ -525,197 +531,197 @@ class Settings(object):
|
|||
|
||||
@output_path.setter
|
||||
def output_path(self, output_path):
|
||||
check_type('output path', output_path, basestring)
|
||||
cv.check_type('output path', output_path, basestring)
|
||||
self._output_path = output_path
|
||||
|
||||
@verbosity.setter
|
||||
def verbosity(self, verbosity):
|
||||
check_type('verbosity', verbosity, Integral)
|
||||
check_greater_than('verbosity', verbosity, 1, True)
|
||||
check_less_than('verbosity', verbosity, 10, True)
|
||||
cv.check_type('verbosity', verbosity, Integral)
|
||||
cv.check_greater_than('verbosity', verbosity, 1, True)
|
||||
cv.check_less_than('verbosity', verbosity, 10, True)
|
||||
self._verbosity = verbosity
|
||||
|
||||
@statepoint_batches.setter
|
||||
def statepoint_batches(self, batches):
|
||||
check_type('statepoint batches', batches, Iterable, Integral)
|
||||
cv.check_type('statepoint batches', batches, Iterable, Integral)
|
||||
for batch in batches:
|
||||
check_greater_than('statepoint batch', batch, 0)
|
||||
cv.check_greater_than('statepoint batch', batch, 0)
|
||||
self._statepoint_batches = batches
|
||||
|
||||
@statepoint_interval.setter
|
||||
def statepoint_interval(self, interval):
|
||||
check_type('statepoint interval', interval, Integral)
|
||||
cv.check_type('statepoint interval', interval, Integral)
|
||||
self._statepoint_interval = interval
|
||||
|
||||
@sourcepoint_batches.setter
|
||||
def sourcepoint_batches(self, batches):
|
||||
check_type('sourcepoint batches', batches, Iterable, Integral)
|
||||
cv.check_type('sourcepoint batches', batches, Iterable, Integral)
|
||||
for batch in batches:
|
||||
check_greater_than('sourcepoint batch', batch, 0)
|
||||
cv.check_greater_than('sourcepoint batch', batch, 0)
|
||||
self._sourcepoint_batches = batches
|
||||
|
||||
@sourcepoint_interval.setter
|
||||
def sourcepoint_interval(self, interval):
|
||||
check_type('sourcepoint interval', interval, Integral)
|
||||
cv.check_type('sourcepoint interval', interval, Integral)
|
||||
self._sourcepoint_interval = interval
|
||||
|
||||
@sourcepoint_separate.setter
|
||||
def sourcepoint_separate(self, source_separate):
|
||||
check_type('sourcepoint separate', source_separate, bool)
|
||||
cv.check_type('sourcepoint separate', source_separate, bool)
|
||||
self._sourcepoint_separate = source_separate
|
||||
|
||||
@sourcepoint_write.setter
|
||||
def sourcepoint_write(self, source_write):
|
||||
check_type('sourcepoint write', source_write, bool)
|
||||
cv.check_type('sourcepoint write', source_write, bool)
|
||||
self._sourcepoint_write = source_write
|
||||
|
||||
@sourcepoint_overwrite.setter
|
||||
def sourcepoint_overwrite(self, source_overwrite):
|
||||
check_type('sourcepoint overwrite', source_overwrite, bool)
|
||||
cv.check_type('sourcepoint overwrite', source_overwrite, bool)
|
||||
self._sourcepoint_overwrite = source_overwrite
|
||||
|
||||
@confidence_intervals.setter
|
||||
def confidence_intervals(self, confidence_intervals):
|
||||
check_type('confidence interval', confidence_intervals, bool)
|
||||
cv.check_type('confidence interval', confidence_intervals, bool)
|
||||
self._confidence_intervals = confidence_intervals
|
||||
|
||||
@cross_sections.setter
|
||||
def cross_sections(self, cross_sections):
|
||||
check_type('cross sections', cross_sections, basestring)
|
||||
cv.check_type('cross sections', cross_sections, basestring)
|
||||
self._cross_sections = cross_sections
|
||||
|
||||
@multipole_library.setter
|
||||
def multipole_library(self, multipole_library):
|
||||
check_type('cross sections', multipole_library, basestring)
|
||||
cv.check_type('cross sections', multipole_library, basestring)
|
||||
self._multipole_library = multipole_library
|
||||
|
||||
@energy_grid.setter
|
||||
def energy_grid(self, energy_grid):
|
||||
check_value('energy grid', energy_grid,
|
||||
cv.check_value('energy grid', energy_grid,
|
||||
['nuclide', 'logarithm', 'material-union'])
|
||||
self._energy_grid = energy_grid
|
||||
|
||||
@ptables.setter
|
||||
def ptables(self, ptables):
|
||||
check_type('probability tables', ptables, bool)
|
||||
cv.check_type('probability tables', ptables, bool)
|
||||
self._ptables = ptables
|
||||
|
||||
@run_cmfd.setter
|
||||
def run_cmfd(self, run_cmfd):
|
||||
check_type('run_cmfd', run_cmfd, bool)
|
||||
cv.check_type('run_cmfd', run_cmfd, bool)
|
||||
self._run_cmfd = run_cmfd
|
||||
|
||||
@seed.setter
|
||||
def seed(self, seed):
|
||||
check_type('random number generator seed', seed, Integral)
|
||||
check_greater_than('random number generator seed', seed, 0)
|
||||
cv.check_type('random number generator seed', seed, Integral)
|
||||
cv.check_greater_than('random number generator seed', seed, 0)
|
||||
self._seed = seed
|
||||
|
||||
@survival_biasing.setter
|
||||
def survival_biasing(self, survival_biasing):
|
||||
check_type('survival biasing', survival_biasing, bool)
|
||||
cv.check_type('survival biasing', survival_biasing, bool)
|
||||
self._survival_biasing = survival_biasing
|
||||
|
||||
@weight.setter
|
||||
def weight(self, weight):
|
||||
check_type('weight cutoff', weight, Real)
|
||||
check_greater_than('weight cutoff', weight, 0.0)
|
||||
cv.check_type('weight cutoff', weight, Real)
|
||||
cv.check_greater_than('weight cutoff', weight, 0.0)
|
||||
self._weight = weight
|
||||
|
||||
@weight_avg.setter
|
||||
def weight_avg(self, weight_avg):
|
||||
check_type('average survival weight', weight_avg, Real)
|
||||
check_greater_than('average survival weight', weight_avg, 0.0)
|
||||
cv.check_type('average survival weight', weight_avg, Real)
|
||||
cv.check_greater_than('average survival weight', weight_avg, 0.0)
|
||||
self._weight_avg = weight_avg
|
||||
|
||||
@entropy_dimension.setter
|
||||
def entropy_dimension(self, dimension):
|
||||
check_type('entropy mesh dimension', dimension, Iterable, Integral)
|
||||
check_length('entropy mesh dimension', dimension, 3)
|
||||
cv.check_type('entropy mesh dimension', dimension, Iterable, Integral)
|
||||
cv.check_length('entropy mesh dimension', dimension, 3)
|
||||
self._entropy_dimension = dimension
|
||||
|
||||
@entropy_lower_left.setter
|
||||
def entropy_lower_left(self, lower_left):
|
||||
check_type('entropy mesh lower left corner', lower_left,
|
||||
cv.check_type('entropy mesh lower left corner', lower_left,
|
||||
Iterable, Real)
|
||||
check_length('entropy mesh lower left corner', lower_left, 3)
|
||||
cv.check_length('entropy mesh lower left corner', lower_left, 3)
|
||||
self._entropy_lower_left = lower_left
|
||||
|
||||
@entropy_upper_right.setter
|
||||
def entropy_upper_right(self, upper_right):
|
||||
check_type('entropy mesh upper right corner', upper_right,
|
||||
cv.check_type('entropy mesh upper right corner', upper_right,
|
||||
Iterable, Real)
|
||||
check_length('entropy mesh upper right corner', upper_right, 3)
|
||||
cv.check_length('entropy mesh upper right corner', upper_right, 3)
|
||||
self._entropy_upper_right = upper_right
|
||||
|
||||
@trigger_active.setter
|
||||
def trigger_active(self, trigger_active):
|
||||
check_type('trigger active', trigger_active, bool)
|
||||
cv.check_type('trigger active', trigger_active, bool)
|
||||
self._trigger_active = trigger_active
|
||||
|
||||
@trigger_max_batches.setter
|
||||
def trigger_max_batches(self, trigger_max_batches):
|
||||
check_type('trigger maximum batches', trigger_max_batches, Integral)
|
||||
check_greater_than('trigger maximum batches', trigger_max_batches, 0)
|
||||
cv.check_type('trigger maximum batches', trigger_max_batches, Integral)
|
||||
cv.check_greater_than('trigger maximum batches', trigger_max_batches, 0)
|
||||
self._trigger_max_batches = trigger_max_batches
|
||||
|
||||
@trigger_batch_interval.setter
|
||||
def trigger_batch_interval(self, trigger_batch_interval):
|
||||
check_type('trigger batch interval', trigger_batch_interval, Integral)
|
||||
check_greater_than('trigger batch interval', trigger_batch_interval, 0)
|
||||
cv.check_type('trigger batch interval', trigger_batch_interval, Integral)
|
||||
cv.check_greater_than('trigger batch interval', trigger_batch_interval, 0)
|
||||
self._trigger_batch_interval = trigger_batch_interval
|
||||
|
||||
@no_reduce.setter
|
||||
def no_reduce(self, no_reduce):
|
||||
check_type('no reduction option', no_reduce, bool)
|
||||
cv.check_type('no reduction option', no_reduce, bool)
|
||||
self._no_reduce = no_reduce
|
||||
|
||||
@threads.setter
|
||||
def threads(self, threads):
|
||||
check_type('number of threads', threads, Integral)
|
||||
check_greater_than('number of threads', threads, 0)
|
||||
cv.check_type('number of threads', threads, Integral)
|
||||
cv.check_greater_than('number of threads', threads, 0)
|
||||
self._threads = threads
|
||||
|
||||
@trace.setter
|
||||
def trace(self, trace):
|
||||
check_type('trace', trace, Iterable, Integral)
|
||||
check_length('trace', trace, 3)
|
||||
check_greater_than('trace batch', trace[0], 0)
|
||||
check_greater_than('trace generation', trace[1], 0)
|
||||
check_greater_than('trace particle', trace[2], 0)
|
||||
cv.check_type('trace', trace, Iterable, Integral)
|
||||
cv.check_length('trace', trace, 3)
|
||||
cv.check_greater_than('trace batch', trace[0], 0)
|
||||
cv.check_greater_than('trace generation', trace[1], 0)
|
||||
cv.check_greater_than('trace particle', trace[2], 0)
|
||||
self._trace = trace
|
||||
|
||||
@track.setter
|
||||
def track(self, track):
|
||||
check_type('track', track, Iterable, Integral)
|
||||
cv.check_type('track', track, Iterable, Integral)
|
||||
if len(track) % 3 != 0:
|
||||
msg = 'Unable to set the track to "{0}" since its length is ' \
|
||||
'not a multiple of 3'.format(track)
|
||||
raise ValueError(msg)
|
||||
for t in zip(track[::3], track[1::3], track[2::3]):
|
||||
check_greater_than('track batch', t[0], 0)
|
||||
check_greater_than('track generation', t[0], 0)
|
||||
check_greater_than('track particle', t[0], 0)
|
||||
cv.check_greater_than('track batch', t[0], 0)
|
||||
cv.check_greater_than('track generation', t[0], 0)
|
||||
cv.check_greater_than('track particle', t[0], 0)
|
||||
self._track = track
|
||||
|
||||
@ufs_dimension.setter
|
||||
def ufs_dimension(self, dimension):
|
||||
check_type('UFS mesh dimension', dimension, Iterable, Integral)
|
||||
check_length('UFS mesh dimension', dimension, 3)
|
||||
cv.check_type('UFS mesh dimension', dimension, Iterable, Integral)
|
||||
cv.check_length('UFS mesh dimension', dimension, 3)
|
||||
for dim in dimension:
|
||||
check_greater_than('UFS mesh dimension', dim, 1, True)
|
||||
cv.check_greater_than('UFS mesh dimension', dim, 1, True)
|
||||
self._ufs_dimension = dimension
|
||||
|
||||
@ufs_lower_left.setter
|
||||
def ufs_lower_left(self, lower_left):
|
||||
check_type('UFS mesh lower left corner', lower_left, Iterable, Real)
|
||||
check_length('UFS mesh lower left corner', lower_left, 3)
|
||||
cv.check_type('UFS mesh lower left corner', lower_left, Iterable, Real)
|
||||
cv.check_length('UFS mesh lower left corner', lower_left, 3)
|
||||
self._ufs_lower_left = lower_left
|
||||
|
||||
@ufs_upper_right.setter
|
||||
def ufs_upper_right(self, upper_right):
|
||||
check_type('UFS mesh upper right corner', upper_right, Iterable, Real)
|
||||
check_length('UFS mesh upper right corner', upper_right, 3)
|
||||
cv.check_type('UFS mesh upper right corner', upper_right, Iterable, Real)
|
||||
cv.check_length('UFS mesh upper right corner', upper_right, 3)
|
||||
self._ufs_upper_right = upper_right
|
||||
|
||||
@dd_mesh_dimension.setter
|
||||
|
|
@ -724,8 +730,8 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD mesh dimension', dimension, Iterable, Integral)
|
||||
check_length('DD mesh dimension', dimension, 3)
|
||||
cv.check_type('DD mesh dimension', dimension, Iterable, Integral)
|
||||
cv.check_length('DD mesh dimension', dimension, 3)
|
||||
|
||||
self._dd_mesh_dimension = dimension
|
||||
|
||||
|
|
@ -735,8 +741,8 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD mesh lower left corner', lower_left, Iterable, Real)
|
||||
check_length('DD mesh lower left corner', lower_left, 3)
|
||||
cv.check_type('DD mesh lower left corner', lower_left, Iterable, Real)
|
||||
cv.check_length('DD mesh lower left corner', lower_left, 3)
|
||||
|
||||
self._dd_mesh_lower_left = lower_left
|
||||
|
||||
|
|
@ -746,8 +752,8 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD mesh upper right corner', upper_right, Iterable, Real)
|
||||
check_length('DD mesh upper right corner', upper_right, 3)
|
||||
cv.check_type('DD mesh upper right corner', upper_right, Iterable, Real)
|
||||
cv.check_length('DD mesh upper right corner', upper_right, 3)
|
||||
|
||||
self._dd_mesh_upper_right = upper_right
|
||||
|
||||
|
|
@ -757,7 +763,7 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD nodemap', nodemap, Iterable)
|
||||
cv.check_type('DD nodemap', nodemap, Iterable)
|
||||
|
||||
nodemap = np.array(nodemap).flatten()
|
||||
|
||||
|
|
@ -782,7 +788,7 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD allow leakage', allow, bool)
|
||||
cv.check_type('DD allow leakage', allow, bool)
|
||||
|
||||
self._dd_allow_leakage = allow
|
||||
|
||||
|
|
@ -793,25 +799,34 @@ class Settings(object):
|
|||
warnings.warn('This feature is not yet implemented in a release '
|
||||
'version of openmc')
|
||||
|
||||
check_type('DD count interactions', interactions, bool)
|
||||
cv.check_type('DD count interactions', interactions, bool)
|
||||
|
||||
self._dd_count_interactions = interactions
|
||||
|
||||
@use_windowed_multipole.setter
|
||||
def use_windowed_multipole(self, active):
|
||||
check_type('use_windowed_multipole', active, bool)
|
||||
cv.check_type('use_windowed_multipole', active, bool)
|
||||
self._multipole_active = active
|
||||
|
||||
@resonance_scattering.setter
|
||||
def resonance_scattering(self, res):
|
||||
if isinstance(res, Iterable):
|
||||
check_type('resonance_scattering', res, Iterable,
|
||||
cv.check_type('resonance_scattering', res, Iterable,
|
||||
ResonanceScattering)
|
||||
self._resonance_scattering = res
|
||||
else:
|
||||
check_type('resonance_scattering', res, ResonanceScattering)
|
||||
cv.check_type('resonance_scattering', res, ResonanceScattering)
|
||||
self._resonance_scattering = [res]
|
||||
|
||||
@volume_calculations.setter
|
||||
def volume_calculations(self, vol_calcs):
|
||||
name = 'stochastic volume calculations'
|
||||
if not isinstance(vol_calcs, MutableSequence):
|
||||
vol_calcs = [vol_calcs]
|
||||
cv.check_type(name, vol_calcs, MutableSequence)
|
||||
self._volume_calculations = cv.CheckedList(VolumeCalculation,
|
||||
name, vol_calcs)
|
||||
|
||||
def _create_run_mode_subelement(self):
|
||||
|
||||
if self.run_mode == 'eigenvalue':
|
||||
|
|
@ -873,6 +888,10 @@ class Settings(object):
|
|||
for source in self.source:
|
||||
self._settings_file.append(source.to_xml())
|
||||
|
||||
def _create_volume_calcs_subelement(self):
|
||||
for calc in self.volume_calculations:
|
||||
self._settings_file.append(calc.to_xml())
|
||||
|
||||
def _create_output_subelement(self):
|
||||
if self._output is not None:
|
||||
element = ET.SubElement(self._settings_file, "output")
|
||||
|
|
@ -1154,6 +1173,7 @@ class Settings(object):
|
|||
self._create_dd_subelement()
|
||||
self._create_use_multipole_subelement()
|
||||
self._create_resonance_scattering_element()
|
||||
self._create_volume_calcs_subelement()
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
clean_xml_indentation(self._settings_file)
|
||||
|
|
@ -1216,29 +1236,29 @@ class ResonanceScattering(object):
|
|||
|
||||
@nuclide.setter
|
||||
def nuclide(self, nuc):
|
||||
check_type('nuclide', nuc, Nuclide)
|
||||
cv.check_type('nuclide', nuc, Nuclide)
|
||||
self._nuclide = nuc
|
||||
|
||||
@nuclide_0K.setter
|
||||
def nuclide_0K(self, nuc):
|
||||
check_type('nuclide_0K', nuc, Nuclide)
|
||||
cv.check_type('nuclide_0K', nuc, Nuclide)
|
||||
self._nuclide_0K = nuc
|
||||
|
||||
@method.setter
|
||||
def method(self, m):
|
||||
check_value('method', m, ('ARES', 'CXS', 'DBRC', 'WCM'))
|
||||
cv.check_value('method', m, ('ARES', 'CXS', 'DBRC', 'WCM'))
|
||||
self._method = m
|
||||
|
||||
@E_min.setter
|
||||
def E_min(self, E):
|
||||
check_type('E_min', E, Real)
|
||||
check_greater_than('E_min', E, 0, True)
|
||||
cv.check_type('E_min', E, Real)
|
||||
cv.check_greater_than('E_min', E, 0, True)
|
||||
self._E_min = E
|
||||
|
||||
@E_max.setter
|
||||
def E_max(self, E):
|
||||
check_type('E_max', E, Real)
|
||||
check_greater_than('E_max', E, 0, True)
|
||||
cv.check_type('E_max', E, Real)
|
||||
cv.check_greater_than('E_max', E, 0, True)
|
||||
self._E_max = E
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
|
|
|
|||
204
openmc/volume.py
Normal file
204
openmc/volume.py
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
from collections import Iterable, Mapping
|
||||
from numbers import Real, Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from openmc import Cell, Union
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
class VolumeCalculation(object):
|
||||
"""Stochastic volume calculation specifications and results.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cells : Iterable of Cell
|
||||
Cells to find volumes of
|
||||
samples : int
|
||||
Number of samples used to generate volume estimates
|
||||
lower_left : Iterable of float
|
||||
Lower-left coordinates of bounding box used to sample points. If this
|
||||
argument is not supplied, an attempt is made to automatically determine
|
||||
a bounding box.
|
||||
upper_right : Iterable of float
|
||||
Upper-right coordinates of bounding box used to sample points. If this
|
||||
argument is not supplied, an attempt is made to automatically determine
|
||||
a bounding box.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
cell_ids : Iterable of int
|
||||
IDs of cells to find volumes of
|
||||
samples : int
|
||||
Number of samples used to generate volume estimates
|
||||
lower_left : Iterable of float
|
||||
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 cells and values are
|
||||
dictionaries with calculated volumes and total number of atoms for each
|
||||
nuclide present in the cell.
|
||||
volumes : dict
|
||||
Dictionary whose keys are unique IDs of cells and values are the
|
||||
estimated volumes
|
||||
atoms_dataframe : pandas.DataFrame
|
||||
DataFrame showing the estimated number of atoms for each nuclide present
|
||||
in each cell specified.
|
||||
|
||||
"""
|
||||
def __init__(self, cells, samples, lower_left=None,
|
||||
upper_right=None):
|
||||
self._results = None
|
||||
|
||||
cv.check_type('cells', cells, Iterable, Cell)
|
||||
self.cell_ids = [c.id for c in cells]
|
||||
self.samples = samples
|
||||
|
||||
if lower_left is not None:
|
||||
self.lower_left = lower_left
|
||||
if upper_right is None:
|
||||
raise ValueError('Both lower-left and upper-right coordinates '
|
||||
'should be specified')
|
||||
self.upper_right = upper_right
|
||||
else:
|
||||
ll, ur = Union(*[c.region for c in cells]).bounding_box
|
||||
if np.any(np.isinf(ll)) or np.any(np.isinf(ur)):
|
||||
raise ValueError('Could not automatically determine bounding box '
|
||||
'for stochastic volume calculation.')
|
||||
else:
|
||||
self.lower_left = ll
|
||||
self.upper_right = ur
|
||||
|
||||
@property
|
||||
def cell_ids(self):
|
||||
return self._cell_ids
|
||||
|
||||
@property
|
||||
def samples(self):
|
||||
return self._samples
|
||||
|
||||
@property
|
||||
def lower_left(self):
|
||||
return self._lower_left
|
||||
|
||||
@property
|
||||
def upper_right(self):
|
||||
return self._upper_right
|
||||
|
||||
@property
|
||||
def results(self):
|
||||
return self._results
|
||||
|
||||
@property
|
||||
def volumes(self):
|
||||
return {uid: results['volume'] for uid, results in self.results.items()}
|
||||
|
||||
@property
|
||||
def atoms_dataframe(self):
|
||||
items = []
|
||||
columns = ['Cell', 'Nuclide', 'Atoms', 'Uncertainty']
|
||||
for cell_id, results in self.results.items():
|
||||
for name, atoms in results['atoms']:
|
||||
items.append((cell_id, name, atoms[0], atoms[1]))
|
||||
|
||||
return pd.DataFrame.from_records(items, columns=columns)
|
||||
|
||||
@cell_ids.setter
|
||||
def cell_ids(self, cell_ids):
|
||||
cv.check_type('cell IDs', cell_ids, Iterable, Real)
|
||||
self._cell_ids = cell_ids
|
||||
|
||||
@samples.setter
|
||||
def samples(self, samples):
|
||||
cv.check_type('number of samples', samples, Integral)
|
||||
cv.check_greater_than('number of samples', samples, 0)
|
||||
self._samples = samples
|
||||
|
||||
@lower_left.setter
|
||||
def lower_left(self, lower_left):
|
||||
name = 'lower-left bounding box coordinates',
|
||||
cv.check_type(name, lower_left, Iterable, Real)
|
||||
cv.check_length(name, lower_left, 3)
|
||||
self._lower_left = lower_left
|
||||
|
||||
@upper_right.setter
|
||||
def upper_right(self, upper_right):
|
||||
name = 'upper-right bounding box coordinates'
|
||||
cv.check_type(name, upper_right, Iterable, Real)
|
||||
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
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, filename):
|
||||
"""Load stochastic volume calculation results from HDF5 file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Path to volume.h5 file
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.VolumeCalculation
|
||||
Results of the stochastic volume calculation
|
||||
|
||||
"""
|
||||
import h5py
|
||||
|
||||
with h5py.File(filename, 'r') as f:
|
||||
samples = f.attrs['samples']
|
||||
lower_left = f.attrs['lower_left']
|
||||
upper_right = f.attrs['upper_right']
|
||||
|
||||
results = {}
|
||||
cell_ids = []
|
||||
for obj_name in f:
|
||||
if obj_name.startswith('cell_'):
|
||||
cell_id = int(obj_name[5:])
|
||||
cell_ids.append(cell_id)
|
||||
group = f[obj_name]
|
||||
volume = tuple(group['volume'].value)
|
||||
nucnames = group['nuclides'].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[cell_id] = {'volume': volume, 'atoms': atom_list}
|
||||
|
||||
# Instantiate some throw-away cells that are used by the constructor to
|
||||
# assign IDs
|
||||
cells = [Cell(uid) for uid in cell_ids]
|
||||
|
||||
# Instantiate the class and assign results
|
||||
vol = cls(cells, samples, lower_left, upper_right)
|
||||
vol.results = results
|
||||
return vol
|
||||
|
||||
def to_xml(self):
|
||||
"""Return XML representation of the volume calculation
|
||||
|
||||
Returns
|
||||
-------
|
||||
element : xml.etree.ElementTree.Element
|
||||
XML element containing volume calculation data
|
||||
|
||||
"""
|
||||
element = ET.Element("volume_calc")
|
||||
cell_elem = ET.SubElement(element, "cells")
|
||||
cell_elem.text = ' '.join(str(uid) for uid in self.cell_ids)
|
||||
samples_elem = ET.SubElement(element, "samples")
|
||||
samples_elem.text = str(self.samples)
|
||||
ll_elem = ET.SubElement(element, "lower_left")
|
||||
ll_elem.text = ' '.join(str(x) for x in self.lower_left)
|
||||
ur_elem = ET.SubElement(element, "upper_right")
|
||||
ur_elem.text = ' '.join(str(x) for x in self.upper_right)
|
||||
return element
|
||||
|
|
@ -142,6 +142,17 @@ element settings {
|
|||
|
||||
element verbosity { xsd:positiveInteger }? &
|
||||
|
||||
element volume_calc {
|
||||
(element cells { list { xsd:positiveInteger+ } } |
|
||||
attribute cells { list { xsd:positiveInteger+ } }) &
|
||||
(element samples { xsd:positiveInteger } |
|
||||
attribute samples { xsd:positiveInteger }) &
|
||||
(element lower_left { list { xsd:double+ } } |
|
||||
attribute lower_left { list { xsd:double+ } }) &
|
||||
(element upper_right { list { xsd:double+ } } |
|
||||
attribute upper_right { list { xsd:double+ } })
|
||||
}+ &
|
||||
|
||||
element uniform_fs{
|
||||
(element dimension { list { xsd:positiveInteger+ } } |
|
||||
attribute dimension { list { xsd:positiveInteger+ } }) &
|
||||
|
|
|
|||
|
|
@ -625,6 +625,68 @@
|
|||
<data type="positiveInteger"/>
|
||||
</element>
|
||||
</optional>
|
||||
<oneOrMore>
|
||||
<element name="volume_calc">
|
||||
<interleave>
|
||||
<choice>
|
||||
<element name="cells">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="positiveInteger"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</element>
|
||||
<attribute name="cells">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="positiveInteger"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</attribute>
|
||||
</choice>
|
||||
<choice>
|
||||
<element name="samples">
|
||||
<data type="positiveInteger"/>
|
||||
</element>
|
||||
<attribute name="samples">
|
||||
<data type="positiveInteger"/>
|
||||
</attribute>
|
||||
</choice>
|
||||
<choice>
|
||||
<element name="lower_left">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="double"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</element>
|
||||
<attribute name="lower_left">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="double"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</attribute>
|
||||
</choice>
|
||||
<choice>
|
||||
<element name="upper_right">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="double"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</element>
|
||||
<attribute name="upper_right">
|
||||
<list>
|
||||
<oneOrMore>
|
||||
<data type="double"/>
|
||||
</oneOrMore>
|
||||
</list>
|
||||
</attribute>
|
||||
</choice>
|
||||
</interleave>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
<optional>
|
||||
<element name="uniform_fs">
|
||||
<interleave>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue