xarray-contrib / xarray-simlab

Xarray extension and framework for computer model simulations
http://xarray-simlab.readthedocs.io
BSD 3-Clause "New" or "Revised" License
73 stars 9 forks source link

Issue with time stepping #191

Open jeanbraun opened 2 years ago

jeanbraun commented 2 years ago

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)

xsimlab.yml.txt xsimlab.list.txt

benbovy commented 2 years ago

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