Fix restart integration offset bugs

Changes in d32139b993 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.
This commit is contained in:
Andrew Johnson 2019-07-30 08:46:23 -05:00
parent d5fa7b5c00
commit afe1b5b68c
No known key found for this signature in database
GPG key ID: 253418E91B7F6FEB
4 changed files with 7 additions and 75 deletions

View file

@ -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"""

View file

@ -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)

View file

@ -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], []

View file

@ -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__(