Skip to content

Setu is ignored by solve #3552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1-Bart-1 opened this issue Apr 9, 2025 · 9 comments
Open

Setu is ignored by solve #3552

1-Bart-1 opened this issue Apr 9, 2025 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@1-Bart-1
Copy link

1-Bart-1 commented Apr 9, 2025

When using setu to update the problem state, this new state is simply ignored by solve. Using setp to update the parameters works fine.

MWE:

using ModelingToolkit, OrdinaryDiffEq
using ModelingToolkit: D_nounits as D, t_nounits as t, setu, setp, getu, getp

Ts = 0.1
@mtkmodel Pendulum begin
    @parameters begin
        g = 9.8
        L = 0.4
        K = 1.2
        m = 0.3
        τ = 0.0 # input
    end
    @variables begin
        θ(t) = 0.0 # state
        ω(t) = 0.0 # state
        y(t) # output
    end
    @equations begin
        D(θ)    ~ ω
        D(ω)    ~ -g/L*sin(θ) - K/m*ω + τ/m/L^2
        y       ~ θ * 180 / π
    end
end

@mtkbuild mtk_model = Pendulum()
prob = ODEProblem(mtk_model, nothing, (0.0, Ts))
set_x = setu(mtk_model, unknowns(mtk_model))
get_x = getu(mtk_model, unknowns(mtk_model))
set_u = setp(mtk_model, [mtk_model.τ])
get_u = getp(mtk_model, [mtk_model.τ])
get_h = getu(mtk_model, [mtk_model.y])
p = (prob, set_x, set_u, get_h)

function f!(xnext, x, u, _, p)
    (prob, set_x, set_u, _) = p
    set_x(prob, x)
    set_u(prob, u)
    sol = solve(prob, Tsit5(); save_on=false, save_start=false)
    xnext .= sol.u[end] # sol.u is the state, called x in the function
    nothing
end

xnext = zeros(2)

println("Initial")
f!(xnext, zeros(2), 0.0, nothing, p)
@show xnext

println("Just changing state x - doesn't work, xnext stays at zero")
f!(xnext, ones(2), 0.0, nothing, p)
@show xnext

println("Just changing input u - does work, xnext is non-zero")
f!(xnext, zeros(2), 1.0, nothing, p)
@show xnext
nothing

From this discussion

@1-Bart-1 1-Bart-1 added the bug Something isn't working label Apr 9, 2025
@AayushSabharwal
Copy link
Member

See https://docs.sciml.ai/ModelingToolkit/stable/tutorials/initialization/#Constant-constraints-in-initialization. Constant constraints in initialization have to be updated by setting Initial(x) not x.

@1-Bart-1
Copy link
Author

Thanks, that works!

@1-Bart-1
Copy link
Author

@AayushSabharwal is it correct that setp and setu are basically undocumented? It would be great if this Initial(x) trick was written in the documentation specifically for setp and setu.

@AayushSabharwal
Copy link
Member

Initial(x) is an MTK concept. setp and setu are in SymbolicIndexingInterface and documented there.

@ChrisRackauckas
Copy link
Member

I don't think this is a sufficient answer. Users using setu would expect u0 to change. If setu needs to update Initial(x) to do that, then setu should do that, not tell users that they need know that we need Initial(x) as a parameter and set that and then later that will set u0. That detail is not public API so users shouldn't have to know or understand it.

@AayushSabharwal
Copy link
Member

Initial(x) is public API though? And setu is too low-level of a function to do this. It's basically setindex!. setu does change prob.u0, but MTK specifically doesn't respect prob.u0 ever since initialization was a thing.

@1-Bart-1
Copy link
Author

But what if I want MTK to respect prob.u0? I don't want to run an initialization algorithm in my use case, I just want the simulation to start instantly from prob.u0, as I know this is a viable start state.

@1-Bart-1
Copy link
Author

Initial(x) is an MTK concept. setp and setu are in SymbolicIndexingInterface and documented there.

I really like the Linearization documentation, which explains clearly that setu is from SymbolicIndexingInterface.jl, and how it can be used to update parameters. This is what I meant with there not being documentation on setu. It would be great if there would be documentation on how to use setu with an ODEProblem.

@AayushSabharwal
Copy link
Member

But what if I want MTK to respect prob.u0? I don't want to run an initialization algorithm in my use case, I just want the simulation to start instantly from prob.u0, as I know this is a viable start state.

Sorry for the delay. In such a case, you could pass initializealg = CheckInit() to ODEProblem/remake/solve (either one) to ignore MTK's initialization. In this case, you would have to set x and not Initial(x). Alternatively, see #3570 and its fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants