mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Get rid of extra Settings class
This commit is contained in:
parent
ccfee55115
commit
a460782691
8 changed files with 77 additions and 151 deletions
|
|
@ -29,7 +29,6 @@ Metaclasses
|
|||
:toctree: generated
|
||||
:nosignatures:
|
||||
|
||||
openmc.deplete.Settings
|
||||
openmc.deplete.Operator
|
||||
|
||||
OpenMC Classes
|
||||
|
|
@ -39,7 +38,6 @@ OpenMC Classes
|
|||
:toctree: generated
|
||||
:nosignatures:
|
||||
|
||||
openmc.deplete.OpenMCSettings
|
||||
openmc.deplete.Materials
|
||||
openmc.deplete.OpenMCOperator
|
||||
|
||||
|
|
|
|||
|
|
@ -7,44 +7,9 @@ to run a full depletion simulation.
|
|||
from collections import namedtuple
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Settings(object):
|
||||
"""The Settings class.
|
||||
|
||||
Contains all parameters necessary for the integrator.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
output_dir : pathlib.Path
|
||||
Path to output directory to save results.
|
||||
chain_file : str
|
||||
Path to the depletion chain XML file. Defaults to the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable if it exists.
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
try:
|
||||
self.chain_file = os.environ["OPENMC_DEPLETE_CHAIN"]
|
||||
except KeyError:
|
||||
self.chain_file = None
|
||||
self.output_dir = '.'
|
||||
self.dilute_initial = 1.0e3
|
||||
|
||||
@property
|
||||
def output_dir(self):
|
||||
return self._output_dir
|
||||
|
||||
@output_dir.setter
|
||||
def output_dir(self, output_dir):
|
||||
self._output_dir = Path(output_dir)
|
||||
|
||||
from .chain import Chain
|
||||
|
||||
OperatorResult = namedtuple('OperatorResult', ['k', 'rates'])
|
||||
|
||||
|
|
@ -52,14 +17,30 @@ OperatorResult = namedtuple('OperatorResult', ['k', 'rates'])
|
|||
class Operator(metaclass=ABCMeta):
|
||||
"""Abstract class defining a transport operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
chain_file : str, optional
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
settings : Settings
|
||||
Settings object.
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
|
||||
"""
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
def __init__(self, chain_file=None):
|
||||
self.dilute_initial = 1.0e3
|
||||
self.output_dir = '.'
|
||||
|
||||
# Read depletion chain
|
||||
if chain_file is None:
|
||||
chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN", None)
|
||||
if chain_file is None:
|
||||
raise IOError("No chain specified, either manually or in "
|
||||
"environment variable OPENMC_DEPLETE_CHAIN.")
|
||||
self.chain = Chain.from_xml(chain_file)
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, vec, print_out=True):
|
||||
|
|
@ -83,11 +64,11 @@ class Operator(metaclass=ABCMeta):
|
|||
def __enter__(self):
|
||||
# Save current directory and move to specific output directory
|
||||
self._orig_dir = os.getcwd()
|
||||
if not self.settings.output_dir.exists():
|
||||
self.settings.output_dir.mkdir() # exist_ok parameter is 3.5+
|
||||
if not self.output_dir.exists():
|
||||
self.output_dir.mkdir() # exist_ok parameter is 3.5+
|
||||
|
||||
# In Python 3.6+, chdir accepts a Path directly
|
||||
os.chdir(str(self.settings.output_dir))
|
||||
os.chdir(str(self.output_dir))
|
||||
|
||||
return self.initial_condition()
|
||||
|
||||
|
|
@ -95,6 +76,14 @@ class Operator(metaclass=ABCMeta):
|
|||
self.finalize()
|
||||
os.chdir(self._orig_dir)
|
||||
|
||||
@property
|
||||
def output_dir(self):
|
||||
return self._output_dir
|
||||
|
||||
@output_dir.setter
|
||||
def output_dir(self, output_dir):
|
||||
self._output_dir = Path(output_dir)
|
||||
|
||||
@abstractmethod
|
||||
def initial_condition(self):
|
||||
"""Performs final setup and returns initial condition.
|
||||
|
|
|
|||
|
|
@ -328,15 +328,7 @@ class Chain(object):
|
|||
chain = cls()
|
||||
|
||||
# Load XML tree
|
||||
try:
|
||||
root = ET.parse(filename)
|
||||
except Exception:
|
||||
if filename is None:
|
||||
msg = ("No chain specified, either manually or in environment "
|
||||
"variable OPENMC_DEPLETE_CHAIN.")
|
||||
else:
|
||||
msg = 'Decay chain "{}" is invalid.'.format(filename)
|
||||
raise IOError(msg)
|
||||
root = ET.parse(str(filename))
|
||||
|
||||
for i, nuclide_elem in enumerate(root.findall('nuclide_table')):
|
||||
nuc = Nuclide.from_xml(nuclide_elem)
|
||||
|
|
@ -367,10 +359,10 @@ class Chain(object):
|
|||
|
||||
tree = ET.ElementTree(root_elem)
|
||||
if _have_lxml:
|
||||
tree.write(filename, encoding='utf-8', pretty_print=True)
|
||||
tree.write(str(filename), encoding='utf-8', pretty_print=True)
|
||||
else:
|
||||
clean_xml_indentation(root_elem)
|
||||
tree.write(filename, encoding='utf-8')
|
||||
tree.write(str(filename), encoding='utf-8')
|
||||
|
||||
def form_matrix(self, rates):
|
||||
"""Forms depletion matrix.
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ import openmc
|
|||
import openmc.capi
|
||||
from openmc.data import JOULE_PER_EV
|
||||
from . import comm
|
||||
from .abc import Settings, Operator, OperatorResult
|
||||
from .abc import Operator, OperatorResult
|
||||
from .atom_number import AtomNumber
|
||||
from .chain import Chain
|
||||
from .reaction_rates import ReactionRates
|
||||
|
||||
|
||||
|
|
@ -40,77 +39,34 @@ def _distribute(items):
|
|||
j += chunk_size
|
||||
|
||||
|
||||
class OpenMCSettings(Settings):
|
||||
"""Extends Settings to provide information OpenMC needs to run.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
output_dir : pathlib.Path
|
||||
Path to output directory to save results.
|
||||
chain_file : str
|
||||
Path to the depletion chain XML file. Defaults to the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable if it exists.
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
power : float
|
||||
Power of the reactor in [W]. For a 2D problem, the power can be given in
|
||||
W/cm as long as the "volume" assigned to a depletion material is
|
||||
actually an area in cm^2.
|
||||
round_number : bool
|
||||
Whether or not to round output to OpenMC to 8 digits.
|
||||
Useful in testing, as OpenMC is incredibly sensitive to exact values.
|
||||
settings : openmc.Settings
|
||||
Settings for OpenMC simulations
|
||||
|
||||
"""
|
||||
|
||||
_depletion_attrs = {'_output_dir', 'chain_file', 'dilute_initial',
|
||||
'round_number'}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.round_number = False
|
||||
|
||||
# Avoid setattr to create OpenMC settings
|
||||
self.__dict__['settings'] = openmc.Settings()
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if hasattr(self.__class__, name):
|
||||
# Use properties when appropriate
|
||||
prop = getattr(self.__class__, name)
|
||||
prop.fset(self, value)
|
||||
elif name in self._depletion_attrs:
|
||||
# For known attributes, store in dictionary
|
||||
self.__dict__[name] = value
|
||||
else:
|
||||
# otherwise, delegate to openmc.Settings
|
||||
setattr(self.__dict__['settings'], name, value)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self._depletion_attrs:
|
||||
return self.__dict__[name]
|
||||
else:
|
||||
return getattr(self.__dict__['settings'], name)
|
||||
|
||||
|
||||
class OpenMCOperator(Operator):
|
||||
"""OpenMC transport operator
|
||||
|
||||
Parameters
|
||||
----------
|
||||
geometry : openmc.Geometry
|
||||
The OpenMC geometry object.
|
||||
settings : openmc.deplete.OpenMCSettings
|
||||
Settings object.
|
||||
OpenMC geometry object
|
||||
settings : openmc.Settings
|
||||
OpenMC Settings object
|
||||
chain_file : str, optional
|
||||
Path to the depletion chain XML file. Defaults to the
|
||||
:envvar:`OPENMC_DEPLETE_CHAIN` environment variable if it exists.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
settings : OpenMCSettings
|
||||
Settings object. (From Operator)
|
||||
geometry : openmc.Geometry
|
||||
The OpenMC geometry object.
|
||||
OpenMC geometry object
|
||||
settings : openmc.Settings
|
||||
OpenMC settings object
|
||||
dilute_initial : float
|
||||
Initial atom density to add for nuclides that are zero in initial
|
||||
condition to ensure they exist in the decay chain. Only done for
|
||||
nuclides with reaction rates. Defaults to 1.0e3.
|
||||
output_dir : pathlib.Path
|
||||
Path to output directory to save results.
|
||||
round_number : bool
|
||||
Whether or not to round output to OpenMC to 8 digits.
|
||||
Useful in testing, as OpenMC is incredibly sensitive to exact values.
|
||||
number : openmc.deplete.AtomNumber
|
||||
Total number of atoms in simulation.
|
||||
nuclides_with_data : set of str
|
||||
|
|
@ -125,13 +81,12 @@ class OpenMCOperator(Operator):
|
|||
All burnable material IDs being managed by a single process
|
||||
|
||||
"""
|
||||
def __init__(self, geometry, settings):
|
||||
super().__init__(settings)
|
||||
def __init__(self, geometry, settings, chain_file=None):
|
||||
super().__init__(chain_file)
|
||||
self.round_number = False
|
||||
self.settings = settings
|
||||
self.geometry = geometry
|
||||
|
||||
# Read depletion chain
|
||||
self.chain = Chain.from_xml(settings.chain_file)
|
||||
|
||||
# Clear out OpenMC, create task lists, distribute
|
||||
openmc.reset_auto_ids()
|
||||
self.burnable_mats, volume, nuclides = self._get_burnable_mats()
|
||||
|
|
@ -253,10 +208,9 @@ class OpenMCOperator(Operator):
|
|||
"""
|
||||
self.number = AtomNumber(local_mats, nuclides, volume, len(self.chain))
|
||||
|
||||
if self.settings.dilute_initial != 0.0:
|
||||
if self.dilute_initial != 0.0:
|
||||
for nuc in self._burnable_nucs:
|
||||
self.number.set_atom_density(np.s_[:], nuc,
|
||||
self.settings.dilute_initial)
|
||||
self.number.set_atom_density(np.s_[:], nuc, self.dilute_initial)
|
||||
|
||||
# Now extract the number densities and store
|
||||
for mat in self.geometry.get_all_materials().values():
|
||||
|
|
@ -290,7 +244,7 @@ class OpenMCOperator(Operator):
|
|||
# Create XML files
|
||||
if comm.rank == 0:
|
||||
self.geometry.export_to_xml()
|
||||
self.settings.settings.export_to_xml()
|
||||
self.settings.export_to_xml()
|
||||
self._generate_materials_xml()
|
||||
|
||||
# Initialize OpenMC library
|
||||
|
|
@ -322,7 +276,7 @@ class OpenMCOperator(Operator):
|
|||
|
||||
# If nuclide is zero, do not add to the problem.
|
||||
if val > 0.0:
|
||||
if self.settings.round_number:
|
||||
if self.round_number:
|
||||
val_magnitude = np.floor(np.log10(val))
|
||||
val_scaled = val / 10**val_magnitude
|
||||
val_round = round(val_scaled, 8)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@ class DummyGeometry(Operator):
|
|||
y_2(1.5) ~ 3.1726475740397628
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, settings):
|
||||
super().__init__(settings)
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __call__(self, vec, power, print_out=False):
|
||||
"""Evaluates F(y)
|
||||
|
|
|
|||
|
|
@ -32,13 +32,8 @@ def test_full(run_in_tmpdir):
|
|||
# Load geometry from example
|
||||
geometry, lower_left, upper_right = generate_problem(n_rings, n_wedges)
|
||||
|
||||
# Depletion settings
|
||||
settings = openmc.deplete.OpenMCSettings()
|
||||
settings.chain_file = str(Path(__file__).parents[2] / 'chains' /
|
||||
'chain_simple.xml')
|
||||
settings.round_number = True
|
||||
|
||||
# Add OpenMC-specific settings
|
||||
# OpenMC-specific settings
|
||||
settings = openmc.Settings()
|
||||
settings.particles = 100
|
||||
settings.batches = 100
|
||||
settings.inactive = 40
|
||||
|
|
@ -47,7 +42,10 @@ def test_full(run_in_tmpdir):
|
|||
settings.seed = 1
|
||||
settings.verbosity = 3
|
||||
|
||||
op = openmc.deplete.OpenMCOperator(geometry, settings)
|
||||
# Create operator
|
||||
chain_file = Path(__file__).parents[2] / 'chains' / 'chain_simple.xml'
|
||||
op = openmc.deplete.OpenMCOperator(geometry, settings, chain_file)
|
||||
op.round_number = True
|
||||
|
||||
# Power and timesteps
|
||||
dt1 = 15.*24*60*60 # 15 days
|
||||
|
|
@ -60,7 +58,7 @@ def test_full(run_in_tmpdir):
|
|||
openmc.deplete.integrator.predictor(op, dt, power)
|
||||
|
||||
# Get path to test and reference results
|
||||
path_test = settings.output_dir / 'depletion_results.h5'
|
||||
path_test = op.output_dir / 'depletion_results.h5'
|
||||
path_reference = Path(__file__).with_name('test_reference.h5')
|
||||
|
||||
# If updating results, do so and return
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@ from tests import dummy_geometry
|
|||
def test_cecm(run_in_tmpdir):
|
||||
"""Integral regression test of integrator algorithm using CE/CM."""
|
||||
|
||||
settings = openmc.deplete.Settings()
|
||||
settings.output_dir = "test_integrator_regression"
|
||||
|
||||
op = dummy_geometry.DummyGeometry(settings)
|
||||
op = dummy_geometry.DummyGeometry()
|
||||
op.output_dir = "test_integrator_regression"
|
||||
|
||||
# Perform simulation using the MCNPX/MCNP6 algorithm
|
||||
dt = [0.75, 0.75]
|
||||
|
|
@ -25,7 +23,7 @@ def test_cecm(run_in_tmpdir):
|
|||
openmc.deplete.cecm(op, dt, power, print_out=False)
|
||||
|
||||
# Load the files
|
||||
res = results.read_results(settings.output_dir / "depletion_results.h5")
|
||||
res = results.read_results(op.output_dir / "depletion_results.h5")
|
||||
|
||||
_, y1 = utilities.evaluate_single_nuclide(res, "1", "1")
|
||||
_, y2 = utilities.evaluate_single_nuclide(res, "1", "2")
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@ from tests import dummy_geometry
|
|||
def test_predictor(run_in_tmpdir):
|
||||
"""Integral regression test of integrator algorithm using predictor/corrector"""
|
||||
|
||||
settings = openmc.deplete.Settings()
|
||||
settings.output_dir = "test_integrator_regression"
|
||||
|
||||
op = dummy_geometry.DummyGeometry(settings)
|
||||
op = dummy_geometry.DummyGeometry()
|
||||
op.output_dir = "test_integrator_regression"
|
||||
|
||||
# Perform simulation using the predictor algorithm
|
||||
dt = [0.75, 0.75]
|
||||
|
|
@ -25,7 +23,7 @@ def test_predictor(run_in_tmpdir):
|
|||
openmc.deplete.predictor(op, dt, power, print_out=False)
|
||||
|
||||
# Load the files
|
||||
res = results.read_results(settings.output_dir / "depletion_results.h5")
|
||||
res = results.read_results(op.output_dir / "depletion_results.h5")
|
||||
|
||||
_, y1 = utilities.evaluate_single_nuclide(res, "1", "1")
|
||||
_, y2 = utilities.evaluate_single_nuclide(res, "1", "2")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue