diff --git a/openmc/deplete/flux_operator.py b/openmc/deplete/flux_operator.py index 3ca046cf2d..37100ac5b5 100644 --- a/openmc/deplete/flux_operator.py +++ b/openmc/deplete/flux_operator.py @@ -16,7 +16,7 @@ import pandas as pd from uncertainties import ufloat import openmc -from openmc.checkvalue import check_type +from openmc.checkvalue import check_type, check_value, check_iterable_type from openmc.data import DataLibrary from openmc.exceptions import DataError from openmc.mpi import comm @@ -27,8 +27,19 @@ from .reaction_rates import ReactionRates from .results import Results from .helpers import ConstantFissionYieldHelper +valid_rxns = list(REACTIONS.keys()) +valid_rxns += ['fission'] -class FluxSpectraDepletionOperator(TransportOperator): +# Convenience function for the micro_xs static methods +def _validate_micro_xs_inputs(nuclides, reactions, data): + check_iterable_type('nuclides', nuclides, str) + check_iterable_type('reactions', reactions, str) + check_type('data', data, np.ndarray, expected_iter_type=float) + [check_value('reactions', reaction, valid_rxns) for reaction in reactions] + + + +class FluxDepletionOperator(TransportOperator): """Depletion operator that uses a user-provided flux spectrum and one-group cross sections to calculate reaction rates. @@ -318,15 +329,13 @@ class FluxSpectraDepletionOperator(TransportOperator): assert data.shape == (len(nuclides), len(reactions)) except AssertionError: raise SyntaxError( - 'Nuclides list of length {len(nuclides)} and' - 'reactions array of length {len(reactions)} do not' - 'match dimensions of data array of shape {data.shape}') + f'Nuclides list of length {len(nuclides)} and ' + f'reactions array of length {len(reactions)} do not ' + f'match dimensions of data array of shape {data.shape}') - check_iterable_type('nuclides', nuclides, str) - check_iterable_type('reactions', reactions, str) - check_type('data', data, float, expected_iter_type=np.array) - check_value('reactions', reactions, chain.REACTIONS) + _validate_micro_xs_inputs(nuclides, reactions, data) + # Convert to cm^2 if units == 'barn': data /= 1e24 @@ -351,7 +360,12 @@ class FluxSpectraDepletionOperator(TransportOperator): A DataFrame object correctly formatted for use in ``FluxOperator`` """ - micro_xs = pd.DataFrame.read_csv(csv_file) + micro_xs = pd.read_csv(csv_file, index_col=0) + + _validate_micro_xs_inputs(list(micro_xs.index), + list(micro_xs.columns), + micro_xs.to_numpy()) + if units == 'barn': micro_xs /= 1e24 diff --git a/tests/micro_xs_simple.csv b/tests/micro_xs_simple.csv new file mode 100644 index 0000000000..40142f5438 --- /dev/null +++ b/tests/micro_xs_simple.csv @@ -0,0 +1,13 @@ +,fission,"(n,gamma)" +U234,0.1,0.0 +U235,0.1,0.0 +U238,0.9,0.0 +U236,0.4,0.0 +O16,0.0,0.0 +O17,0.0,0.0 +I135,0.0,0.1 +Xe135,0.0,0.9 +Xe136,0.0,0.0 +Cs135,0.0,0.0 +Gd157,0.0,0.1 +Gd156,0.0,0.1 diff --git a/tests/unit_tests/test_flux_deplete_operator.py b/tests/unit_tests/test_flux_deplete_operator.py new file mode 100644 index 0000000000..a2b1504938 --- /dev/null +++ b/tests/unit_tests/test_flux_deplete_operator.py @@ -0,0 +1,73 @@ +"""Basic unit tests for openmc.deplete.FluxDepletionOperator 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.flux_operator import FluxDepletionOperator +import pandas as pd +import numpy as np + +FLUX_SPECTRA = 5e16 +CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml" +ONE_GROUP_XS = Path(__file__).parents[1] / "micro_xs_simple.csv" + + +def test_create_micro_xs_from_data_array(): + nuclides = [ + 'U234', + 'U235', + 'U238', + 'U236', + 'O16', + 'O17', + 'I135', + 'Xe135', + 'Xe136', + 'Cs135', + 'Gd157', + 'Gd156'] + reactions = ['fission', '(n,gamma)'] + # These values are placeholders and are not at all + # physically meaningful. + data = np.array([[0.1, 0.], + [0.1, 0.], + [0.9, 0.], + [0.4, 0.], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.9], + [0., 0.], + [0., 0.], + [0., 0.1], + [0., 0.1]]) + + FluxDepletionOperator.create_micro_xs_from_data_array( + nuclides, reactions, data) + with pytest.raises(SyntaxError, match=r'Nuclides list of length \d* and ' + r'reactions array of length \d* do not ' + r'match dimensions of data array of shape \(\d*\,d*\)'): + FluxDepletionOperator.create_micro_xs_from_data_array( + nuclides, reactions, data[:, 0]) + + +def test_create_micro_xs_from_csv(): + FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_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.""" + nuclides = {'U234': 8.922411359424315e+18, + 'U235': 9.98240191860822e+20, + 'U238': 2.2192386373095893e+22, + 'U236': 4.5724195495061115e+18, + 'O16': 4.639065406771322e+22, + 'O17': 1.7588724018066158e+19} + micro_xs = FluxDepletionOperator.create_micro_xs_from_csv(ONE_GROUP_XS) + my_flux_operator = FluxDepletionOperator( + 1, nuclides, micro_xs, FLUX_SPECTRA, CHAIN_PATH)