-
-
Notifications
You must be signed in to change notification settings - Fork 231
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
Implement automatic absolute tolerance computation as MATLAB #118
Comments
Yes, the implementation would be pretty easy to do. The hard part would be the interface. We would need to think about what to use instead of @mauro3 you have any input? |
This would be something each solver would have to implement, right? Or a callback? What about setting |
Yeah. It would be possible with a callback, but then we'd have to keep expanding what's in the standard callbacks.
Side note: we really need that keyword arg dispatch PR to be part of v0.6. |
Thinking about this again: how much does this actually help? I am torn between "if MATLAB has it, it must be useful enough that we shouldn't require users who want it to write a very special callback" and "is it actually useful? Won't the relative tolerance kind of handle this?" |
Maybe a library of standard call-backs would be good? |
I don't think so, unless it's one solver specific (OrdinaryDiffEq.jl would be the natural target since it's the most flexible to do these things). I will be creating libraries which generate event functions because events are a high enough level that they can be generically applied to many solvers. Callbacks are much too low level. This problem is actually a good example of that. Let's say for example, to accommodate this problem, we extend the common callback proposal to be: callback(alg::Alg,t,u,du,f,cache,reltol,abstol,args...) I claim this is a bad idea. For OrdinaryDiffEq.jl, But that will work for nothing else. It won't work for PR49 because it uses an immutable type for its adaptive options (and its probably unwise to change that, so maybe you make flag = @checkflag CVodeSStolerances(mem, reltol, abstol) So now the code starts to get really messy. You could create a macro function callback(alg::Alg,t,u,du,f,cache,reltol,abstol,args...)
@adaptive_abstol
end which generates function callback(alg::Alg,t,u,du,f,cache,reltol,abstol,args...)
# calculate new abstol
if typeof(alg) <: SundialsAlgorithm
...
...
end and condition that all out, but you're still missing the fact that you need to cache the value for the maximum @ode_callback begin
@adaptive_abstol
end and have it create a separate dispatch with "standard naming" for each algorithm (what repo would this be in? It would need to depend on every solver package), and the inner macro should still have the conditionals unless you make that outer macro "super smart" which would be very time consuming to develop / maintain. The other way to do this with Sundials is to allow it to accept I think this shows how callbacks are low-level and close enough to the actual algorithm that it would be a nightmare to maintain. But callbacks are very useful. When I give you the function signature for OrdinaryDiffEq.jl, it's pretty easy to write a callback which implements this for OrdinaryDiffEq.jl. And same for Sundials.jl (if you're familiar with the Sundials API). So callbacks let you easily extend an algorithm as much as you want, but uniformity in doing so is out of the question (unlike events). [Maybe I should just write a library of really cool callbacks for OrdinaryDiffEq.jl and not worry about the other solvers, just for handling these kinds of odd cases. It would be restricting, but for a case like this its an easy fix] The real problem here is that it's hard to do via events as well. Sure, we could pass |
Scratch what I had at the end there. For interop packages like Sundials, it will need to check for changes and use API calls to change the temporary arrays in the So that should work everywhere except PR49 (unless it finds a way to deal with the immutability issue). This could then go into events library. That would extend it to: apply_event!(t,u,du,event_cache,cache,abstol,reltol,funcs...) Is it fine to add more arguments? Will there be other cases of tolerance changing? |
I think this would be better combined with the
The |
Wow, sorry this got so long. But here's the brain dump. There's a lot of very integrated things in this idea to mention. That doesn't help in all cases, and would actually exacerbate the problem in some. For any solver which cannot work directly on the init type (any interop solver), every field which needs some nontrivial change when changed (i.e. any field which needs to be passed to the Sundials/DASKR/LSODA/... That said, it's worth looking into. Now that we really have something together I think we can take stock and use our current results as a point to test off of. Specifically:
(Do you want to run some benchmarks, or would you be willing to wait a little bit for me to get around to it?).
One thing to note is that the options type would need to silently contain a field That could be a set Once we have that, I think we should go a little further with sol,integrator,opts = init(prob, alg; solve_kwargs...,pre_allocated_arrays...)
solve!(sol,prob,integrator,opts) will mutate Of course, sol = solve(prob,alg,pre_allocated...;kwargs...) would just fold into the above. Then, actually we can just put another type parameter into the solution object and just make it have the field
There are two more questions that this opens up. The first is why keep Now, the last thing that probably will get brought up here is why keep I feel the next proposal would be to then just say, oh well So in the end, I think it's best to pass an instantiated |
For an update on this issue, see SciML/Roadmap#10 (comment) |
This has been implemented with the new callback interface in DiffEq callbacks. |
Hi @ChrisRackauckas, Sorry, I was completely offline due to a travel. I read your new Callback interface and the Integrator interface and I only can say what an amazing work! This solved all my problems :) I will study it better and port my code to use these new features. Thanks you very much! |
No worries. You have time because it hasn't been released yet (hence the "developer preview" and the lack of docs change for the callbacks so far). If it does get released and you haven't changed your code, just |
Good! So I will clone master and test it! |
Btw, can you point me what packages should I track from master? |
OrdinaryDiffEq.jl, DiffEqBase.jl, and I think you may need ParameterizedFunctions.jl. |
Hi @ChrisRackauckas, Does this package support a vector as the absolute tolerance? I think this can only be fully implemented with this feature. The code you proposed at DiffEqCallbacks seems to compute the maximum value of the state vector, and then it multiplies by the relative tolerance to obtain the new absolute tolerance. However, it seems that Matlab adapts the absolute tolerance for each value separately. Hence, we should have a vector of absolute tolerances with the dimension equals to that of the state vector. Am I right? |
Yes. I just don't support vector tolerances yet because it will be free in v0.6. What I mean is that the following code: currently is a loop. Without broadcast, I would need at least two different loops: one where the tolerances are indexed and one where they're not (and every combination if you want to support more!). However, instead of looping this could be broadcast: atmp .= ((utilde.-u)./(integrator.opts.abstol.+max.(abs.(uprev),abs.(u)).*integrator.opts.reltol)) On v0.5, that will allocate more memory and slow things down. On v0.6 that will be just as efficient as the loop, and will handle both scalar and vector tolerances, along with every combination of them. So that's why I am waiting. Then, the same could happen to the callback in DiffEqCallbacks. |
Hi guys!
Simulink, as can be seen here https://www.mathworks.com/help/simulink/gui/absolute-tolerance.html, has the capability of controlling the absolute tolerance automatically. It seems a very simple algorithm:
I am wondering if it is possible to implement this feature in this package.
The text was updated successfully, but these errors were encountered: