Issue with time stepping
Hello @benbovy,
I noted a strange behavior with the framework. It is illustrated in the following basic model. It should produce an output array that goes from 0 to 1 by updating the a variable junk by one unit per time step. At every time step it also prints the value of junk as well as the step_start and step_end times.
Two features seem unrealistic: first, the end times are smaller than the start times and the first end time is not defined; second, the result seems to be stored in the final array ds_out.empty__junk with a negative offset of -1 and the result for the last time step is repeated from the previous one (i.e., the output should be [0,1,2,3,4,5,6,7,8,9,10] whereas it is [1,2,3,4,5,6,7,8,9,10,10]).
Am I doing something wrong or is it a problem with the framework? I am surprised that we would not have noted this behavior before. I attach a description of the environment I am using for this.
Thanks in advance for your help
Jean
import numpy as np
import xsimlab as xs
@xs.process
class Empty:
junk = xs.variable(intent="inout")
@xs.runtime(args=("step_delta","step_start","step_end"))
def run_step(self, dt, t0, t1):
print('time', t0,t1,dt)
print('junk before', self.junk)
self.junk = self.junk + 1
print('junk after', self.junk)
model = xs.Model({"empty": Empty})
ds_in = xs.create_setup(
model=model,
clocks={"time": np.linspace(0,.2,11),
"out": np.linspace(0,.2,11)},
master_clock = "time",
input_vars={"empty__junk": 0},
output_vars={"empty__junk":"out"})
with model, xs.monitoring.ProgressBar():
ds_out = ds_in.xsimlab.run()
print(ds_out.empty__junk)
Hi Jean,
The first issue is a bug (thanks for reporting it): in the line below the shift value should be -1 instead of 1.
https://github.com/xarray-contrib/xarray-simlab/blob/33a4c83b3046153ff4a63c44925d67b54d42beb0/xsimlab/drivers.py#L175
The second issue is actually expected behavior in xarray-simlab, which could be clarified in the documentation. For all output variables, snapshots are saved between the run_step and finalize_step simulation stages. So in your example the value of the junk variable is incremented before being saved (you should increment it within the finalize_step stage instead to get the desired behavior). This is because we currently make no distinction between intent='out' and intent='inout' variables and because variables with intent='out' may have undefined (or outdated) values before executing run_step.
I admit that it was probably a design mistake and a better solution might be to save snapshots before run_step for "inout" variables and after run_step for "out" variables (and probably get rid of finalize_step).