Hello all. I have a question about using remake on an ODEproblem constructed using modeling toolkit (MTK). I’ll note that I’m using MTK v8.76.0. I am aware that v9 introduces new structure referencing (Frequently Asked Questions · ModelingToolkit.jl), but it sounds like this is experimental so I would prefer not to rely on it yet.
The basic goal is to create and ODEproblem from a MTK model, and then remake the problem with a subset of the parameters changed. Specifically, I would like to be able to change the values of a subset of parameters by named reference rather than by index. I found the following syntax in the SciML docs (Optimizing through an ODE solve and re-creating MTK Problems · ModelingToolkit.jl) (full code below).
prob2 = remake(prob; p = [:r => 42.0]);
However this does not work. The new problem does not have the new parameter value. I can do this all using extracted parameter indexes.
p = prob.p;
p[r_ind] = 42.0;
prob3 = remake(prob; p = p);
r_val = prob3.p[r_ind]
This is however really clunky and more prone to introducing errors.
This should be a standard issue, and I am pulling the syntax directly from the SciML docs. The docs are really well done so I’m assuming I have either a typo or a mis-understanding of how the structures are handled in the background.
Any thoughts on where I am going wrong or suggestions for a better way to do this?
FULL CODE BELOW
using DifferentialEquations, ModelingToolkit, Plots
## Construct MTK model.
LV = function(; name)
@variables t, [description = "time"]
Dt = Differential(t)
pars = @parameters begin
r = 1.0, [description = "growth rate"]
K = 2.0, [description = "carrying capacity"]
end
vars = @variables begin
x(t) = 0.1
end
eqs = [Dt(x) ~ r*x*(1.0-x/K)]
ODESystem(eqs, t, vars, pars; name=name)
end
## Instantiate model and ode problem
@mtkbuild LV1 = LV();
prob = ODEProblem(LV1, [], (0.0, 20.0), []);
sol = solve(prob, Tsit5());
##### Change one parameter and return with new value
# This does NOT work. It does not change the value of 'r'.
r_ind = ModelingToolkit.parameter_index(LV1, :r);
r_val = prob.p[r_ind]
prob2 = remake(prob; p = [:r => 42.0]);
r_val = prob2.p[r_ind]
##### Try again, but with direct indexing. This does work, but is clunky.
p = prob.p;
p[r_ind] = 42.0;
prob3 = remake(prob; p = p);
r_val = prob3.p[r_ind]