FourierFlows/FourierFlows.jl

Compute solution at time `t` that is not necessarily an integer multiple of timestep `dt`

navidcy opened this issue · 6 comments

Currently FourierFlows.jl can only find solutions at integer multiples of the prescribed timestep dt.

It would be useful to be able to compute the solution at any time t even if that is not necessarily an integer multiple of dt.

One idea to do that is:

prescribe t and dt:

  • nstep = Int(ceil(t/dt)); this way (nstep-1)*dt < t <= nstep*dt.
  • compute solution for up to nstep*dt
  • output a linear interpolation of the solution between the last and the previous-to-last timesteps, e.g.,
(nstep*dt - t) / dt * sol[nstep-1] + (t-(nstep-1)*dt) / dt * sol[nstep]

In the case that t=nstep*dt then the above becomes simply sol[nstep] (similarly for if t=(nstep-1)*dt).

DifferentialEquations.jl does interpolate the output solution to the prescribed time t; I'm not sure what exactly the do there.

[This feature request came after discussions I had with @rveltz]

The above idea will probably affect the order of accuracy of the time-stepping algorithm. Another idea, might be the following:

prescribe t and dt:

  • nsteps = Int(floor(t/dt));
  • stepforward!(prob, nsteps)
  • t_remaining = t - nsteps * dt
  • dt = prob.clock.dt
  • prob.clock.dt = t_remaining (this should be < dt)
  • stepforward!(prob)
  • prob.clock.dt=dt

Then it should be that prob.clock.t == t.

You should probably put the initial dt back in prob after this

I edited the above as per @rveltz's suggestion.

@glwagner, what's the best way to overload stepforward! to do that you think?

We need a more detailed description of the feature request. DifferentialEquations is different because it returns a full timeseries of the solution. We do not do this, and in general we don't have much support for output.

One possible solution, depending on exactly what is being asked for, is to write a new function called step_until! which takes an argument stop_time. With a specified stop time, the simulation can be run forward until prob.clock.t + prob.clock.dt >= stop_time. Then we can take a small time-step with dt = stop_time - prob.clock.t to bring prob.clock.t up to stop_time. We can spit out a warning for ETDRK4 saying that this will be slow for that method due to the need to recompute matrices when dt changes.

step_until! is not a bad idea.

We can make it work for only fully explicit time steppers.