Merge pull request #1273 from drewejohnson/feat-op-qvalues

Option to pass fission q values to Chain, Operator, Model
This commit is contained in:
Paul Romano 2019-06-29 06:47:43 -05:00 committed by GitHub
commit 3952f5bba1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 15 deletions

View file

@ -49,6 +49,9 @@ class TransportOperator(metaclass=ABCMeta):
Path to the depletion chain XML file. Defaults to the file
listed under ``depletion_chain`` in
:envvar:`OPENMC_CROSS_SECTIONS` environment variable.
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV]. If not given,
values will be pulled from the ``chain_file``.
Attributes
----------
@ -58,7 +61,7 @@ class TransportOperator(metaclass=ABCMeta):
nuclides with reaction rates. Defaults to 1.0e3.
"""
def __init__(self, chain_file=None):
def __init__(self, chain_file=None, fission_q=None):
self.dilute_initial = 1.0e3
self.output_dir = '.'
@ -81,7 +84,7 @@ class TransportOperator(metaclass=ABCMeta):
warn("Use of OPENMC_DEPLETE_CHAIN is deprecated in favor "
"of adding depletion_chain to OPENMC_CROSS_SECTIONS",
FutureWarning)
self.chain = Chain.from_xml(chain_file)
self.chain = Chain.from_xml(chain_file, fission_q)
@abstractmethod
def __call__(self, vec, print_out=True):

View file

@ -4,16 +4,18 @@ This module contains information about a depletion chain. A depletion chain is
loaded from an .xml file and all the nuclides are linked together.
"""
from collections import OrderedDict, defaultdict
from io import StringIO
from itertools import chain
import math
import re
import os
from collections import OrderedDict, defaultdict
from collections.abc import Mapping
from openmc.checkvalue import check_type
# Try to use lxml if it is available. It preserves the order of attributes and
# provides a pretty-printer by default. If not available, use OpenMC function to
# pretty print.
# provides a pretty-printer by default. If not available,
# use OpenMC function to pretty print.
try:
import lxml.etree as ET
_have_lxml = True
@ -312,22 +314,32 @@ class Chain(object):
return chain
@classmethod
def from_xml(cls, filename):
def from_xml(cls, filename, fission_q=None):
"""Reads a depletion chain XML file.
Parameters
----------
filename : str
The path to the depletion chain XML file.
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV].
If not given, values will be pulled from ``filename``
"""
chain = cls()
if fission_q is not None:
check_type("fission_q", fission_q, Mapping)
else:
fission_q = {}
# Load XML tree
root = ET.parse(str(filename))
for i, nuclide_elem in enumerate(root.findall('nuclide')):
nuc = Nuclide.from_xml(nuclide_elem)
this_q = fission_q.get(nuclide_elem.get("name"))
nuc = Nuclide.from_xml(nuclide_elem, this_q)
chain.nuclide_dict[nuc.name] = i
# Check for reaction paths

View file

@ -112,13 +112,16 @@ class Nuclide(object):
return len(self.reactions)
@classmethod
def from_xml(cls, element):
def from_xml(cls, element, fission_q=None):
"""Read nuclide from an XML element.
Parameters
----------
element : xml.etree.ElementTree.Element
XML element to write nuclide data to
fission_q : None or float
User-supplied fission Q value [eV].
Will be read from the element if not given
Returns
-------
@ -153,6 +156,8 @@ class Nuclide(object):
target = reaction_elem.get('target')
else:
target = None
if fission_q is not None:
Q = fission_q
# Append reaction
nuc.reactions.append(ReactionTuple(

View file

@ -73,6 +73,9 @@ class Operator(TransportOperator):
in the previous results.
diff_burnable_mats : bool, optional
Whether to differentiate burnable materials with multiple instances
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV]. If not given,
values will be pulled from the ``chain_file``.
Attributes
----------
@ -110,14 +113,14 @@ class Operator(TransportOperator):
"""
def __init__(self, geometry, settings, chain_file=None, prev_results=None,
diff_burnable_mats=False):
super().__init__(chain_file)
diff_burnable_mats=False, fission_q=None):
super().__init__(chain_file, fission_q)
self.round_number = False
self.settings = settings
self.geometry = geometry
self.diff_burnable_mats = diff_burnable_mats
if prev_results != None:
if prev_results is not None:
# Reload volumes into geometry
prev_results[-1].transfer_volumes(geometry)
@ -149,7 +152,6 @@ class Operator(TransportOperator):
self.reaction_rates = ReactionRates(
self.local_mats, self._burnable_nucs, self.chain.reactions)
def __call__(self, vec, power, print_out=True):
"""Runs a simulation.

View file

@ -124,7 +124,7 @@ class Model(object):
self._plots.append(plot)
def deplete(self, timesteps, chain_file=None, method='cecm',
**kwargs):
fission_q=None, **kwargs):
"""Deplete model using specified timesteps/power
Parameters
@ -138,6 +138,9 @@ class Model(object):
:envvar:`OPENMC_CROSS_SECTIONS` environment variable if it exists.
method : str
Integration method used for depletion (e.g., 'cecm', 'predictor')
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV].
If not given, values will be pulled from the ``chain_file``.
**kwargs
Keyword arguments passed to integration function (e.g.,
:func:`openmc.deplete.integrator.cecm`)
@ -149,7 +152,10 @@ class Model(object):
import openmc.deplete as dep
# Create OpenMC transport operator
op = dep.Operator(self.geometry, self.settings, chain_file)
op = dep.Operator(
self.geometry, self.settings, chain_file,
fission_q=fission_q,
)
# Perform depletion
check_value('method', method, ('cecm', 'predictor', 'cf4', 'epc_rk4',

View file

@ -231,3 +231,15 @@ def test_getitem():
assert "NucA" == chain["NucA"]
assert "NucB" == chain["NucB"]
assert "NucC" == chain["NucC"]
def test_set_fiss_q():
"""Make sure new fission q values can be set on the chain"""
new_q = {"U235": 2.0E8, "U238": 2.0E8, "U234": 5.0E7}
chain_file = Path(__file__).parents[1] / "chain_simple.xml"
mod_chain = Chain.from_xml(chain_file, new_q)
for name, q in new_q.items():
chain_nuc = mod_chain[name]
for rx in chain_nuc.reactions:
if rx.type == 'fission':
assert rx.Q == q

View file

@ -68,3 +68,16 @@ def test_operator_init(bare_xs):
'decay_modes', 'yield_data', 'yield_energies',
]:
assert getattr(act_nuc, prop) == getattr(ref_nuc, prop), prop
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)
mod_chain = operator.chain
for name, q in new_q.items():
chain_nuc = mod_chain[name]
for rx in chain_nuc.reactions:
if rx.type == 'fission':
assert rx.Q == q