From ee7b95245a981d59f9e3bc2a6ba5da1adba0c60b Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Sat, 17 Jun 2023 04:34:02 +0100 Subject: [PATCH] Static errors continuation (#2557) Co-authored-by: Christina Cai Co-authored-by: christinacai123 <63215816+christinacai123@users.noreply.github.com> --- openmc/arithmetic.py | 176 ++++----- openmc/cell.py | 184 ++++----- openmc/data/angle_distribution.py | 8 +- openmc/data/correlated.py | 32 +- openmc/data/data.py | 5 +- openmc/data/decay.py | 48 +-- openmc/data/energy_distribution.py | 97 +++-- openmc/data/fission_energy.py | 70 ++-- openmc/data/function.py | 64 +-- openmc/data/kalbach_mann.py | 40 +- openmc/data/laboratory.py | 31 +- openmc/data/multipole.py | 66 ++-- openmc/data/nbody.py | 24 +- openmc/data/neutron.py | 84 ++-- openmc/data/photon.py | 64 +-- openmc/data/product.py | 40 +- openmc/data/reaction.py | 40 +- openmc/data/resonance.py | 12 +- openmc/data/thermal.py | 8 +- openmc/data/uncorrelated.py | 8 +- openmc/data/urr.py | 40 +- openmc/filter.py | 48 +-- openmc/geometry.py | 18 +- openmc/lattice.py | 58 +-- openmc/lib/plot.py | 52 +-- openmc/lib/tally.py | 8 +- openmc/material.py | 60 +-- openmc/mesh.py | 190 ++++----- openmc/mgxs/groups.py | 8 +- openmc/mgxs/library.py | 224 +++++------ openmc/mgxs/mdgxs.py | 14 +- openmc/mgxs/mgxs.py | 392 +++++++++---------- openmc/mgxs_library.py | 170 ++++---- openmc/model/model.py | 80 ++-- openmc/model/triso.py | 136 +++---- openmc/plots.py | 218 +++++------ openmc/settings.py | 598 ++++++++++++++--------------- openmc/source.py | 100 ++--- openmc/statepoint.py | 40 +- openmc/stats/multivariate.py | 88 ++--- openmc/stats/univariate.py | 72 ++-- openmc/surface.py | 24 +- openmc/tallies.py | 220 +++++------ openmc/tally_derivative.py | 16 +- openmc/trigger.py | 16 +- openmc/universe.py | 18 +- openmc/volume.py | 110 +++--- 47 files changed, 2061 insertions(+), 2058 deletions(-) diff --git a/openmc/arithmetic.py b/openmc/arithmetic.py index 3655ef2a3d..5ca7cc6668 100644 --- a/openmc/arithmetic.py +++ b/openmc/arithmetic.py @@ -61,26 +61,26 @@ class CrossScore: def left_score(self): return self._left_score - @property - def right_score(self): - return self._right_score - - @property - def binary_op(self): - return self._binary_op - @left_score.setter def left_score(self, left_score): cv.check_type('left_score', left_score, (str, CrossScore, AggregateScore)) self._left_score = left_score + @property + def right_score(self): + return self._right_score + @right_score.setter def right_score(self, right_score): cv.check_type('right_score', right_score, (str, CrossScore, AggregateScore)) self._right_score = right_score + @property + def binary_op(self): + return self._binary_op + @binary_op.setter def binary_op(self, binary_op): cv.check_type('binary_op', binary_op, str) @@ -132,14 +132,32 @@ class CrossNuclide: def left_nuclide(self): return self._left_nuclide + @left_nuclide.setter + def left_nuclide(self, left_nuclide): + cv.check_type('left_nuclide', left_nuclide, + (openmc.Nuclide, CrossNuclide, AggregateNuclide)) + self._left_nuclide = left_nuclide + @property def right_nuclide(self): return self._right_nuclide + @right_nuclide.setter + def right_nuclide(self, right_nuclide): + cv.check_type('right_nuclide', right_nuclide, + (openmc.Nuclide, CrossNuclide, AggregateNuclide)) + self._right_nuclide = right_nuclide + @property def binary_op(self): return self._binary_op + @binary_op.setter + def binary_op(self, binary_op): + cv.check_type('binary_op', binary_op, str) + cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) + self._binary_op = binary_op + @property def name(self): @@ -163,24 +181,6 @@ class CrossNuclide: return string - @left_nuclide.setter - def left_nuclide(self, left_nuclide): - cv.check_type('left_nuclide', left_nuclide, - (openmc.Nuclide, CrossNuclide, AggregateNuclide)) - self._left_nuclide = left_nuclide - - @right_nuclide.setter - def right_nuclide(self, right_nuclide): - cv.check_type('right_nuclide', right_nuclide, - (openmc.Nuclide, CrossNuclide, AggregateNuclide)) - self._right_nuclide = right_nuclide - - @binary_op.setter - def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, str) - cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) - self._binary_op = binary_op - class CrossFilter: """A special-purpose filter used to encapsulate all combinations of two @@ -241,14 +241,32 @@ class CrossFilter: def left_filter(self): return self._left_filter + @left_filter.setter + def left_filter(self, left_filter): + cv.check_type('left_filter', left_filter, + (openmc.Filter, CrossFilter, AggregateFilter)) + self._left_filter = left_filter + @property def right_filter(self): return self._right_filter + @right_filter.setter + def right_filter(self, right_filter): + cv.check_type('right_filter', right_filter, + (openmc.Filter, CrossFilter, AggregateFilter)) + self._right_filter = right_filter + @property def binary_op(self): return self._binary_op + @binary_op.setter + def binary_op(self, binary_op): + cv.check_type('binary_op', binary_op, str) + cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) + self._binary_op = binary_op + @property def type(self): left_type = self.left_filter.type @@ -266,24 +284,6 @@ class CrossFilter: else: return 0 - @left_filter.setter - def left_filter(self, left_filter): - cv.check_type('left_filter', left_filter, - (openmc.Filter, CrossFilter, AggregateFilter)) - self._left_filter = left_filter - - @right_filter.setter - def right_filter(self, right_filter): - cv.check_type('right_filter', right_filter, - (openmc.Filter, CrossFilter, AggregateFilter)) - self._right_filter = right_filter - - @binary_op.setter - def binary_op(self, binary_op): - cv.check_type('binary_op', binary_op, str) - cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS) - self._binary_op = binary_op - def get_bin_index(self, filter_bin): """Returns the index in the CrossFilter for some bin. @@ -412,10 +412,21 @@ class AggregateScore: def scores(self): return self._scores + @scores.setter + def scores(self, scores): + cv.check_iterable_type('scores', scores, str) + self._scores = scores + @property def aggregate_op(self): return self._aggregate_op + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, (str, CrossScore)) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + @property def name(self): @@ -423,17 +434,6 @@ class AggregateScore: string = '(' + ', '.join(self.scores) + ')' return string - @scores.setter - def scores(self, scores): - cv.check_iterable_type('scores', scores, str) - self._scores = scores - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, (str, CrossScore)) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - class AggregateNuclide: """A special-purpose tally nuclide used to encapsulate an aggregate of a @@ -486,10 +486,21 @@ class AggregateNuclide: def nuclides(self): return self._nuclides + @nuclides.setter + def nuclides(self, nuclides): + cv.check_iterable_type('nuclides', nuclides, (str, CrossNuclide)) + self._nuclides = nuclides + @property def aggregate_op(self): return self._aggregate_op + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, str) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + @property def name(self): @@ -499,17 +510,6 @@ class AggregateNuclide: string = '(' + ', '.join(map(str, names)) + ')' return string - @nuclides.setter - def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, (str, CrossNuclide)) - self._nuclides = nuclides - - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, str) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op - class AggregateFilter: """A special-purpose tally filter used to encapsulate an aggregate of a @@ -588,26 +588,26 @@ class AggregateFilter: def aggregate_filter(self): return self._aggregate_filter + @aggregate_filter.setter + def aggregate_filter(self, aggregate_filter): + cv.check_type('aggregate_filter', aggregate_filter, + (openmc.Filter, CrossFilter)) + self._aggregate_filter = aggregate_filter + @property def aggregate_op(self): return self._aggregate_op + @aggregate_op.setter + def aggregate_op(self, aggregate_op): + cv.check_type('aggregate_op', aggregate_op, str) + cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) + self._aggregate_op = aggregate_op + @property def type(self): return self._type - @property - def bins(self): - return self._bins - - @property - def num_bins(self): - return len(self.bins) if self.aggregate_filter else 0 - - @property - def shape(self): - return (self.num_bins,) - @type.setter def type(self, filter_type): if filter_type not in _FILTER_TYPES: @@ -617,22 +617,22 @@ class AggregateFilter: self._type = filter_type - @aggregate_filter.setter - def aggregate_filter(self, aggregate_filter): - cv.check_type('aggregate_filter', aggregate_filter, - (openmc.Filter, CrossFilter)) - self._aggregate_filter = aggregate_filter + @property + def bins(self): + return self._bins @bins.setter def bins(self, bins): cv.check_iterable_type('bins', bins, Iterable) self._bins = list(map(tuple, bins)) - @aggregate_op.setter - def aggregate_op(self, aggregate_op): - cv.check_type('aggregate_op', aggregate_op, str) - cv.check_value('aggregate_op', aggregate_op, _TALLY_AGGREGATE_OPS) - self._aggregate_op = aggregate_op + @property + def num_bins(self): + return len(self.bins) if self.aggregate_filter else 0 + + @property + def shape(self): + return (self.num_bins,) def get_bin_index(self, filter_bin): """Returns the index in the AggregateFilter for some bin. diff --git a/openmc/cell.py b/openmc/cell.py index 5797bc0f62..b0be1ea79a 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -150,10 +150,37 @@ class Cell(IDManagerMixin): def name(self): return self._name + @name.setter + def name(self, name): + if name is not None: + cv.check_type('cell name', name, str) + self._name = name + else: + self._name = '' + @property def fill(self): return self._fill + @fill.setter + def fill(self, fill): + if fill is not None: + if isinstance(fill, Iterable): + for i, f in enumerate(fill): + if f is not None: + cv.check_type('cell.fill[i]', f, openmc.Material) + + elif not isinstance(fill, (openmc.Material, openmc.Lattice, + openmc.UniverseBase)): + msg = (f'Unable to set Cell ID="{self._id}" to use a ' + f'non-Material or Universe fill "{fill}"') + raise ValueError(msg) + self._fill = fill + + # Info about atom content can now be invalid + # (since fill has just changed) + self._atoms = None + @property def fill_type(self): if isinstance(self.fill, openmc.Material): @@ -171,10 +198,37 @@ class Cell(IDManagerMixin): def region(self): return self._region + @region.setter + def region(self, region): + if region is not None: + cv.check_type('cell region', region, Region) + self._region = region + @property def rotation(self): return self._rotation + @rotation.setter + def rotation(self, rotation): + cv.check_length('cell rotation', rotation, 3) + self._rotation = np.asarray(rotation) + + # Save rotation matrix -- the reason we do this instead of having it be + # automatically calculated when the rotation_matrix property is accessed + # is so that plotting on a rotated geometry can be done faster. + if self._rotation.ndim == 2: + # User specified rotation matrix directly + self._rotation_matrix = self._rotation + else: + phi, theta, psi = self.rotation*(-pi/180.) + c3, s3 = cos(phi), sin(phi) + c2, s2 = cos(theta), sin(theta) + c1, s1 = cos(psi), sin(psi) + self._rotation_matrix = np.array([ + [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], + [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], + [-s2, c2*s3, c2*c3]]) + @property def rotation_matrix(self): return self._rotation_matrix @@ -183,14 +237,52 @@ class Cell(IDManagerMixin): def temperature(self): return self._temperature + @temperature.setter + def temperature(self, temperature): + # Make sure temperatures are positive + cv.check_type('cell temperature', temperature, (Iterable, Real), none_ok=True) + if isinstance(temperature, Iterable): + cv.check_type('cell temperature', temperature, Iterable, Real) + for T in temperature: + cv.check_greater_than('cell temperature', T, 0.0, True) + elif isinstance(temperature, Real): + cv.check_greater_than('cell temperature', temperature, 0.0, True) + + # If this cell is filled with a universe or lattice, propagate + # temperatures to all cells contained. Otherwise, simply assign it. + if self.fill_type in ('universe', 'lattice'): + for c in self.get_all_cells().values(): + if c.fill_type == 'material': + c._temperature = temperature + else: + self._temperature = temperature + @property def translation(self): return self._translation + @translation.setter + def translation(self, translation): + cv.check_type('cell translation', translation, Iterable, Real) + cv.check_length('cell translation', translation, 3) + self._translation = np.asarray(translation) + @property def volume(self): return self._volume + @volume.setter + def volume(self, volume): + if volume is not None: + cv.check_type('cell volume', volume, (Real, UFloat)) + cv.check_greater_than('cell volume', volume, 0.0, equality=True) + + self._volume = volume + + # Info about atom content can now be invalid + # (since volume has just changed) + self._atoms = None + @property def atoms(self): if self._atoms is None: @@ -263,98 +355,6 @@ class Cell(IDManagerMixin): 'Geometry.determine_paths() method.') return self._num_instances - @name.setter - def name(self, name): - if name is not None: - cv.check_type('cell name', name, str) - self._name = name - else: - self._name = '' - - @fill.setter - def fill(self, fill): - if fill is not None: - if isinstance(fill, Iterable): - for i, f in enumerate(fill): - if f is not None: - cv.check_type('cell.fill[i]', f, openmc.Material) - - elif not isinstance(fill, (openmc.Material, openmc.Lattice, - openmc.UniverseBase)): - msg = (f'Unable to set Cell ID="{self._id}" to use a ' - f'non-Material or Universe fill "{fill}"') - raise ValueError(msg) - self._fill = fill - - # Info about atom content can now be invalid - # (since fill has just changed) - self._atoms = None - - @rotation.setter - def rotation(self, rotation): - cv.check_length('cell rotation', rotation, 3) - self._rotation = np.asarray(rotation) - - # Save rotation matrix -- the reason we do this instead of having it be - # automatically calculated when the rotation_matrix property is accessed - # is so that plotting on a rotated geometry can be done faster. - if self._rotation.ndim == 2: - # User specified rotation matrix directly - self._rotation_matrix = self._rotation - else: - phi, theta, psi = self.rotation*(-pi/180.) - c3, s3 = cos(phi), sin(phi) - c2, s2 = cos(theta), sin(theta) - c1, s1 = cos(psi), sin(psi) - self._rotation_matrix = np.array([ - [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], - [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], - [-s2, c2*s3, c2*c3]]) - - @translation.setter - def translation(self, translation): - cv.check_type('cell translation', translation, Iterable, Real) - cv.check_length('cell translation', translation, 3) - self._translation = np.asarray(translation) - - @temperature.setter - def temperature(self, temperature): - # Make sure temperatures are positive - cv.check_type('cell temperature', temperature, (Iterable, Real), none_ok=True) - if isinstance(temperature, Iterable): - cv.check_type('cell temperature', temperature, Iterable, Real) - for T in temperature: - cv.check_greater_than('cell temperature', T, 0.0, True) - elif isinstance(temperature, Real): - cv.check_greater_than('cell temperature', temperature, 0.0, True) - - # If this cell is filled with a universe or lattice, propagate - # temperatures to all cells contained. Otherwise, simply assign it. - if self.fill_type in ('universe', 'lattice'): - for c in self.get_all_cells().values(): - if c.fill_type == 'material': - c._temperature = temperature - else: - self._temperature = temperature - - @region.setter - def region(self, region): - if region is not None: - 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, UFloat)) - cv.check_greater_than('cell volume', volume, 0.0, equality=True) - - self._volume = volume - - # Info about atom content can now be invalid - # (since volume has just changed) - self._atoms = None - def add_volume_information(self, volume_calc): """Add volume information to a cell. diff --git a/openmc/data/angle_distribution.py b/openmc/data/angle_distribution.py index 4d058bcb7c..bb0eafe5a0 100644 --- a/openmc/data/angle_distribution.py +++ b/openmc/data/angle_distribution.py @@ -42,16 +42,16 @@ class AngleDistribution(EqualityMixin): def energy(self): return self._energy - @property - def mu(self): - return self._mu - @energy.setter def energy(self, energy): cv.check_type('angle distribution incoming energy', energy, Iterable, Real) self._energy = energy + @property + def mu(self): + return self._mu + @mu.setter def mu(self, mu): cv.check_type('angle distribution scattering cosines', mu, diff --git a/openmc/data/correlated.py b/openmc/data/correlated.py index 1aa4c20c8c..f131ce30d5 100644 --- a/openmc/data/correlated.py +++ b/openmc/data/correlated.py @@ -58,46 +58,46 @@ class CorrelatedAngleEnergy(AngleEnergy): def breakpoints(self): return self._breakpoints - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - - @property - def mu(self): - return self._mu - @breakpoints.setter def breakpoints(self, breakpoints): cv.check_type('correlated angle-energy breakpoints', breakpoints, Iterable, Integral) self._breakpoints = breakpoints + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_type('correlated angle-energy interpolation', interpolation, Iterable, Integral) self._interpolation = interpolation + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('correlated angle-energy incoming energy', energy, Iterable, Real) self._energy = energy + @property + def energy_out(self): + return self._energy_out + @energy_out.setter def energy_out(self, energy_out): cv.check_type('correlated angle-energy outgoing energy', energy_out, Iterable, Univariate) self._energy_out = energy_out + @property + def mu(self): + return self._mu + @mu.setter def mu(self, mu): cv.check_iterable_type('correlated angle-energy outgoing cosine', diff --git a/openmc/data/data.py b/openmc/data/data.py index 16c7ecf54c..609a901d9b 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -5,6 +5,7 @@ import re from pathlib import Path from math import sqrt, log from warnings import warn +from typing import Dict # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions # of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), @@ -195,13 +196,13 @@ AVOGADRO = 6.02214076e23 NEUTRON_MASS = 1.00866491595 # Used in atomic_mass function as a cache -_ATOMIC_MASS = {} +_ATOMIC_MASS: Dict[str, float] = {} # Regex for GNDS nuclide names (used in zam function) _GNDS_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)') # Used in half_life function as a cache -_HALF_LIFE = {} +_HALF_LIFE: Dict[str, float] = {} _LOG_TWO = log(2.0) def atomic_mass(isotope): diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 57327c07f3..4f9d6f4603 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -228,6 +228,18 @@ class DecayMode(EqualityMixin): def branching_ratio(self): return self._branching_ratio + @branching_ratio.setter + def branching_ratio(self, branching_ratio): + cv.check_type('branching ratio', branching_ratio, UFloat) + cv.check_greater_than('branching ratio', + branching_ratio.nominal_value, 0.0, True) + if branching_ratio.nominal_value == 0.0: + warn('Decay mode {} of parent {} has a zero branching ratio.' + .format(self.modes, self.parent)) + cv.check_greater_than('branching ratio uncertainty', + branching_ratio.std_dev, 0.0, True) + self._branching_ratio = branching_ratio + @property def daughter(self): # Determine atomic number and mass number of parent @@ -249,29 +261,18 @@ class DecayMode(EqualityMixin): else: return '{}{}'.format(ATOMIC_SYMBOL[Z], A) - @property - def energy(self): - return self._energy - - @property - def modes(self): - return self._modes - @property def parent(self): return self._parent - @branching_ratio.setter - def branching_ratio(self, branching_ratio): - cv.check_type('branching ratio', branching_ratio, UFloat) - cv.check_greater_than('branching ratio', - branching_ratio.nominal_value, 0.0, True) - if branching_ratio.nominal_value == 0.0: - warn('Decay mode {} of parent {} has a zero branching ratio.' - .format(self.modes, self.parent)) - cv.check_greater_than('branching ratio uncertainty', - branching_ratio.std_dev, 0.0, True) - self._branching_ratio = branching_ratio + @parent.setter + def parent(self, parent): + cv.check_type('parent nuclide', parent, str) + self._parent = parent + + @property + def energy(self): + return self._energy @energy.setter def energy(self, energy): @@ -281,16 +282,15 @@ class DecayMode(EqualityMixin): energy.std_dev, 0.0, True) self._energy = energy + @property + def modes(self): + return self._modes + @modes.setter def modes(self, modes): cv.check_type('decay modes', modes, Iterable, str) self._modes = modes - @parent.setter - def parent(self, parent): - cv.check_type('parent nuclide', parent, str) - self._parent = parent - class Decay(EqualityMixin): """Radioactive decay data. diff --git a/openmc/data/energy_distribution.py b/openmc/data/energy_distribution.py index 3b6d325eff..a13893a68f 100644 --- a/openmc/data/energy_distribution.py +++ b/openmc/data/energy_distribution.py @@ -253,15 +253,15 @@ class MaxwellEnergy(EnergyDistribution): def theta(self): return self._theta - @property - def u(self): - return self._u - @theta.setter def theta(self, theta): cv.check_type('Maxwell theta', theta, Tabulated1D) self._theta = theta + @property + def u(self): + return self._u + @u.setter def u(self, u): cv.check_type('Maxwell restriction energy', u, Real) @@ -386,15 +386,15 @@ class Evaporation(EnergyDistribution): def theta(self): return self._theta - @property - def u(self): - return self._u - @theta.setter def theta(self, theta): cv.check_type('Evaporation theta', theta, Tabulated1D) self._theta = theta + @property + def u(self): + return self._u + @u.setter def u(self, u): cv.check_type('Evaporation restriction energy', u, Real) @@ -523,24 +523,24 @@ class WattEnergy(EnergyDistribution): def a(self): return self._a - @property - def b(self): - return self._b - - @property - def u(self): - return self._u - @a.setter def a(self, a): cv.check_type('Watt a', a, Tabulated1D) self._a = a + @property + def b(self): + return self._b + @b.setter def b(self, b): cv.check_type('Watt b', b, Tabulated1D) self._b = b + @property + def u(self): + return self._u + @u.setter def u(self, u): cv.check_type('Watt restriction energy', u, Real) @@ -691,14 +691,6 @@ class MadlandNix(EnergyDistribution): def efl(self): return self._efl - @property - def efh(self): - return self._efh - - @property - def tm(self): - return self._tm - @efl.setter def efl(self, efl): name = 'Madland-Nix light fragment energy' @@ -706,6 +698,10 @@ class MadlandNix(EnergyDistribution): cv.check_greater_than(name, efl, 0.) self._efl = efl + @property + def efh(self): + return self._efh + @efh.setter def efh(self, efh): name = 'Madland-Nix heavy fragment energy' @@ -713,6 +709,10 @@ class MadlandNix(EnergyDistribution): cv.check_greater_than(name, efh, 0.) self._efh = efh + @property + def tm(self): + return self._tm + @tm.setter def tm(self, tm): cv.check_type('Madland-Nix maximum temperature', tm, Tabulated1D) @@ -778,7 +778,6 @@ class MadlandNix(EnergyDistribution): return cls(efl, efh, tm) - class DiscretePhoton(EnergyDistribution): """Discrete photon energy distribution @@ -814,24 +813,24 @@ class DiscretePhoton(EnergyDistribution): def primary_flag(self): return self._primary_flag - @property - def energy(self): - return self._energy - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - @primary_flag.setter def primary_flag(self, primary_flag): cv.check_type('discrete photon primary_flag', primary_flag, Integral) self._primary_flag = primary_flag + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('discrete photon energy', energy, Real) self._energy = energy + @property + def atomic_weight_ratio(self): + return self._atomic_weight_ratio + @atomic_weight_ratio.setter def atomic_weight_ratio(self, atomic_weight_ratio): cv.check_type('atomic weight ratio', atomic_weight_ratio, Real) @@ -922,15 +921,15 @@ class LevelInelastic(EnergyDistribution): def threshold(self): return self._threshold - @property - def mass_ratio(self): - return self._mass_ratio - @threshold.setter def threshold(self, threshold): cv.check_type('level inelastic threhsold', threshold, Real) self._threshold = threshold + @property + def mass_ratio(self): + return self._mass_ratio + @mass_ratio.setter def mass_ratio(self, mass_ratio): cv.check_type('level inelastic mass ratio', mass_ratio, Real) @@ -1029,36 +1028,36 @@ class ContinuousTabular(EnergyDistribution): def breakpoints(self): return self._breakpoints - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - @breakpoints.setter def breakpoints(self, breakpoints): cv.check_type('continuous tabular breakpoints', breakpoints, Iterable, Integral) self._breakpoints = breakpoints + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_type('continuous tabular interpolation', interpolation, Iterable, Integral) self._interpolation = interpolation + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('continuous tabular incoming energy', energy, Iterable, Real) self._energy = energy + @property + def energy_out(self): + return self._energy_out + @energy_out.setter def energy_out(self, energy_out): cv.check_type('continuous tabular outgoing energy', energy_out, diff --git a/openmc/data/fission_energy.py b/openmc/data/fission_energy.py index bdce84ff79..870881dbaf 100644 --- a/openmc/data/fission_energy.py +++ b/openmc/data/fission_energy.py @@ -100,30 +100,65 @@ class FissionEnergyRelease(EqualityMixin): def fragments(self): return self._fragments + @fragments.setter + def fragments(self, energy_release): + cv.check_type('fragments', energy_release, Callable) + self._fragments = energy_release + @property def prompt_neutrons(self): return self._prompt_neutrons + @prompt_neutrons.setter + def prompt_neutrons(self, energy_release): + cv.check_type('prompt_neutrons', energy_release, Callable) + self._prompt_neutrons = energy_release + @property def delayed_neutrons(self): return self._delayed_neutrons + @delayed_neutrons.setter + def delayed_neutrons(self, energy_release): + cv.check_type('delayed_neutrons', energy_release, Callable) + self._delayed_neutrons = energy_release + @property def prompt_photons(self): return self._prompt_photons + @prompt_photons.setter + def prompt_photons(self, energy_release): + cv.check_type('prompt_photons', energy_release, Callable) + self._prompt_photons = energy_release + @property def delayed_photons(self): return self._delayed_photons + @delayed_photons.setter + def delayed_photons(self, energy_release): + cv.check_type('delayed_photons', energy_release, Callable) + self._delayed_photons = energy_release + @property def betas(self): return self._betas + @betas.setter + def betas(self, energy_release): + cv.check_type('betas', energy_release, Callable) + self._betas = energy_release + @property def neutrinos(self): return self._neutrinos + @neutrinos.setter + def neutrinos(self, energy_release): + cv.check_type('neutrinos', energy_release, Callable) + self._neutrinos = energy_release + @property def recoverable(self): components = ['fragments', 'prompt_neutrons', 'delayed_neutrons', @@ -154,41 +189,6 @@ class FissionEnergyRelease(EqualityMixin): # Use a polynomial to subtract incident energy. return sum_functions([self.total, Polynomial((0.0, -1.0))]) - @fragments.setter - def fragments(self, energy_release): - cv.check_type('fragments', energy_release, Callable) - self._fragments = energy_release - - @prompt_neutrons.setter - def prompt_neutrons(self, energy_release): - cv.check_type('prompt_neutrons', energy_release, Callable) - self._prompt_neutrons = energy_release - - @delayed_neutrons.setter - def delayed_neutrons(self, energy_release): - cv.check_type('delayed_neutrons', energy_release, Callable) - self._delayed_neutrons = energy_release - - @prompt_photons.setter - def prompt_photons(self, energy_release): - cv.check_type('prompt_photons', energy_release, Callable) - self._prompt_photons = energy_release - - @delayed_photons.setter - def delayed_photons(self, energy_release): - cv.check_type('delayed_photons', energy_release, Callable) - self._delayed_photons = energy_release - - @betas.setter - def betas(self, energy_release): - cv.check_type('betas', energy_release, Callable) - self._betas = energy_release - - @neutrinos.setter - def neutrinos(self, energy_release): - cv.check_type('neutrinos', energy_release, Callable) - self._neutrinos = energy_release - @classmethod def from_endf(cls, ev, incident_neutron): """Generate fission energy release data from an ENDF file. diff --git a/openmc/data/function.py b/openmc/data/function.py index b0390d19cd..299924b37c 100644 --- a/openmc/data/function.py +++ b/openmc/data/function.py @@ -255,18 +255,38 @@ class Tabulated1D(Function1D): def x(self): return self._x + @x.setter + def x(self, x): + cv.check_type('x values', x, Iterable, Real) + self._x = x + @property def y(self): return self._y + @y.setter + def y(self, y): + cv.check_type('y values', y, Iterable, Real) + self._y = y + @property def breakpoints(self): return self._breakpoints + @breakpoints.setter + def breakpoints(self, breakpoints): + cv.check_type('breakpoints', breakpoints, Iterable, Integral) + self._breakpoints = breakpoints + @property def interpolation(self): return self._interpolation + @interpolation.setter + def interpolation(self, interpolation): + cv.check_type('interpolation', interpolation, Iterable, Integral) + self._interpolation = interpolation + @property def n_pairs(self): return len(self.x) @@ -275,26 +295,6 @@ class Tabulated1D(Function1D): def n_regions(self): return len(self.breakpoints) - @x.setter - def x(self, x): - cv.check_type('x values', x, Iterable, Real) - self._x = x - - @y.setter - def y(self, y): - cv.check_type('y values', y, Iterable, Real) - self._y = y - - @breakpoints.setter - def breakpoints(self, breakpoints): - cv.check_type('breakpoints', breakpoints, Iterable, Integral) - self._breakpoints = breakpoints - - @interpolation.setter - def interpolation(self, interpolation): - cv.check_type('interpolation', interpolation, Iterable, Integral) - self._interpolation = interpolation - def integral(self): """Integral of the tabulated function over its tabulated range. @@ -664,15 +664,15 @@ class Regions1D(EqualityMixin): def functions(self): return self._functions - @property - def breakpoints(self): - return self._breakpoints - @functions.setter def functions(self, functions): cv.check_type('functions', functions, Iterable, Callable) self._functions = functions + @property + def breakpoints(self): + return self._breakpoints + @breakpoints.setter def breakpoints(self, breakpoints): cv.check_iterable_type('breakpoints', breakpoints, Real) @@ -734,24 +734,24 @@ class ResonancesWithBackground(EqualityMixin): def background(self): return self._background - @property - def mt(self): - return self._mt - - @property - def resonances(self): - return self._resonances - @background.setter def background(self, background): cv.check_type('background cross section', background, Callable) self._background = background + @property + def mt(self): + return self._mt + @mt.setter def mt(self, mt): cv.check_type('MT value', mt, Integral) self._mt = mt + @property + def resonances(self): + return self._resonances + @resonances.setter def resonances(self, resonances): cv.check_type('resolved resonance parameters', resonances, diff --git a/openmc/data/kalbach_mann.py b/openmc/data/kalbach_mann.py index f98bb41869..b49399139d 100644 --- a/openmc/data/kalbach_mann.py +++ b/openmc/data/kalbach_mann.py @@ -302,56 +302,56 @@ class KalbachMann(AngleEnergy): def breakpoints(self): return self._breakpoints - @property - def interpolation(self): - return self._interpolation - - @property - def energy(self): - return self._energy - - @property - def energy_out(self): - return self._energy_out - - @property - def precompound(self): - return self._precompound - - @property - def slope(self): - return self._slope - @breakpoints.setter def breakpoints(self, breakpoints): cv.check_type('Kalbach-Mann breakpoints', breakpoints, Iterable, Integral) self._breakpoints = breakpoints + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_type('Kalbach-Mann interpolation', interpolation, Iterable, Integral) self._interpolation = interpolation + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('Kalbach-Mann incoming energy', energy, Iterable, Real) self._energy = energy + @property + def energy_out(self): + return self._energy_out + @energy_out.setter def energy_out(self, energy_out): cv.check_type('Kalbach-Mann distributions', energy_out, Iterable, Univariate) self._energy_out = energy_out + @property + def precompound(self): + return self._precompound + @precompound.setter def precompound(self, precompound): cv.check_type('Kalbach-Mann precompound factor', precompound, Iterable, Tabulated1D) self._precompound = precompound + @property + def slope(self): + return self._slope + @slope.setter def slope(self, slope): cv.check_type('Kalbach-Mann slope', slope, Iterable, Tabulated1D) diff --git a/openmc/data/laboratory.py b/openmc/data/laboratory.py index 87d9d29618..c20b459684 100644 --- a/openmc/data/laboratory.py +++ b/openmc/data/laboratory.py @@ -54,45 +54,46 @@ class LaboratoryAngleEnergy(AngleEnergy): def breakpoints(self): return self._breakpoints - @property - def interpolation(self): - return self._interpolation - @property - def energy(self): - return self._energy - - @property - def mu(self): - return self._mu - - @property - def energy_out(self): - return self._energy_out - @breakpoints.setter def breakpoints(self, breakpoints): cv.check_type('laboratory angle-energy breakpoints', breakpoints, Iterable, Integral) self._breakpoints = breakpoints + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_type('laboratory angle-energy interpolation', interpolation, Iterable, Integral) self._interpolation = interpolation + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('laboratory angle-energy incoming energy', energy, Iterable, Real) self._energy = energy + @property + def mu(self): + return self._mu + @mu.setter def mu(self, mu): cv.check_type('laboratory angle-energy outgoing cosine', mu, Iterable, Univariate) self._mu = mu + @property + def energy_out(self): + return self._energy_out + @energy_out.setter def energy_out(self, energy_out): cv.check_iterable_type('laboratory angle-energy outgoing energy', diff --git a/openmc/data/multipole.py b/openmc/data/multipole.py index 5e22799023..9fd6c9a9be 100644 --- a/openmc/data/multipole.py +++ b/openmc/data/multipole.py @@ -799,6 +799,11 @@ class WindowedMultipole(EqualityMixin): def name(self): return self._name + @name.setter + def name(self, name): + cv.check_type('name', name, str) + self._name = name + @property def fit_order(self): return self.curvefit.shape[1] - 1 @@ -823,39 +828,6 @@ class WindowedMultipole(EqualityMixin): def spacing(self): return self._spacing - @property - def sqrtAWR(self): - return self._sqrtAWR - - @property - def E_min(self): - return self._E_min - - @property - def E_max(self): - return self._E_max - - @property - def data(self): - return self._data - - @property - def windows(self): - return self._windows - - @property - def broaden_poly(self): - return self._broaden_poly - - @property - def curvefit(self): - return self._curvefit - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - @spacing.setter def spacing(self, spacing): if spacing is not None: @@ -863,6 +835,10 @@ class WindowedMultipole(EqualityMixin): cv.check_greater_than('spacing', spacing, 0.0, equality=False) self._spacing = spacing + @property + def sqrtAWR(self): + return self._sqrtAWR + @sqrtAWR.setter def sqrtAWR(self, sqrtAWR): if sqrtAWR is not None: @@ -870,6 +846,10 @@ class WindowedMultipole(EqualityMixin): cv.check_greater_than('sqrtAWR', sqrtAWR, 0.0, equality=False) self._sqrtAWR = sqrtAWR + @property + def E_min(self): + return self._E_min + @E_min.setter def E_min(self, E_min): if E_min is not None: @@ -877,6 +857,10 @@ class WindowedMultipole(EqualityMixin): cv.check_greater_than('E_min', E_min, 0.0, equality=True) self._E_min = E_min + @property + def E_max(self): + return self._E_max + @E_max.setter def E_max(self, E_max): if E_max is not None: @@ -884,6 +868,10 @@ class WindowedMultipole(EqualityMixin): cv.check_greater_than('E_max', E_max, 0.0, equality=False) self._E_max = E_max + @property + def data(self): + return self._data + @data.setter def data(self, data): if data is not None: @@ -899,6 +887,10 @@ class WindowedMultipole(EqualityMixin): raise TypeError('Multipole data arrays must be complex dtype') self._data = data + @property + def windows(self): + return self._windows + @windows.setter def windows(self, windows): if windows is not None: @@ -910,6 +902,10 @@ class WindowedMultipole(EqualityMixin): ' dtype') self._windows = windows + @property + def broaden_poly(self): + return self._broaden_poly + @broaden_poly.setter def broaden_poly(self, broaden_poly): if broaden_poly is not None: @@ -921,6 +917,10 @@ class WindowedMultipole(EqualityMixin): ' dtype') self._broaden_poly = broaden_poly + @property + def curvefit(self): + return self._curvefit + @curvefit.setter def curvefit(self, curvefit): if curvefit is not None: diff --git a/openmc/data/nbody.py b/openmc/data/nbody.py index 4db9934b95..1f2ff5b4d1 100644 --- a/openmc/data/nbody.py +++ b/openmc/data/nbody.py @@ -43,18 +43,6 @@ class NBodyPhaseSpace(AngleEnergy): def total_mass(self): return self._total_mass - @property - def n_particles(self): - return self._n_particles - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @property - def q_value(self): - return self._q_value - @total_mass.setter def total_mass(self, total_mass): name = 'N-body phase space total mass' @@ -62,6 +50,10 @@ class NBodyPhaseSpace(AngleEnergy): cv.check_greater_than(name, total_mass, 0.) self._total_mass = total_mass + @property + def n_particles(self): + return self._n_particles + @n_particles.setter def n_particles(self, n_particles): name = 'N-body phase space number of particles' @@ -69,6 +61,10 @@ class NBodyPhaseSpace(AngleEnergy): cv.check_greater_than(name, n_particles, 0) self._n_particles = n_particles + @property + def atomic_weight_ratio(self): + return self._atomic_weight_ratio + @atomic_weight_ratio.setter def atomic_weight_ratio(self, atomic_weight_ratio): name = 'N-body phase space atomic weight ratio' @@ -76,6 +72,10 @@ class NBodyPhaseSpace(AngleEnergy): cv.check_greater_than(name, atomic_weight_ratio, 0.0) self._atomic_weight_ratio = atomic_weight_ratio + @property + def q_value(self): + return self._q_value + @q_value.setter def q_value(self, q_value): name = 'N-body phase space Q value' diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index 2d4c139635..11d1456f85 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -135,54 +135,14 @@ class IncidentNeutron(EqualityMixin): def name(self): return self._name - @property - def atomic_number(self): - return self._atomic_number - - @property - def mass_number(self): - return self._mass_number - - @property - def metastable(self): - return self._metastable - - @property - def atomic_weight_ratio(self): - return self._atomic_weight_ratio - - @property - def fission_energy(self): - return self._fission_energy - - @property - def reactions(self): - return self._reactions - - @property - def resonances(self): - return self._resonances - - @property - def resonance_covariance(self): - return self._resonance_covariance - - @property - def urr(self): - return self._urr - - @property - def temperatures(self): - return ["{}K".format(int(round(kT / K_BOLTZMANN))) for kT in self.kTs] - @name.setter def name(self, name): cv.check_type('name', name, str) self._name = name @property - def atomic_symbol(self): - return ATOMIC_SYMBOL[self.atomic_number] + def atomic_number(self): + return self._atomic_number @atomic_number.setter def atomic_number(self, atomic_number): @@ -190,46 +150,78 @@ class IncidentNeutron(EqualityMixin): cv.check_greater_than('atomic number', atomic_number, 0, True) self._atomic_number = atomic_number + @property + def mass_number(self): + return self._mass_number + @mass_number.setter def mass_number(self, mass_number): cv.check_type('mass number', mass_number, Integral) cv.check_greater_than('mass number', mass_number, 0, True) self._mass_number = mass_number + @property + def metastable(self): + return self._metastable + @metastable.setter def metastable(self, metastable): cv.check_type('metastable', metastable, Integral) cv.check_greater_than('metastable', metastable, 0, True) self._metastable = metastable + @property + def atomic_weight_ratio(self): + return self._atomic_weight_ratio + @atomic_weight_ratio.setter def atomic_weight_ratio(self, atomic_weight_ratio): cv.check_type('atomic weight ratio', atomic_weight_ratio, Real) cv.check_greater_than('atomic weight ratio', atomic_weight_ratio, 0.0) self._atomic_weight_ratio = atomic_weight_ratio + @property + def fission_energy(self): + return self._fission_energy + @fission_energy.setter def fission_energy(self, fission_energy): cv.check_type('fission energy release', fission_energy, FissionEnergyRelease) self._fission_energy = fission_energy + @property + def reactions(self): + return self._reactions + @reactions.setter def reactions(self, reactions): cv.check_type('reactions', reactions, Mapping) self._reactions = reactions + @property + def resonances(self): + return self._resonances + @resonances.setter def resonances(self, resonances): cv.check_type('resonances', resonances, res.Resonances) self._resonances = resonances + @property + def resonance_covariance(self): + return self._resonance_covariance + @resonance_covariance.setter def resonance_covariance(self, resonance_covariance): cv.check_type('resonance covariance', resonance_covariance, res_cov.ResonanceCovariances) self._resonance_covariance = resonance_covariance + @property + def urr(self): + return self._urr + @urr.setter def urr(self, urr): cv.check_type('probability table dictionary', urr, MutableMapping) @@ -238,6 +230,14 @@ class IncidentNeutron(EqualityMixin): cv.check_type('probability tables', value, ProbabilityTables) self._urr = urr + @property + def temperatures(self): + return ["{}K".format(int(round(kT / K_BOLTZMANN))) for kT in self.kTs] + + @property + def atomic_symbol(self): + return ATOMIC_SYMBOL[self.atomic_number] + def add_temperature_from_ace(self, ace_or_filename, metastable_scheme='nndc'): """Append data from an ACE file at a different temperature. diff --git a/openmc/data/photon.py b/openmc/data/photon.py index e83ff844d1..1d2546f0e5 100644 --- a/openmc/data/photon.py +++ b/openmc/data/photon.py @@ -168,18 +168,6 @@ class AtomicRelaxation(EqualityMixin): def binding_energy(self): return self._binding_energy - @property - def num_electrons(self): - return self._num_electrons - - @property - def subshells(self): - return list(sorted(self.binding_energy.keys())) - - @property - def transitions(self): - return self._transitions - @binding_energy.setter def binding_energy(self, binding_energy): cv.check_type('binding energies', binding_energy, Mapping) @@ -189,6 +177,10 @@ class AtomicRelaxation(EqualityMixin): cv.check_greater_than('binding energy', energy, 0.0, True) self._binding_energy = binding_energy + @property + def num_electrons(self): + return self._num_electrons + @num_electrons.setter def num_electrons(self, num_electrons): cv.check_type('number of electrons', num_electrons, Mapping) @@ -198,6 +190,14 @@ class AtomicRelaxation(EqualityMixin): cv.check_greater_than('number of electrons', num, 0.0, True) self._num_electrons = num_electrons + @property + def subshells(self): + return list(sorted(self.binding_energy.keys())) + + @property + def transitions(self): + return self._transitions + @transitions.setter def transitions(self, transitions): cv.check_type('transitions', transitions, Mapping) @@ -464,26 +464,26 @@ class IncidentPhoton(EqualityMixin): def atomic_number(self): return self._atomic_number - @property - def atomic_relaxation(self): - return self._atomic_relaxation - - @property - def name(self): - return ATOMIC_SYMBOL[self.atomic_number] - @atomic_number.setter def atomic_number(self, atomic_number): cv.check_type('atomic number', atomic_number, Integral) cv.check_greater_than('atomic number', atomic_number, 0, True) self._atomic_number = atomic_number + @property + def atomic_relaxation(self): + return self._atomic_relaxation + @atomic_relaxation.setter def atomic_relaxation(self, atomic_relaxation): cv.check_type('atomic relaxation data', atomic_relaxation, AtomicRelaxation) self._atomic_relaxation = atomic_relaxation + @property + def name(self): + return ATOMIC_SYMBOL[self.atomic_number] + @classmethod def from_ace(cls, ace_or_filename): """Generate incident photon data from an ACE table @@ -934,35 +934,35 @@ class PhotonReaction(EqualityMixin): def anomalous_real(self): return self._anomalous_real - @property - def anomalous_imag(self): - return self._anomalous_imag - - @property - def scattering_factor(self): - return self._scattering_factor - - @property - def xs(self): - return self._xs - @anomalous_real.setter def anomalous_real(self, anomalous_real): cv.check_type('real part of anomalous scattering factor', anomalous_real, Callable) self._anomalous_real = anomalous_real + @property + def anomalous_imag(self): + return self._anomalous_imag + @anomalous_imag.setter def anomalous_imag(self, anomalous_imag): cv.check_type('imaginary part of anomalous scattering factor', anomalous_imag, Callable) self._anomalous_imag = anomalous_imag + @property + def scattering_factor(self): + return self._scattering_factor + @scattering_factor.setter def scattering_factor(self, scattering_factor): cv.check_type('scattering factor', scattering_factor, Callable) self._scattering_factor = scattering_factor + @property + def xs(self): + return self._xs + @xs.setter def xs(self, xs): cv.check_type('reaction cross section', xs, Callable) diff --git a/openmc/data/product.py b/openmc/data/product.py index a6b2fd89e5..93697a9e7b 100644 --- a/openmc/data/product.py +++ b/openmc/data/product.py @@ -61,55 +61,55 @@ class Product(EqualityMixin): def applicability(self): return self._applicability - @property - def decay_rate(self): - return self._decay_rate - - @property - def distribution(self): - return self._distribution - - @property - def emission_mode(self): - return self._emission_mode - - @property - def particle(self): - return self._particle - - @property - def yield_(self): - return self._yield - @applicability.setter def applicability(self, applicability): cv.check_type('product distribution applicability', applicability, Iterable, Tabulated1D) self._applicability = applicability + @property + def decay_rate(self): + return self._decay_rate + @decay_rate.setter def decay_rate(self, decay_rate): cv.check_type('product decay rate', decay_rate, Real) cv.check_greater_than('product decay rate', decay_rate, 0.0, True) self._decay_rate = decay_rate + @property + def distribution(self): + return self._distribution + @distribution.setter def distribution(self, distribution): cv.check_type('product angle-energy distribution', distribution, Iterable, AngleEnergy) self._distribution = distribution + @property + def emission_mode(self): + return self._emission_mode + @emission_mode.setter def emission_mode(self, emission_mode): cv.check_value('product emission mode', emission_mode, ('prompt', 'delayed', 'total')) self._emission_mode = emission_mode + @property + def particle(self): + return self._particle + @particle.setter def particle(self, particle): cv.check_type('product particle type', particle, str) self._particle = particle + @property + def yield_(self): + return self._yield + @yield_.setter def yield_(self, yield_): cv.check_type('product yield', yield_, Function1D) diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index ac9d7f14e9..650e8663ef 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -855,52 +855,52 @@ class Reaction(EqualityMixin): def center_of_mass(self): return self._center_of_mass - @property - def redundant(self): - return self._redundant - - @property - def q_value(self): - return self._q_value - - @property - def products(self): - return self._products - - @property - def derived_products(self): - return self._derived_products - - @property - def xs(self): - return self._xs - @center_of_mass.setter def center_of_mass(self, center_of_mass): cv.check_type('center of mass', center_of_mass, (bool, np.bool_)) self._center_of_mass = center_of_mass + @property + def redundant(self): + return self._redundant + @redundant.setter def redundant(self, redundant): cv.check_type('redundant', redundant, (bool, np.bool_)) self._redundant = redundant + @property + def q_value(self): + return self._q_value + @q_value.setter def q_value(self, q_value): cv.check_type('Q value', q_value, Real) self._q_value = q_value + @property + def products(self): + return self._products + @products.setter def products(self, products): cv.check_type('reaction products', products, Iterable, Product) self._products = products + @property + def derived_products(self): + return self._derived_products + @derived_products.setter def derived_products(self, derived_products): cv.check_type('reaction derived products', derived_products, Iterable, Product) self._derived_products = derived_products + @property + def xs(self): + return self._xs + @xs.setter def xs(self, xs): cv.check_type('reaction cross section dictionary', xs, MutableMapping) diff --git a/openmc/data/resonance.py b/openmc/data/resonance.py index 7d27ea7cc3..7b9cd268f5 100644 --- a/openmc/data/resonance.py +++ b/openmc/data/resonance.py @@ -46,6 +46,12 @@ class Resonances: def ranges(self): return self._ranges + @ranges.setter + def ranges(self, ranges): + cv.check_type('resonance ranges', ranges, MutableSequence) + self._ranges = cv.CheckedList(ResonanceRange, 'resonance ranges', + ranges) + @property def resolved(self): resolved_ranges = [r for r in self.ranges @@ -65,12 +71,6 @@ class Resonances: else: return None - @ranges.setter - def ranges(self, ranges): - cv.check_type('resonance ranges', ranges, MutableSequence) - self._ranges = cv.CheckedList(ResonanceRange, 'resonance ranges', - ranges) - @classmethod def from_endf(cls, ev): """Generate resonance data from an ENDF evaluation. diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index 48f6bfc9b3..b6e700a0cb 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -193,15 +193,15 @@ class CoherentElastic(Function1D): def bragg_edges(self): return self._bragg_edges - @property - def factors(self): - return self._factors - @bragg_edges.setter def bragg_edges(self, bragg_edges): cv.check_type('Bragg edges', bragg_edges, Iterable, Real) self._bragg_edges = np.asarray(bragg_edges) + @property + def factors(self): + return self._factors + @factors.setter def factors(self, factors): cv.check_type('structure factor cumulative sums', factors, diff --git a/openmc/data/uncorrelated.py b/openmc/data/uncorrelated.py index 0361c9b37a..9dcb18bf61 100644 --- a/openmc/data/uncorrelated.py +++ b/openmc/data/uncorrelated.py @@ -38,16 +38,16 @@ class UncorrelatedAngleEnergy(AngleEnergy): def angle(self): return self._angle - @property - def energy(self): - return self._energy - @angle.setter def angle(self, angle): cv.check_type('uncorrelated angle distribution', angle, AngleDistribution) self._angle = angle + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('uncorrelated energy distribution', energy, diff --git a/openmc/data/urr.py b/openmc/data/urr.py index 53961a50ac..f129c98f81 100644 --- a/openmc/data/urr.py +++ b/openmc/data/urr.py @@ -79,51 +79,51 @@ class ProbabilityTables(EqualityMixin): def absorption_flag(self): return self._absorption_flag - @property - def energy(self): - return self._energy - - @property - def inelastic_flag(self): - return self._inelastic_flag - - @property - def interpolation(self): - return self._interpolation - - @property - def multiply_smooth(self): - return self._multiply_smooth - - @property - def table(self): - return self._table - @absorption_flag.setter def absorption_flag(self, absorption_flag): cv.check_type('absorption flag', absorption_flag, Integral) self._absorption_flag = absorption_flag + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('probability table energies', energy, Iterable, Real) self._energy = energy + @property + def inelastic_flag(self): + return self._inelastic_flag + @inelastic_flag.setter def inelastic_flag(self, inelastic_flag): cv.check_type('inelastic flag', inelastic_flag, Integral) self._inelastic_flag = inelastic_flag + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_value('interpolation', interpolation, [2, 5]) self._interpolation = interpolation + @property + def multiply_smooth(self): + return self._multiply_smooth + @multiply_smooth.setter def multiply_smooth(self, multiply_smooth): cv.check_type('multiply by smooth', multiply_smooth, bool) self._multiply_smooth = multiply_smooth + @property + def table(self): + return self._table + @table.setter def table(self, table): cv.check_type('probability tables', table, np.ndarray) diff --git a/openmc/filter.py b/openmc/filter.py index 1ad2892783..9b3dd51629 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1575,6 +1575,11 @@ class DistribcellFilter(Filter): def paths(self): return self._paths + @paths.setter + def paths(self, paths): + cv.check_iterable_type('paths', paths, str) + self._paths = paths + @Filter.bins.setter def bins(self, bins): # Format the bins as a 1D numpy array. @@ -1593,11 +1598,6 @@ class DistribcellFilter(Filter): self._bins = bins - @paths.setter - def paths(self, paths): - cv.check_iterable_type('paths', paths, str) - self._paths = paths - def can_merge(self, other): # Distribcell filters cannot have more than one bin return False @@ -2060,22 +2060,6 @@ class EnergyFunctionFilter(Filter): def energy(self): return self._energy - @property - def y(self): - return self._y - - @property - def interpolation(self): - return self._interpolation - - @property - def bins(self): - raise AttributeError('EnergyFunctionFilters have no bins.') - - @property - def num_bins(self): - return 1 - @energy.setter def energy(self, energy): # Format the bins as a 1D numpy array. @@ -2088,6 +2072,10 @@ class EnergyFunctionFilter(Filter): self._energy = energy + @property + def y(self): + return self._y + @y.setter def y(self, y): # Format the bins as a 1D numpy array. @@ -2098,9 +2086,9 @@ class EnergyFunctionFilter(Filter): self._y = y - @bins.setter - def bins(self, bins): - raise RuntimeError('EnergyFunctionFilters have no bins.') + @property + def interpolation(self): + return self._interpolation @interpolation.setter def interpolation(self, val): @@ -2115,6 +2103,18 @@ class EnergyFunctionFilter(Filter): self._interpolation = val + @property + def bins(self): + raise AttributeError('EnergyFunctionFilters have no bins.') + + @bins.setter + def bins(self, bins): + raise RuntimeError('EnergyFunctionFilters have no bins.') + + @property + def num_bins(self): + return 1 + def to_xml_element(self): """Return XML Element representing the Filter. diff --git a/openmc/geometry.py b/openmc/geometry.py index 9038895b84..d4e7aa201d 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -57,6 +57,11 @@ class Geometry: def root_universe(self) -> openmc.UniverseBase: return self._root_universe + @root_universe.setter + def root_universe(self, root_universe): + check_type('root universe', root_universe, openmc.UniverseBase) + self._root_universe = root_universe + @property def bounding_box(self) -> np.ndarray: return self.root_universe.bounding_box @@ -65,20 +70,15 @@ class Geometry: def merge_surfaces(self) -> bool: return self._merge_surfaces - @property - def surface_precision(self) -> int: - return self._surface_precision - - @root_universe.setter - def root_universe(self, root_universe): - check_type('root universe', root_universe, openmc.UniverseBase) - self._root_universe = root_universe - @merge_surfaces.setter def merge_surfaces(self, merge_surfaces): check_type('merge surfaces', merge_surfaces, bool) self._merge_surfaces = merge_surfaces + @property + def surface_precision(self) -> int: + return self._surface_precision + @surface_precision.setter def surface_precision(self, surface_precision): check_type('surface precision', surface_precision, int) diff --git a/openmc/lattice.py b/openmc/lattice.py index 37faaf00fc..0983f6d0c7 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -57,18 +57,6 @@ class Lattice(IDManagerMixin, ABC): def name(self): return self._name - @property - def pitch(self): - return self._pitch - - @property - def outer(self): - return self._outer - - @property - def universes(self): - return self._universes - @name.setter def name(self, name): if name is not None: @@ -77,11 +65,23 @@ class Lattice(IDManagerMixin, ABC): else: self._name = '' + @property + def pitch(self): + return self._pitch + + @property + def outer(self): + return self._outer + @outer.setter def outer(self, outer): cv.check_type('outer universe', outer, openmc.UniverseBase) self._outer = outer + @property + def universes(self): + return self._universes + @staticmethod def from_hdf5(group, universes): """Create lattice from HDF5 group @@ -460,6 +460,12 @@ class RectLattice(Lattice): def lower_left(self): return self._lower_left + @lower_left.setter + def lower_left(self, lower_left): + cv.check_type('lattice lower left corner', lower_left, Iterable, Real) + cv.check_length('lattice lower left corner', lower_left, 2, 3) + self._lower_left = lower_left + @property def ndim(self): if self.pitch is not None: @@ -472,12 +478,6 @@ class RectLattice(Lattice): def shape(self): return self._universes.shape[::-1] - @lower_left.setter - def lower_left(self, lower_left): - cv.check_type('lattice lower left corner', lower_left, Iterable, Real) - cv.check_length('lattice lower left corner', lower_left, 2, 3) - self._lower_left = lower_left - @Lattice.pitch.setter def pitch(self, pitch): cv.check_type('lattice pitch', pitch, Iterable, Real) @@ -1127,6 +1127,11 @@ class HexLattice(Lattice): @property def orientation(self): return self._orientation + + @orientation.setter + def orientation(self, orientation): + cv.check_value('orientation', orientation.lower(), ('x', 'y')) + self._orientation = orientation.lower() @property def num_axial(self): @@ -1136,6 +1141,12 @@ class HexLattice(Lattice): def center(self): return self._center + @center.setter + def center(self, center): + cv.check_type('lattice center', center, Iterable, Real) + cv.check_length('lattice center', center, 2, 3) + self._center = center + @property def indices(self): if self.num_axial is None: @@ -1175,17 +1186,6 @@ class HexLattice(Lattice): def ndim(self): return 2 if isinstance(self.universes[0][0], openmc.UniverseBase) else 3 - @center.setter - def center(self, center): - cv.check_type('lattice center', center, Iterable, Real) - cv.check_length('lattice center', center, 2, 3) - self._center = center - - @orientation.setter - def orientation(self, orientation): - cv.check_value('orientation', orientation.lower(), ('x', 'y')) - self._orientation = orientation.lower() - @Lattice.pitch.setter def pitch(self, pitch): cv.check_type('lattice pitch', pitch, Iterable, Real) diff --git a/openmc/lib/plot.py b/openmc/lib/plot.py index da42ea49e0..d142d6cd20 100644 --- a/openmc/lib/plot.py +++ b/openmc/lib/plot.py @@ -96,14 +96,28 @@ class _PlotBase(Structure): def origin(self): return self.origin_ + @origin.setter + def origin(self, origin): + self.origin_.x = origin[0] + self.origin_.y = origin[1] + self.origin_.z = origin[2] + @property def width(self): return self.width_.x + @width.setter + def width(self, width): + self.width_.x = width + @property def height(self): return self.width_.y + @height.setter + def height(self, height): + self.width_.y = height + @property def basis(self): if self.basis_ == 1: @@ -145,14 +159,26 @@ class _PlotBase(Structure): def h_res(self): return self.pixels_[0] + @h_res.setter + def h_res(self, h_res): + self.pixels_[0] = h_res + @property def v_res(self): return self.pixels_[1] + @v_res.setter + def v_res(self, v_res): + self.pixels_[1] = v_res + @property def level(self): return int(self.level_) + @level.setter + def level(self, level): + self.level_ = level + @property def color_overlaps(self): return self.color_overlaps_ @@ -161,32 +187,6 @@ class _PlotBase(Structure): def color_overlaps(self, color_overlaps): self.color_overlaps_ = color_overlaps - @origin.setter - def origin(self, origin): - self.origin_.x = origin[0] - self.origin_.y = origin[1] - self.origin_.z = origin[2] - - @width.setter - def width(self, width): - self.width_.x = width - - @height.setter - def height(self, height): - self.width_.y = height - - @h_res.setter - def h_res(self, h_res): - self.pixels_[0] = h_res - - @v_res.setter - def v_res(self, v_res): - self.pixels_[1] = v_res - - @level.setter - def level(self, level): - self.level_ = level - @property def color_overlaps(self): return self.color_overlaps_ diff --git a/openmc/lib/tally.py b/openmc/lib/tally.py index b8e048974d..f327692e73 100644 --- a/openmc/lib/tally.py +++ b/openmc/lib/tally.py @@ -231,6 +231,10 @@ class Tally(_FortranObjectWithID): _dll.openmc_tally_get_active(self._index, active) return active.value + @active.setter + def active(self, active): + _dll.openmc_tally_set_active(self._index, active) + @property def type(self): type = c_int32() @@ -251,10 +255,6 @@ class Tally(_FortranObjectWithID): def estimator(self, estimator): _dll.openmc_tally_set_estimator(self._index, estimator.encode()) - @active.setter - def active(self, active): - _dll.openmc_tally_set_active(self._index, active) - @property def id(self): tally_id = c_int32() diff --git a/openmc/material.py b/openmc/material.py index 20041aa53c..5f28535dba 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -170,10 +170,25 @@ class Material(IDManagerMixin): def name(self) -> Optional[str]: return self._name + @name.setter + def name(self, name: Optional[str]): + if name is not None: + cv.check_type(f'name for Material ID="{self._id}"', + name, str) + self._name = name + else: + self._name = '' + @property def temperature(self) -> Optional[float]: return self._temperature + @temperature.setter + def temperature(self, temperature: Optional[Real]): + cv.check_type(f'Temperature for Material ID="{self._id}"', + temperature, (Real, type(None))) + self._temperature = temperature + @property def density(self) -> Optional[float]: return self._density @@ -186,6 +201,12 @@ class Material(IDManagerMixin): def depletable(self) -> bool: return self._depletable + @depletable.setter + def depletable(self, depletable: bool): + cv.check_type(f'Depletable flag for Material ID="{self._id}"', + depletable, bool) + self._depletable = depletable + @property def paths(self) -> List[str]: if self._paths is None: @@ -209,6 +230,12 @@ class Material(IDManagerMixin): def isotropic(self) -> List[str]: return self._isotropic + @isotropic.setter + def isotropic(self, isotropic: typing.Iterable[str]): + cv.check_iterable_type('Isotropic scattering nuclides', isotropic, + str) + self._isotropic = list(isotropic) + @property def average_molar_mass(self) -> float: # Using the sum of specified atomic or weight amounts as a basis, sum @@ -230,42 +257,15 @@ class Material(IDManagerMixin): def volume(self) -> Optional[float]: return self._volume - @property - def ncrystal_cfg(self) -> Optional[str]: - return self._ncrystal_cfg - - @name.setter - def name(self, name: Optional[str]): - if name is not None: - cv.check_type(f'name for Material ID="{self._id}"', - name, str) - self._name = name - else: - self._name = '' - - @temperature.setter - def temperature(self, temperature: Optional[Real]): - cv.check_type(f'Temperature for Material ID="{self._id}"', - temperature, (Real, type(None))) - self._temperature = temperature - - @depletable.setter - def depletable(self, depletable: bool): - cv.check_type(f'Depletable flag for Material ID="{self._id}"', - depletable, bool) - self._depletable = depletable - @volume.setter def volume(self, volume: Real): if volume is not None: cv.check_type('material volume', volume, Real) self._volume = volume - @isotropic.setter - def isotropic(self, isotropic: typing.Iterable[str]): - cv.check_iterable_type('Isotropic scattering nuclides', isotropic, - str) - self._isotropic = list(isotropic) + @property + def ncrystal_cfg(self) -> Optional[str]: + return self._ncrystal_cfg @property def fissionable_mass(self) -> float: diff --git a/openmc/mesh.py b/openmc/mesh.py index 0a5dff6433..f9eaff6d5f 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -522,6 +522,12 @@ class RegularMesh(StructuredMesh): def dimension(self): return tuple(self._dimension) + @dimension.setter + def dimension(self, dimension): + cv.check_type('mesh dimension', dimension, Iterable, Integral) + cv.check_length('mesh dimension', dimension, 1, 3) + self._dimension = dimension + @property def n_dimension(self): if self._dimension is not None: @@ -533,6 +539,15 @@ class RegularMesh(StructuredMesh): def lower_left(self): return self._lower_left + @lower_left.setter + def lower_left(self, lower_left): + cv.check_type('mesh lower_left', lower_left, Iterable, Real) + cv.check_length('mesh lower_left', lower_left, 1, 3) + self._lower_left = lower_left + + if self.upper_right is not None and any(np.isclose(self.upper_right, lower_left)): + raise ValueError("Mesh cannot have zero thickness in any dimension") + @property def upper_right(self): if self._upper_right is not None: @@ -544,6 +559,19 @@ class RegularMesh(StructuredMesh): dims = self._dimension return [l + w * d for l, w, d in zip(ls, ws, dims)] + @upper_right.setter + def upper_right(self, upper_right): + cv.check_type('mesh upper_right', upper_right, Iterable, Real) + cv.check_length('mesh upper_right', upper_right, 1, 3) + self._upper_right = upper_right + + if self._width is not None: + self._width = None + warnings.warn("Unsetting width attribute.") + + if self.lower_left is not None and any(np.isclose(self.lower_left, upper_right)): + raise ValueError("Mesh cannot have zero thickness in any dimension") + @property def width(self): if self._width is not None: @@ -555,6 +583,16 @@ class RegularMesh(StructuredMesh): dims = self._dimension return [(u - l) / d for u, l, d in zip(us, ls, dims)] + @width.setter + def width(self, width): + cv.check_type('mesh width', width, Iterable, Real) + cv.check_length('mesh width', width, 1, 3) + self._width = width + + if self._upper_right is not None: + self._upper_right = None + warnings.warn("Unsetting upper_right attribute.") + @property def cartesian_vertices(self): """Returns vertices in cartesian coordiantes. Identical to ``vertices`` for RegularMesh and RectilinearMesh @@ -626,44 +664,6 @@ class RegularMesh(StructuredMesh): np.array(self.lower_left), np.array(self.upper_right) ) - @dimension.setter - def dimension(self, dimension): - cv.check_type('mesh dimension', dimension, Iterable, Integral) - cv.check_length('mesh dimension', dimension, 1, 3) - self._dimension = dimension - - @lower_left.setter - def lower_left(self, lower_left): - cv.check_type('mesh lower_left', lower_left, Iterable, Real) - cv.check_length('mesh lower_left', lower_left, 1, 3) - self._lower_left = lower_left - - if self.upper_right is not None and any(np.isclose(self.upper_right, lower_left)): - raise ValueError("Mesh cannot have zero thickness in any dimension") - - @upper_right.setter - def upper_right(self, upper_right): - cv.check_type('mesh upper_right', upper_right, Iterable, Real) - cv.check_length('mesh upper_right', upper_right, 1, 3) - self._upper_right = upper_right - - if self._width is not None: - self._width = None - warnings.warn("Unsetting width attribute.") - - if self.lower_left is not None and any(np.isclose(self.lower_left, upper_right)): - raise ValueError("Mesh cannot have zero thickness in any dimension") - - @width.setter - def width(self, width): - cv.check_type('mesh width', width, Iterable, Real) - cv.check_length('mesh width', width, 1, 3) - self._width = width - - if self._upper_right is not None: - self._upper_right = None - warnings.warn("Unsetting upper_right attribute.") - def __repr__(self): string = super().__repr__() string += '{0: <16}{1}{2}\n'.format('\tDimensions', '=\t', self.n_dimension) @@ -1020,14 +1020,29 @@ class RectilinearMesh(StructuredMesh): def x_grid(self): return self._x_grid + @x_grid.setter + def x_grid(self, grid): + cv.check_type('mesh x_grid', grid, Iterable, Real) + self._x_grid = np.asarray(grid) + @property def y_grid(self): return self._y_grid + @y_grid.setter + def y_grid(self, grid): + cv.check_type('mesh y_grid', grid, Iterable, Real) + self._y_grid = np.asarray(grid) + @property def z_grid(self): return self._z_grid + @z_grid.setter + def z_grid(self, grid): + cv.check_type('mesh z_grid', grid, Iterable, Real) + self._z_grid = np.asarray(grid) + @property def _grids(self): return (self.x_grid, self.y_grid, self.z_grid) @@ -1069,21 +1084,6 @@ class RectilinearMesh(StructuredMesh): for y in range(1, ny + 1) for x in range(1, nx + 1)) - @x_grid.setter - def x_grid(self, grid): - cv.check_type('mesh x_grid', grid, Iterable, Real) - self._x_grid = np.asarray(grid) - - @y_grid.setter - def y_grid(self, grid): - cv.check_type('mesh y_grid', grid, Iterable, Real) - self._y_grid = np.asarray(grid) - - @z_grid.setter - def z_grid(self, grid): - cv.check_type('mesh z_grid', grid, Iterable, Real) - self._z_grid = np.asarray(grid) - def __repr__(self): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() @@ -1225,17 +1225,38 @@ class CylindricalMesh(StructuredMesh): def origin(self): return self._origin + @origin.setter + def origin(self, coords): + cv.check_type('mesh origin', coords, Iterable, Real) + cv.check_length("mesh origin", coords, 3) + self._origin = np.asarray(coords) + @property def r_grid(self): return self._r_grid + @r_grid.setter + def r_grid(self, grid): + cv.check_type('mesh r_grid', grid, Iterable, Real) + self._r_grid = np.asarray(grid) + @property def phi_grid(self): return self._phi_grid + @phi_grid.setter + def phi_grid(self, grid): + cv.check_type('mesh phi_grid', grid, Iterable, Real) + self._phi_grid = np.asarray(grid) + @property def z_grid(self): return self._z_grid + + @z_grid.setter + def z_grid(self, grid): + cv.check_type('mesh z_grid', grid, Iterable, Real) + self._z_grid = np.asarray(grid) @property def _grids(self): @@ -1251,27 +1272,6 @@ class CylindricalMesh(StructuredMesh): for p in range(1, np + 1) for r in range(1, nr + 1)) - @origin.setter - def origin(self, coords): - cv.check_type('mesh origin', coords, Iterable, Real) - cv.check_length("mesh origin", coords, 3) - self._origin = np.asarray(coords) - - @r_grid.setter - def r_grid(self, grid): - cv.check_type('mesh r_grid', grid, Iterable, Real) - self._r_grid = np.asarray(grid) - - @phi_grid.setter - def phi_grid(self, grid): - cv.check_type('mesh phi_grid', grid, Iterable, Real) - self._phi_grid = np.asarray(grid) - - @z_grid.setter - def z_grid(self, grid): - cv.check_type('mesh z_grid', grid, Iterable, Real) - self._z_grid = np.asarray(grid) - def __repr__(self): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() @@ -1525,18 +1525,39 @@ class SphericalMesh(StructuredMesh): def origin(self): return self._origin + @origin.setter + def origin(self, coords): + cv.check_type('mesh origin', coords, Iterable, Real) + cv.check_length("mesh origin", coords, 3) + self._origin = np.asarray(coords) + @property def r_grid(self): return self._r_grid + @r_grid.setter + def r_grid(self, grid): + cv.check_type('mesh r_grid', grid, Iterable, Real) + self._r_grid = np.asarray(grid) + @property def theta_grid(self): return self._theta_grid + @theta_grid.setter + def theta_grid(self, grid): + cv.check_type('mesh theta_grid', grid, Iterable, Real) + self._theta_grid = np.asarray(grid) + @property def phi_grid(self): return self._phi_grid + @phi_grid.setter + def phi_grid(self, grid): + cv.check_type('mesh phi_grid', grid, Iterable, Real) + self._phi_grid = np.asarray(grid) + @property def _grids(self): return (self.r_grid, self.theta_grid, self.phi_grid) @@ -1551,27 +1572,6 @@ class SphericalMesh(StructuredMesh): for t in range(1, nt + 1) for r in range(1, nr + 1)) - @origin.setter - def origin(self, coords): - cv.check_type('mesh origin', coords, Iterable, Real) - cv.check_length("mesh origin", coords, 3) - self._origin = np.asarray(coords) - - @r_grid.setter - def r_grid(self, grid): - cv.check_type('mesh r_grid', grid, Iterable, Real) - self._r_grid = np.asarray(grid) - - @theta_grid.setter - def theta_grid(self, grid): - cv.check_type('mesh theta_grid', grid, Iterable, Real) - self._theta_grid = np.asarray(grid) - - @phi_grid.setter - def phi_grid(self, grid): - cv.check_type('mesh phi_grid', grid, Iterable, Real) - self._phi_grid = np.asarray(grid) - def __repr__(self): fmt = '{0: <16}{1}{2}\n' string = super().__repr__() diff --git a/openmc/mgxs/groups.py b/openmc/mgxs/groups.py index eaef519da1..ef4b78f7ed 100644 --- a/openmc/mgxs/groups.py +++ b/openmc/mgxs/groups.py @@ -75,16 +75,16 @@ class EnergyGroups: def group_edges(self): return self._group_edges - @property - def num_groups(self): - return len(self.group_edges) - 1 - @group_edges.setter def group_edges(self, edges): cv.check_type('group edges', edges, Iterable, Real) cv.check_greater_than('number of group edges', len(edges), 1) self._group_edges = np.array(edges) + @property + def num_groups(self): + return len(self.group_edges) - 1 + def get_group(self, energy): """Returns the energy group in which the given energy resides. diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 8ab052b0d4..988b7cc756 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -178,22 +178,65 @@ class Library: def geometry(self): return self._geometry + @geometry.setter + def geometry(self, geometry): + cv.check_type('geometry', geometry, openmc.Geometry) + self._geometry = geometry + @property def name(self): return self._name + @name.setter + def name(self, name): + cv.check_type('name', name, str) + self._name = name + @property def mgxs_types(self): return self._mgxs_types + @mgxs_types.setter + def mgxs_types(self, mgxs_types): + all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + \ + openmc.mgxs.ARBITRARY_VECTOR_TYPES + \ + openmc.mgxs.ARBITRARY_MATRIX_TYPES + if mgxs_types == 'all': + self._mgxs_types = all_mgxs_types + else: + cv.check_iterable_type('mgxs_types', mgxs_types, str) + for mgxs_type in mgxs_types: + cv.check_value('mgxs_type', mgxs_type, all_mgxs_types) + self._mgxs_types = mgxs_types + @property def by_nuclide(self): return self._by_nuclide + @by_nuclide.setter + def by_nuclide(self, by_nuclide): + cv.check_type('by_nuclide', by_nuclide, bool) + + if by_nuclide and self.domain_type == 'mesh': + raise ValueError('Unable to create MGXS library by nuclide with ' + 'mesh domain') + + self._by_nuclide = by_nuclide + @property def domain_type(self): return self._domain_type + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, openmc.mgxs.DOMAIN_TYPES) + + if self.by_nuclide and domain_type == 'mesh': + raise ValueError('Unable to create MGXS library by nuclide with ' + 'mesh domain') + + self._domain_type = domain_type + @property def domains(self): if self._domains == 'all': @@ -212,118 +255,6 @@ class Library: else: return self._domains - @property - def nuclides(self): - return self._nuclides - - @property - def energy_groups(self): - return self._energy_groups - - @property - def num_delayed_groups(self): - return self._num_delayed_groups - - @property - def num_polar(self): - return self._num_polar - - @property - def num_azimuthal(self): - return self._num_azimuthal - - @property - def correction(self): - return self._correction - - @property - def scatter_format(self): - return self._scatter_format - - @property - def legendre_order(self): - return self._legendre_order - - @property - def histogram_bins(self): - return self._histogram_bins - - @property - def tally_trigger(self): - return self._tally_trigger - - @property - def estimator(self): - return self._estimator - - @property - def num_groups(self): - return self.energy_groups.num_groups - - @property - def all_mgxs(self): - return self._all_mgxs - - @property - def sp_filename(self): - return self._sp_filename - - @property - def keff(self): - return self._keff - - @property - def sparse(self): - return self._sparse - - @geometry.setter - def geometry(self, geometry): - cv.check_type('geometry', geometry, openmc.Geometry) - self._geometry = geometry - - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, str) - self._nuclides = nuclides - - @mgxs_types.setter - def mgxs_types(self, mgxs_types): - all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + \ - openmc.mgxs.ARBITRARY_VECTOR_TYPES + \ - openmc.mgxs.ARBITRARY_MATRIX_TYPES - if mgxs_types == 'all': - self._mgxs_types = all_mgxs_types - else: - cv.check_iterable_type('mgxs_types', mgxs_types, str) - for mgxs_type in mgxs_types: - cv.check_value('mgxs_type', mgxs_type, all_mgxs_types) - self._mgxs_types = mgxs_types - - @by_nuclide.setter - def by_nuclide(self, by_nuclide): - cv.check_type('by_nuclide', by_nuclide, bool) - - if by_nuclide and self.domain_type == 'mesh': - raise ValueError('Unable to create MGXS library by nuclide with ' - 'mesh domain') - - self._by_nuclide = by_nuclide - - @domain_type.setter - def domain_type(self, domain_type): - cv.check_value('domain type', domain_type, openmc.mgxs.DOMAIN_TYPES) - - if self.by_nuclide and domain_type == 'mesh': - raise ValueError('Unable to create MGXS library by nuclide with ' - 'mesh domain') - - self._domain_type = domain_type - @domains.setter def domains(self, domains): @@ -363,11 +294,28 @@ class Library: self._domains = list(domains) + @property + def nuclides(self): + return self._nuclides + + @nuclides.setter + def nuclides(self, nuclides): + cv.check_iterable_type('nuclides', nuclides, str) + self._nuclides = nuclides + + @property + def energy_groups(self): + return self._energy_groups + @energy_groups.setter def energy_groups(self, energy_groups): cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) self._energy_groups = energy_groups + @property + def num_delayed_groups(self): + return self._num_delayed_groups + @num_delayed_groups.setter def num_delayed_groups(self, num_delayed_groups): @@ -376,6 +324,10 @@ class Library: cv.check_greater_than('num delayed groups', num_delayed_groups, 0, equality=True) self._num_delayed_groups = num_delayed_groups + + @property + def num_polar(self): + return self._num_polar @num_polar.setter def num_polar(self, num_polar): @@ -383,12 +335,20 @@ class Library: cv.check_greater_than('num_polar', num_polar, 0) self._num_polar = num_polar + @property + def num_azimuthal(self): + return self._num_azimuthal + @num_azimuthal.setter def num_azimuthal(self, num_azimuthal): cv.check_type('num_azimuthal', num_azimuthal, Integral) cv.check_greater_than('num_azimuthal', num_azimuthal, 0) self._num_azimuthal = num_azimuthal + @property + def correction(self): + return self._correction + @correction.setter def correction(self, correction): cv.check_value('correction', correction, ('P0', None)) @@ -406,6 +366,10 @@ class Library: self._correction = correction + @property + def scatter_format(self): + return self._scatter_format + @scatter_format.setter def scatter_format(self, scatter_format): cv.check_value('scatter_format', scatter_format, @@ -418,6 +382,10 @@ class Library: self.correction = None self._scatter_format = scatter_format + + @property + def legendre_order(self): + return self._legendre_order @legendre_order.setter def legendre_order(self, legendre_order): @@ -440,6 +408,10 @@ class Library: self._legendre_order = legendre_order + @property + def histogram_bins(self): + return self._histogram_bins + @histogram_bins.setter def histogram_bins(self, histogram_bins): cv.check_type('histogram_bins', histogram_bins, Integral) @@ -459,16 +431,44 @@ class Library: self._histogram_bins = histogram_bins + @property + def tally_trigger(self): + return self._tally_trigger + @tally_trigger.setter def tally_trigger(self, tally_trigger): cv.check_type('tally trigger', tally_trigger, openmc.Trigger) self._tally_trigger = tally_trigger + @property + def estimator(self): + return self._estimator + @estimator.setter def estimator(self, estimator): cv.check_value('estimator', estimator, ESTIMATOR_TYPES) self._estimator = estimator + @property + def num_groups(self): + return self.energy_groups.num_groups + + @property + def all_mgxs(self): + return self._all_mgxs + + @property + def sp_filename(self): + return self._sp_filename + + @property + def keff(self): + return self._keff + + @property + def sparse(self): + return self._sparse + @sparse.setter def sparse(self, sparse): """Convert tally data from NumPy arrays to SciPy list of lists (LIL) diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 96192323e0..7643757d46 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -187,13 +187,6 @@ class MDGXS(MGXS): def delayed_groups(self): return self._delayed_groups - @property - def num_delayed_groups(self): - if self.delayed_groups is None: - return 1 - else: - return len(self.delayed_groups) - @delayed_groups.setter def delayed_groups(self, delayed_groups): @@ -210,6 +203,13 @@ class MDGXS(MGXS): self._delayed_groups = delayed_groups + @property + def num_delayed_groups(self): + if self.delayed_groups is None: + return 1 + else: + return len(self.delayed_groups) + @property def filters(self): diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 1077896ccc..264cbc8924 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -453,6 +453,11 @@ class MGXS: def name(self): return self._name + @name.setter + def name(self, name): + cv.check_type('name', name, str) + self._name = name + @property def rxn_type(self): return self._rxn_type @@ -461,30 +466,78 @@ class MGXS: def by_nuclide(self): return self._by_nuclide + @by_nuclide.setter + def by_nuclide(self, by_nuclide): + cv.check_type('by_nuclide', by_nuclide, bool) + self._by_nuclide = by_nuclide + @property def domain(self): return self._domain + @domain.setter + def domain(self, domain): + cv.check_type('domain', domain, _DOMAINS) + self._domain = domain + + # Assign a domain type + if self.domain_type is None: + if isinstance(domain, openmc.Material): + self._domain_type = 'material' + elif isinstance(domain, openmc.Cell): + self._domain_type = 'cell' + elif isinstance(domain, openmc.Universe): + self._domain_type = 'universe' + elif isinstance(domain, openmc.RegularMesh): + self._domain_type = 'mesh' + @property def domain_type(self): return self._domain_type + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, DOMAIN_TYPES) + self._domain_type = domain_type + @property def energy_groups(self): return self._energy_groups + @energy_groups.setter + def energy_groups(self, energy_groups): + cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) + self._energy_groups = energy_groups + @property def num_polar(self): return self._num_polar + @num_polar.setter + def num_polar(self, num_polar): + cv.check_type('num_polar', num_polar, Integral) + cv.check_greater_than('num_polar', num_polar, 0) + self._num_polar = num_polar + @property def num_azimuthal(self): return self._num_azimuthal + @num_azimuthal.setter + def num_azimuthal(self, num_azimuthal): + cv.check_type('num_azimuthal', num_azimuthal, Integral) + cv.check_greater_than('num_azimuthal', num_azimuthal, 0) + self._num_azimuthal = num_azimuthal + @property def tally_trigger(self): return self._tally_trigger + @tally_trigger.setter + def tally_trigger(self, tally_trigger): + cv.check_type('tally trigger', tally_trigger, openmc.Trigger) + self._tally_trigger = tally_trigger + @property def num_groups(self): return self.energy_groups.num_groups @@ -511,6 +564,11 @@ class MGXS: def estimator(self): return self._estimator + @estimator.setter + def estimator(self, estimator): + cv.check_value('estimator', estimator, self._valid_estimators) + self._estimator = estimator + @property def tallies(self): @@ -585,6 +643,31 @@ class MGXS: def sparse(self): return self._sparse + @sparse.setter + def sparse(self, sparse): + """Convert tally data from NumPy arrays to SciPy list of lists (LIL) + sparse matrices, and vice versa. + + This property may be used to reduce the amount of data in memory during + tally data processing. The tally data will be stored as SciPy LIL + matrices internally within the Tally object. All tally data access + properties and methods will return data as a dense NumPy array. + + """ + + cv.check_type('sparse', sparse, bool) + + # Sparsify or densify the derived MGXS tallies and the base tallies + if self._xs_tally: + self.xs_tally.sparse = sparse + if self._rxn_rate_tally: + self.rxn_rate_tally.sparse = sparse + + for tally_name in self.tallies: + self.tallies[tally_name].sparse = sparse + + self._sparse = sparse + @property def num_subdomains(self): if self.domain_type.startswith('sum('): @@ -612,6 +695,11 @@ class MGXS: else: return ['sum'] + @nuclides.setter + def nuclides(self, nuclides): + cv.check_iterable_type('nuclides', nuclides, str) + self._nuclides = nuclides + @property def loaded_sp(self): return self._loaded_sp @@ -627,94 +715,6 @@ class MGXS: else: return self._rxn_type - @name.setter - def name(self, name): - cv.check_type('name', name, str) - self._name = name - - @by_nuclide.setter - def by_nuclide(self, by_nuclide): - cv.check_type('by_nuclide', by_nuclide, bool) - self._by_nuclide = by_nuclide - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_iterable_type('nuclides', nuclides, str) - self._nuclides = nuclides - - @estimator.setter - def estimator(self, estimator): - cv.check_value('estimator', estimator, self._valid_estimators) - self._estimator = estimator - - @domain.setter - def domain(self, domain): - cv.check_type('domain', domain, _DOMAINS) - self._domain = domain - - # Assign a domain type - if self.domain_type is None: - if isinstance(domain, openmc.Material): - self._domain_type = 'material' - elif isinstance(domain, openmc.Cell): - self._domain_type = 'cell' - elif isinstance(domain, openmc.Universe): - self._domain_type = 'universe' - elif isinstance(domain, openmc.RegularMesh): - self._domain_type = 'mesh' - - @domain_type.setter - def domain_type(self, domain_type): - cv.check_value('domain type', domain_type, DOMAIN_TYPES) - self._domain_type = domain_type - - @energy_groups.setter - def energy_groups(self, energy_groups): - cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) - self._energy_groups = energy_groups - - @num_polar.setter - def num_polar(self, num_polar): - cv.check_type('num_polar', num_polar, Integral) - cv.check_greater_than('num_polar', num_polar, 0) - self._num_polar = num_polar - - @num_azimuthal.setter - def num_azimuthal(self, num_azimuthal): - cv.check_type('num_azimuthal', num_azimuthal, Integral) - cv.check_greater_than('num_azimuthal', num_azimuthal, 0) - self._num_azimuthal = num_azimuthal - - @tally_trigger.setter - def tally_trigger(self, tally_trigger): - cv.check_type('tally trigger', tally_trigger, openmc.Trigger) - self._tally_trigger = tally_trigger - - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within the Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - - # Sparsify or densify the derived MGXS tallies and the base tallies - if self._xs_tally: - self.xs_tally.sparse = sparse - if self._rxn_rate_tally: - self.rxn_rate_tally.sparse = sparse - - for tally_name in self.tallies: - self.tallies[tally_name].sparse = sparse - - self._sparse = sparse - @staticmethod def get_mgxs(mgxs_type, domain=None, domain_type=None, energy_groups=None, by_nuclide=False, name='', num_polar=1, @@ -3453,10 +3453,6 @@ class FissionXS(MGXS): def nu(self): return self._nu - @property - def prompt(self): - return self._prompt - @nu.setter def nu(self, nu): cv.check_type('nu', nu, bool) @@ -3469,6 +3465,10 @@ class FissionXS(MGXS): else: self._rxn_type = 'prompt-nu-fission' + @property + def prompt(self): + return self._prompt + @prompt.setter def prompt(self, prompt): cv.check_type('prompt', prompt, bool) @@ -4006,26 +4006,115 @@ class ScatterMatrixXS(MatrixMGXS): def formulation(self): return self._formulation + @formulation.setter + def formulation(self, formulation): + cv.check_value('formulation', formulation, ('simple', 'consistent')) + self._formulation = formulation + + if self.formulation == 'simple': + self._valid_estimators = ['analog'] + if not self.nu: + self._mgxs_type = 'scatter matrix' + else: + self._mgxs_type = 'nu-scatter matrix' + else: + self._valid_estimators = ['tracklength'] + if not self.nu: + self._mgxs_type = 'consistent scatter matrix' + else: + self._mgxs_type = 'consistent nu-scatter matrix' + @property def correction(self): return self._correction + @correction.setter + def correction(self, correction): + cv.check_value('correction', correction, ('P0', None)) + + if self.scatter_format == SCATTER_LEGENDRE: + if correction == 'P0' and self.legendre_order > 0: + msg = 'The P0 correction will be ignored since the ' \ + 'scattering order {} is greater than '\ + 'zero'.format(self.legendre_order) + warnings.warn(msg) + elif self.scatter_format == SCATTER_HISTOGRAM: + msg = 'The P0 correction will be ignored since the ' \ + 'scatter format is set to histogram' + warnings.warn(msg) + + self._correction = correction + @property def scatter_format(self): return self._scatter_format + @scatter_format.setter + def scatter_format(self, scatter_format): + cv.check_value('scatter_format', scatter_format, MU_TREATMENTS) + self._scatter_format = scatter_format + @property def legendre_order(self): return self._legendre_order + @legendre_order.setter + def legendre_order(self, legendre_order): + cv.check_type('legendre_order', legendre_order, Integral) + cv.check_greater_than('legendre_order', legendre_order, 0, + equality=True) + cv.check_less_than('legendre_order', legendre_order, _MAX_LEGENDRE, + equality=True) + + if self.scatter_format == SCATTER_LEGENDRE: + if self.correction == 'P0' and legendre_order > 0: + msg = 'The P0 correction will be ignored since the ' \ + 'scattering order {} is greater than '\ + 'zero'.format(legendre_order) + warnings.warn(msg, RuntimeWarning) + self.correction = None + elif self.scatter_format == SCATTER_HISTOGRAM: + msg = 'The legendre order will be ignored since the ' \ + 'scatter format is set to histogram' + warnings.warn(msg) + + self._legendre_order = legendre_order + @property def histogram_bins(self): return self._histogram_bins + @histogram_bins.setter + def histogram_bins(self, histogram_bins): + cv.check_type('histogram_bins', histogram_bins, Integral) + cv.check_greater_than('histogram_bins', histogram_bins, 0) + + self._histogram_bins = histogram_bins + @property def nu(self): return self._nu + @nu.setter + def nu(self, nu): + cv.check_type('nu', nu, bool) + self._nu = nu + + if self.formulation == 'simple': + if not nu: + self._rxn_type = 'scatter' + self._mgxs_type = 'scatter matrix' + else: + self._rxn_type = 'nu-scatter' + self._mgxs_type = 'nu-scatter matrix' + else: + if not nu: + self._rxn_type = 'scatter' + self._mgxs_type = 'consistent scatter matrix' + else: + self._rxn_type = 'nu-scatter' + self._mgxs_type = 'consistent nu-scatter matrix' + @property def scores(self): @@ -4307,95 +4396,6 @@ class ScatterMatrixXS(MatrixMGXS): return self._xs_tally - @nu.setter - def nu(self, nu): - cv.check_type('nu', nu, bool) - self._nu = nu - - if self.formulation == 'simple': - if not nu: - self._rxn_type = 'scatter' - self._mgxs_type = 'scatter matrix' - else: - self._rxn_type = 'nu-scatter' - self._mgxs_type = 'nu-scatter matrix' - else: - if not nu: - self._rxn_type = 'scatter' - self._mgxs_type = 'consistent scatter matrix' - else: - self._rxn_type = 'nu-scatter' - self._mgxs_type = 'consistent nu-scatter matrix' - - @formulation.setter - def formulation(self, formulation): - cv.check_value('formulation', formulation, ('simple', 'consistent')) - self._formulation = formulation - - if self.formulation == 'simple': - self._valid_estimators = ['analog'] - if not self.nu: - self._mgxs_type = 'scatter matrix' - else: - self._mgxs_type = 'nu-scatter matrix' - else: - self._valid_estimators = ['tracklength'] - if not self.nu: - self._mgxs_type = 'consistent scatter matrix' - else: - self._mgxs_type = 'consistent nu-scatter matrix' - - @correction.setter - def correction(self, correction): - cv.check_value('correction', correction, ('P0', None)) - - if self.scatter_format == SCATTER_LEGENDRE: - if correction == 'P0' and self.legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(self.legendre_order) - warnings.warn(msg) - elif self.scatter_format == SCATTER_HISTOGRAM: - msg = 'The P0 correction will be ignored since the ' \ - 'scatter format is set to histogram' - warnings.warn(msg) - - self._correction = correction - - @scatter_format.setter - def scatter_format(self, scatter_format): - cv.check_value('scatter_format', scatter_format, MU_TREATMENTS) - self._scatter_format = scatter_format - - @legendre_order.setter - def legendre_order(self, legendre_order): - cv.check_type('legendre_order', legendre_order, Integral) - cv.check_greater_than('legendre_order', legendre_order, 0, - equality=True) - cv.check_less_than('legendre_order', legendre_order, _MAX_LEGENDRE, - equality=True) - - if self.scatter_format == SCATTER_LEGENDRE: - if self.correction == 'P0' and legendre_order > 0: - msg = 'The P0 correction will be ignored since the ' \ - 'scattering order {} is greater than '\ - 'zero'.format(legendre_order) - warnings.warn(msg, RuntimeWarning) - self.correction = None - elif self.scatter_format == SCATTER_HISTOGRAM: - msg = 'The legendre order will be ignored since the ' \ - 'scatter format is set to histogram' - warnings.warn(msg) - - self._legendre_order = legendre_order - - @histogram_bins.setter - def histogram_bins(self, histogram_bins): - cv.check_type('histogram_bins', histogram_bins, Integral) - cv.check_greater_than('histogram_bins', histogram_bins, 0) - - self._histogram_bins = histogram_bins - def load_from_statepoint(self, statepoint): """Extracts tallies in an OpenMC StatePoint with the data needed to compute multi-group cross sections. @@ -5416,6 +5416,17 @@ class Chi(MGXS): def prompt(self): return self._prompt + @prompt.setter + def prompt(self, prompt): + cv.check_type('prompt', prompt, bool) + self._prompt = prompt + if not self.prompt: + self._rxn_type = 'chi' + self._mgxs_type = 'chi' + else: + self._rxn_type = 'chi-prompt' + self._mgxs_type = 'chi-prompt' + @property def _dont_squeeze(self): """Create a tuple of axes which should not be removed during the get_xs @@ -5472,17 +5483,6 @@ class Chi(MGXS): return self._xs_tally - @prompt.setter - def prompt(self, prompt): - cv.check_type('prompt', prompt, bool) - self._prompt = prompt - if not self.prompt: - self._rxn_type = 'chi' - self._mgxs_type = 'chi' - else: - self._rxn_type = 'chi-prompt' - self._mgxs_type = 'chi-prompt' - def get_homogenized_mgxs(self, other_mgxs): """Construct a homogenized mgxs with other MGXS objects. @@ -5968,10 +5968,6 @@ class MeshSurfaceMGXS(MGXS): def domain(self): return self._domain - @property - def domain_type(self): - return self._domain_type - @domain.setter def domain(self, domain): cv.check_type('domain', domain, openmc.RegularMesh) @@ -5981,6 +5977,10 @@ class MeshSurfaceMGXS(MGXS): if self.domain_type is None: self._domain_type = 'mesh' + @property + def domain_type(self): + return self._domain_type + @domain_type.setter def domain_type(self, domain_type): cv.check_value('domain type', domain_type, 'mesh') diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 98a99196e5..85e15f8ebc 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -260,22 +260,62 @@ class XSdata: def name(self): return self._name + @name.setter + def name(self, name): + + check_type('name for XSdata', name, str) + self._name = name + @property def energy_groups(self): return self._energy_groups + @energy_groups.setter + def energy_groups(self, energy_groups): + + check_type('energy_groups', energy_groups, openmc.mgxs.EnergyGroups) + if energy_groups.group_edges is None: + msg = 'Unable to assign an EnergyGroups object ' \ + 'with uninitialized group edges' + raise ValueError(msg) + + self._energy_groups = energy_groups + @property def num_delayed_groups(self): return self._num_delayed_groups + @num_delayed_groups.setter + def num_delayed_groups(self, num_delayed_groups): + + check_type('num_delayed_groups', num_delayed_groups, Integral) + check_less_than('num_delayed_groups', num_delayed_groups, + openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) + check_greater_than('num_delayed_groups', num_delayed_groups, 0, + equality=True) + self._num_delayed_groups = num_delayed_groups + @property def representation(self): return self._representation + @representation.setter + def representation(self, representation): + + check_value('representation', representation, _REPRESENTATIONS) + self._representation = representation + @property def atomic_weight_ratio(self): return self._atomic_weight_ratio + @atomic_weight_ratio.setter + def atomic_weight_ratio(self, atomic_weight_ratio): + + check_type('atomic_weight_ratio', atomic_weight_ratio, Real) + check_greater_than('atomic_weight_ratio', atomic_weight_ratio, 0.0) + self._atomic_weight_ratio = atomic_weight_ratio + @property def fissionable(self): return self._fissionable @@ -284,22 +324,55 @@ class XSdata: def temperatures(self): return self._temperatures + @temperatures.setter + def temperatures(self, temperatures): + + check_iterable_type('temperatures', temperatures, Real) + self._temperatures = np.array(temperatures) + @property def scatter_format(self): return self._scatter_format + @scatter_format.setter + def scatter_format(self, scatter_format): + + check_value('scatter_format', scatter_format, _SCATTER_TYPES) + self._scatter_format = scatter_format + @property def order(self): return self._order + @order.setter + def order(self, order): + + check_type('order', order, Integral) + check_greater_than('order', order, 0, equality=True) + self._order = order + @property def num_polar(self): return self._num_polar + @num_polar.setter + def num_polar(self, num_polar): + + check_type('num_polar', num_polar, Integral) + check_greater_than('num_polar', num_polar, 0) + self._num_polar = num_polar + @property def num_azimuthal(self): return self._num_azimuthal + @num_azimuthal.setter + def num_azimuthal(self, num_azimuthal): + + check_type('num_azimuthal', num_azimuthal, Integral) + check_greater_than('num_azimuthal', num_azimuthal, 0) + self._num_azimuthal = num_azimuthal + @property def total(self): return self._total @@ -401,79 +474,6 @@ class XSdata: return self._xs_shapes - @name.setter - def name(self, name): - - check_type('name for XSdata', name, str) - self._name = name - - @energy_groups.setter - def energy_groups(self, energy_groups): - - check_type('energy_groups', energy_groups, openmc.mgxs.EnergyGroups) - if energy_groups.group_edges is None: - msg = 'Unable to assign an EnergyGroups object ' \ - 'with uninitialized group edges' - raise ValueError(msg) - - self._energy_groups = energy_groups - - @num_delayed_groups.setter - def num_delayed_groups(self, num_delayed_groups): - - check_type('num_delayed_groups', num_delayed_groups, Integral) - check_less_than('num_delayed_groups', num_delayed_groups, - openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) - check_greater_than('num_delayed_groups', num_delayed_groups, 0, - equality=True) - self._num_delayed_groups = num_delayed_groups - - @representation.setter - def representation(self, representation): - - check_value('representation', representation, _REPRESENTATIONS) - self._representation = representation - - @atomic_weight_ratio.setter - def atomic_weight_ratio(self, atomic_weight_ratio): - - check_type('atomic_weight_ratio', atomic_weight_ratio, Real) - check_greater_than('atomic_weight_ratio', atomic_weight_ratio, 0.0) - self._atomic_weight_ratio = atomic_weight_ratio - - @temperatures.setter - def temperatures(self, temperatures): - - check_iterable_type('temperatures', temperatures, Real) - self._temperatures = np.array(temperatures) - - @scatter_format.setter - def scatter_format(self, scatter_format): - - check_value('scatter_format', scatter_format, _SCATTER_TYPES) - self._scatter_format = scatter_format - - @order.setter - def order(self, order): - - check_type('order', order, Integral) - check_greater_than('order', order, 0, equality=True) - self._order = order - - @num_polar.setter - def num_polar(self, num_polar): - - check_type('num_polar', num_polar, Integral) - check_greater_than('num_polar', num_polar, 0) - self._num_polar = num_polar - - @num_azimuthal.setter - def num_azimuthal(self, num_azimuthal): - - check_type('num_azimuthal', num_azimuthal, Integral) - check_greater_than('num_azimuthal', num_azimuthal, 0) - self._num_azimuthal = num_azimuthal - def add_temperature(self, temperature): """This method re-sizes the attributes of this XSdata object so that it can accommodate an additional temperature. Note that the set_* methods @@ -2330,23 +2330,15 @@ class MGXSLibrary: def energy_groups(self): return self._energy_groups - @property - def num_delayed_groups(self): - return self._num_delayed_groups - - @property - def xsdatas(self): - return self._xsdatas - - @property - def names(self): - return [xsdata.name for xsdata in self.xsdatas] - @energy_groups.setter def energy_groups(self, energy_groups): check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups) self._energy_groups = energy_groups + @property + def num_delayed_groups(self): + return self._num_delayed_groups + @num_delayed_groups.setter def num_delayed_groups(self, num_delayed_groups): check_type('num_delayed_groups', num_delayed_groups, Integral) @@ -2356,6 +2348,14 @@ class MGXSLibrary: openmc.mgxs.MAX_DELAYED_GROUPS, equality=True) self._num_delayed_groups = num_delayed_groups + @property + def xsdatas(self): + return self._xsdatas + + @property + def names(self): + return [xsdata.name for xsdata in self.xsdatas] + def add_xsdata(self, xsdata): """Add an XSdata entry to the file. diff --git a/openmc/model/model.py b/openmc/model/model.py index ee7f3647fd..db0b05e15d 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -98,22 +98,62 @@ class Model: def geometry(self) -> Optional[openmc.Geometry]: return self._geometry + @geometry.setter + def geometry(self, geometry): + check_type('geometry', geometry, openmc.Geometry) + self._geometry = geometry + @property def materials(self) -> Optional[openmc.Materials]: return self._materials + @materials.setter + def materials(self, materials): + check_type('materials', materials, Iterable, openmc.Material) + if isinstance(materials, openmc.Materials): + self._materials = materials + else: + del self._materials[:] + for mat in materials: + self._materials.append(mat) + @property def settings(self) -> Optional[openmc.Settings]: return self._settings + @settings.setter + def settings(self, settings): + check_type('settings', settings, openmc.Settings) + self._settings = settings + @property def tallies(self) -> Optional[openmc.Tallies]: return self._tallies + @tallies.setter + def tallies(self, tallies): + check_type('tallies', tallies, Iterable, openmc.Tally) + if isinstance(tallies, openmc.Tallies): + self._tallies = tallies + else: + del self._tallies[:] + for tally in tallies: + self._tallies.append(tally) + @property def plots(self) -> Optional[openmc.Plots]: return self._plots + @plots.setter + def plots(self, plots): + check_type('plots', plots, Iterable, openmc.Plot) + if isinstance(plots, openmc.Plots): + self._plots = plots + else: + del self._plots[:] + for plot in plots: + self._plots.append(plot) + @property def is_initialized(self) -> bool: try: @@ -166,46 +206,6 @@ class Model: result[mat.name].add(mat) return result - @geometry.setter - def geometry(self, geometry): - check_type('geometry', geometry, openmc.Geometry) - self._geometry = geometry - - @materials.setter - def materials(self, materials): - check_type('materials', materials, Iterable, openmc.Material) - if isinstance(materials, openmc.Materials): - self._materials = materials - else: - del self._materials[:] - for mat in materials: - self._materials.append(mat) - - @settings.setter - def settings(self, settings): - check_type('settings', settings, openmc.Settings) - self._settings = settings - - @tallies.setter - def tallies(self, tallies): - check_type('tallies', tallies, Iterable, openmc.Tally) - if isinstance(tallies, openmc.Tallies): - self._tallies = tallies - else: - del self._tallies[:] - for tally in tallies: - self._tallies.append(tally) - - @plots.setter - def plots(self, plots): - check_type('plots', plots, Iterable, openmc.Plot) - if isinstance(plots, openmc.Plots): - self._plots = plots - else: - del self._plots[:] - for plot in plots: - self._plots.append(plot) - @classmethod def from_xml(cls, geometry='geometry.xml', materials='materials.xml', settings='settings.xml', tallies='tallies.xml', diff --git a/openmc/model/triso.py b/openmc/model/triso.py index b41ae7fa61..f344b8edd4 100644 --- a/openmc/model/triso.py +++ b/openmc/model/triso.py @@ -138,10 +138,20 @@ class _Container(ABC): def sphere_radius(self): return self._sphere_radius + @sphere_radius.setter + def sphere_radius(self, sphere_radius): + self._sphere_radius = float(sphere_radius) + self._limits = None + self._cell_length = None + @property def center(self): return self._center + @center.setter + def center(self, center): + self._center = center + @abstractproperty def limits(self): pass @@ -154,15 +164,6 @@ class _Container(ABC): def volume(self): pass - @sphere_radius.setter - def sphere_radius(self, sphere_radius): - self._sphere_radius = float(sphere_radius) - self._limits = None - self._cell_length = None - - @center.setter - def center(self, center): - self._center = center def mesh_cell(self, p): """Calculate the index of the cell in a mesh overlaid on the domain in @@ -300,14 +301,32 @@ class _RectangularPrism(_Container): def width(self): return self._width + @width.setter + def width(self, width): + self._width = float(width) + self._limits = None + self._cell_length = None + @property def depth(self): return self._depth + @depth.setter + def depth(self, depth): + self._depth = float(depth) + self._limits = None + self._cell_length = None + @property def height(self): return self._height + @height.setter + def height(self, height): + self._height = float(height) + self._limits = None + self._cell_length = None + @property def limits(self): if self._limits is None: @@ -316,8 +335,13 @@ class _RectangularPrism(_Container): x, y, z = self.width/2, self.depth/2, self.height/2 self._limits = [[c[0] - x + r, c[1] - y + r, c[2] - z + r], [c[0] + x - r, c[1] + y - r, c[2] + z - r]] + return self._limits + @limits.setter + def limits(self, limits): + self._limits = limits + @property def cell_length(self): if self._cell_length is None: @@ -330,28 +354,6 @@ class _RectangularPrism(_Container): def volume(self): return self.width*self.depth*self.height - @width.setter - def width(self, width): - self._width = float(width) - self._limits = None - self._cell_length = None - - @depth.setter - def depth(self, depth): - self._depth = float(depth) - self._limits = None - self._cell_length = None - - @height.setter - def height(self, height): - self._height = float(height) - self._limits = None - self._cell_length = None - - @limits.setter - def limits(self, limits): - self._limits = limits - @classmethod def from_region(self, region, sphere_radius): check_type('region', region, openmc.Region) @@ -470,14 +472,31 @@ class _Cylinder(_Container): def length(self): return self._length + @length.setter + def length(self, length): + self._length = float(length) + self._limits = None + self._cell_length = None + @property def radius(self): return self._radius + @radius.setter + def radius(self, radius): + self._radius = float(radius) + self._limits = None + self._cell_length = None + @property def axis(self): return self._axis + @axis.setter + def axis(self, axis): + self._axis = axis + self._shift = None + @property def shift(self): if self._shift is None: @@ -498,6 +517,10 @@ class _Cylinder(_Container): self._limits = [[z0 - z + r], [z0 + z - r, self.radius - r]] return self._limits + @limits.setter + def limits(self, limits): + self._limits = limits + @property def cell_length(self): if self._cell_length is None: @@ -513,27 +536,6 @@ class _Cylinder(_Container): def volume(self): return self.length*pi*self.radius**2 - @length.setter - def length(self, length): - self._length = float(length) - self._limits = None - self._cell_length = None - - @radius.setter - def radius(self, radius): - self._radius = float(radius) - self._limits = None - self._cell_length = None - - @axis.setter - def axis(self, axis): - self._axis = axis - self._shift = None - - @limits.setter - def limits(self, limits): - self._limits = limits - @classmethod def from_region(self, region, sphere_radius): check_type('region', region, openmc.Region) @@ -676,10 +678,21 @@ class _SphericalShell(_Container): def radius(self): return self._radius + @radius.setter + def radius(self, radius): + self._radius = float(radius) + self._limits = None + self._cell_length = None + @property def inner_radius(self): return self._inner_radius + @inner_radius.setter + def inner_radius(self, inner_radius): + self._inner_radius = float(inner_radius) + self._limits = None + @property def limits(self): if self._limits is None: @@ -691,6 +704,10 @@ class _SphericalShell(_Container): self._limits = [[r_min], [r_max]] return self._limits + @limits.setter + def limits(self, limits): + self._limits = limits + @property def cell_length(self): if self._cell_length is None: @@ -703,21 +720,6 @@ class _SphericalShell(_Container): def volume(self): return _volume_sphere(self.radius) - _volume_sphere(self.inner_radius) - @radius.setter - def radius(self, radius): - self._radius = float(radius) - self._limits = None - self._cell_length = None - - @inner_radius.setter - def inner_radius(self, inner_radius): - self._inner_radius = float(inner_radius) - self._limits = None - - @limits.setter - def limits(self, limits): - self._limits = limits - @classmethod def from_region(self, region, sphere_radius): check_type('region', region, openmc.Region) diff --git a/openmc/plots.py b/openmc/plots.py index 5d8cf9ba40..5bc8a2e6e8 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -315,51 +315,15 @@ class PlotBase(IDManagerMixin): def name(self): return self._name - @property - def pixels(self): - return self._pixels - - @property - def filename(self): - return self._filename - - @property - def color_by(self): - return self._color_by - - @property - def background(self): - return self._background - - @property - def mask_components(self): - return self._mask_components - - @property - def mask_background(self): - return self._mask_background - - @property - def show_overlaps(self): - return self._show_overlaps - - @property - def overlap_color(self): - return self._overlap_color - - @property - def colors(self): - return self._colors - - @property - def level(self): - return self._level - @name.setter def name(self, name): cv.check_type('plot name', name, str) self._name = name + @property + def pixels(self): + return self._pixels + @pixels.setter def pixels(self, pixels): cv.check_type('plot pixels', pixels, Iterable, Integral) @@ -368,21 +332,75 @@ class PlotBase(IDManagerMixin): cv.check_greater_than('plot pixels', dim, 0) self._pixels = pixels + @property + def filename(self): + return self._filename + @filename.setter def filename(self, filename): cv.check_type('filename', filename, str) self._filename = filename + @property + def color_by(self): + return self._color_by + @color_by.setter def color_by(self, color_by): cv.check_value('plot color_by', color_by, ['cell', 'material']) self._color_by = color_by + @property + def background(self): + return self._background + @background.setter def background(self, background): self._check_color('plot background', background) self._background = background + @property + def mask_components(self): + return self._mask_components + + @mask_components.setter + def mask_components(self, mask_components): + cv.check_type('plot mask components', mask_components, Iterable, + (openmc.Cell, openmc.Material, Integral)) + self._mask_components = mask_components + + @property + def mask_background(self): + return self._mask_background + + @mask_background.setter + def mask_background(self, mask_background): + self._check_color('plot mask background', mask_background) + self._mask_background = mask_background + + @property + def show_overlaps(self): + return self._show_overlaps + + @show_overlaps.setter + def show_overlaps(self, show_overlaps): + cv.check_type(f'Show overlaps flag for Plot ID="{self.id}"', + show_overlaps, bool) + self._show_overlaps = show_overlaps + + @property + def overlap_color(self): + return self._overlap_color + + @overlap_color.setter + def overlap_color(self, overlap_color): + self._check_color('plot overlap color', overlap_color) + self._overlap_color = overlap_color + + @property + def colors(self): + return self._colors + @colors.setter def colors(self, colors): cv.check_type('plot colors', colors, Mapping) @@ -392,27 +410,9 @@ class PlotBase(IDManagerMixin): self._check_color('plot color value', value) self._colors = colors - @mask_components.setter - def mask_components(self, mask_components): - cv.check_type('plot mask components', mask_components, Iterable, - (openmc.Cell, openmc.Material, Integral)) - self._mask_components = mask_components - - @mask_background.setter - def mask_background(self, mask_background): - self._check_color('plot mask background', mask_background) - self._mask_background = mask_background - - @show_overlaps.setter - def show_overlaps(self, show_overlaps): - cv.check_type(f'Show overlaps flag for Plot ID="{self.id}"', - show_overlaps, bool) - self._show_overlaps = show_overlaps - - @overlap_color.setter - def overlap_color(self, overlap_color): - self._check_color('plot overlap color', overlap_color) - self._overlap_color = overlap_color + @property + def level(self): + return self._level @level.setter def level(self, plot_level): @@ -584,44 +584,44 @@ class Plot(PlotBase): def width(self): return self._width - @property - def origin(self): - return self._origin - - @property - def type(self): - return self._type - - @property - def basis(self): - return self._basis - - @property - def meshlines(self): - return self._meshlines - @width.setter def width(self, width): cv.check_type('plot width', width, Iterable, Real) cv.check_length('plot width', width, 2, 3) self._width = width + @property + def origin(self): + return self._origin + @origin.setter def origin(self, origin): cv.check_type('plot origin', origin, Iterable, Real) cv.check_length('plot origin', origin, 3) self._origin = origin + @property + def type(self): + return self._type + @type.setter def type(self, plottype): cv.check_value('plot type', plottype, ['slice', 'voxel']) self._type = plottype + @property + def basis(self): + return self._basis + @basis.setter def basis(self, basis): cv.check_value('plot basis', basis, _BASES) self._basis = basis + @property + def meshlines(self): + return self._meshlines + @meshlines.setter def meshlines(self, meshlines): cv.check_type('plot meshlines', meshlines, dict) @@ -1046,38 +1046,6 @@ class ProjectionPlot(PlotBase): def horizontal_field_of_view(self): return self._horizontal_field_of_view - @property - def camera_position(self): - return self._camera_position - - @property - def look_at(self): - return self._look_at - - @property - def up(self): - return self._up - - @property - def orthographic_width(self): - return self._orthographic_width - - @property - def wireframe_thickness(self): - return self._wireframe_thickness - - @property - def wireframe_color(self): - return self._wireframe_color - - @property - def wireframe_domains(self): - return self._wireframe_domains - - @property - def xs(self): - return self._xs - @horizontal_field_of_view.setter def horizontal_field_of_view(self, horizontal_field_of_view): cv.check_type('plot horizontal field of view', horizontal_field_of_view, @@ -1086,30 +1054,50 @@ class ProjectionPlot(PlotBase): assert horizontal_field_of_view < 180.0 self._horizontal_field_of_view = horizontal_field_of_view + @property + def camera_position(self): + return self._camera_position + @camera_position.setter def camera_position(self, camera_position): cv.check_type('plot camera position', camera_position, Iterable, Real) cv.check_length('plot camera position', camera_position, 3) self._camera_position = camera_position + @property + def look_at(self): + return self._look_at + @look_at.setter def look_at(self, look_at): cv.check_type('plot look at', look_at, Iterable, Real) cv.check_length('plot look at', look_at, 3) self._look_at = look_at + @property + def up(self): + return self._up + @up.setter def up(self, up): cv.check_type('plot up', up, Iterable, Real) cv.check_length('plot up', up, 3) self._up = up + @property + def orthographic_width(self): + return self._orthographic_width + @orthographic_width.setter def orthographic_width(self, orthographic_width): cv.check_type('plot orthographic width', orthographic_width, Real) assert orthographic_width >= 0.0 self._orthographic_width = orthographic_width + @property + def wireframe_thickness(self): + return self._wireframe_thickness + @wireframe_thickness.setter def wireframe_thickness(self, wireframe_thickness): cv.check_type('plot wireframe thickness', @@ -1117,11 +1105,19 @@ class ProjectionPlot(PlotBase): assert wireframe_thickness >= 0 self._wireframe_thickness = wireframe_thickness + @property + def wireframe_color(self): + return self._wireframe_color + @wireframe_color.setter def wireframe_color(self, wireframe_color): self._check_color('plot wireframe color', wireframe_color) self._wireframe_color = wireframe_color + @property + def wireframe_domains(self): + return self._wireframe_domains + @wireframe_domains.setter def wireframe_domains(self, wireframe_domains): for region in wireframe_domains: @@ -1135,6 +1131,10 @@ class ProjectionPlot(PlotBase): wireframe_region if color_by=cell') self._wireframe_domains = wireframe_domains + @property + def xs(self): + return self._xs + @xs.setter def xs(self, xs): cv.check_type('plot xs', xs, Mapping) diff --git a/openmc/settings.py b/openmc/settings.py index 8b6d5f0fe5..fbbb0c7199 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -335,213 +335,6 @@ class Settings: def run_mode(self) -> str: return self._run_mode.value - @property - def batches(self) -> int: - return self._batches - - @property - def generations_per_batch(self) -> int: - return self._generations_per_batch - - @property - def inactive(self) -> int: - return self._inactive - - @property - def max_lost_particles(self) -> int: - return self._max_lost_particles - - @property - def rel_max_lost_particles(self) -> float: - return self._rel_max_lost_particles - - @property - def particles(self) -> int: - return self._particles - - @property - def keff_trigger(self) -> dict: - return self._keff_trigger - - @property - def energy_mode(self) -> str: - return self._energy_mode - - @property - def max_order(self) -> int: - return self._max_order - - @property - def source(self) -> typing.List[Source]: - return self._source - - @property - def confidence_intervals(self) -> bool: - return self._confidence_intervals - - @property - def electron_treatment(self) -> str: - return self._electron_treatment - - @property - def ptables(self) -> bool: - return self._ptables - - @property - def photon_transport(self) -> bool: - return self._photon_transport - - @property - def seed(self) -> int: - return self._seed - - @property - def survival_biasing(self) -> bool: - return self._survival_biasing - - @property - def entropy_mesh(self) -> RegularMesh: - return self._entropy_mesh - - @property - def trigger_active(self) -> bool: - return self._trigger_active - - @property - def trigger_max_batches(self) -> int: - return self._trigger_max_batches - - @property - def trigger_batch_interval(self) -> int: - return self._trigger_batch_interval - - @property - def output(self) -> dict: - return self._output - - @property - def sourcepoint(self) -> dict: - return self._sourcepoint - - @property - def statepoint(self) -> dict: - return self._statepoint - - @property - def surf_source_read(self) -> dict: - return self._surf_source_read - - @property - def surf_source_write(self) -> dict: - return self._surf_source_write - - @property - def no_reduce(self) -> bool: - return self._no_reduce - - @property - def verbosity(self) -> int: - return self._verbosity - - @property - def tabular_legendre(self) -> dict: - return self._tabular_legendre - - @property - def temperature(self) -> dict: - return self._temperature - - @property - def trace(self) -> typing.Iterable: - return self._trace - - @property - def track(self) -> typing.Iterable[typing.Iterable[int]]: - return self._track - - @property - def cutoff(self) -> dict: - return self._cutoff - - @property - def ufs_mesh(self) -> RegularMesh: - return self._ufs_mesh - - @property - def resonance_scattering(self) -> dict: - return self._resonance_scattering - - @property - def volume_calculations(self) -> typing.List[VolumeCalculation]: - return self._volume_calculations - - @property - def create_fission_neutrons(self) -> bool: - return self._create_fission_neutrons - - @property - def create_delayed_neutrons(self) -> bool: - return self._create_delayed_neutrons - - @property - def delayed_photon_scaling(self) -> bool: - return self._delayed_photon_scaling - - @property - def material_cell_offsets(self) -> bool: - return self._material_cell_offsets - - @property - def log_grid_bins(self) -> int: - return self._log_grid_bins - - @property - def event_based(self) -> bool: - return self._event_based - - @property - def max_particles_in_flight(self) -> int: - return self._max_particles_in_flight - - @property - def write_initial_source(self) -> bool: - return self._write_initial_source - - @property - def weight_windows(self) -> typing.List[WeightWindows]: - return self._weight_windows - - @property - def weight_windows_on(self) -> bool: - return self._weight_windows_on - - @property - def weight_windows_file(self) -> Optional[PathLike]: - return self._weight_windows_file - - @weight_windows_file.setter - def weight_windows_file(self, value: PathLike): - cv.check_type('weight windows file', value, (str, Path)) - self._weight_windows_file = value - - @property - def weight_window_generators(self) -> typing.List[WeightWindowGenerator]: - return self._weight_window_generators - - @weight_window_generators.setter - def weight_window_generators(self, wwgs): - if not isinstance(wwgs, MutableSequence): - wwgs = [wwgs] - self._weight_window_generators = cv.CheckedList(WeightWindowGenerator, 'weight window generators', wwgs) - - @property - def max_splits(self) -> int: - return self._max_splits - - @property - def max_tracks(self) -> int: - return self._max_tracks - @run_mode.setter def run_mode(self, run_mode: str): cv.check_value('run mode', run_mode, {x.value for x in RunMode}) @@ -549,30 +342,50 @@ class Settings: if mode.value == run_mode: self._run_mode = mode + @property + def batches(self) -> int: + return self._batches + @batches.setter def batches(self, batches: int): cv.check_type('batches', batches, Integral) cv.check_greater_than('batches', batches, 0) self._batches = batches + @property + def generations_per_batch(self) -> int: + return self._generations_per_batch + @generations_per_batch.setter def generations_per_batch(self, generations_per_batch: int): 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 + @property + def inactive(self) -> int: + return self._inactive + @inactive.setter def inactive(self, inactive: int): cv.check_type('inactive batches', inactive, Integral) cv.check_greater_than('inactive batches', inactive, 0, True) self._inactive = inactive + @property + def max_lost_particles(self) -> int: + return self._max_lost_particles + @max_lost_particles.setter def max_lost_particles(self, max_lost_particles: int): cv.check_type('max_lost_particles', max_lost_particles, Integral) cv.check_greater_than('max_lost_particles', max_lost_particles, 0) self._max_lost_particles = max_lost_particles + @property + def rel_max_lost_particles(self) -> float: + return self._rel_max_lost_particles + @rel_max_lost_particles.setter def rel_max_lost_particles(self, rel_max_lost_particles: float): cv.check_type('rel_max_lost_particles', rel_max_lost_particles, Real) @@ -580,12 +393,20 @@ class Settings: cv.check_less_than('rel_max_lost_particles', rel_max_lost_particles, 1) self._rel_max_lost_particles = rel_max_lost_particles + @property + def particles(self) -> int: + return self._particles + @particles.setter def particles(self, particles: int): cv.check_type('particles', particles, Integral) cv.check_greater_than('particles', particles, 0) self._particles = particles + @property + def keff_trigger(self) -> dict: + return self._keff_trigger + @keff_trigger.setter def keff_trigger(self, keff_trigger: dict): if not isinstance(keff_trigger, dict): @@ -615,12 +436,20 @@ class Settings: self._keff_trigger = keff_trigger + @property + def energy_mode(self) -> str: + return self._energy_mode + @energy_mode.setter def energy_mode(self, energy_mode: str): cv.check_value('energy mode', energy_mode, ['continuous-energy', 'multi-group']) self._energy_mode = energy_mode + @property + def max_order(self) -> int: + return self._max_order + @max_order.setter def max_order(self, max_order: Optional[int]): if max_order is not None: @@ -629,12 +458,113 @@ class Settings: True) self._max_order = max_order + @property + def source(self) -> typing.List[Source]: + return self._source + @source.setter def source(self, source: typing.Union[Source, typing.Iterable[Source]]): if not isinstance(source, MutableSequence): source = [source] self._source = cv.CheckedList(Source, 'source distributions', source) + @property + def confidence_intervals(self) -> bool: + return self._confidence_intervals + + @confidence_intervals.setter + def confidence_intervals(self, confidence_intervals: bool): + cv.check_type('confidence interval', confidence_intervals, bool) + self._confidence_intervals = confidence_intervals + + @property + def electron_treatment(self) -> str: + return self._electron_treatment + + @electron_treatment.setter + def electron_treatment(self, electron_treatment: str): + cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) + self._electron_treatment = electron_treatment + + @property + def ptables(self) -> bool: + return self._ptables + + @ptables.setter + def ptables(self, ptables: bool): + cv.check_type('probability tables', ptables, bool) + self._ptables = ptables + + @property + def photon_transport(self) -> bool: + return self._photon_transport + + @photon_transport.setter + def photon_transport(self, photon_transport: bool): + cv.check_type('photon transport', photon_transport, bool) + self._photon_transport = photon_transport + + @property + def seed(self) -> int: + return self._seed + + @seed.setter + def seed(self, seed: int): + cv.check_type('random number generator seed', seed, Integral) + cv.check_greater_than('random number generator seed', seed, 0) + self._seed = seed + + @property + def survival_biasing(self) -> bool: + return self._survival_biasing + + @survival_biasing.setter + def survival_biasing(self, survival_biasing: bool): + cv.check_type('survival biasing', survival_biasing, bool) + self._survival_biasing = survival_biasing + + @property + def entropy_mesh(self) -> RegularMesh: + return self._entropy_mesh + + @entropy_mesh.setter + def entropy_mesh(self, entropy: RegularMesh): + cv.check_type('entropy mesh', entropy, RegularMesh) + self._entropy_mesh = entropy + + @property + def trigger_active(self) -> bool: + return self._trigger_active + + @trigger_active.setter + def trigger_active(self, trigger_active: bool): + cv.check_type('trigger active', trigger_active, bool) + self._trigger_active = trigger_active + + @property + def trigger_max_batches(self) -> int: + return self._trigger_max_batches + + @trigger_max_batches.setter + def trigger_max_batches(self, trigger_max_batches: int): + 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 + + @property + def trigger_batch_interval(self) -> int: + return self._trigger_batch_interval + + @trigger_batch_interval.setter + def trigger_batch_interval(self, trigger_batch_interval: int): + 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 + + @property + def output(self) -> dict: + return self._output + @output.setter def output(self, output: dict): cv.check_type('output', output, Mapping) @@ -646,12 +576,9 @@ class Settings: cv.check_type("output['path']", value, str) self._output = output - @verbosity.setter - def verbosity(self, verbosity: int): - 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 + @property + def sourcepoint(self) -> dict: + return self._sourcepoint @sourcepoint.setter def sourcepoint(self, sourcepoint: dict): @@ -674,6 +601,10 @@ class Settings: "setting sourcepoint options.") self._sourcepoint = sourcepoint + @property + def statepoint(self) -> dict: + return self._statepoint + @statepoint.setter def statepoint(self, statepoint: dict): cv.check_type('statepoint options', statepoint, Mapping) @@ -687,6 +618,10 @@ class Settings: "setting statepoint options.") self._statepoint = statepoint + @property + def surf_source_read(self) -> dict: + return self._surf_source_read + @surf_source_read.setter def surf_source_read(self, surf_source_read: dict): cv.check_type('surface source reading options', surf_source_read, Mapping) @@ -697,6 +632,10 @@ class Settings: cv.check_type('path to surface source file', value, str) self._surf_source_read = surf_source_read + @property + def surf_source_write(self) -> dict: + return self._surf_source_write + @surf_source_write.setter def surf_source_write(self, surf_source_write: dict): cv.check_type('surface source writing options', surf_source_write, Mapping) @@ -719,88 +658,30 @@ class Settings: self._surf_source_write = surf_source_write - @confidence_intervals.setter - def confidence_intervals(self, confidence_intervals: bool): - cv.check_type('confidence interval', confidence_intervals, bool) - self._confidence_intervals = confidence_intervals - - @electron_treatment.setter - def electron_treatment(self, electron_treatment: str): - cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) - self._electron_treatment = electron_treatment - - @photon_transport.setter - def photon_transport(self, photon_transport: bool): - cv.check_type('photon transport', photon_transport, bool) - self._photon_transport = photon_transport - - @ptables.setter - def ptables(self, ptables: bool): - cv.check_type('probability tables', ptables, bool) - self._ptables = ptables - - @seed.setter - def seed(self, seed: int): - 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: bool): - cv.check_type('survival biasing', survival_biasing, bool) - self._survival_biasing = survival_biasing - - @cutoff.setter - def cutoff(self, cutoff: dict): - if not isinstance(cutoff, Mapping): - msg = f'Unable to set cutoff from "{cutoff}" which is not a '\ - 'Python dictionary' - raise ValueError(msg) - for key in cutoff: - if key == 'weight': - cv.check_type('weight cutoff', cutoff[key], Real) - cv.check_greater_than('weight cutoff', cutoff[key], 0.0) - elif key == 'weight_avg': - cv.check_type('average survival weight', cutoff[key], Real) - cv.check_greater_than('average survival weight', - cutoff[key], 0.0) - elif key in ['energy_neutron', 'energy_photon', 'energy_electron', - 'energy_positron']: - cv.check_type('energy cutoff', cutoff[key], Real) - cv.check_greater_than('energy cutoff', cutoff[key], 0.0) - else: - msg = f'Unable to set cutoff to "{key}" which is unsupported ' \ - 'by OpenMC' - - self._cutoff = cutoff - - @entropy_mesh.setter - def entropy_mesh(self, entropy: RegularMesh): - cv.check_type('entropy mesh', entropy, RegularMesh) - self._entropy_mesh = entropy - - @trigger_active.setter - def trigger_active(self, 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: int): - 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: int): - 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 + @property + def no_reduce(self) -> bool: + return self._no_reduce @no_reduce.setter def no_reduce(self, no_reduce: bool): cv.check_type('no reduction option', no_reduce, bool) self._no_reduce = no_reduce + @property + def verbosity(self) -> int: + return self._verbosity + + @verbosity.setter + def verbosity(self, verbosity: int): + 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 + + @property + def tabular_legendre(self) -> dict: + return self._tabular_legendre + @tabular_legendre.setter def tabular_legendre(self, tabular_legendre: dict): cv.check_type('tabular_legendre settings', tabular_legendre, Mapping) @@ -814,6 +695,10 @@ class Settings: cv.check_greater_than('num_points tabular_legendre', value, 0) self._tabular_legendre = tabular_legendre + @property + def temperature(self) -> dict: + return self._temperature + @temperature.setter def temperature(self, temperature: dict): @@ -838,6 +723,10 @@ class Settings: self._temperature = temperature + @property + def trace(self) -> typing.Iterable: + return self._trace + @trace.setter def trace(self, trace: Iterable): cv.check_type('trace', trace, Iterable, Integral) @@ -847,6 +736,10 @@ class Settings: cv.check_greater_than('trace particle', trace[2], 0) self._trace = trace + @property + def track(self) -> typing.Iterable[typing.Iterable[int]]: + return self._track + @track.setter def track(self, track: typing.Iterable[typing.Iterable[int]]): cv.check_type('track', track, Iterable) @@ -862,6 +755,38 @@ class Settings: cv.check_type('track particle', t[2], Integral) self._track = track + @property + def cutoff(self) -> dict: + return self._cutoff + + @cutoff.setter + def cutoff(self, cutoff: dict): + if not isinstance(cutoff, Mapping): + msg = f'Unable to set cutoff from "{cutoff}" which is not a '\ + 'Python dictionary' + raise ValueError(msg) + for key in cutoff: + if key == 'weight': + cv.check_type('weight cutoff', cutoff[key], Real) + cv.check_greater_than('weight cutoff', cutoff[key], 0.0) + elif key == 'weight_avg': + cv.check_type('average survival weight', cutoff[key], Real) + cv.check_greater_than('average survival weight', + cutoff[key], 0.0) + elif key in ['energy_neutron', 'energy_photon', 'energy_electron', + 'energy_positron']: + cv.check_type('energy cutoff', cutoff[key], Real) + cv.check_greater_than('energy cutoff', cutoff[key], 0.0) + else: + msg = f'Unable to set cutoff to "{key}" which is unsupported ' \ + 'by OpenMC' + + self._cutoff = cutoff + + @property + def ufs_mesh(self) -> RegularMesh: + return self._ufs_mesh + @ufs_mesh.setter def ufs_mesh(self, ufs_mesh: RegularMesh): cv.check_type('UFS mesh', ufs_mesh, RegularMesh) @@ -870,6 +795,10 @@ class Settings: cv.check_length('UFS mesh upper-right corner', ufs_mesh.upper_right, 3) self._ufs_mesh = ufs_mesh + @property + def resonance_scattering(self) -> dict: + return self._resonance_scattering + @resonance_scattering.setter def resonance_scattering(self, res: dict): cv.check_type('resonance scattering settings', res, Mapping) @@ -894,6 +823,10 @@ class Settings: Iterable, str) self._resonance_scattering = res + @property + def volume_calculations(self) -> typing.List[VolumeCalculation]: + return self._volume_calculations + @volume_calculations.setter def volume_calculations( self, vol_calcs: typing.Union[VolumeCalculation, typing.Iterable[VolumeCalculation]] @@ -903,73 +836,140 @@ class Settings: self._volume_calculations = cv.CheckedList( VolumeCalculation, 'stochastic volume calculations', vol_calcs) + @property + def create_fission_neutrons(self) -> bool: + return self._create_fission_neutrons + @create_fission_neutrons.setter def create_fission_neutrons(self, create_fission_neutrons: bool): cv.check_type('Whether create fission neutrons', create_fission_neutrons, bool) self._create_fission_neutrons = create_fission_neutrons + @property + def create_delayed_neutrons(self) -> bool: + return self._create_delayed_neutrons + @create_delayed_neutrons.setter def create_delayed_neutrons(self, create_delayed_neutrons: bool): cv.check_type('Whether create only prompt neutrons', create_delayed_neutrons, bool) self._create_delayed_neutrons = create_delayed_neutrons + @property + def delayed_photon_scaling(self) -> bool: + return self._delayed_photon_scaling + @delayed_photon_scaling.setter def delayed_photon_scaling(self, value: bool): cv.check_type('delayed photon scaling', value, bool) self._delayed_photon_scaling = value - @event_based.setter - def event_based(self, value: bool): - cv.check_type('event based', value, bool) - self._event_based = value - - @max_particles_in_flight.setter - def max_particles_in_flight(self, value: int): - cv.check_type('max particles in flight', value, Integral) - cv.check_greater_than('max particles in flight', value, 0) - self._max_particles_in_flight = value + @property + def material_cell_offsets(self) -> bool: + return self._material_cell_offsets @material_cell_offsets.setter def material_cell_offsets(self, value: bool): cv.check_type('material cell offsets', value, bool) self._material_cell_offsets = value + @property + def log_grid_bins(self) -> int: + return self._log_grid_bins + @log_grid_bins.setter def log_grid_bins(self, log_grid_bins: int): cv.check_type('log grid bins', log_grid_bins, Real) cv.check_greater_than('log grid bins', log_grid_bins, 0) self._log_grid_bins = log_grid_bins + @property + def event_based(self) -> bool: + return self._event_based + + @event_based.setter + def event_based(self, value: bool): + cv.check_type('event based', value, bool) + self._event_based = value + + @property + def max_particles_in_flight(self) -> int: + return self._max_particles_in_flight + + @max_particles_in_flight.setter + def max_particles_in_flight(self, value: int): + cv.check_type('max particles in flight', value, Integral) + cv.check_greater_than('max particles in flight', value, 0) + self._max_particles_in_flight = value + + @property + def write_initial_source(self) -> bool: + return self._write_initial_source + @write_initial_source.setter def write_initial_source(self, value: bool): cv.check_type('write initial source', value, bool) self._write_initial_source = value + @property + def weight_windows(self) -> typing.List[WeightWindows]: + return self._weight_windows + @weight_windows.setter def weight_windows(self, value: typing.Union[WeightWindows, typing.Iterable[WeightWindows]]): if not isinstance(value, MutableSequence): value = [value] self._weight_windows = cv.CheckedList(WeightWindows, 'weight windows', value) + @property + def weight_windows_on(self) -> bool: + return self._weight_windows_on + @weight_windows_on.setter def weight_windows_on(self, value: bool): cv.check_type('weight windows on', value, bool) self._weight_windows_on = value + @property + def max_splits(self) -> int: + return self._max_splits + @max_splits.setter def max_splits(self, value: int): cv.check_type('maximum particle splits', value, Integral) cv.check_greater_than('max particle splits', value, 0) self._max_splits = value + @property + def max_tracks(self) -> int: + return self._max_tracks + @max_tracks.setter def max_tracks(self, value: int): cv.check_type('maximum particle tracks', value, Integral) cv.check_greater_than('maximum particle tracks', value, 0, True) self._max_tracks = value + @property + def weight_windows_file(self) -> Optional[PathLike]: + return self._weight_windows_file + + @weight_windows_file.setter + def weight_windows_file(self, value: PathLike): + cv.check_type('weight windows file', value, (str, Path)) + self._weight_windows_file = value + + @property + def weight_window_generators(self) -> typing.List[WeightWindowGenerator]: + return self._weight_window_generators + + @weight_window_generators.setter + def weight_window_generators(self, wwgs): + if not isinstance(wwgs, MutableSequence): + wwgs = [wwgs] + self._weight_window_generators = cv.CheckedList(WeightWindowGenerator, 'weight window generators', wwgs) + def _create_run_mode_subelement(self, root): elem = ET.SubElement(root, "run_mode") elem.text = self._run_mode.value diff --git a/openmc/source.py b/openmc/source.py index cc68c9535b..150830cc82 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -127,102 +127,102 @@ class Source: def file(self): return self._file - @property - def library(self): - return self._library - - @property - def parameters(self): - return self._parameters - - @property - def space(self): - return self._space - - @property - def angle(self): - return self._angle - - @property - def energy(self): - return self._energy - - @property - def time(self): - return self._time - - @property - def strength(self): - return self._strength - - @property - def particle(self): - return self._particle - - @property - def domain_ids(self): - return self._domain_ids - - @property - def domain_type(self): - return self._domain_type - - @domain_ids.setter - def domain_ids(self, ids): - cv.check_type('domain IDs', ids, Iterable, Real) - self._domain_ids = ids - - @domain_type.setter - def domain_type(self, domain_type): - cv.check_value('domain type', domain_type, ('cell', 'material', 'universe')) - self._domain_type = domain_type - @file.setter def file(self, filename): cv.check_type('source file', filename, str) self._file = filename + @property + def library(self): + return self._library + @library.setter def library(self, library_name): cv.check_type('library', library_name, str) self._library = library_name + @property + def parameters(self): + return self._parameters + @parameters.setter def parameters(self, parameters_path): cv.check_type('parameters', parameters_path, str) self._parameters = parameters_path + @property + def space(self): + return self._space + @space.setter def space(self, space): cv.check_type('spatial distribution', space, Spatial) self._space = space + @property + def angle(self): + return self._angle + @angle.setter def angle(self, angle): cv.check_type('angular distribution', angle, UnitSphere) self._angle = angle + @property + def energy(self): + return self._energy + @energy.setter def energy(self, energy): cv.check_type('energy distribution', energy, Univariate) self._energy = energy + @property + def time(self): + return self._time + @time.setter def time(self, time): cv.check_type('time distribution', time, Univariate) self._time = time + @property + def strength(self): + return self._strength + @strength.setter def strength(self, strength): cv.check_type('source strength', strength, Real) cv.check_greater_than('source strength', strength, 0.0, True) self._strength = strength + @property + def particle(self): + return self._particle + @particle.setter def particle(self, particle): cv.check_value('source particle', particle, ['neutron', 'photon']) self._particle = particle + @property + def domain_ids(self): + return self._domain_ids + + @domain_ids.setter + def domain_ids(self, ids): + cv.check_type('domain IDs', ids, Iterable, Real) + self._domain_ids = ids + + @property + def domain_type(self): + return self._domain_type + + @domain_type.setter + def domain_type(self, domain_type): + cv.check_value('domain type', domain_type, ('cell', 'material', 'universe')) + self._domain_type = domain_type + def to_xml_element(self) -> ET.Element: """Return XML representation of the source diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 7c1ecd1377..f6df01bd4f 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -367,6 +367,26 @@ class StatePoint: def sparse(self): return self._sparse + @sparse.setter + def sparse(self, sparse): + """Convert tally data from NumPy arrays to SciPy list of lists (LIL) + sparse matrices, and vice versa. + + This property may be used to reduce the amount of data in memory during + tally data processing. The tally data will be stored as SciPy LIL + matrices internally within each Tally object. All tally data access + properties and methods will return data as a dense NumPy array. + + """ + + cv.check_type('sparse', sparse, bool) + self._sparse = sparse + + # Update tally sparsities + if self._tallies_read: + for tally_id in self.tallies: + self.tallies[tally_id].sparse = self.sparse + @property def tallies(self): if self.tallies_present and not self._tallies_read: @@ -484,26 +504,6 @@ class StatePoint: def summary(self): return self._summary - @sparse.setter - def sparse(self, sparse): - """Convert tally data from NumPy arrays to SciPy list of lists (LIL) - sparse matrices, and vice versa. - - This property may be used to reduce the amount of data in memory during - tally data processing. The tally data will be stored as SciPy LIL - matrices internally within each Tally object. All tally data access - properties and methods will return data as a dense NumPy array. - - """ - - cv.check_type('sparse', sparse, bool) - self._sparse = sparse - - # Update tally sparsities - if self._tallies_read: - for tally_id in self.tallies: - self.tallies[tally_id].sparse = self.sparse - def close(self): """Close the statepoint HDF5 file and the corresponding summary HDF5 file if present. diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 190dfd64d0..058bee7da6 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -102,15 +102,15 @@ class PolarAzimuthal(UnitSphere): def mu(self): return self._mu - @property - def phi(self): - return self._phi - @mu.setter def mu(self, mu): cv.check_type('cosine of polar angle', mu, Univariate) self._mu = mu + @property + def phi(self): + return self._phi + @phi.setter def phi(self, phi): cv.check_type('azimuthal angle', phi, Univariate) @@ -313,24 +313,24 @@ class CartesianIndependent(Spatial): def x(self): return self._x - @property - def y(self): - return self._y - - @property - def z(self): - return self._z - @x.setter def x(self, x): cv.check_type('x coordinate', x, Univariate) self._x = x + @property + def y(self): + return self._y + @y.setter def y(self, y): cv.check_type('y coordinate', y, Univariate) self._y = y + @property + def z(self): + return self._z + @z.setter def z(self, z): cv.check_type('z coordinate', z, Univariate) @@ -426,33 +426,33 @@ class SphericalIndependent(Spatial): def r(self): return self._r - @property - def cos_theta(self): - return self._cos_theta - - @property - def phi(self): - return self._phi - - @property - def origin(self): - return self._origin - @r.setter def r(self, r): cv.check_type('r coordinate', r, Univariate) self._r = r + @property + def cos_theta(self): + return self._cos_theta + @cos_theta.setter def cos_theta(self, cos_theta): cv.check_type('cos_theta coordinate', cos_theta, Univariate) self._cos_theta = cos_theta + @property + def phi(self): + return self._phi + @phi.setter def phi(self, phi): cv.check_type('phi coordinate', phi, Univariate) self._phi = phi + @property + def origin(self): + return self._origin + @origin.setter def origin(self, origin): cv.check_type('origin coordinates', origin, Iterable, Real) @@ -548,33 +548,33 @@ class CylindricalIndependent(Spatial): def r(self): return self._r - @property - def phi(self): - return self._phi - - @property - def z(self): - return self._z - - @property - def origin(self): - return self._origin - @r.setter def r(self, r): cv.check_type('r coordinate', r, Univariate) self._r = r + @property + def phi(self): + return self._phi + @phi.setter def phi(self, phi): cv.check_type('phi coordinate', phi, Univariate) self._phi = phi + @property + def z(self): + return self._z + @z.setter def z(self, z): cv.check_type('z coordinate', z, Univariate) self._z = z + @property + def origin(self): + return self._origin + @origin.setter def origin(self, origin): cv.check_type('origin coordinates', origin, Iterable, Real) @@ -781,26 +781,26 @@ class Box(Spatial): def lower_left(self): return self._lower_left - @property - def upper_right(self): - return self._upper_right - - @property - def only_fissionable(self): - return self._only_fissionable - @lower_left.setter def lower_left(self, lower_left): cv.check_type('lower left coordinate', lower_left, Iterable, Real) cv.check_length('lower left coordinate', lower_left, 3) self._lower_left = lower_left + @property + def upper_right(self): + return self._upper_right + @upper_right.setter def upper_right(self, upper_right): cv.check_type('upper right coordinate', upper_right, Iterable, Real) cv.check_length('upper right coordinate', upper_right, 3) self._upper_right = upper_right + @property + def only_fissionable(self): + return self._only_fissionable + @only_fissionable.setter def only_fissionable(self, only_fissionable): cv.check_type('only fissionable', only_fissionable, bool) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index b98b87d6f4..5625d26acb 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -130,10 +130,6 @@ class Discrete(Univariate): def x(self): return self._x - @property - def p(self): - return self._p - @x.setter def x(self, x): if isinstance(x, Real): @@ -141,6 +137,10 @@ class Discrete(Univariate): cv.check_type('discrete values', x, Iterable, Real) self._x = np.array(x, dtype=float) + @property + def p(self): + return self._p + @p.setter def p(self, p): if isinstance(p, Real): @@ -282,15 +282,15 @@ class Uniform(Univariate): def a(self): return self._a - @property - def b(self): - return self._b - @a.setter def a(self, a): cv.check_type('Uniform a', a, Real) self._a = a + @property + def b(self): + return self._b + @b.setter def b(self, b): cv.check_type('Uniform b', b, Real) @@ -384,24 +384,24 @@ class PowerLaw(Univariate): def a(self): return self._a - @property - def b(self): - return self._b - - @property - def n(self): - return self._n - @a.setter def a(self, a): cv.check_type('interval lower bound', a, Real) self._a = a + @property + def b(self): + return self._b + @b.setter def b(self, b): cv.check_type('interval upper bound', b, Real) self._b = b + @property + def n(self): + return self._n + @n.setter def n(self, n): cv.check_type('power law exponent', n, Real) @@ -570,16 +570,16 @@ class Watt(Univariate): def a(self): return self._a - @property - def b(self): - return self._b - @a.setter def a(self, a): cv.check_type('Watt a', a, Real) cv.check_greater_than('Watt a', a, 0.0) self._a = a + @property + def b(self): + return self._b + @b.setter def b(self, b): cv.check_type('Watt b', b, Real) @@ -664,15 +664,15 @@ class Normal(Univariate): def mean_value(self): return self._mean_value - @property - def std_dev(self): - return self._std_dev - @mean_value.setter def mean_value(self, mean_value): cv.check_type('Normal mean_value', mean_value, Real) self._mean_value = mean_value + @property + def std_dev(self): + return self._std_dev + @std_dev.setter def std_dev(self, std_dev): cv.check_type('Normal std_dev', std_dev, Real) @@ -807,19 +807,15 @@ class Tabular(Univariate): def x(self): return self._x - @property - def p(self): - return self._p - - @property - def interpolation(self): - return self._interpolation - @x.setter def x(self, x): cv.check_type('tabulated values', x, Iterable, Real) self._x = np.array(x, dtype=float) + @property + def p(self): + return self._p + @p.setter def p(self, p): cv.check_type('tabulated probabilities', p, Iterable, Real) @@ -828,6 +824,10 @@ class Tabular(Univariate): cv.check_greater_than('tabulated probability', pk, 0.0, True) self._p = np.array(p, dtype=float) + @property + def interpolation(self): + return self._interpolation + @interpolation.setter def interpolation(self, interpolation): cv.check_value('interpolation', interpolation, _INTERPOLATION_SCHEMES) @@ -1093,10 +1093,6 @@ class Mixture(Univariate): def probability(self): return self._probability - @property - def distribution(self): - return self._distribution - @probability.setter def probability(self, probability): cv.check_type('mixture distribution probabilities', probability, @@ -1106,6 +1102,10 @@ class Mixture(Univariate): p, 0.0, True) self._probability = probability + @property + def distribution(self): + return self._distribution + @distribution.setter def distribution(self, distribution): cv.check_type('mixture distribution components', distribution, diff --git a/openmc/surface.py b/openmc/surface.py index b195c0af2b..1f35e7bff4 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -185,18 +185,6 @@ class Surface(IDManagerMixin, ABC): def name(self): return self._name - @property - def type(self): - return self._type - - @property - def boundary_type(self): - return self._boundary_type - - @property - def coefficients(self): - return self._coefficients - @name.setter def name(self, name): if name is not None: @@ -205,12 +193,24 @@ class Surface(IDManagerMixin, ABC): else: self._name = '' + @property + def type(self): + return self._type + + @property + def boundary_type(self): + return self._boundary_type + @boundary_type.setter def boundary_type(self, boundary_type): check_type('boundary type', boundary_type, str) check_value('boundary type', boundary_type, _BOUNDARY_TYPES) self._boundary_type = boundary_type + @property + def coefficients(self): + return self._coefficients + def bounding_box(self, side): """Determine an axis-aligned bounding box. diff --git a/openmc/tallies.py b/openmc/tallies.py index 6f56fbb64d..5de00f43c3 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -150,18 +150,61 @@ class Tally(IDManagerMixin): def name(self): return self._name + @name.setter + def name(self, name): + cv.check_type('tally name', name, str, none_ok=True) + self._name = name + @property def multiply_density(self): return self._multiply_density + @multiply_density.setter + def multiply_density(self, value): + cv.check_type('multiply density', value, bool) + self._multiply_density = value + @property def filters(self): return self._filters + @filters.setter + def filters(self, filters): + cv.check_type('tally filters', filters, MutableSequence) + + # If the filter is already in the Tally, raise an error + visited_filters = set() + for f in filters: + if f in visited_filters: + msg = (f'Unable to add a duplicate filter "{f}" to Tally ' + f'ID="{self.id}" since duplicate filters are not ' + 'supported in the OpenMC Python API') + raise ValueError(msg) + visited_filters.add(f) + + self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters', filters) + @property def nuclides(self): return self._nuclides + @nuclides.setter + def nuclides(self, nuclides): + cv.check_type('tally nuclides', nuclides, MutableSequence) + + # If the nuclide is already in the Tally, raise an error + visited_nuclides = set() + for nuc in nuclides: + if nuc in visited_nuclides: + msg = (f'Unable to add a duplicate nuclide "{nuc}" to Tally ID=' + f'"{self.id}" since duplicate nuclides are not supported ' + 'in the OpenMC Python API') + raise ValueError(msg) + visited_nuclides.add(nuc) + + self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides', + nuclides) + @property def num_nuclides(self): return len(self._nuclides) @@ -170,6 +213,33 @@ class Tally(IDManagerMixin): def scores(self): return self._scores + @scores.setter + def scores(self, scores): + cv.check_type('tally scores', scores, MutableSequence) + + visited_scores = set() + for i, score in enumerate(scores): + # If the score is already in the Tally, raise an error + if score in visited_scores: + msg = (f'Unable to add a duplicate score "{score}" to Tally ' + f'ID="{self.id}" since duplicate scores are not ' + 'supported in the OpenMC Python API') + raise ValueError(msg) + visited_scores.add(score) + + # If score is a string, strip whitespace + if isinstance(score, str): + # Check to see if scores are deprecated before storing + for deprecated in ['scatter-', 'nu-scatter-', 'scatter-p', + 'nu-scatter-p', 'scatter-y', 'nu-scatter-y', + 'flux-y', 'total-y']: + if score.strip().startswith(deprecated): + msg = score.strip() + ' is no longer supported.' + raise ValueError(msg) + scores[i] = score.strip() + + self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) + @property def num_scores(self): return len(self._scores) @@ -194,18 +264,40 @@ class Tally(IDManagerMixin): def estimator(self): return self._estimator + @estimator.setter + def estimator(self, estimator): + cv.check_value('estimator', estimator, ESTIMATOR_TYPES) + self._estimator = estimator + @property def triggers(self): return self._triggers + @triggers.setter + def triggers(self, triggers): + cv.check_type('tally triggers', triggers, MutableSequence) + self._triggers = cv.CheckedList(openmc.Trigger, 'tally triggers', + triggers) + @property def num_realizations(self): return self._num_realizations + @num_realizations.setter + def num_realizations(self, num_realizations): + cv.check_type('number of realizations', num_realizations, Integral) + cv.check_greater_than('number of realizations', num_realizations, 0, True) + self._num_realizations = num_realizations + @property def with_summary(self): return self._with_summary + @with_summary.setter + def with_summary(self, with_summary): + cv.check_type('with_summary', with_summary, bool) + self._with_summary = with_summary + def _read_results(self): if self._results_read: return @@ -246,6 +338,11 @@ class Tally(IDManagerMixin): else: return self._sum + @sum.setter + def sum(self, sum): + cv.check_type('sum', sum, Iterable) + self._sum = sum + @property def sum_sq(self): if not self._sp_filename or self.derived: @@ -259,6 +356,11 @@ class Tally(IDManagerMixin): else: return self._sum_sq + @sum_sq.setter + def sum_sq(self, sum_sq): + cv.check_type('sum_sq', sum_sq, Iterable) + self._sum_sq = sum_sq + @property def mean(self): if self._mean is None: @@ -305,6 +407,11 @@ class Tally(IDManagerMixin): def with_batch_statistics(self): return self._with_batch_statistics + @with_batch_statistics.setter + def with_batch_statistics(self, with_batch_statistics): + cv.check_type('with_batch_statistics', with_batch_statistics, bool) + self._with_batch_statistics = with_batch_statistics + @property def derived(self): return self._derived @@ -313,122 +420,15 @@ class Tally(IDManagerMixin): def derivative(self): return self._derivative - @property - def sparse(self): - return self._sparse - - @estimator.setter - def estimator(self, estimator): - cv.check_value('estimator', estimator, ESTIMATOR_TYPES) - self._estimator = estimator - - @triggers.setter - def triggers(self, triggers): - cv.check_type('tally triggers', triggers, MutableSequence) - self._triggers = cv.CheckedList(openmc.Trigger, 'tally triggers', - triggers) - - @name.setter - def name(self, name): - cv.check_type('tally name', name, str, none_ok=True) - self._name = name - - @multiply_density.setter - def multiply_density(self, value): - cv.check_type('multiply density', value, bool) - self._multiply_density = value - @derivative.setter def derivative(self, deriv): cv.check_type('tally derivative', deriv, openmc.TallyDerivative, none_ok=True) self._derivative = deriv - @filters.setter - def filters(self, filters): - cv.check_type('tally filters', filters, MutableSequence) - - # If the filter is already in the Tally, raise an error - visited_filters = set() - for f in filters: - if f in visited_filters: - msg = (f'Unable to add a duplicate filter "{f}" to Tally ' - f'ID="{self.id}" since duplicate filters are not ' - 'supported in the OpenMC Python API') - raise ValueError(msg) - visited_filters.add(f) - - self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters', filters) - - @nuclides.setter - def nuclides(self, nuclides): - cv.check_type('tally nuclides', nuclides, MutableSequence) - - # If the nuclide is already in the Tally, raise an error - visited_nuclides = set() - for nuc in nuclides: - if nuc in visited_nuclides: - msg = (f'Unable to add a duplicate nuclide "{nuc}" to Tally ID=' - f'"{self.id}" since duplicate nuclides are not supported ' - 'in the OpenMC Python API') - raise ValueError(msg) - visited_nuclides.add(nuc) - - self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides', - nuclides) - - @scores.setter - def scores(self, scores): - cv.check_type('tally scores', scores, MutableSequence) - - visited_scores = set() - for i, score in enumerate(scores): - # If the score is already in the Tally, raise an error - if score in visited_scores: - msg = (f'Unable to add a duplicate score "{score}" to Tally ' - f'ID="{self.id}" since duplicate scores are not ' - 'supported in the OpenMC Python API') - raise ValueError(msg) - visited_scores.add(score) - - # If score is a string, strip whitespace - if isinstance(score, str): - # Check to see if scores are deprecated before storing - for deprecated in ['scatter-', 'nu-scatter-', 'scatter-p', - 'nu-scatter-p', 'scatter-y', 'nu-scatter-y', - 'flux-y', 'total-y']: - if score.strip().startswith(deprecated): - msg = score.strip() + ' is no longer supported.' - raise ValueError(msg) - scores[i] = score.strip() - - self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) - - @num_realizations.setter - def num_realizations(self, num_realizations): - cv.check_type('number of realizations', num_realizations, Integral) - cv.check_greater_than('number of realizations', num_realizations, 0, True) - self._num_realizations = num_realizations - - @with_summary.setter - def with_summary(self, with_summary): - cv.check_type('with_summary', with_summary, bool) - self._with_summary = with_summary - - @with_batch_statistics.setter - def with_batch_statistics(self, with_batch_statistics): - cv.check_type('with_batch_statistics', with_batch_statistics, bool) - self._with_batch_statistics = with_batch_statistics - - @sum.setter - def sum(self, sum): - cv.check_type('sum', sum, Iterable) - self._sum = sum - - @sum_sq.setter - def sum_sq(self, sum_sq): - cv.check_type('sum_sq', sum_sq, Iterable) - self._sum_sq = sum_sq + @property + def sparse(self): + return self._sparse @sparse.setter def sparse(self, sparse): diff --git a/openmc/tally_derivative.py b/openmc/tally_derivative.py index d8e165e8be..779ca619f2 100644 --- a/openmc/tally_derivative.py +++ b/openmc/tally_derivative.py @@ -60,14 +60,6 @@ class TallyDerivative(EqualityMixin, IDManagerMixin): def variable(self): return self._variable - @property - def material(self): - return self._material - - @property - def nuclide(self): - return self._nuclide - @variable.setter def variable(self, var): if var is not None: @@ -76,12 +68,20 @@ class TallyDerivative(EqualityMixin, IDManagerMixin): ('density', 'nuclide_density', 'temperature')) self._variable = var + @property + def material(self): + return self._material + @material.setter def material(self, mat): if mat is not None: cv.check_type('derivative material', mat, Integral) self._material = mat + @property + def nuclide(self): + return self._nuclide + @nuclide.setter def nuclide(self, nuc): if nuc is not None: diff --git a/openmc/trigger.py b/openmc/trigger.py index 3f7d8d7d07..86d17dfefd 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -45,25 +45,25 @@ class Trigger(EqualityMixin): def trigger_type(self): return self._trigger_type - @property - def threshold(self): - return self._threshold - - @property - def scores(self): - return self._scores - @trigger_type.setter def trigger_type(self, trigger_type): cv.check_value('tally trigger type', trigger_type, ['variance', 'std_dev', 'rel_err']) self._trigger_type = trigger_type + @property + def threshold(self): + return self._threshold + @threshold.setter def threshold(self, threshold): cv.check_type('tally trigger threshold', threshold, Real) self._threshold = threshold + @property + def scores(self): + return self._scores + @scores.setter def scores(self, scores): cv.check_type('trigger scores', scores, Iterable, str) diff --git a/openmc/universe.py b/openmc/universe.py index 458729d5cf..6acecf8006 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -58,10 +58,6 @@ class UniverseBase(ABC, IDManagerMixin): def name(self): return self._name - @property - def volume(self): - return self._volume - @name.setter def name(self, name): if name is not None: @@ -70,6 +66,10 @@ class UniverseBase(ABC, IDManagerMixin): else: self._name = '' + @property + def volume(self): + return self._volume + @volume.setter def volume(self, volume): if volume is not None: @@ -854,6 +854,11 @@ class DAGMCUniverse(UniverseBase): def auto_mat_ids(self): return self._auto_mat_ids + @auto_mat_ids.setter + def auto_mat_ids(self, val): + cv.check_type('DAGMC automatic material ids', val, bool) + self._auto_mat_ids = val + @property def material_names(self): dagmc_file_contents = h5py.File(self.filename) @@ -870,11 +875,6 @@ class DAGMCUniverse(UniverseBase): return sorted(set(material_tags_ascii)) - @auto_mat_ids.setter - def auto_mat_ids(self, val): - cv.check_type('DAGMC automatic material ids', val, bool) - self._auto_mat_ids = val - def get_all_cells(self, memo=None): return OrderedDict() diff --git a/openmc/volume.py b/openmc/volume.py index 363b108c9f..72fe89fbc4 100644 --- a/openmc/volume.py +++ b/openmc/volume.py @@ -126,30 +126,75 @@ class VolumeCalculation: def ids(self): return self._ids + @ids.setter + def ids(self, ids): + cv.check_type('domain IDs', ids, Iterable, Real) + self._ids = ids + @property def samples(self): return self._samples + @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 + @property def lower_left(self): return self._lower_left + @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 + @property def upper_right(self): return self._upper_right + @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 + @property def threshold(self): return self._threshold + @threshold.setter + def threshold(self, threshold): + name = 'volume std. dev. threshold' + cv.check_type(name, threshold, Real) + cv.check_greater_than(name, threshold, 0.0) + self._threshold = threshold + @property def trigger_type(self): return self._trigger_type + @trigger_type.setter + def trigger_type(self, trigger_type): + cv.check_value('tally trigger type', trigger_type, + ('variance', 'std_dev', 'rel_err')) + self._trigger_type = trigger_type + @property def iterations(self): return self._iterations + @iterations.setter + def iterations(self, iterations): + name = 'volume calculation iterations' + cv.check_type(name, iterations, Integral) + cv.check_greater_than(name, iterations, 0) + self._iterations = iterations + @property def domain_type(self): return self._domain_type @@ -158,10 +203,20 @@ class VolumeCalculation: def atoms(self): return self._atoms + @atoms.setter + def atoms(self, atoms): + cv.check_type('atoms', atoms, Mapping) + self._atoms = atoms + @property def volumes(self): return self._volumes + @volumes.setter + def volumes(self, volumes): + cv.check_type('volumes', volumes, Mapping) + self._volumes = volumes + @property def atoms_dataframe(self): items = [] @@ -172,61 +227,6 @@ class VolumeCalculation: return pd.DataFrame.from_records(items, columns=columns) - @ids.setter - def ids(self, ids): - cv.check_type('domain IDs', ids, Iterable, Real) - self._ids = 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 - - @threshold.setter - def threshold(self, threshold): - name = 'volume std. dev. threshold' - cv.check_type(name, threshold, Real) - cv.check_greater_than(name, threshold, 0.0) - self._threshold = threshold - - @trigger_type.setter - def trigger_type(self, trigger_type): - cv.check_value('tally trigger type', trigger_type, - ('variance', 'std_dev', 'rel_err')) - self._trigger_type = trigger_type - - @iterations.setter - def iterations(self, iterations): - name = 'volume calculation iterations' - cv.check_type(name, iterations, Integral) - cv.check_greater_than(name, iterations, 0) - self._iterations = iterations - - @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 - def set_trigger(self, threshold, trigger_type): """Set a trigger on the volume calculation