-
-
Notifications
You must be signed in to change notification settings - Fork 104
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
Make error check more compatible with SciML interface #896
base: master
Are you sure you want to change the base?
Make error check more compatible with SciML interface #896
Conversation
function get_retcode(integrator::DEIntegrator) | ||
return integrator.sol.retcode | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To quickly elaborate on this, I essentially have problems where "time sub-integrators" advance parts of the solution and I could not find a sane way to define this distributed solution stuff into the current solution interface. Technically I do not even need every subintegrator to hold a solution. They just need to communicate return codes between each other. Having this interface here would be a compromise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most integrators don't set the return code until the end though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. But for operator splitting methods I have essentially a tree of integrators, each solving subproblems on small time intervals. The easiest example is essentially to have an additivley split right hand side for some ODE:
which I want to integrate from [0,T]. Operator splitting method now definine two ODEs
and
$d_t u^{} = f_2(u^{},p,t)$
and they intrgrate each of these in a specific order on subintervals on
- Set
$u^*(0) = u_0$ - Solve
$d_t u^* = f_1(u^*,p,t)$ on$[0,dt]$ (with your algorithm of choice) - Set
$u^{**}(0) = u^*(dt)$ - Solve $d_t u^{} = f_2(u^{},p,t)$ on
$[0,dt]$ (with your algorithm of choice)
In my implementation right now I have three separate integrators. One custom time integrator for the coordination of which subintegrator needs to integrate its associated problem next (+ time step controll of the time intervals to solve the subproblems on), and another two integrators for the respective subproblems. To check whether a solve worked or not the outer time integrator essentially checks the inner integrators return code after each solve of the subproblems. Does this explain it?
Probably not the best architecture, but at least it is functional.
function controller_message_on_dtmin_error(integrator::DEIntegrator) | ||
if isdefined(integrator, :EEst) | ||
return ", and step error estimate = $(integrator.EEst)" | ||
else | ||
return "" | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some voodoo time adaption algorithms actually work without defining an error estimate, so I would like to remove the dependency that the integrator itself needs to carry the error estimate and would like to propose in the future that there is either some kind of ControllerCache or the contoller itself carries the estimate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... that's going to be rough because there needs to be a tie-in in every stepper for how to calculate and store EEst, if it's needed. I'm not opposed though, because yes some methods like a priori estimates don't need the EEst and so it shouldn't spend the time to calculate it.
(!step_accepted || (hasproperty(opts, :tstops) ? | ||
integrator.t + integrator.dt < integrator.tdir * first(opts.tstops) : | ||
true)) | ||
step_rejected = last_step_failed(integrator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now this does not work, as last_step_failed
is always false if the integrator is adaptive. If everyone agrees that this is closer to the semantics that we really want, then I will go through all subpackages and make the corresponding change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be reasonable.
Co-authored-by: Dennis Ogiermann <[email protected]>
This will require some changed in many downstream packages. The main issue for now is that
SciMLBase.last_step_failed
never returns true if the integrator is adaptive.