I’d like to have an MTK model like D(x) = k*x, and plot the solution in real time (after 1 second, the plot shows the solution from t=0 to t=1, etc.)
I’d like k to be supplied by a real-time interactive slider (so that when the user moves it, the real-time plot reacts accordingly). What’s the easiest way to achieve something like that? Ideally in Pluto (perhaps this is asking too much )
From Playing with live plots in Pluto - Specific Domains / Visualization - Julia Programming Language (julialang.org) I can make pluto-side animations, but each time-step has to be a single call (i.e. that wouldn’t work with a callback). So at each animation frame I’d have to setup the MTK problem and solve it over (current_t, current_t+1/30) (to target 30FPS). This might be doable, but I’d have to build the current total solution (t=0 to t=current_t) from the individual solutions, and set up each ODEProblem’s initial condition from the previous ODEProblem’s final values. This would definitely work, but it looks rather painful to setup.
Perhaps there is a solution using MTK callbacks? As in, I setup a periodic callback corresponding to my target FPS, somehow update k from the current slider value, somehow update the plot, then sleep() until the next frame? I’m a lot fuzzier on the details of that solution. It might involve… threads?
Here’s an implementation of a discrete callback that makes the simulation progress in real time
you can probably adapt this to your use case. To achieve the slider controlling a parameter, you can probably go through a global variable, but you need to make sure that the simulation and the slider update happens on different threads. The solution I linked above uses systemsleep which does not yield, but has better accuracy than sleep. If your real-time requirements are not very tight, you can use sleep instead, which is yielding. Then it’s enough for the simulation and the slider to run on different tasks (which may be on the same thread).
That looks perfect for the Pluto interaction code, I’ll give it a try!
One question: from reading the integrator interface documentation, it looks like mutating the state between each step! call is not a good idea. So I guess I should set up a periodic callback to read the slider’s current value and assign it to k. I’m assuming that this is OK? Are periodic callbacks ever called more than once for a given t? (in which case, they might read a different value, which sounds bad…?)
Worked great, thank you. For the Pluto interaction I had to use a function of t which accesses a global Ref, that is set by the Pluto slider (through another intermediary variable + cell). So quite roundabout, but nothing too difficult.
Double check if you’re doing anything that violates assumptions of being an ODE. As an ODE, the right-hand side f function should always give you the same result: u' = f(u,p,t) needs to be uniquely defined. These issues are just fundamental to the mathematics: if you do these things in f , then f no longer defines an ODE so of course it cannot be solved!
makes me worry that maybe step! can go before the current time t and get upset that f(t-1) no longer returns the value it did before.
You might want to u_modified!(integrator. true) to let it know that you just placed a derivative discontinuity when using the integrator interface live like that.