diff --git a/docs/source/usersguide/depletion.rst b/docs/source/usersguide/depletion.rst index e95e098c4..cfb373e13 100644 --- a/docs/source/usersguide/depletion.rst +++ b/docs/source/usersguide/depletion.rst @@ -19,10 +19,10 @@ transmutation equations and the method used for advancing time. At present, the :class:`openmc.deplete.Operator` (which uses the OpenMC transport solver), but in principle additional operator classes based on other transport codes could be implemented and no changes to the depletion solver itself would be needed. The -operator class requires a :class:`openmc.model.Model` instance containing +operator class requires a :class:`~openmc.Model` instance containing material, geometry, and settings information:: - model = openmc.model.Model() + model = openmc.Model() ... op = openmc.deplete.Operator(model) @@ -189,17 +189,18 @@ Transport-independent depletion OpenMC supports running depletion calculations independent of the OpenMC transport solver using the :class:`~openmc.deplete.FluxDepletionOperator` class. -This class supports both constant-flux and constant-power depletion. +This class supports both constant-flux (``source-rate`` normalization) and +constant-power depletion (``fission-q`` normalization). .. important:: - Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``flux`` parameter when ``normalization_mode == constant-flux``, and use ``power`` or ``power_density`` when ``normalization_mode == constant-power``. + Make sure you set the correct parameter in the :class:`openmc.abc.Integrator` class. Use the ``source_rates`` parameter when ``normalization_mode == source-rate``, and use ``power`` or ``power_density`` when ``normalization_mode == fission-q``. .. warning:: - The accuracy of results when using ``constant-power`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. + The accuracy of results when using ``fission-q`` is entirely dependent on your depletion chain. Make sure it has sufficient data to resolve the dynamics of your particular scenario. -This class has two ways to initalize it: the default constructor accepts an +This class has two ways to initialize it: the default constructor accepts an :class:`openmc.Materials` object and one-group microscopic cross sections as a :class:`pandas.DataFrame`, while the ``from_nuclides`` method accepts a volume and dictionary of nuclide concentrations in place of @@ -221,7 +222,8 @@ or from data arrays:: 'O16': 4.64e22, 'O17': 1.76e19} volume = 0.5 - op = FluxDepletionOperator.from_nuclides(volume, nuclides, micro_xs, flux, chain_file) + op = FluxDepletionOperator.from_nuclides(volume, nuclides, 'atom/cm3', + micro_xs, flux, chain_file) A user can then define an integrator class as they would for a coupled transport-depletion calculation and follow the same steps from there. diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index 24859151f..90a353d93 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -524,11 +524,10 @@ class Integrator(ABC): power_density : float or iterable of float, optional Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` - is not speficied. - flux : float or iterable of float, optional - neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` + is not specified. source_rates : float or iterable of float, optional - source rate in [neutron/sec] for each interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} @@ -579,7 +578,7 @@ class Integrator(ABC): """ def __init__(self, operator, timesteps, power=None, power_density=None, - flux=None, source_rates=None, timestep_units='s', solver="cram48"): + source_rates=None, timestep_units='s', solver="cram48"): # Check number of stages previously used if operator.prev_res is not None: res = operator.prev_res[-1] @@ -601,10 +600,8 @@ class Integrator(ABC): source_rates = power_density * operator.heavy_metal else: source_rates = [p*operator.heavy_metal for p in power_density] - elif flux is not None: - source_rates = flux elif source_rates is None: - raise ValueError("Either power, power_density, flux, or source_rates must be set") + raise ValueError("Either power, power_density, source_rates must be set") if not isinstance(source_rates, Iterable): # Ensure that rate is single value if that is the case @@ -865,11 +862,10 @@ class SIIntegrator(Integrator): power_density : float or iterable of float, optional Power density of the reactor in [W/gHM]. It is multiplied by initial heavy metal inventory to get total power if ``power`` - is not speficied. - flux : float or iterable of float, optional - neutron flux in [neut/s-cm^2] for each interval in :attr:`timesteps` + is not specified. source_rates : float or iterable of float, optional - Source rate in [neutron/sec] for each interval in :attr:`timesteps` + Source rate in [neutron/sec] or neutron flux in [neut/s-cm^2] for each + interval in :attr:`timesteps` .. versionadded:: 0.12.1 timestep_units : {'s', 'min', 'h', 'd', 'MWd/kg'} @@ -924,12 +920,12 @@ class SIIntegrator(Integrator): """ def __init__(self, operator, timesteps, power=None, power_density=None, - flux=None, source_rates=None, timestep_units='s', n_steps=10, + source_rates=None, timestep_units='s', n_steps=10, solver="cram48"): check_type("n_steps", n_steps, Integral) check_greater_than("n_steps", n_steps, 0) super().__init__( - operator, timesteps, power, power_density, flux, source_rates, + operator, timesteps, power, power_density, source_rates, timestep_units=timestep_units, solver=solver) self.n_steps = n_steps @@ -1014,7 +1010,7 @@ class DepSystemSolver(ABC): Parameters ---------- A : scipy.sparse.csr_matrix - Sparse transmutation matrix ``A[j, i]`` desribing rates at + Sparse transmutation matrix ``A[j, i]`` describing rates at which isotope ``i`` transmutes to isotope ``j`` n0 : numpy.ndarray Initial compositions, typically given in number of atoms in some diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 974255753..410552671 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -1,7 +1,7 @@ """Pure depletion operator -This module implements a pure depletion operator that uses user- provided fluxes -and one-group cross sections. +This module implements a pure depletion operator that user-provided one-group +cross sections. """ @@ -20,12 +20,84 @@ from openmc.mpi import comm from openmc.mgxs import EnergyGroups, ArbitraryXS, FissionXS from .abc import ReactionRateHelper, OperatorResult from .chain import REACTIONS -from .openmc_operator import OpenMCOperator +from .openmc_operator import OpenMCOperator, _distribute +from .results import Results from .helpers import ChainFissionHelper, ConstantFissionYieldHelper, SourceRateHelper _valid_rxns = list(REACTIONS) _valid_rxns.append('fission') +def generate_1g_cross_sections(model, + reaction_domain, + reactions=['(n,gamma)', + '(n,2n)', + '(n,p)', + '(n,a)', + '(n,3n)', + '(n,4n)', + 'fission'], + energy_bounds=(0, 20e6), + write_to_csv=False, + filename='micro_xs.csv'): + """Helper function to generate a one-group cross-section dataframe using + OpenMC. Note that the ``openmc`` executable must be compiled. + + Parameters + ---------- + model : openmc.model.Model + 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. + reactions : list of str, optional + Reaction names to tally + energy_bound : 2-tuple of float, optional + Bounds for the energy group. + write_to_csv : bool, optional + Option to write the DataFrame to a `.csv` file. + filename : str + Name for csv file. Only applicable if ``write_to_csv == True`` + + Returns + ------- + None or pandas.DataFrame + + """ + groups = EnergyGroups(energy_bounds) + + # Set up the reaction tallies + original_tallies = model.tallies + tallies = openmc.Tallies() + xs = {} + for rxn in reactions: + if rxn == 'fission': + xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) + else: + xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) + tallies += xs[rxn].tallies.values() + + model.tallies = tallies + statepoint_path = model.run() + + # Revert to the original tallies + model.tallies = old_tallies + + with openmc.StatePoint(statepoint_path) as sp: + for rxn in xs: + xs[rxn].load_from_statepoint(sp) + + # Build the DataFrame + micro_xs = pd.DataFrame() + for rxn in xs: + df = xs[rxn].get_pandas_dataframe(xs_type='micro') + df.index = df['nuclide'] + df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) + df.rename({'mean':rxn}, axis=1, inplace=True) + micro_xs = pd.concat([micro_xs, df], axis=1) + + if write_to_csv: + micro_xs.to_csv(filename) + + return micro_xs class FluxDepletionOperator(OpenMCOperator): """Depletion operator that uses one-group @@ -50,14 +122,16 @@ class FluxDepletionOperator(OpenMCOperator): Default is None. prev_results : Results, optional Results from a previous depletion calculation. - normalization_mode : {"constant-power", "constant-flux"} + normalization_mode : {"fission-q", "source-rate"} Indicate how reaction rates should be calculated. - ``"constant-power"`` uses the fission Q values from the depletion chain to - compute the flux based on the power. ``"constant-flux"`` uses the value stored in `_normalization_helper` as the flux. + ``"fission-q"`` uses the fission Q values from the depletion chain to + compute the flux based on the power. ``"source-rate"`` uses a the + source rate (assumed to be neutron flux) to calculate the + reaction rates. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only applicable - if ``"normalization_mode" == "constant-power"``. + if ``"normalization_mode" == "fission-q"``. reduce_chain : bool, optional If True, use :meth:`openmc.deplete.Chain.reduce` to reduce the depletion chain up to ``reduce_chain_level``. Default is False. @@ -104,14 +178,14 @@ class FluxDepletionOperator(OpenMCOperator): Results from a previous depletion calculation. ``None`` if no results are to be used. - """ + """ def __init__(self, materials, micro_xs, chain_file, keff=None, - normalization_mode = 'constant-flux', + normalization_mode='source-rate', fission_q=None, prev_results=None, reduce_chain=False, @@ -126,7 +200,8 @@ class FluxDepletionOperator(OpenMCOperator): self._keff = keff - helper_kwargs = dict() + if fission_yield_opts is None: + fission_yield_opts = {} helper_kwargs = {'normalization_mode': normalization_mode, 'fission_yield_opts': fission_yield_opts} @@ -141,10 +216,11 @@ class FluxDepletionOperator(OpenMCOperator): reduce_chain_level=reduce_chain_level) @classmethod - def from_nuclides(cls, volume, nuclides, micro_xs, + def from_nuclides(cls, volume, nuclides, nuc_units, + micro_xs, chain_file, keff=None, - normalization_mode='constant-flux', + normalization_mode='source-rate', fission_q=None, prev_results=None, reduce_chain=False, @@ -156,8 +232,10 @@ class FluxDepletionOperator(OpenMCOperator): volume : float Volume of the material being depleted in [cm^3] nuclides : dict of str to float - ,Dictionary with nuclide names as keys and nuclide concentrations as - values. Nuclide concentration units are [atom/cm^3]. + Dictionary with nuclide names as keys and nuclide concentrations as + values. + nuc_units : {'atom/cm3', 'atom/b-cm'} + Units for nuclide concentration. micro_xs : pandas.DataFrame DataFrame with nuclides names as index and microscopic cross section data in the columns. Cross section units are [cm^-2]. @@ -166,15 +244,16 @@ class FluxDepletionOperator(OpenMCOperator): keff : 2-tuple of float, optional keff eigenvalue and uncertainty from transport calculation. Default is None. - normalization_mode : {"constant-power", "constant-flux"} + normalization_mode : {"fission-q", "source-rate"} Indicate how reaction rates should be calculated. - ``"constant-power"`` uses the fission Q values from the depletion - chain to compute the flux based on the power. ``"constant-flux"`` - uses the value stored in `_normalization_helper` as the flux. + ``"fission-q"`` uses the fission Q values from the depletion + chain to compute the flux based on the power. ``"source-rate"`` uses + the source rate (assumed to be neutron flux) to calculate the + reaction rates. fission_q : dict, optional Dictionary of nuclides and their fission Q values [eV]. If not given, values will be pulled from the ``chain_file``. Only - applicable if ``"normalization_mode" == "constant-power"``. + applicable if ``"normalization_mode" == "fission-q"``. prev_results : Results, optional Results from a previous depletion calculation. reduce_chain : bool, optional @@ -191,7 +270,7 @@ class FluxDepletionOperator(OpenMCOperator): """ check_type('nuclides', nuclides, dict, str) - materials = cls._consolidate_nuclides_to_material(nuclides, volume) + materials = cls._consolidate_nuclides_to_material(nuclides, nuc_units, volume) return cls(materials, micro_xs, chain_file, @@ -205,14 +284,20 @@ class FluxDepletionOperator(OpenMCOperator): @staticmethod - def _consolidate_nuclides_to_material(nuclides, volume): + def _consolidate_nuclides_to_material(nuclides, nuc_units, volume): """Puts nuclide list into an openmc.Materials object. """ openmc.reset_auto_ids() mat = openmc.Material() - for nuc, conc in nuclides.items(): - mat.add_nuclide(nuc, conc * 1e-24) # convert to at/b-cm + if nuc_units == 'atom/b-cm': + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc) + elif nuc_units == 'atom/cm3': + for nuc, conc in nuclides.items(): + mat.add_nuclide(nuc, conc * 1e-24) # convert to at/b-cm + else: + raise ValueError(f"Unit '{nuc_units}' is invalid.") mat.volume = volume mat.depletable = True @@ -273,13 +358,12 @@ class FluxDepletionOperator(OpenMCOperator): mat_index : int Material index - """ + """ volume = self._op.number.get_mat_volume(mat_index) - densities = np.empty(np.shape(fission_rates)) - for i_nuc in self.nuc_ind_map: - nuc = self.nuc_ind_map[i_nuc] + densities = np.empty_like(fission_rates) + for i_nuc, nuc in self.nuc_ind_map.items(): densities[i_nuc] = self._op.number.get_atom_density(mat_index, nuc) - fission_rates = fission_rates * volume * densities + fission_rates *= volume * densities super().update(fission_rates) @@ -294,10 +378,6 @@ class FluxDepletionOperator(OpenMCOperator): Parameters ---------- - n_nucs : int - Number of burnable nuclides tracked by :class:`openmc.deplete.Operator` - n_react : int - Number of reactions tracked by :class:`openmc.deplete.Operator` op : openmc.deplete.FluxDepletionOperator Reference to the object encapsulate _FluxDepletionRateHelper. We pass this so we don't have to duplicate the ``number`` object. @@ -312,9 +392,9 @@ class FluxDepletionOperator(OpenMCOperator): """ - def __init__(self, n_nuc, n_react, op): - super().__init__(n_nuc, n_react) + def __init__(self, op): rates = op.reaction_rates + super().__init__(rates.n_nuc, rates.n_react) self.nuc_ind_map = {ind: nuc for nuc, ind in rates.index_nuc.items()} self.rxn_ind_map = {ind: rxn for rxn, ind in rates.index_rx.items()} @@ -349,7 +429,7 @@ class FluxDepletionOperator(OpenMCOperator): return self._results_cache def _get_helper_classes(self, helper_kwargs): - """Get helper classes for calculating reation rates and fission yields + """Get helper classes for calculating reaction rates and fission yields Parameters ---------- @@ -359,19 +439,16 @@ class FluxDepletionOperator(OpenMCOperator): """ normalization_mode = helper_kwargs['normalization_mode'] - fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) + fission_yield_opts = helper_kwargs['fission_yield_opts'] - self._rate_helper = self._FluxDepletionRateHelper( - self.reaction_rates.n_nuc, self.reaction_rates.n_react, self) - if normalization_mode == "constant-power": + self._rate_helper = self._FluxDepletionRateHelper(self) + if normalization_mode == "fission-q": self._normalization_helper = self._FluxDepletionNormalizationHelper(self) else: self._normalization_helper = SourceRateHelper() # Select and create fission yield helper fission_helper = ConstantFissionYieldHelper - if fission_yield_opts is None: - fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -395,7 +472,7 @@ class FluxDepletionOperator(OpenMCOperator): vec : list of numpy.ndarray Total atoms to be used in function. source_rate : float - Power in [W] or source rate in [neutron/sec] + Power in [W] or flux in [neut/s-cm^2] Returns ------- @@ -444,11 +521,11 @@ class FluxDepletionOperator(OpenMCOperator): print(f'WARNING: nuclide {nuc} in material' f'{mat} is negative (density = {val}' - ' at/barn-cm)') + ' atom/b-cm)') number_i[mat, nuc] = 0.0 @staticmethod - def create_micro_xs_from_data_array(nuclides, reactions, data, units='barn'): + def create_micro_xs_from_data_array(nuclides, reactions, data): """ Creates a ``micro_xs`` parameter from a dictionary. @@ -458,12 +535,10 @@ class FluxDepletionOperator(OpenMCOperator): List of nuclide symbols for that have data for at least one reaction. reactions : list of str - List of reactions. All reactions must match those in ``chain.REACTONS`` + List of reactions. All reactions must match those in ``chain.REACTIONS`` data : ndarray of floats - Array containing one-group microscopic cross section information for each - nuclide and reaction. - units : {'barn', 'cm^2'}, optional - Units of cross section values in ``data`` array. Defaults to ``barn``. + Array containing one-group microscopic cross section values, in + [barn], for each nuclide and reaction. Returns ------- @@ -483,8 +558,7 @@ class FluxDepletionOperator(OpenMCOperator): nuclides, reactions, data) # Convert to cm^2 - if units == 'barn': - data *= 1e-24 + data *= 1e-24 return pd.DataFrame(index=nuclides, columns=reactions, data=data) @@ -497,9 +571,7 @@ class FluxDepletionOperator(OpenMCOperator): ---------- csv_file : str Relative path to csv-file containing microscopic cross section - data. - units : {'barn', 'cm^2'}, optional - Units of cross section values in the ``.csv`` file array. Defaults to ``barn``. + data. Cross section values should be in [barn]. Returns ------- @@ -514,8 +586,7 @@ class FluxDepletionOperator(OpenMCOperator): list(micro_xs.columns), micro_xs.to_numpy()) - if units == 'barn': - micro_xs *= 1e-24 + micro_xs *= 1e-24 return micro_xs @@ -528,67 +599,3 @@ class FluxDepletionOperator(OpenMCOperator): for reaction in reactions: check_value('reactions', reaction, _valid_rxns) - - @staticmethod - def generate_1g_cross_sections(model, reaction_domain, reactions=['(n,gamma)', '(n,2n)', '(n,p)', '(n,a)', '(n,3n)', '(n,4n)', 'fission'], energy_bounds=(0, 20e6), write_to_csv=True, filename='micro_xs.csv'): - """Helper function to generate a one-group cross-section dataframe - using OpenMC. Note that the ``openmc`` C executable must be compiled. - - Parameters - ---------- - model : openmc.model.Model - 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. - reactions : list of str, optional - Reaction names to tally - energy_bound : 2-tuple of float, optional - Bounds for the energy group. - write_to_csv : bool, optional - Option to write the DataFrame to a `.csv` file. If `False`, - returns the dataframe object. - filename : str - Name for csv file. Only applicable if ``write_to_csv == True`` - - Returns - ------- - None or pandas.DataFrame - - """ - groups = EnergyGroups() - groups.group_edges = np.array(list(energy_bounds)) - - # Set up the reaction tallies - tallies = openmc.Tallies() - xs = dict() - for rxn in reactions: - if rxn == 'fission': - xs[rxn] = FissionXS(domain=reaction_domain, groups=groups, by_nuclide=True) - else: - xs[rxn] = ArbitraryXS(rxn, domain=reaction_domain, groups=groups, by_nuclide=True) - tallies += xs[rxn].tallies.values() - - model.tallies = tallies - statepoint_path = model.run() - - sp = openmc.StatePoint(statepoint_path) - - for rxn in xs: - xs[rxn].load_from_statepoint(sp) - - sp.close() - - # Build the DataFrame - micro_xs = pd.DataFrame() - for rxn in xs: - df = xs[rxn].get_pandas_dataframe(xs_type='micro') - df.index = df['nuclide'] - df.drop(['nuclide', xs[rxn].domain_type, 'group in', 'std. dev.'], axis=1, inplace=True) - df.rename({'mean':rxn}, axis=1, inplace=True) - micro_xs = pd.concat([micro_xs, df], axis=1) - - if write_to_csv: - micro_xs.to_csv(filename) - return None - else: - return micro_xs diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index 0aaa3b08a..7b863b69a 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -612,7 +612,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Default: 0.0253 [eV] fast_energy : float, optional Energy of yield data corresponding to fast yields. - Default: 500 [kev] + Default: 500 [KeV] Attributes ---------- @@ -634,7 +634,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): Array of fission rate fractions with shape ``(n_mats, 2, n_nucs)``. ``results[:, 0]`` corresponds to the fraction of all fissions - that occured below ``cutoff``. The number + that occurred below ``cutoff``. The number of materials in the first axis corresponds to the number of materials burned by the :class:`openmc.deplete.Operator` @@ -790,7 +790,7 @@ class FissionYieldCutoffHelper(TalliedFissionYieldHelper): class AveragedFissionYieldHelper(TalliedFissionYieldHelper): r"""Class that computes fission yields based on average fission energy - Computes average energy at which fission events occured with + Computes average energy at which fission events occurred with .. math:: @@ -908,7 +908,7 @@ class AveragedFissionYieldHelper(TalliedFissionYieldHelper): Use the computed average energy of fission events to determine fission yields. If average energy is between two sets of yields, linearly - interpolate bewteen the two. + interpolate between the two. Otherwise take the closet set of yields. Parameters diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py index c19ef076a..74a3cebdb 100644 --- a/openmc/deplete/integrators.py +++ b/openmc/deplete/integrators.py @@ -103,7 +103,7 @@ class CECMIntegrator(Integrator): op_results : list of openmc.deplete.OperatorResult Eigenvalue and reaction rates from transport simulations """ - # deplete across first half of inteval + # deplete across first half of interval time0, x_middle = self._timed_deplete(conc, rates, dt / 2) res_middle = self.operator(x_middle, source_rate) diff --git a/openmc/deplete/openmc_operator.py b/openmc/deplete/openmc_operator.py index aafa1adf9..7c0bb6678 100644 --- a/openmc/deplete/openmc_operator.py +++ b/openmc/deplete/openmc_operator.py @@ -90,7 +90,6 @@ class OpenMCOperator(TransportOperator): cross_sections : str or pandas.DataFrame Path to continuous energy cross section library, or object containing one-group cross-sections. - dilute_initial : float Initial atom density [atoms/cm^3] to add for nuclides that are zero in initial condition to ensure they exist in the decay @@ -527,7 +526,9 @@ class OpenMCOperator(TransportOperator): # Accumulate energy from fission if fission_ind is not None: - self._normalization_helper.update(tally_rates[:, fission_ind], mat_index=mat_index) + self._normalization_helper.update( + tally_rates[:, fission_ind], + mat_index=mat_index) # Divide by total number and store rates[i] = self._rate_helper.divide_by_adens(number) diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 61573832c..db4e80b19 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -225,7 +225,10 @@ class Operator(OpenMCOperator): self.cleanup_when_done = True - helper_kwargs = dict() + if reaction_rate_opts is None: + reaction_rate_opts = {} + if fission_yield_opts is None: + fission_yield_opts = {} helper_kwargs = { 'reaction_rate_mode': reaction_rate_mode, 'normalization_mode': normalization_mode, @@ -329,17 +332,14 @@ class Operator(OpenMCOperator): reaction_rate_mode = helper_kwargs['reaction_rate_mode'] normalization_mode = helper_kwargs['normalization_mode'] fission_yield_mode = helper_kwargs['fission_yield_mode'] - reaction_rate_opts = helper_kwargs.get('reaction_rate_opts', {}) - fission_yield_opts = helper_kwargs.get('fission_yield_opts', {}) + reaction_rate_opts = helper_kwargs['reaction_rate_opts'] + fission_yield_opts = helper_kwargs['fission_yield_opts'] # Get classes to assist working with tallies if reaction_rate_mode == "direct": self._rate_helper = DirectReactionRateHelper( self.reaction_rates.n_nuc, self.reaction_rates.n_react) elif reaction_rate_mode == "flux": - if reaction_rate_opts is None: - reaction_rate_opts = {} - # Ensure energy group boundaries were specified if 'energies' not in reaction_rate_opts: raise ValueError( @@ -365,8 +365,6 @@ class Operator(OpenMCOperator): # Select and create fission yield helper fission_helper = self._fission_helpers[fission_yield_mode] - if fission_yield_opts is None: - fission_yield_opts = {} self._yield_helper = fission_helper.from_operator( self, **fission_yield_opts) @@ -489,7 +487,7 @@ class Operator(OpenMCOperator): print(f'WARNING: nuclide {nuc} in material' f'{mat} is negative (density = {val}' - ' at/barn-cm)') + ' atom/b-cm)') number_i[mat, nuc] = 0.0 diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 9ae0f84f4..38d4aaf2e 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -3,8 +3,8 @@ from math import floor import shutil from pathlib import Path - from difflib import unified_diff + import numpy as np import pytest import openmc @@ -12,7 +12,6 @@ from openmc.data import JOULE_PER_EV import openmc.deplete from openmc.deplete import FluxDepletionOperator - from tests.regression_tests import config @@ -22,7 +21,7 @@ def fuel(): fuel.add_element("U", 1, percent_type="ao", enrichment=4.25) fuel.add_element("O", 2) fuel.set_density("g/cc", 10.4) - fuel.depletable=True + fuel.depletable = True fuel.volume = np.pi * 0.42 ** 2 @@ -30,14 +29,14 @@ def fuel(): @pytest.mark.parametrize("multiproc, from_nuclides, normalization_mode, power, flux", [ - (True, True,'constant-flux', None, 1164719970082145.0), - (False, True, 'constant-flux', None, 1164719970082145.0), - (True, True, 'constant-power', 174, None), - (False, True, 'constant-power', 174, None), - (True, False,'constant-flux', None, 1164719970082145.0), - (False, False, 'constant-flux', None, 1164719970082145.0), - (True, False, 'constant-power', 174, None), - (False, False, 'constant-power', 174, None)]) + (True, True,'source-rate', None, 1164719970082145.0), + (False, True, 'source-rate', None, 1164719970082145.0), + (True, True, 'fission-q', 174, None), + (False, True, 'fission-q', 174, None), + (True, False,'source-rate', None, 1164719970082145.0), + (False, False, 'source-rate', None, 1164719970082145.0), + (True, False, 'fission-q', 174, None), + (False, False, 'fission-q', 174, None)]) def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclides, normalization_mode, power, flux): """Transport free system test suite. @@ -53,10 +52,10 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide if from_nuclides: nuclides = {} for nuc, dens in fuel.get_nuclide_atom_densities().items(): - nuclides[nuc] = dens * 1e24 + nuclides[nuc] = dens op = FluxDepletionOperator.from_nuclides( - fuel.volume, nuclides, micro_xs, chain_file, normalization_mode=normalization_mode) + fuel.volume, nuclides,'atom/b-cm', micro_xs, chain_file, normalization_mode=normalization_mode) else: op = FluxDepletionOperator(openmc.Materials([fuel]), micro_xs, chain_file, normalization_mode=normalization_mode) @@ -67,14 +66,14 @@ def test_no_transport_from_nuclides(run_in_tmpdir, fuel, multiproc, from_nuclide # Perform simulation using the predictor algorithm openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator( - op, dt, power=power, flux=flux, timestep_units='d').integrate() + op, dt, power=power, source_rates=flux, timestep_units='d').integrate() # Get path to test and reference results path_test = op.output_dir / 'depletion_results.h5' if flux is not None: - ref_path = 'test_reference_constant_flux.h5' + ref_path = 'test_reference_source_rate.h5' else: - ref_path = 'test_reference_constant_power.h5' + ref_path = 'test_reference_fission_q.h5' path_reference = Path(__file__).with_name(ref_path) # Load the reference/test results diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 similarity index 99% rename from tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 rename to tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 index c6e1a4080..6c1b3de84 100644 Binary files a/tests/regression_tests/deplete_no_transport/test_reference_constant_power.h5 and b/tests/regression_tests/deplete_no_transport/test_reference_fission_q.h5 differ diff --git a/tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 b/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 similarity index 100% rename from tests/regression_tests/deplete_no_transport/test_reference_constant_flux.h5 rename to tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 diff --git a/tests/unit_tests/test_deplete_flux_operator.py b/tests/unit_tests/test_deplete_flux_operator.py index 9019d123d..8f17538ed 100644 --- a/tests/unit_tests/test_deplete_flux_operator.py +++ b/tests/unit_tests/test_deplete_flux_operator.py @@ -71,7 +71,7 @@ def test_operator_init(): 'O17': 1.7588724018066158e+19} micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) nuclide_flux_operator = FluxDepletionOperator.from_nuclides( - volume, nuclides, micro_xs, CHAIN_PATH) + volume, nuclides, 'atom/cm3', micro_xs, CHAIN_PATH) fuel = Material(name="uo2") fuel.add_element("U", 1, percent_type="ao", enrichment=4.25)