From b1ea5b89421f0793e8c61defaecd1674750d160a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 30 Jul 2019 15:56:24 -0500 Subject: [PATCH] Add type and value checking to Integrators - SI_Integrator must be passed positive integer. - Number of powers computed must be equal to the number of time steps Added unit test to ensure that the right errors are raised. --- openmc/deplete/integrator/abc.py | 11 +++++-- tests/unit_tests/test_deplete_integrator.py | 35 +++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/integrator/abc.py b/openmc/deplete/integrator/abc.py index 94ed2a86c3..26ca6b5819 100644 --- a/openmc/deplete/integrator/abc.py +++ b/openmc/deplete/integrator/abc.py @@ -1,9 +1,11 @@ from copy import deepcopy from abc import ABC, abstractmethod from collections.abc import Iterable +from numbers import Integral from uncertainties import ufloat +from openmc.checkvalue import check_type, check_greater_than from openmc.capi import statepoint_write from openmc.deplete import Results, OperatorResult @@ -60,9 +62,12 @@ class Integrator(ABC): power = [p * operator.heavy_metal for p in power_density] if not isinstance(power, Iterable): - # TODO Maybe use itertools.zip_longest? # Ensure that power is single value if that is the case power = [power] * len(self.timesteps) + elif len(power) != len(self.timesteps): + raise ValueError( + "Number of time steps != number of powers. {} vs {}".format( + len(self.timesteps), len(power))) self.power = power @@ -208,8 +213,10 @@ class SI_Integrator(Integrator): is not speficied. n_steps : int, optional Number of stochastic iterations per depletion interval. - Default : 10 + Must be greater than zero. Default : 10 """ + check_type("n_steps", n_steps, Integral) + check_greater_than("n_steps", n_steps, 0) super().__init__(operator, timesteps, power, power_density) self.n_steps = n_steps diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index 1750abd3d1..69f6ee6797 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -12,9 +12,11 @@ from unittest.mock import MagicMock import numpy as np from uncertainties import ufloat +import pytest -from openmc.deplete import (ReactionRates, Results, ResultsList, comm, - OperatorResult) +from openmc.deplete import ( + ReactionRates, Results, ResultsList, comm, OperatorResult, + PredictorIntegrator, SI_CELI_Integrator) def test_results_save(run_in_tmpdir): @@ -99,3 +101,32 @@ def test_results_save(run_in_tmpdir): np.testing.assert_array_equal(res[1].k, eigvl2) np.testing.assert_array_equal(res[1].time, t2) + + +@pytest.mark.parametrize("timesteps", (1, [1])) +def test_bad_integrator_inputs(timesteps): + """Test failure modes for Integrator inputs""" + + op = MagicMock() + op.prev_res = None + op.chain = None + op.heavy_metal = 1.0 + + # No power nor power density given + with pytest.raises(ValueError, match="Either power or power density"): + PredictorIntegrator(op, timesteps) + + # Length of power != length time + with pytest.raises(ValueError, match="number of powers"): + PredictorIntegrator(op, timesteps, power=[1, 2]) + + # Length of power density != length time + with pytest.raises(ValueError, match="number of powers"): + PredictorIntegrator(op, timesteps, power_density=[1, 2]) + + # SI integrator with bad steps + with pytest.raises(TypeError, match="n_steps"): + SI_CELI_Integrator(op, timesteps, [1], n_steps=2.5) + + with pytest.raises(ValueError, match="n_steps"): + SI_CELI_Integrator(op, timesteps, [1], n_steps=0)