Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrdinaryDiffEq arguably uses the wrong DAE initializealg after callbacks. #2143

Open
oscardssmith opened this issue Feb 20, 2024 · 5 comments
Labels

Comments

@oscardssmith
Copy link
Contributor

Describe the bug 馃悶
After hitting a callback, daes are re-initialized with their initializealg (

DiffEqBase.initialize_dae!(integrator)
) rather than BrownFullBasicInit. This means that if the user is using a custom initializealg (or ShampineColocationInit), that initialization will be called after callbacks which is likely not desired. Note, however that fixing this correctly is somewhat difficult (hence the lack of a PR), because if the user is using a custom init for different reasons (e.g. turning off autodiff for initialization), we don't want to use the default BrownFullBasicInit as doing so would try to use autodiff and potentially crash. The code below reproduces this (and the problem with the obvious fix)

using DiffEqCallbacks, OrdinaryDiffEq, LinearAlgebra, DiffEqBase, ADTypes, NonlinearSolve, Plots
f(u::Vector{Float64}, p, t) = u
fun = ODEFunction(f, mass_matrix=Diagonal([1., 0.]))
callback = PresetTimeCallback(0.5, Returns(nothing))
struct CustomInitialize <: DiffEqBase.DAEInitializationAlgorithm
end
function OrdinaryDiffEq._initialize_dae!(integrator, prob::ODEProblem, alg::CustomInitialize, iip)
    integrator.u .= 1
    OrdinaryDiffEq._initialize_dae!(integrator, prob, BrownFullBasicInit(;nlsolve=RobustMultiNewton(autodiff=AutoFiniteDiff())), iip)
end
prob = ODEProblem(fun, zeros(2), (0., 1.); callback, initializealg=CustomInitialize())
sol = solve(prob, FBDF(autodiff=false))
plot(sol)

image

@staticfloat
Copy link
Contributor

So it sounds to me like one path forward might be to have two initializealg arguments, something like initializealg and reinitializealg, where reinitializealg would just default to BrownFullBasicInit? And reinitializealg would be what gets called after discontinuities?

@topolarity
Copy link

What information/flag does the standard initializealg use that prevents it from modifying differential variables when re-initializing after a callback?

@oscardssmith
Copy link
Contributor Author

the standard initializealg is BrownFullBasicInit.

@topolarity
Copy link

Ah, and BrownFullBasicInit does not modify any differential variables.

@ChrisRackauckas
Copy link
Member

So it sounds to me like one path forward might be to have two initializealg arguments, something like initializealg and reinitializealg, where reinitializealg would just default to BrownFullBasicInit? And reinitializealg would be what gets called after discontinuities?

In general you may want to tag callbacks with a reinitialization routine, because what variables to keep constant could depend on which ones you just modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants