Speeding up DifferentialEquations solver by using different time steps for an ODE

Dear developers,

We are facing a project with the necessity of solving an ODE in Python. In order to do so we opted for a wrapper of Julia as it was the best option we found when a research on which ODE solver was a better choice to use was carried out.

Nevertheless, we are facing some problems in terms of computation performance and the opened issue aims to find an optimal solution for that, while trying to minimize the impact on the general code. Thus, we ask for help to see whether there is a setup of the Julia solver which can achieve our expectations.

We are using the ‘Tsit5’ DifferentialEquations solver to integrate an aircraft trajectory that performs a quick manoeuvre of a maximum duration of around 10 seconds, while the whole trajectory to integrate is of 100 seconds, thus performing a straight flight for the non-manoeuvre period. We initially programmed an adaptive solver saving the results at our desired dt (using saveat=dt), but the results were not accurate as the time step used by Julia was too large and did not obey the manoeuvre constraints. The output was a straight flight for the whole time duration, ignoring the manoeuvre. (We understand that what the solver does is to wisely choose a time step and then interpolate to obtain the results at the requested dt)

def integrate(f, x0, time0, timef, dt, solver):
    tspan = (time0, timef)
    prob = de.ODEProblem(f, x0, tspan)
    solver_obj = eval('de.' + solver + '()')
    sol = de.solve(prob, solver_obj, saveat = dt)
    
    x = np.asarray(sol.u)[:,:,0].T;
    t = sol.t;              

    return x, t;

To solve this, we programmed an also adaptive solver but limiting the maximum time step to our desired dt, as follows:

def integrate(f, x0, time0, timef, dt, solver):
    tspan = (time0, timef)
    prob = de.ODEProblem(f, x0, tspan)
    solver_obj = eval('de.' + solver + '()')
    sol = de.solve(prob, solver_obj, dtmax = dt)
    
    x = np.asarray(sol.u)[:,:,0].T;
    t = sol.t;              

    return x, t;

This resulted in a correct trajectory but in detriment of computation performance, as the solver uses small time steps in the straight flight section too, where a higher time step would be more than enough.

Our question is if there is a configuration of the Julia solver that enables us to program an adaptive time step solver but forcing it to use a time step equal or lower to our desired one for the duration of the manoeuvre and allowing it to be higher otherwise during straight flight outside the manoeuvre, where interpolation between larger time steps is good enough. Is there any option in DifferentialEquations that would allow us to do that? In that case, which configuration of the solver should we use to achieve it?

Thanks in advance for your help

I don’t have deep experience with the ODE solvers but in my simulations but I have found Callbacks to be very useful and wonder if they would be helpful in your application

See here: http://docs.juliadiffeq.org/stable/features/callback_functions.html#Introduction-to-Callback-Functions-1.

I’ve used these to change a set point of a (continuous) controller at certain times, to model friction, and to emulate a periodic controller.

Also you may be interested in this Juliacon video JuliaCon 2019 | A New Breed of Vehicle Simulation | Tucker McClure - YouTube ( A New Breed of Vehicle Simulation | Tucker McClure).

Use tstops to add time point which are required to be hit. saveat allows stepping over and interpolating back for efficiency (common way of doing it since you just step as far as possible and can still get the same order solution). It sounds like what you’re trying to do is best done with a callback as @klaff mentioned, but using tstops at the time points where a discontinuity happens may still do the trick.

1 Like

Thank you very much for your answers. We tried using tstops (by entering the time points of the maneouver part of the trajectory) and leaving saveat (for the rest of the trajectory, where we do not need such a short time step), and it works for us. The degree of accuracy of the results remains equal, but the time that it takes to solve the ODE drops at less than half the time that it took before (from ~6 min to less than 3 min). We may study using callbacks in the future.