Skip to content

[v10] refactor: use ImplicitDiscreteSystem to implement affects in callback systems #3452

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
wants to merge 65 commits into
base: master
Choose a base branch
from

Conversation

vyudu
Copy link
Member

@vyudu vyudu commented Mar 12, 2025

Close #2639 #2612

@vyudu vyudu marked this pull request as draft March 12, 2025 08:01
@vyudu vyudu force-pushed the callback branch 2 times, most recently from 4a6f2f6 to b7997b0 Compare March 20, 2025 21:28
@vyudu vyudu marked this pull request as ready for review April 2, 2025 14:12
@vyudu vyudu changed the title WIP: refactor: use ImplicitDiscreteSystem to implement affects in callback systems refactor: use ImplicitDiscreteSystem to implement affects in callback systems Apr 2, 2025
@vyudu
Copy link
Member Author

vyudu commented Apr 2, 2025

@ChrisRackauckas @AayushSabharwal This is very close, just needs a release for ImplicitDiscreteSolve and getting all the doc blocks working. One of the FMI tests is failing because the reinitialization isn't accurate enough (like 1.008e-8 but the tolerance is 1e-8), but I am unsure if that is related.

@vyudu vyudu changed the title refactor: use ImplicitDiscreteSystem to implement affects in callback systems [v10] refactor: use ImplicitDiscreteSystem to implement affects in callback systems Apr 3, 2025
@vyudu
Copy link
Member Author

vyudu commented Apr 23, 2025

@AayushSabharwal I think this is basically ready to merge into the v10 branch. The FMI failure is the thing we discussed where the initialization fails with some error very close to the tolerance; the other test failures seem unrelated

@vyudu
Copy link
Member Author

vyudu commented Apr 25, 2025

@AayushSabharwal

Copy link
Member

@AayushSabharwal AayushSabharwal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are significant performance regressions in this PR.


@mtkbuild sys = ODESystem(
D(x) ~ c * cos(x), t, [x], [c]; discrete_events = [1.0 => [c ~ c + 1]])
D(x) ~ c * cos(x), t, [x], [c]; discrete_events = [1.0 => [c ~ Pre(c) + 1]])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is c updated in this case, even if it is not saved? That's actually pretty useful if it works this way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is yes

@vyudu vyudu requested a review from AayushSabharwal April 29, 2025 21:32
end
outvar = :p
function (u, t, integ)
if DiffEqBase.isinplace(integ.sol.prob)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if DiffEqBase.isinplace(integ.sol.prob)
if DiffEqBase.isinplace(SciMLBase.get_sol(integ).prob)

This seems safer

else
initialize = handle_optional_setup_fn(
map(fn -> fn.initialize, affect_functions), SciMLBase.INITIALIZE_DEFAULT)
return CallbackSet(compiled_callbacks...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah, this is fine then. Thanks for the clarification.

Comment on lines +945 to +950
u_getters = [getsym(sys, aff_map[u]) for u in dvs_to_access]
p_getters = [getsym(sys, unPre(p)) for p in ps_to_access]
u_setters = [setsym(sys, u) for u in dvs_to_update]
p_setters = [setsym(sys, p) for p in ps_to_update]
affu_getters = [getsym(affsys, sys_map[u]) for u in dvs_to_update]
affp_getters = [getsym(affsys, sys_map[p]) for p in ps_to_update]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these can just call getsym or setsym with an array of symbolics. That way the getter just returns an array of values, instead of having to call an array of getters.

pmap = Pair[p => getp(integ) for (p, getp) in zip(ps_to_access, p_getters)]
u0map = Pair[u => getu(integ)
for (u, getu) in zip(dvs_to_access, u_getters)]
affprob = remake(affprob, u0 = u0map, p = pmap, tspan = (integ.t, integ.t))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Symbolic remake is still very slow. We know exactly what the u0 and p should be for this, so they should be passed directly to remake. This can leverage setsym_oop. So we'd have ugetter = getsym(sys, ...) and usetter = setsym_oop(affsys, ...) and do

new_us = ugetter(integ)
new_u0, _ = usetter(affprob, new_us)

And similarly,

new_ps = pgetter(integ)
_, new_p = psetter(affprob, new_ps)

Then affprob = remake(affprob, u0 = new_u0, p = new_p, tspan = (integ.t, integ.t))

The reason I suggest two different usetter and psetter is because getsym(sys, [dvs..., ps...]) is not type-stable, so we need two getters and consequently two setters.

Comment on lines +320 to +326

alg_eqs = filter(eq -> eq.lhs isa Union{Symbolic, Number} && !is_diff_equation(eq),
deqs)
cont_callbacks = to_cb_vector(continuous_events; CB_TYPE = SymbolicContinuousCallback,
iv = iv, alg_eqs = alg_eqs, warn_no_algebraic = false)
disc_callbacks = to_cb_vector(discrete_events; CB_TYPE = SymbolicDiscreteCallback,
iv = iv, alg_eqs = alg_eqs, warn_no_algebraic = false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're doing the same thing in the SDEProblem constructor (and should do it in DDEProblem and SDDEProblem as well) can this code block be extracted into a function that is called in all 4 problem constructors? That way we don't have to be concerned about them falling out of sync.

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

Successfully merging this pull request may close these issues.

SymbolicDiscreteCallback and SymbolicContiniuousCallback have different affect field names
4 participants