diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 62db6915e4..b171d9356c 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -250,23 +250,44 @@ class ReactionRateHelper(ABC): return results -class FissionEnergyHelper(ABC): - """Abstract class for normalizing fission reactions to a given level +class EnergyHelper(ABC): + """Abstract class for obtaining energy produced + + The ultimate goal of this helper is to provide instances of + :class:`openmc.deplete.Operator` with the total energy produced + in a transport simulation. This information, provided with the + power requested by the user and reaction rates from a + :class:`ReactionRateHelper` will scale reaction rates to the + correct values. Attributes ---------- nuclides : list of str All nuclides with desired reaction rates. Ordered to be consistent with :class:`openmc.deplete.Operator` + energy : float + Total energy [eV/s] produced in a transport simulation. + Updated in the material iteration with :meth:`update`. """ def __init__(self): self._nuclides = None - self._fission_E = None + self._energy = 0.0 + + @property + def energy(self): + return self._energy + + def reset(self): + """Reset energy produced prior to unpacking tallies""" + self._energy = 0.0 @abstractmethod def prepare(self, chain_nucs, rate_index, materials): - """Perform work needed to obtain fission energy per material + """Perform work needed to obtain energy produced + + This method is called prior to the transport simulations + in :meth:`openmc.deplete.Operator.initial_condition`. Parameters ---------- @@ -274,15 +295,15 @@ class FissionEnergyHelper(ABC): All nuclides to be tracked in this problem rate_index : dict of str to int Mapping from nuclide name to index in the - reaction rate vector used in :meth:`get_energy`. + `fission_rates` for :meth:`update`. materials : list of str All materials tracked on the operator helped by this - object + object. Should correspond to + :attr:`openmc.deplete.Operator.burnable_materials` """ - @abstractmethod - def get_fission_energy(self, fission_rates, mat_index): - """Return fission energy in this material given fission rates + def update(self, fission_rates, mat_index): + """Update the energy produced Parameters ---------- @@ -291,10 +312,10 @@ class FissionEnergyHelper(ABC): material. Should be ordered corresponding to initial ``rate_index`` used in :meth:`prepare` mat_index : int - Index for the material requested. + Index for the specific material in the list of all burnable + materials. """ - @property def nuclides(self): """List of nuclides with requested reaction rates""" diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 5e8b4146e8..da85312a84 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -6,7 +6,7 @@ from itertools import product from numpy import dot, zeros from openmc.capi import Tally, MaterialFilter -from .abc import ReactionRateHelper, FissionEnergyHelper +from .abc import ReactionRateHelper, EnergyHelper # ------------------------------------- # Helpers for generating reaction rates @@ -68,9 +68,13 @@ class DirectReactionRateHelper(ReactionRateHelper): # ------------------------------------ -class ChainFissHelper(FissionEnergyHelper): +class ChainFissionHelper(EnergyHelper): """Fission Q-values are pulled from chain""" + def __init__(self): + super().__init__() + self._fission_q_vector = None + def prepare(self, chain_nucs, rate_index, _materials): """Populate the fission Q value vector from a chain. @@ -86,23 +90,23 @@ class ChainFissHelper(FissionEnergyHelper): _materials : list of str Unused. Materials to be tracked for this helper. """ - if (self._fission_E is not None - and self._fission_E.shape == (len(rate_index),)): + if (self._fission_q_vector is not None + and self._fission_q_vector.shape == (len(rate_index),)): return - fiss_E = zeros(len(rate_index)) + fission_qs = zeros(len(rate_index)) for nuclide in chain_nucs: if nuclide.name in rate_index: for rx in nuclide.reactions: if rx.type == "fission": - fiss_E[rate_index[nuclide.name]] = rx.Q + fission_qs[rate_index[nuclide.name]] = rx.Q break - self._fission_E = fiss_E + self._fission_q_vector = fission_qs - def get_fission_energy(self, fiss_rates, _mat_index): - """Return fission energy for this material + def update(self, fission_rates, _mat_index): + """Update energy produced with fission rates in a material Parameters ---------- @@ -114,4 +118,4 @@ class ChainFissHelper(FissionEnergyHelper): index for the material requested. Unused, as identical isotopes in all materials have the same Q value. """ - return dot(fiss_rates, self._fission_E) + self._energy += dot(fission_rates, self._fission_q_vector) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 03c9813f52..815602247c 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -24,7 +24,7 @@ from . import comm from .abc import TransportOperator, OperatorResult from .atom_number import AtomNumber from .reaction_rates import ReactionRates -from .helpers import DirectReactionRateHelper, ChainFissHelper +from .helpers import DirectReactionRateHelper, ChainFissionHelper def _distribute(items): @@ -154,9 +154,9 @@ class Operator(TransportOperator): self.reaction_rates = ReactionRates( self.local_mats, self._burnable_nucs, self.chain.reactions) - # Get class to assist working with tallies + # Get classes to assist working with tallies self._rate_helper = DirectReactionRateHelper() - self._energy_helper = ChainFissHelper() + self._energy_helper = ChainFissionHelper() def __call__(self, vec, power, print_out=True): @@ -534,7 +534,7 @@ class Operator(TransportOperator): # Keep track of energy produced from all reactions in eV per source # particle - energy = 0.0 + self._energy_helper.reset() # Create arrays to store fission Q values, reaction rates, and nuclide # numbers, zeroed out in material iteration @@ -558,17 +558,13 @@ class Operator(TransportOperator): mat_index, nuc_ind, react_ind) # Accumulate energy from fission - energy += self._energy_helper.get_fission_energy( - tally_rates[:, fission_ind], i) + self._energy_helper.update(tally_rates[:, fission_ind], mat_index) # Divide by total number and store rates[i] = self._rate_helper.divide_by_adens(number) # Reduce energy produced from all processes - print("Energy - {}: {:9.7e}".format(comm.rank, energy)) - energy = comm.allreduce(energy) - if comm.rank == 0: - print("Energy: {:9.7e}".format(energy)) + energy = comm.allreduce(self._energy_helper.energy) # Determine power in eV/s power /= JOULE_PER_EV