From afe1b5b68ced2b07991097132e16fe9f17bbf6ec Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 30 Jul 2019 08:46:23 -0500 Subject: [PATCH] Fix restart integration offset bugs Changes in d32139b993053912ba0d8117424d1585eb0aed0b highlighted the repeated data that was saved during non-predictor restart runs. All Integrator subclasses now have the same _get_bos_data_from_openmc and _get_bos_data_from_restart methods, where the restart index ``self._ires`` is one less than the number of previous results stored on the Operator. This allows all schemes to write their data in the correct index during restart calculations. A side benefit of this is that now, the Predictor implementation can rely entirely on the updated Integrator, without the need for re-writing the integrate method nor __init__ method. --- openmc/deplete/integrator/abc.py | 2 +- openmc/deplete/integrator/leqi.py | 2 +- openmc/deplete/integrator/predictor.py | 76 ++------------------------ openmc/deplete/integrator/si_leqi.py | 2 +- 4 files changed, 7 insertions(+), 75 deletions(-) diff --git a/openmc/deplete/integrator/abc.py b/openmc/deplete/integrator/abc.py index 24bd06395e..ca21f2a1b9 100644 --- a/openmc/deplete/integrator/abc.py +++ b/openmc/deplete/integrator/abc.py @@ -110,7 +110,7 @@ class Integrator(ABC): def _get_start_data(self): if self.operator.prev_res is None: return 0.0, 0 - return self.operator.prev_res[-1].time[-1], len(self.operator.prev_res) + return self.operator.prev_res[-1].time[-1], len(self.operator.prev_res) - 1 def integrate(self): """Perform the entire depletion process across all steps""" diff --git a/openmc/deplete/integrator/leqi.py b/openmc/deplete/integrator/leqi.py index 4b1c072b52..4bf4cf4d90 100644 --- a/openmc/deplete/integrator/leqi.py +++ b/openmc/deplete/integrator/leqi.py @@ -66,7 +66,7 @@ class LEQIIntegrator(Integrator): simulation """ if i == 0: - if self._ires <= 1: # need at least previous transport solution + if self._ires < 1: # need at least previous transport solution self._prev_rates = bos_rates return CELIIntegrator.__call__( self, bos_conc, bos_rates, dt, power, i) diff --git a/openmc/deplete/integrator/predictor.py b/openmc/deplete/integrator/predictor.py index 45783b2793..0e4dce423e 100644 --- a/openmc/deplete/integrator/predictor.py +++ b/openmc/deplete/integrator/predictor.py @@ -40,32 +40,7 @@ class PredictorIntegrator(Integrator): is not speficied. """ - def __init__(self, operator, timesteps, power=None, power_density=None): - """ - Parameters - ---------- - operator : openmc.deplete.TransportOperator - The operator object to simulate on. - timesteps : iterable of float - Array of timesteps in units of [s]. Note that values are not - cumulative. - power : float or iterable of float, optional - Power of the reactor in [W]. A single value indicates that - the power is constant over all timesteps. An iterable - indicates potentially different power levels for each timestep. - For a 2D problem, the power can be given in [W/cm] as long - as the "volume" assigned to a depletion material is actually - an area in [cm^2]. Either ``power`` or ``power_density`` must be - specified. - 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. - """ - super().__init__(operator, timesteps, power, power_density) - self._dep_proc_time = None - - def __call__(self, conc, rates, dt, power): + def __call__(self, conc, rates, dt, power, _i=None): """Perform the integration across one time step Parameters @@ -78,6 +53,8 @@ class PredictorIntegrator(Integrator): Time in [s] for the entire depletion interval power : float Power of the system [W] + _i : int or None + Iteration index. Not used Returns ------- @@ -91,49 +68,4 @@ class PredictorIntegrator(Integrator): """ proc_time, conc_end = timed_deplete(self.chain, conc, rates, dt) - return proc_time, conc_end, [] - - def _get_start_data(self): - if self.operator.prev_res is None: - return 0.0, 0 - return ( - self.operator.prev_res[-1].time[-1], - len(self.operator.prev_res) - 1) - - def _get_bos_data_from_openmc(self, step_index, step_power, prev_conc): - conc = deepcopy(prev_conc) - res = self.operator(conc, step_power) - if step_index == len(self) - 1: - tvec = [self.timesteps[step_index]] * 2 - else: - tvec = self.timesteps[step_index:step_index + 2] - - self._save_results( - [conc], [res], tvec, step_power, - self._istart + step_index, self._dep_proc_time) - return conc, res - - def integrate(self): - """Perform the entire depletion process across all steps""" - - with self.operator as conc: - t, self._istart = self._get_start_data() - - for i, (dt, p) in enumerate(self): - if i > 0 or self.operator.prev_res is None: - conc, res = self._get_bos_data_from_openmc(i, p, conc) - else: - conc, res = self._get_bos_data_from_restart(i, p, conc) - - # __call__ returns empty list since there aren't - # intermediate transport solutions - self._dep_proc_time, conc, _res_list = self( - conc, res.rates, dt, p) - - t += dt - - # Final simulation - res_list = [self.operator(conc, p)] - self._save_results( - [conc], res_list, [t, t], p, - self._istart + len(self), self._dep_proc_time) + return proc_time, [conc_end], [] diff --git a/openmc/deplete/integrator/si_leqi.py b/openmc/deplete/integrator/si_leqi.py index bd42104ea1..015650269d 100644 --- a/openmc/deplete/integrator/si_leqi.py +++ b/openmc/deplete/integrator/si_leqi.py @@ -53,7 +53,7 @@ class SI_LEQI_Integrator(SI_Integrator): simulation """ if i == 0: - if self._ires <= 1: + if self._ires < 1: self._prev_rates = bos_rates # Perform CELI for initial steps return SI_CELI_Integrator.__call__(