From c29fb407d5794089da62b7bf53049097fc74c725 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 16:20:42 -0500 Subject: [PATCH 01/12] Add global configuration via openmc.config --- openmc/__init__.py | 1 + openmc/config.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 openmc/config.py diff --git a/openmc/__init__.py b/openmc/__init__.py index abcac899f..214695e67 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -32,6 +32,7 @@ from openmc.search import * from openmc.polynomial import * from openmc.tracks import * from . import examples +from .config import * # Import a few names from the model module from openmc.model import rectangular_prism, hexagonal_prism, Model diff --git a/openmc/config.py b/openmc/config.py new file mode 100644 index 000000000..a883c74cc --- /dev/null +++ b/openmc/config.py @@ -0,0 +1,54 @@ +from collections.abc import MutableMapping +import os +from pathlib import Path + +from openmc.data import DataLibrary + + +class _Config(MutableMapping): + def __init__(self, data=()): + self._mapping = {} + self.update(data) + + def __getitem__(self, key): + return self._mapping[key] + + def __delitem__(self, key): + del self._mapping[key] + + def __setitem__(self, key, value): + if key == 'cross_sections': + # Force environment variable to match + self._mapping[key] = Path(value) + os.environ['OPENMC_CROSS_SECTIONS'] = str(value) + elif key == 'chain_file': + self._mapping[key] = Path(value) + else: + raise KeyError(f'Unrecognized config key: {key}') + + def __iter__(self): + return iter(self._mapping) + + def __len__(self): + return len(self._mapping) + + def __repr__(self): + return repr(self._mapping) + + +# Create default configuration +config = _Config() + +# Set cross sections using environment variable +config['cross_sections'] = os.environ.get("OPENMC_CROSS_SECTIONS") + +# Check for depletion chain in cross_sections.xml +# Set depletion chain +chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") +if chain_file is None and config['cross_sections'] is not None: + data = DataLibrary.from_xml(config['cross_sections']) + for lib in reversed(data.libraries): + if lib['type'] == 'depletion_chain': + chain_file = lib['path'] + break +config['chain_file'] = chain_file From a074e0a5cf985ce3a2763133aaa04e73c38d482b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 22:13:54 -0500 Subject: [PATCH 02/12] Use openmc.config['cross_sections'] instead of OPENMC_CROSS_SECTIONS --- openmc/data/library.py | 17 ++++++++------- openmc/deplete/chain.py | 23 ++------------------- openmc/deplete/coupled_operator.py | 15 +++++--------- openmc/deplete/openmc_operator.py | 16 +++++++++++---- openmc/deplete/results.py | 4 ++-- openmc/element.py | 33 +++++++++++++++--------------- openmc/material.py | 10 ++++----- openmc/mgxs_library.py | 2 +- 8 files changed, 51 insertions(+), 69 deletions(-) diff --git a/openmc/data/library.py b/openmc/data/library.py index bf937e57a..ad6c65fb6 100644 --- a/openmc/data/library.py +++ b/openmc/data/library.py @@ -4,6 +4,7 @@ import pathlib import h5py +import openmc from openmc.mixin import EqualityMixin from openmc._xml import clean_indentation, reorder_attributes @@ -124,8 +125,8 @@ class DataLibrary(EqualityMixin): Parameters ---------- path : str, optional - Path to XML file to read. If not provided, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used. + Path to XML file to read. If not provided, + openmc.config['cross_sections'] will be used. Returns ------- @@ -136,15 +137,14 @@ class DataLibrary(EqualityMixin): data = cls() - # If path is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # If path is None, get the cross sections from the global configuration if path is None: - path = os.environ.get('OPENMC_CROSS_SECTIONS') + path = openmc.config.get('cross_sections') - # Check to make sure there was an environmental variable. + # Check to make sure we picked up cross sections if path is None: - raise ValueError("Either path or OPENMC_CROSS_SECTIONS " - "environmental variable must be set") + raise ValueError("Either path or openmc.config['cross_sections'] " + "must be set") tree = ET.parse(path) root = tree.getroot() @@ -162,7 +162,6 @@ class DataLibrary(EqualityMixin): data.libraries.append(library) # get depletion chain data - dep_node = root.find("depletion_chain") if dep_node is not None: filename = os.path.join(directory, dep_node.attrib['path']) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index d63bc6bfb..217c9cac0 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -239,24 +239,6 @@ def replace_missing_fpy(actinide, fpy_data, decay_data): return 'U235' -def _find_chain_file(cross_sections=None): - # First check deprecated OPENMC_DEPLETE_CHAIN environment variable - chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") - if chain_file is not None: - warn("Use of OPENMC_DEPLETE_CHAIN is deprecated in favor of adding " - "depletion_chain to OPENMC_CROSS_SECTIONS", FutureWarning) - return chain_file - - # Check for depletion chain in cross_sections.xml - data = DataLibrary.from_xml(cross_sections) - for lib in reversed(data.libraries): - if lib['type'] == 'depletion_chain': - return lib['path'] - - raise DataError("No depletion chain specified and could not find depletion " - f"chain in {cross_sections}") - - class Chain: """Full representation of a depletion chain. @@ -265,9 +247,8 @@ class Chain: yield sublibrary files. The depletion chain used during a depletion simulation is indicated by either an argument to :class:`openmc.deplete.CoupledOperator` or - :class:`openmc.deplete.IndependentOperator`, or through the - ``depletion_chain`` item in the :envvar:`OPENMC_CROSS_SECTIONS` - environment variable. + :class:`openmc.deplete.IndependentOperator`, or through + openmc.config['chain_file']. Attributes ---------- diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index dd14f282f..4a7c5c56f 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -9,7 +9,6 @@ filesystem. """ import copy -import os from warnings import warn import numpy as np @@ -22,7 +21,6 @@ from openmc.exceptions import DataError import openmc.lib from openmc.mpi import comm from .abc import OperatorResult -from .chain import _find_chain_file from .openmc_operator import OpenMCOperator, _distribute from .results import Results from .helpers import ( @@ -48,11 +46,11 @@ def _find_cross_sections(model): return model.materials.cross_sections # otherwise fallback to environment variable - cross_sections = os.environ.get("OPENMC_CROSS_SECTIONS") + cross_sections = openmc.config.get("cross_sections") if cross_sections is None: raise DataError( "Cross sections were not specified in Model.materials and " - "the OPENMC_CROSS_SECTIONS environment variable is not set." + "openmc.config['cross_sections'] is not set." ) return cross_sections @@ -103,9 +101,8 @@ class CoupledOperator(OpenMCOperator): model : openmc.model.Model OpenMC model object chain_file : str, optional - Path to the depletion chain XML file. Defaults to the file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. + Path to the depletion chain XML file. Defaults to + ``openmc.config['chain_file']``. prev_results : Results, optional Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state @@ -231,10 +228,8 @@ class CoupledOperator(OpenMCOperator): " model with which to generate the transport Operator." raise TypeError(msg) - # Determine cross sections / depletion chain + # Determine cross sections cross_sections = _find_cross_sections(model) - if chain_file is None: - chain_file = _find_chain_file(cross_sections) check_value('fission yield mode', fission_yield_mode, self._fission_helpers.keys()) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index ee569bf71..91dc49b54 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -11,6 +11,7 @@ from collections import OrderedDict import numpy as np import openmc +from openmc.exceptions import DataError from openmc.mpi import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber @@ -57,9 +58,8 @@ class OpenMCOperator(TransportOperator): Path to continuous energy cross section library, or object containing one-group cross-sections. chain_file : str, optional - Path to the depletion chain XML file. Defaults to the file - listed under ``depletion_chain`` in - :envvar:`OPENMC_CROSS_SECTIONS` environment variable. + Path to the depletion chain XML file. Defaults to + openmc.config['chain_file']. prev_results : Results, optional Results from a previous depletion calculation. If this argument is specified, the depletion calculation will start from the latest state @@ -83,7 +83,6 @@ class OpenMCOperator(TransportOperator): if ``reduce_chain`` evaluates to true. The default value of ``None`` implies no limit on the depth. - Attributes ---------- materials : openmc.Materials @@ -133,6 +132,15 @@ class OpenMCOperator(TransportOperator): reduce_chain=False, reduce_chain_level=None): + # If chain file was not specified, try to get it from global config + if chain_file is None: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "No depletion chain specified and could not find depletion " + "chain in openmc.config['chain_file']" + ) + super().__init__(chain_file, fission_q, dilute_initial, prev_results) self.round_number = False self.materials = materials diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 15a65e98a..b2c8e7733 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -392,7 +392,7 @@ class Results(list): as such cannot be used in subsequent transport calculations. If not provided, nuclides from the cross_sections element of materials.xml will be used. If that element is not present, - nuclides from OPENMC_CROSS_SECTIONS will be used. + nuclides from openmc.config['cross_sections'] will be used. Returns ------- @@ -412,7 +412,7 @@ class Results(list): # the new materials XML file. The precedence of nuclides to select # is first ones provided as a kwarg here, then ones specified # in the materials.xml file if provided, then finally from - # the environment variable OPENMC_CROSS_SECTIONS. + # openmc.config['cross_sections']. if nuc_with_data: cv.check_iterable_type('nuclide names', nuc_with_data, str) available_cross_sections = nuc_with_data diff --git a/openmc/element.py b/openmc/element.py index 1473bd63e..49aeaf464 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -1,9 +1,9 @@ from collections import OrderedDict -import os import re from xml.etree import ElementTree as ET import openmc.checkvalue as cv +import openmc from openmc.data import NATURAL_ABUNDANCE, atomic_mass, \ isotopes as natural_isotopes @@ -40,10 +40,10 @@ class Element(str): cross_sections=None): """Expand natural element into its naturally-occurring isotopes. - An optional cross_sections argument or the :envvar:`OPENMC_CROSS_SECTIONS` - environment variable is used to specify a cross_sections.xml file. - If the cross_sections.xml file is found, the element is expanded only - into the isotopes/nuclides present in cross_sections.xml. If no + An optional cross_sections argument or the ``cross_sections`` + configuration value is used to specify a cross_sections.xml file. If the + cross_sections.xml file is found, the element is expanded only into the + isotopes/nuclides present in cross_sections.xml. If no cross_sections.xml file is found, the element is expanded based on its naturally occurring isotopes. @@ -54,12 +54,13 @@ class Element(str): percent_type : {'ao', 'wo'} 'ao' for atom percent and 'wo' for weight percent enrichment : float, optional - Enrichment of an enrichment_target nuclide in percent (ao or wo). - If enrichment_target is not supplied then it is enrichment for U235 - in weight percent. For example, input 4.95 for 4.95 weight percent + Enrichment of an enrichment_target nuclide in percent (ao or wo). If + enrichment_target is not supplied then it is enrichment for U235 in + weight percent. For example, input 4.95 for 4.95 weight percent enriched U. Default is None (natural composition). enrichment_target: str, optional - Single nuclide name to enrich from a natural composition (e.g., 'O16') + Single nuclide name to enrich from a natural composition (e.g., + 'O16') .. versionadded:: 0.12 enrichment_type: {'ao', 'wo'}, optional @@ -82,8 +83,8 @@ class Element(str): ValueError No data is available for any of natural isotopes of the element ValueError - If only some natural isotopes are available in the cross-section data - library and the element is not O, W, or Ta + If only some natural isotopes are available in the cross-section + data library and the element is not O, W, or Ta ValueError If a non-naturally-occurring isotope is requested ValueError @@ -101,8 +102,8 @@ class Element(str): `ORNL/CSD/TM-244 `_ is used to calculate the weight fractions of U234, U235, U236, and U238. Namely, the weight fraction of U234 and U236 are taken to be 0.89% and 0.46%, - respectively, of the U235 weight fraction. The remainder of the - isotopic weight is assigned to U238. + respectively, of the U235 weight fraction. The remainder of the isotopic + weight is assigned to U238. When the `enrichment` argument is specified with `enrichment_target`, a general enrichment procedure is used for elements composed of exactly @@ -125,10 +126,10 @@ class Element(str): # Create dict to store the expanded nuclides and abundances abundances = OrderedDict() - # If cross_sections is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # If cross_sections is None, get the cross sections from the global + # configuration if cross_sections is None: - cross_sections = os.environ.get('OPENMC_CROSS_SECTIONS') + cross_sections = openmc.config.get('cross_sections') # If a cross_sections library is present, check natural nuclides # against the nuclides in the library diff --git a/openmc/material.py b/openmc/material.py index ece70df88..96a660b8b 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1310,9 +1310,8 @@ class Materials(cv.CheckedList): """Collection of Materials used for an OpenMC simulation. This class corresponds directly to the materials.xml input file. It can be - thought of as a normal Python list where each member is a - :class:`Material`. It behaves like a list as the following example - demonstrates: + thought of as a normal Python list where each member is a :class:`Material`. + It behaves like a list as the following example demonstrates: >>> fuel = openmc.Material() >>> clad = openmc.Material() @@ -1330,9 +1329,8 @@ class Materials(cv.CheckedList): ---------- cross_sections : str or path-like Indicates the path to an XML cross section listing file (usually named - cross_sections.xml). If it is not set, the - :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for - continuous-energy calculations and + cross_sections.xml). If it is not set, openmc.config['cross_sections'] + will be used for continuous-energy calculations and :envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group calculations to find the path to the HDF5 cross section file. diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 67ad151cc..8d6e4bec9 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -2546,7 +2546,7 @@ class MGXSLibrary: """ # If filename is None, get the cross sections from the - # OPENMC_CROSS_SECTIONS environment variable + # OPENMC_MG_CROSS_SECTIONS environment variable if filename is None: filename = os.environ.get('OPENMC_MG_CROSS_SECTIONS') From 225e40db0c5da659b2e040fa5fe455e569ee25aa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 31 Aug 2022 22:23:29 -0500 Subject: [PATCH 03/12] Add mg_cross_sections to openmc.config --- openmc/config.py | 11 +++++++++-- openmc/material.py | 9 +++++---- openmc/mgxs_library.py | 13 +++++-------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index a883c74cc..65b7e0863 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -21,6 +21,9 @@ class _Config(MutableMapping): # Force environment variable to match self._mapping[key] = Path(value) os.environ['OPENMC_CROSS_SECTIONS'] = str(value) + elif key == 'mg_cross_sections': + self._mapping[key] = Path(value) + os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': self._mapping[key] = Path(value) else: @@ -40,7 +43,10 @@ class _Config(MutableMapping): config = _Config() # Set cross sections using environment variable -config['cross_sections'] = os.environ.get("OPENMC_CROSS_SECTIONS") +if "OPENMC_CROSS_SECTIONS" in os.environ: + config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] +if "OPENMC_MG_CROSS_SECTIONS" in os.environ: + config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] # Check for depletion chain in cross_sections.xml # Set depletion chain @@ -51,4 +57,5 @@ if chain_file is None and config['cross_sections'] is not None: if lib['type'] == 'depletion_chain': chain_file = lib['path'] break -config['chain_file'] = chain_file +if chain_file is not None: + config['chain_file'] = chain_file diff --git a/openmc/material.py b/openmc/material.py index 96a660b8b..1b2b46a73 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -1329,10 +1329,11 @@ class Materials(cv.CheckedList): ---------- cross_sections : str or path-like Indicates the path to an XML cross section listing file (usually named - cross_sections.xml). If it is not set, openmc.config['cross_sections'] - will be used for continuous-energy calculations and - :envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group - calculations to find the path to the HDF5 cross section file. + cross_sections.xml). If it is not set, the + :envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for + continuous-energy calculations and :envvar:`OPENMC_MG_CROSS_SECTIONS` + will be used for multi-group calculations to find the path to the HDF5 + cross section file. """ diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index 8d6e4bec9..98a99196e 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -1,6 +1,5 @@ import copy from numbers import Real, Integral -import os import h5py import numpy as np @@ -2536,8 +2535,7 @@ class MGXSLibrary: ---------- filename : str, optional Name of HDF5 file containing MGXS data. Default is None. - If not provided, the value of the OPENMC_MG_CROSS_SECTIONS - environmental variable will be used + If not provided, openmc.config['mg_cross_sections'] will be used. Returns ------- @@ -2545,15 +2543,14 @@ class MGXSLibrary: Multi-group cross section data object. """ - # If filename is None, get the cross sections from the - # OPENMC_MG_CROSS_SECTIONS environment variable + # If filename is None, get the cross sections from openmc.config if filename is None: - filename = os.environ.get('OPENMC_MG_CROSS_SECTIONS') + filename = openmc.config.get('mg_cross_sections') # Check to make sure there was an environmental variable. if filename is None: - raise ValueError("Either path or OPENMC_MG_CROSS_SECTIONS " - "environmental variable must be set") + raise ValueError("Either path or openmc.config['mg_cross_sections']" + "must be set") check_type('filename', filename, str) file = h5py.File(filename, 'r') From fb1e92b614adfbafd0567a6bafc3e1adbb4f7990 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 1 Sep 2022 09:37:05 -0500 Subject: [PATCH 04/12] Cleanup config namespace --- openmc/config.py | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index 65b7e0863..23a355467 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -4,6 +4,8 @@ from pathlib import Path from openmc.data import DataLibrary +__all__ = ["config"] + class _Config(MutableMapping): def __init__(self, data=()): @@ -39,23 +41,29 @@ class _Config(MutableMapping): return repr(self._mapping) -# Create default configuration -config = _Config() +def _default_config(): + """Return default configuration""" + config = _Config() -# Set cross sections using environment variable -if "OPENMC_CROSS_SECTIONS" in os.environ: - config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] -if "OPENMC_MG_CROSS_SECTIONS" in os.environ: - config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] + # Set cross sections using environment variable + if "OPENMC_CROSS_SECTIONS" in os.environ: + config['cross_sections'] = os.environ["OPENMC_CROSS_SECTIONS"] + if "OPENMC_MG_CROSS_SECTIONS" in os.environ: + config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] -# Check for depletion chain in cross_sections.xml -# Set depletion chain -chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") -if chain_file is None and config['cross_sections'] is not None: - data = DataLibrary.from_xml(config['cross_sections']) - for lib in reversed(data.libraries): - if lib['type'] == 'depletion_chain': - chain_file = lib['path'] - break -if chain_file is not None: - config['chain_file'] = chain_file + # Check for depletion chain in cross_sections.xml + # Set depletion chain + chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") + if chain_file is None and config['cross_sections'] is not None: + data = DataLibrary.from_xml(config['cross_sections']) + for lib in reversed(data.libraries): + if lib['type'] == 'depletion_chain': + chain_file = lib['path'] + break + if chain_file is not None: + config['chain_file'] = chain_file + + return config + + +config = _default_config() From c5012996df45eb1130ee8e7f03f4e1bede4ec1af Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 6 Sep 2022 16:00:51 -0500 Subject: [PATCH 05/12] Handle missing files in openmc.config --- openmc/config.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/openmc/config.py b/openmc/config.py index 23a355467..08b8c3cb6 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -1,6 +1,7 @@ from collections.abc import MutableMapping import os from pathlib import Path +import warnings from openmc.data import DataLibrary @@ -17,17 +18,21 @@ class _Config(MutableMapping): def __delitem__(self, key): del self._mapping[key] + if key == 'cross_sections': + del os.environ['OPENMC_CROSS_SECTIONS'] + elif key == 'mg_cross_sections': + del os.environ['OPENMC_MG_CROSS_SECTIONS'] def __setitem__(self, key, value): if key == 'cross_sections': # Force environment variable to match - self._mapping[key] = Path(value) + self._set_path(key, value) os.environ['OPENMC_CROSS_SECTIONS'] = str(value) elif key == 'mg_cross_sections': - self._mapping[key] = Path(value) + self._set_path(key, value) os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': - self._mapping[key] = Path(value) + self._set_path(key, value) else: raise KeyError(f'Unrecognized config key: {key}') @@ -40,6 +45,11 @@ class _Config(MutableMapping): def __repr__(self): return repr(self._mapping) + def _set_path(self, key, value): + self._mapping[key] = p = Path(value) + if not p.exists(): + warnings.warn(f"'{value}' does not exist.") + def _default_config(): """Return default configuration""" @@ -51,10 +61,13 @@ def _default_config(): if "OPENMC_MG_CROSS_SECTIONS" in os.environ: config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] - # Check for depletion chain in cross_sections.xml # Set depletion chain chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") - if chain_file is None and config['cross_sections'] is not None: + if (chain_file is None and + config['cross_sections'] is not None and + config['cross_sections'].exists() + ): + # Check for depletion chain in cross_sections.xml data = DataLibrary.from_xml(config['cross_sections']) for lib in reversed(data.libraries): if lib['type'] == 'depletion_chain': From 8f20c20af045267ee6729eeedd0b3c75243472f4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 6 Sep 2022 16:01:46 -0500 Subject: [PATCH 06/12] Move cross_sections.rst to data.rst and rename section header --- docs/source/usersguide/{cross_sections.rst => data.rst} | 8 ++++---- docs/source/usersguide/index.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename docs/source/usersguide/{cross_sections.rst => data.rst} (99%) diff --git a/docs/source/usersguide/cross_sections.rst b/docs/source/usersguide/data.rst similarity index 99% rename from docs/source/usersguide/cross_sections.rst rename to docs/source/usersguide/data.rst index 0cbb581bd..6a135df76 100644 --- a/docs/source/usersguide/cross_sections.rst +++ b/docs/source/usersguide/data.rst @@ -1,8 +1,8 @@ -.. _usersguide_cross_sections: +.. _usersguide_data: -=========================== -Cross Section Configuration -=========================== +================== +Data Configuration +================== In order to run a simulation with OpenMC, you will need cross section data for each nuclide or material in your problem. OpenMC can be run in continuous-energy diff --git a/docs/source/usersguide/index.rst b/docs/source/usersguide/index.rst index fab353c77..511bdc6ce 100644 --- a/docs/source/usersguide/index.rst +++ b/docs/source/usersguide/index.rst @@ -13,7 +13,7 @@ essential aspects of using OpenMC to perform simulations. beginners install - cross_sections + data basics materials geometry From 683910aba4fb0ad106752e0ea94f79522be38b40 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:09:21 -0500 Subject: [PATCH 07/12] Discuss openmc.config in user's guide --- docs/source/usersguide/data.rst | 154 ++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 45 deletions(-) diff --git a/docs/source/usersguide/data.rst b/docs/source/usersguide/data.rst index 6a135df76..fccc93940 100644 --- a/docs/source/usersguide/data.rst +++ b/docs/source/usersguide/data.rst @@ -4,49 +4,93 @@ Data Configuration ================== -In order to run a simulation with OpenMC, you will need cross section data for -each nuclide or material in your problem. OpenMC can be run in continuous-energy -or multi-group mode. +OpenMC relies on a variety of physical data in order to carry out transport +simulations, depletion simulations, and other common tasks. As a user, you are +responsible for specifying one or more of the following: -In continuous-energy mode, OpenMC uses a native `HDF5 -`_ format (see :ref:`io_nuclear_data`) to -store all nuclear data. Pregenerated HDF5 libraries can be found at -https://openmc.org; unless you have specific data needs, it is highly -recommended to use one of the pregenerated libraries. Alternatively, if you have -ACE format data that was produced with NJOY_, such as that distributed with -MCNP_ or Serpent_, it can be converted to the HDF5 format using the :ref:`using -the Python API `. Several sources provide openly available -ACE data including the `ENDF/B`_, JEFF_, and TENDL_ libraries as well as the -`LANL Nuclear Data Team `_. In addition to -tabulated cross sections in the HDF5 files, OpenMC relies on :ref:`windowed -multipole ` data to perform on-the-fly Doppler broadening. +- **Cross sections (XML)** -- A :ref:`cross sections XML ` + file (commonly named ``cross_sections.xml``) contains a listing of other data + files, in particular neutron cross sections, photon cross sections, and + windowed multipole data. Each of those files, in turn, uses a `HDF5 + `_ format (see :ref:`io_nuclear_data`). In + order to run transport simulations with continuous-energy cross sections, you + need to specify this file. -In multi-group mode, OpenMC utilizes an HDF5-based library format which can be -used to describe nuclide- or material-specific quantities. +- **Depletion chain (XML)** -- A :ref:`depletion chain XML ` + file contains decay data, fission product yields, and information on what + neutron reactions can result in transmutation. This file is needed for + depletion/activation calculations as well as some basic functions in the + :mod:`openmc.data` module. + +- **Multigroup cross sections (HDF5)** -- OpenMC can also perform transport + simulations using multigroup data. In this case, multigroup cross sections are + stored in a single :ref:`HDF5 file `. Thus, in order to run a + multigroup transport simulation, this file needs to be specified. + +Each of the above files can specified in several ways. In the Python API, a +:ref:`runtime configuration variable ` +:data:`openmc.config` can be used to specify any of the above. Alternatively, +you can specify these files using a set of :ref:`environment variables +`. + +.. _usersguide_data_runtime: + +--------------------- +Runtime Configuration +--------------------- + +Data sources for OpenMC can be specified at runtime in Python using the +:data:`openmc.config` variable. This variable acts like a dictionary and stores +key-values pairs, where the values are file paths (strings or path-like objects) +and the key can be one of the following: + +``"cross_sections"`` + Indicates the path to the :ref:`cross sections XML ` file + that lists HDF5 format neutron cross sections, photon cross sections, and + windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` + attribute will override this, if specified. + +``"chain_file"`` + Indicates the path to the :ref:`depletion chain XML ` file + that contains decay data, fission product yields, and what neutron reactions + may result in transmutation of a target nuclide. + +``"mg_cross_sections"`` + Indicates the path to an :ref:`HDF5 file ` that contains + multigroup cross sections. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this if + specified. + +At the time the :mod:`openmc` Python module is imported, the +:data:`openmc.config` dictionary will be initialized using a set of +:ref:`environment variable `. + +.. _usersguide_data_envvar: --------------------- Environment Variables --------------------- -When :ref:`scripts_openmc` is run, it will look for several environment -variables that indicate where cross sections can be found. While the location of -cross sections can also be indicated through the -:attr:`openmc.Materials.cross_sections` attribute (or in the :ref:`materials.xml -` file), if you always use the same set of cross section data, it -is often easier to just set an environment variable that will be picked up by -default every time OpenMC is run. The following environment variables are used: +In addition to the :ref:`runtime configuration `, data +sources can be specified using a set of environment variables. The following +environment variables are recognized by OpenMC: :envvar:`OPENMC_CROSS_SECTIONS` - Indicates the path to the :ref:`cross_sections.xml ` - summary file that is used to locate HDF5 format cross section libraries if the - user has not specified :attr:`openmc.Materials.cross_sections` (equivalently, - the :ref:`cross_sections` in :ref:`materials.xml `). + Indicates the path to the :ref:`cross sections XML ` file + that lists HDF5 format neutron cross sections, photon cross sections, and + windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` + attribute will override this if specified. + +:envvar:`OPENMC_CHAIN_FILE` + Indicates the path to the :ref:`depletion chain XML ` file + that contains decay data, fission product yields, and what neutron reactions + may result in transmutation of a target nuclide. :envvar:`OPENMC_MG_CROSS_SECTIONS` Indicates the path to an :ref:`HDF5 file ` that contains - multi-group cross sections if the user has not specified - :attr:`openmc.Materials.cross_sections` (equivalently, the - :ref:`cross_sections` in :ref:`materials.xml `). + multigroup cross sections. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this if + specified. To set these environment variables persistently, export them from your shell profile (``.profile`` or ``.bashrc`` in bash_). @@ -61,12 +105,13 @@ Using Pregenerated Libraries ---------------------------- Various evaluated nuclear data libraries have been processed into the HDF5 -format required by OpenMC and can be found at https://openmc.org. You -can find both libraries generated by the OpenMC development team as well as -libraries based on ACE files distributed elsewhere. To use these libraries, -download the archive file, unpack it, and then set your -:envvar:`OPENMC_CROSS_SECTIONS` environment variable to the absolute path of -the ``cross_sections.xml`` file contained in the unpacked directory. +format required by OpenMC and can be found at https://openmc.org. Unless you +have specific data needs, it is highly recommended to use one of the +pregenerated libraries. You can find both libraries generated by the OpenMC +development team as well as libraries based on ACE files distributed elsewhere. +To use these libraries, download the archive file, unpack it, and then specify +the path of the ``cross_sections.xml`` file contained in the unpacked directory +as described in :ref:`usersguide_data_runtime`. .. _create_xs_library: @@ -75,6 +120,12 @@ Manually Creating a Library from ACE files .. currentmodule:: openmc.data +If you have ACE format data that was produced with NJOY_, such as that +distributed with MCNP_ or Serpent_, it can be converted to the HDF5 format using +the using the Python API. Several sources provide openly available ACE data +including the `ENDF/B`_, JEFF_, and TENDL_ libraries as well as the `LANL +Nuclear Data Team `_. + The :mod:`openmc.data` module in the Python API enables users to directly convert ACE data to OpenMC's HDF5 format and create a corresponding :ref:`cross_sections.xml ` file. For those who prefer to use @@ -224,6 +275,19 @@ relaxation sublibrary files are required: Once the HDF5 files have been generated, a library can be created using the :class:`DataLibrary` class as described in :ref:`create_xs_library`. +----------- +Chain Files +----------- + +Pregenerated depletion chain XML files can be found at https://openmc.org. +Additionally, depletion chains can be generated using the +:class:`openmc.deplete.Chain` class. In particular, the +:meth:`~openmc.deplete.Chain.from_endf` method allows a chain to be generated +starting from a set of ENDF incident neutron, decay, and fission product yield +sublibrary files. Once you've downloaded or generated a depletion chain XML +file, make sure to specify its path as described in +:ref:`usersguide_data_runtime`. + ----------------------- Windowed Multipole Data ----------------------- @@ -241,16 +305,16 @@ The `official ENDF/B-VII.1 HDF5 library multipole library, so if you are using this library, the windowed multipole data will already be available to you. --------------------------- -Multi-Group Cross Sections --------------------------- +------------------------- +Multigroup Cross Sections +------------------------- -Multi-group cross section libraries are generally tailored to the specific +Multigroup cross section libraries are generally tailored to the specific calculation to be performed. Therefore, at this point in time, OpenMC is not -distributed with any pre-existing multi-group cross section libraries. -However, if obtained or generated their own library, the user -should set the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable -to the absolute path of the file library expected to used most frequently. +distributed with any pre-existing multi-group cross section libraries. However, +if obtained or generated their own library, the user should set the +:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable to the absolute path of +the file library expected to used most frequently. For an example of how to create a multi-group library, see the `example notebook <../examples/mg-mode-part-i.ipynb>`__. From ab6f9247cafc4689399f41bd9c07a71289c1b396 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:14:35 -0500 Subject: [PATCH 08/12] Remove specific section on environment variables --- docs/source/usersguide/data.rst | 64 ++++++++++----------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/docs/source/usersguide/data.rst b/docs/source/usersguide/data.rst index fccc93940..48003ecb7 100644 --- a/docs/source/usersguide/data.rst +++ b/docs/source/usersguide/data.rst @@ -29,9 +29,8 @@ responsible for specifying one or more of the following: Each of the above files can specified in several ways. In the Python API, a :ref:`runtime configuration variable ` -:data:`openmc.config` can be used to specify any of the above. Alternatively, -you can specify these files using a set of :ref:`environment variables -`. +:data:`openmc.config` can be used to specify any of the above and is initialized +using a set of environment variables. .. _usersguide_data_runtime: @@ -47,53 +46,28 @@ and the key can be one of the following: ``"cross_sections"`` Indicates the path to the :ref:`cross sections XML ` file that lists HDF5 format neutron cross sections, photon cross sections, and - windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` - attribute will override this, if specified. + windowed multipole data. At startup, this is initialized with the value of the + :envvar:`OPENMC_CROSS_SECTIONS` environment variable. Note that the + :attr:`openmc.Materials.cross_sections` attribute will override this, if + specified. ``"chain_file"`` Indicates the path to the :ref:`depletion chain XML ` file that contains decay data, fission product yields, and what neutron reactions - may result in transmutation of a target nuclide. + may result in transmutation of a target nuclide. At startup, this is + initialized with the value of the :envvar:`OPENMC_CHAIN_FILE` environment + variable. ``"mg_cross_sections"`` Indicates the path to an :ref:`HDF5 file ` that contains - multigroup cross sections. Note that the + multigroup cross sections. At startup, this is initialized with the value of + the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable. Note that the :attr:`openmc.Materials.cross_sections` attribute will override this if specified. -At the time the :mod:`openmc` Python module is imported, the -:data:`openmc.config` dictionary will be initialized using a set of -:ref:`environment variable `. - -.. _usersguide_data_envvar: - ---------------------- -Environment Variables ---------------------- - -In addition to the :ref:`runtime configuration `, data -sources can be specified using a set of environment variables. The following -environment variables are recognized by OpenMC: - -:envvar:`OPENMC_CROSS_SECTIONS` - Indicates the path to the :ref:`cross sections XML ` file - that lists HDF5 format neutron cross sections, photon cross sections, and - windowed multipole data. Note that the :attr:`openmc.Materials.cross_sections` - attribute will override this if specified. - -:envvar:`OPENMC_CHAIN_FILE` - Indicates the path to the :ref:`depletion chain XML ` file - that contains decay data, fission product yields, and what neutron reactions - may result in transmutation of a target nuclide. - -:envvar:`OPENMC_MG_CROSS_SECTIONS` - Indicates the path to an :ref:`HDF5 file ` that contains - multigroup cross sections. Note that the - :attr:`openmc.Materials.cross_sections` attribute will override this if - specified. - -To set these environment variables persistently, export them from your shell -profile (``.profile`` or ``.bashrc`` in bash_). +If you want to persistently set the environment variables used to initialized +the configuration, export them from your shell profile (``.profile`` or +``.bashrc`` in bash_). .. _bash: http://www.linuxfromscratch.org/blfs/view/6.3/postlfs/profile.html @@ -311,12 +285,10 @@ Multigroup Cross Sections Multigroup cross section libraries are generally tailored to the specific calculation to be performed. Therefore, at this point in time, OpenMC is not -distributed with any pre-existing multi-group cross section libraries. However, -if obtained or generated their own library, the user should set the -:envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable to the absolute path of -the file library expected to used most frequently. - -For an example of how to create a multi-group library, see the `example notebook +distributed with any pre-existing multigroup cross section libraries. However, +if a multigroup library file is downloaded or generated, the path to the file +needs to be specified as described in :ref:`usersguide_data_runtime`. For an +example of how to create a multigroup library, see the `example notebook <../examples/mg-mode-part-i.ipynb>`__. .. _NJOY: http://www.njoy21.io/ From 35930e0422426ee972b8ddfc6a9147288afb7d37 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Sep 2022 16:36:33 -0500 Subject: [PATCH 09/12] Add tests for openmc.config --- openmc/config.py | 3 ++- tests/unit_tests/test_config.py | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/test_config.py diff --git a/openmc/config.py b/openmc/config.py index 08b8c3cb6..fe7c5aa06 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -33,6 +33,7 @@ class _Config(MutableMapping): os.environ['OPENMC_MG_CROSS_SECTIONS'] = str(value) elif key == 'chain_file': self._set_path(key, value) + os.environ['OPENMC_CHAIN_FILE'] = str(value) else: raise KeyError(f'Unrecognized config key: {key}') @@ -62,7 +63,7 @@ def _default_config(): config['mg_cross_sections'] = os.environ["OPENMC_MG_CROSS_SECTIONS"] # Set depletion chain - chain_file = os.environ.get("OPENMC_DEPLETE_CHAIN") + chain_file = os.environ.get("OPENMC_CHAIN_FILE") if (chain_file is None and config['cross_sections'] is not None and config['cross_sections'].exists() diff --git a/tests/unit_tests/test_config.py b/tests/unit_tests/test_config.py new file mode 100644 index 000000000..1d3c0f173 --- /dev/null +++ b/tests/unit_tests/test_config.py @@ -0,0 +1,43 @@ +from collections.abc import Mapping +import os + +import openmc +import pytest + + +@pytest.fixture(autouse=True, scope='module') +def reset_config(): + config = dict(openmc.config) + try: + yield + finally: + openmc.config.clear() + openmc.config.update(config) + + +def test_config_basics(): + assert isinstance(openmc.config, Mapping) + for key, value in openmc.config.items(): + assert isinstance(key, str) + assert isinstance(value, os.PathLike) + + # Set and delete + openmc.config['cross_sections'] = '/path/to/cross_sections.xml' + del openmc.config['cross_sections'] + assert 'cross_sections' not in openmc.config + assert 'OPENMC_CROSS_SECTIONS' not in os.environ + + # Can't use any key + with pytest.raises(KeyError): + openmc.config['🐖'] = '/like/to/eat/bacon' + + +def test_config_set_envvar(): + openmc.config['cross_sections'] = '/path/to/cross_sections.xml' + assert os.environ['OPENMC_CROSS_SECTIONS'] == '/path/to/cross_sections.xml' + + openmc.config['mg_cross_sections'] = '/path/to/mg_cross_sections.h5' + assert os.environ['OPENMC_MG_CROSS_SECTIONS'] == '/path/to/mg_cross_sections.h5' + + openmc.config['chain_file'] = '/path/to/chain_file.xml' + assert os.environ['OPENMC_CHAIN_FILE'] == '/path/to/chain_file.xml' From a7abe84b380450bc5e40e9199c026292a5b9de3b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 09:35:03 -0500 Subject: [PATCH 10/12] Fix openmc.config when OPENMC_CROSS_SECTIONS is not set --- openmc/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/config.py b/openmc/config.py index fe7c5aa06..628df7edc 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -65,7 +65,7 @@ def _default_config(): # Set depletion chain chain_file = os.environ.get("OPENMC_CHAIN_FILE") if (chain_file is None and - config['cross_sections'] is not None and + config.get('cross_sections') is not None and config['cross_sections'].exists() ): # Check for depletion chain in cross_sections.xml From a95f4cc0d73bbb4b4c025d92caa66d9e5fddd632 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 8 Sep 2022 10:50:09 -0500 Subject: [PATCH 11/12] Remove use of _find_chain_file in test_deplete_operator.py --- tests/unit_tests/test_deplete_operator.py | 31 +++-------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/tests/unit_tests/test_deplete_operator.py b/tests/unit_tests/test_deplete_operator.py index 5fe8715ac..6ea89fc4a 100644 --- a/tests/unit_tests/test_deplete_operator.py +++ b/tests/unit_tests/test_deplete_operator.py @@ -1,37 +1,15 @@ """Basic unit tests for openmc.deplete.Operator instantiation -Modifies and resets environment variable OPENMC_CROSS_SECTIONS -to a custom file with new depletion_chain node """ from pathlib import Path -import pytest from openmc.deplete.abc import TransportOperator -from openmc.deplete.chain import Chain, _find_chain_file +from openmc.deplete.chain import Chain -BARE_XS_FILE = "bare_cross_sections.xml" CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" -@pytest.fixture() -def bare_xs(run_in_tmpdir): - """Create a very basic cross_sections file, return simple Chain. - - """ - - bare_xs_contents = """ - - - -""".format(CHAIN_PATH) - - with open(BARE_XS_FILE, "w") as out: - out.write(bare_xs_contents) - - yield BARE_XS_FILE - - class BareDepleteOperator(TransportOperator): """Very basic class for testing the initialization.""" @@ -52,10 +30,10 @@ class BareDepleteOperator(TransportOperator): pass -def test_operator_init(bare_xs): +def test_operator_init(): """The test uses a temporary dummy chain. This file will be removed at the end of the test, and only contains a depletion_chain node.""" - bare_op = BareDepleteOperator(_find_chain_file(bare_xs)) + bare_op = BareDepleteOperator(CHAIN_PATH) act_chain = bare_op.chain ref_chain = Chain.from_xml(CHAIN_PATH) assert len(act_chain) == len(ref_chain) @@ -73,8 +51,7 @@ def test_operator_init(bare_xs): def test_operator_fiss_q(): """Make sure fission q values can be set""" new_q = {"U235": 2.0E8, "U238": 2.0E8, "U234": 5.0E7} - chain_file = Path(__file__).parents[1] / "chain_simple.xml" - operator = BareDepleteOperator(chain_file=chain_file, fission_q=new_q) + operator = BareDepleteOperator(chain_file=CHAIN_PATH, fission_q=new_q) mod_chain = operator.chain for name, q in new_q.items(): chain_nuc = mod_chain[name] From 3645a418615c454a4ee5c7c67f8f5f7cc65ac5fc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 21 Sep 2022 07:26:27 -0500 Subject: [PATCH 12/12] Address @shimwell comments on #2211 --- openmc/deplete/coupled_operator.py | 2 +- openmc/deplete/independent_operator.py | 5 +++-- openmc/deplete/microxs.py | 26 ++++++++++++++++---------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/openmc/deplete/coupled_operator.py b/openmc/deplete/coupled_operator.py index 4a7c5c56f..a8c1fa156 100644 --- a/openmc/deplete/coupled_operator.py +++ b/openmc/deplete/coupled_operator.py @@ -101,7 +101,7 @@ class CoupledOperator(OpenMCOperator): model : openmc.model.Model OpenMC model object chain_file : str, optional - Path to the depletion chain XML file. Defaults to + Path to the depletion chain XML file. Defaults to ``openmc.config['chain_file']``. prev_results : Results, optional Results from a previous depletion calculation. If this argument is diff --git a/openmc/deplete/independent_operator.py b/openmc/deplete/independent_operator.py index 200bc195e..2dcdff343 100644 --- a/openmc/deplete/independent_operator.py +++ b/openmc/deplete/independent_operator.py @@ -40,7 +40,8 @@ class IndependentOperator(OpenMCOperator): micro_xs : MicroXS One-group microscopic cross sections in [b] . chain_file : str - Path to the depletion chain XML file. + Path to the depletion chain XML file. Defaults to + ``openmc.config['chain_file']``. keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. @@ -111,7 +112,7 @@ class IndependentOperator(OpenMCOperator): def __init__(self, materials, micro_xs, - chain_file, + chain_file=None, keff=None, normalization_mode='fission-q', fission_q=None, diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 72d87d3b7..7f3a84bf6 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -5,18 +5,16 @@ nuclide names as row indices and reaction names as column indices. """ import tempfile -from pathlib import Path from copy import deepcopy -from pandas import DataFrame, read_csv, concat +from pandas import DataFrame, read_csv import numpy as np from openmc.checkvalue import check_type, check_value, check_iterable_type +from openmc.exceptions import DataError from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS -from openmc.data import DataLibrary -from openmc import Tallies, StatePoint, Materials, Material - - +from openmc import Tallies, StatePoint, Materials +import openmc from .chain import Chain, REACTIONS from .coupled_operator import _find_cross_sections, _get_nuclides_with_data @@ -35,7 +33,7 @@ class MicroXS(DataFrame): def from_model(cls, model, reaction_domain, - chain_file, + chain_file=None, dilute_initial=1.0e3, energy_bounds=(0, 20e6), run_kwargs=None): @@ -48,11 +46,12 @@ class MicroXS(DataFrame): OpenMC model object. Must contain geometry, materials, and settings. reaction_domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh Domain in which to tally reaction rates. - chain_file : str + chain_file : str, optional Path to the depletion chain XML file that will be used in depletion simulation. Used to determine cross sections for materials not - present in the inital composition. - dilute_initial : float + present in the inital composition. Defaults to + ``openmc.config['chain_file']``. + dilute_initial : float, optional Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the cross section data. Only done for nuclides with reaction rates. @@ -144,6 +143,13 @@ class MicroXS(DataFrame): :class:`openmc.Materials` object with nuclides added to burnable materials. """ + if chain_file is None: + chain_file = openmc.config.get('chain_file') + if chain_file is None: + raise DataError( + "No depletion chain specified and could not find depletion " + "chain in openmc.config['chain_file']" + ) chain = Chain.from_xml(chain_file) reactions = chain.reactions cross_sections = _find_cross_sections(model)