I agree that the specific implementation (CVODES) is not so of interest to the user. I am suggesting a blend of the above:
- we have two simple go-to default functions for users:
integrate_ode => non-stiff
integrate_ode_stiff => stiff
These functions set the default abs+rel tol and maximum number of steps.
- Additionally, we have functions with more control which are named for their algorithm:
integrate_ode_rk45
integrate_ode_adams_moulton
integrate_ode_bdf
These functions would take extra arguments for abs+rel tol and maximum number of steps.
This way we would have covered expert users and normal mortals. This would also be in line with what I see in other ODE packages, i.e. they make the options named after the algorithm.
I would prefer to keep the rk45 from boost in addition to the adams_moulton from CVODES. The material is far to complex for me to exhaustively cover this with benchmark tests to decide which one is really better and I do think this will actually always depend on the exact model, etc.. RK45 is around for ages as is adams_moulton. Moreover, adams_moulton is advertised as requiring fewer calls to the ODE RHS and the sensitivity ODE RHS. From that angle adams_moulton should be better than RK45, since it avoids a few calls to AD.
If you think getting rid of boost odeint is a big advantage, then so be it.
Best,
Sebastian
Hmm... your arguments make sense. Also, thinking about how much code could go away if we remove the odeint RK45 integrator...that's quite a lot of code+testing code. From that perspective going with CVODES only is a big win, true. Ok, even though this won't cover everything I will fire off tomorrow a benchmark for a non-stiff problem which takes 2-3 days. That is a good stress test for the Adams-Moulton and the RK45 integrator.
And 4 variants of integrate_ode are easier to read than using algorithms name for the advanced functions, also agreed. I only think that this naming scheme is not really expandable (and only experts use it, so it's fine to have the names), but maybe that is just a minor point. As I have been exposed to these things so much, I like my details; but maybe they don't matter so much in the end. Bottom line: I can live with your option A.
Sebastian
I have done now a bit of benchmarking and from this I can say that RK45 is 3-5x FASTER in comparison to the Adams-Moulton from CVODES! So I would definitely recommend to keep RK45.
In order to double check that my approaches with ode_model (used in the Adams-Moulton) etc. is not the root cause for the slow down I also went ahead an reimplemented the odeint integrator with these building blocks. The speed of this newly implemented odeint RK45 integrator is the same as the old one. The nice thing though is that I can cut down on lines of code from ~800 to ~300 and out of the ~300 about 200 come from ode_model and decouple_ode_states. Hence, I would recommend to refactor the old code with these pieces, but surely keep RK45.
I have the code written, but as it depends on pieces in the CVODES branch, can I just branch of that one?
Sebastian
(I ran the new RK45 code with the existing tests for odeint and all were good)
On Thursday, April 14, 2016 at 10:09:27 PM UTC+2, Bob Carpenter wrote:
> Let's discuss this at the meeting Tuesday and see if
> everyone else is OK getting rid of Boost's odeint and
> just going with CVODES.
>
> No matter what we do with function names, the details
> of what's going on under the hood will be available.
> I think it's critical to make the high-level code to
> lower-level code path as transparent as possible for
> power users --- it's the only way to write good code
> in a language, be it C++ or Stan or R.
>
> - Bob
>
> > On Apr 13, 2016, at 3:02 PM, Sebastian Weber
> >
Sebastian, I'm sure this is stuff that's "known" somewhere by some experts but it's fantastic to have careful benchmarks done in-house for Stan to help us figure out how to incorporate these algorithms. Thanks! Krzysztof
Thanks - and I can tell you, this is quite some work. By now I have formalized a few tests which makes it a bit less work. However, from my experience you have to benchmark things in order to know. Moreover, there are "experts" out there, yes; but apparently there is not a golden rule or a standard. Otherwise, we would not see so many options out there. Different ODE systems my run with Adams-Moulton faster than with RK45, I am almost sure about that...
Sebastian
Agreed, and that's a great reason to formalize and keep these longer benchmarks around. Really it might be worth a repo of it's own to have performance-oriented benchmarks for different models/configurations... do you have these benchmarks on github?
Hi Daniel!
The benchmarks I did apply to my test case (2cmt oral PK model). I would recommend (in order of importance):
1. Keep integrate_ode with the RK45 for non-stiff
2. replace integrate_ode_cvode with a CVODES based stiff solver
3. Add a further integrate_ode function which allows to set abs+rel tol and maximum number of steps
4. use code from step 2 to refactor integrate_ode in order to have less code to maintain to go forward
5. consider exposing the adams_moulton of CVODES - I am sure some models will benefit from this
We still need to decide of how to name those functions; to be discussed Tuesday?
I don't think it has to go into one of the official repos but I refuse to temper
my enthusiasm on the subject!
>
> I always start with a repo or branch and try to keep everything
> "clean" as I go. I find it's easier in the long run that way,
> sort of like cleaning as you go when cooking a large meal.
You should see my sink.
K
My benchmarks tests are somewhat specialized to our computing environment. So I use a system like
1. An R script which sets up simulated data, inits and everything else what is needed to kick off a Stan run. This is the "model" file as I call it.
2. Another R script which takes the model file, parses it, creates a sub-directory, serializes the data into that directory, copies the stan source and executable into it, sets up init files and finally creates "fit.sh" and optionally "post.sh".
3. then I submit things into the SGE cluster queue
However, the script fit.sh can be called from the command line like
./fit.sh
(trivial). This will start chain id 1; if you want chain X then you do
SGE_TASK_ID=X ./fit.sh
Is that too "local" or would that suffices to linger in one of the stan repos?
Sebastian
Putting things into the stan github raises the bar a bit for me - I don't always go forward with clean code (although I put quite some tests in my code) and before I share code some polishing should be done...