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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/issue #767 DAE solver #768

Merged

Conversation

yizhang-yiz
Copy link
Contributor

@yizhang-yiz yizhang-yiz commented Feb 15, 2018

Submission Checklist

  • Run unit tests: ./runTests.py test/unit
  • Run cpplint: make cpplint
  • Declare copyright holder and open-source license: see below

Summary:

This PR addresses #767 . It implements interface to IDAS library for DAE solutions.

A DAE solver solves equations in the form
F(yp, yy, t) = 0
where F: R^n -> R^n contains both differential and algebraic components, yy is the unknown variable vector, and yp=yy' is the derivative of yy. In a trivia DAE the differential and algebraic equation components are decoupled. When they are not, an involved process needs to be formulated to convert the system into canonical forms.

Intended Effect:

The proposed interface is as follows

  template<typename F, typename Tyy, typename Typ, typename Tpar>
  std::vector<std::vector<typename stan::return_type<Tyy, Typ, Tpar>::type> >
  integrate_dae(const F& f,
                const std::vector<int>& eq_id,
                const std::vector<Tyy>& yy0,
                const std::vector<Typ>& yp0,
                double t0,
                const std::vector<double>& ts,
                const std::vector<Tpar>& theta,
                const std::vector<double>& x_r,
                const std::vector<int>& x_i,
                const double rtol = 1e-8,
                const double atol = 1e-10,
                const int64_t max_num_steps = 1e6,
                std::ostream* msgs = 0) {
  • f: the function for DAE residual
  • eq_id: integer vector to identify differential and algebraic components in the system. 1 for differential, 0 for algebraic.
  • yy0: initial condition for primary unknowns
  • yp0: initial condition for derivative of unknowns. yy0 and yp0 together must meet F(yp0, yy0,t0)=0
  • t0: initial time
  • ts: vector for observation time
  • theta: parameters

When TYY, TYP and TPAR are not all data, the DAE system is augmented with forward sensitivity variables s and s' for sensitivity analysis.

A demo for prey-predator-harvest dynamical system.

How to Verify:

Unit tests

Side Effects:

N/A

Copyright and Licensing

Please list the copyright holder for the work you are submitting (this will be you or your assignee, such as a university or company):
Metrum Research Group, LLC

By submitting this pull request, the copyright holder is agreeing to license the submitted work under the following licenses:

@yizhang-yiz yizhang-yiz changed the title Feature/issue #767 dae solver Feature/issue #767 DAE solver Feb 15, 2018
@bob-carpenter
Copy link
Contributor

@yizhang-cae Would you mind updating this to include copyright for Metrum? Thanks.

@yizhang-yiz
Copy link
Contributor Author

Put the line in a wrong spot. Corrected.

@yizhang-yiz yizhang-yiz mentioned this pull request Feb 24, 2018
3 tasks
@yizhang-yiz
Copy link
Contributor Author

I wonder why Jenkins fails to resolve headers. All my gcc and clang builds are fine. Maybe @seantalts can take a look? Thanks.

@seantalts
Copy link
Member

I'm not sure, this looks like a pretty legit error to me (i.e. not a problem with Jenkins). Did you add a new library and not add it to the include path properly or something?

@seantalts
Copy link
Member

I think you're just missing the appropriate includes, like

#include <stan/math/prim/scal/err/check_greater_or_equal.hpp>

@yizhang-yiz
Copy link
Contributor Author

Mmm, I wonder why it didn't break my local build.

@seantalts
Copy link
Member

Are you running the same command Jenkins is, i.e. make test-headers? It's a special invocation that tests that you are including the right things in your files, etc.

@yizhang-yiz
Copy link
Contributor Author

No...didn't know that.

@yizhang-yiz
Copy link
Contributor Author

Upstream tests fail with cmdstan. So I guess I need update cmdstan's makefile at the same time. @seantalts, what's the workflow here?

@syclik
Copy link
Member

syclik commented Feb 28, 2018

The steps are:

  1. create an issue on CmdStan, RStan, and PyStan for adding the includes. This affects all 3.
  2. create a pull request on CmdStan to update the includes.
  3. We'll need to review both together. We'll want to merge math, then CmdStan shortly after.

Just FYI, we'll have to discuss this with the RStan and PyStan maintainers because doing something like this isn't as easy to extend as in CmdStan.

@yizhang-yiz
Copy link
Contributor Author

It figures. In that case we may want to do the sundials merge first(#779).

@syclik
Copy link
Member

syclik commented Feb 28, 2018 via email

@wds15
Copy link
Contributor

wds15 commented Apr 29, 2018

One question: In ODE problems there is usually a stiff and a non-stiff variant. Do we have the same choices with the DAE solver? Or are these problems always stiff?

@yizhang-yiz
Copy link
Contributor Author

yizhang-yiz commented Apr 29, 2018 via email

@syclik
Copy link
Member

syclik commented May 24, 2018

@yizhang-cae, could you work on the merge conflicts? If it's not ready to be reviewed, please close the pull request and reopen when ready.

@yizhang-yiz
Copy link
Contributor Author

yizhang-yiz commented May 24, 2018 via email

@syclik
Copy link
Member

syclik commented May 24, 2018 via email

@yizhang-yiz yizhang-yiz force-pushed the feature/issue-#767-DAE-solver branch from 5da5e21 to 92ef70f Compare May 30, 2018 01:47
@yizhang-yiz
Copy link
Contributor Author

@seantalts , pipeline tests show "unstable". What does it mean?

@seantalts
Copy link
Member

A test failed: http://d1m1s1b1.stat.columbia.edu:8080/blue/organizations/jenkins/Math%20Pipeline/detail/PR-768/19/tests

The parsing of the test failure also failed because the xml file wasn't valid, which makes me suspect multiple mpi processes were executing this test writing to the same file or something. @wds15 any ideas about this one?

@yizhang-yiz
Copy link
Contributor Author

@seantalts, I see only "fail-to-read" of xml. The MPI tests actually are passed.

@seantalts
Copy link
Member

Yep. The XML hasn't been created properly even though the tests pass. I think we need @wds15 to look at it - he did something special to enable some mpi tests to be run multicore and still write valid XMLs (...most of the time).

@wds15
Copy link
Contributor

wds15 commented May 31, 2018

Ok, I will take a look these days.

@wds15
Copy link
Contributor

wds15 commented Jun 3, 2018

this is a bit of mystery as to why it failed... could you please try just again? So restart the testing? Thanks.

@seantalts
Copy link
Member

Restarting! Would also like to keep an eye on these tests to see if they're flaky and fix them if so.

@yizhang-yiz
Copy link
Contributor Author

Thanks @seantalts.
@syclik , I've rebased this one and it passed tests.

@yizhang-yiz
Copy link
Contributor Author

Hi @syclik @bob-carpenter , who would be a proper reviewer for this one?

@yizhang-yiz
Copy link
Contributor Author

@bbbales2 , I've cleaned up according to the reviews. In particular, new DAE model has been added to unit tests. Thanks.

@bbbales2
Copy link
Member

bbbales2 commented Aug 1, 2018

Man every time I come back to these pull requests I am surprised by how long it took me to get around to it... 5 days haha. I gotta work on my turnaround.

Why keep things templated on the types of yy0 and yp0? If we don't have any plans of addressing the consistency thing, that should be removed and these should be doubles always. It's currently unusable for non-trivial reasons. For sustainability, stuff like this needs to stay out of develop.

Also delete code that's not being used (https://github.com/stan-dev/math/pull/768/files#diff-6739115919f8681b87e9bb7e13a5cf16R49). If there's something special about the adjoint DAE systems that needs documented, that should go in an Implement Adjoint DAE issue.

Speaking of adjoint sensitivity stuff, are you interested in doing it for the regular ODEs? I know my buddy @pourzanj has been wanting this stuff (he works with @syclik at Generable). I'd be curious to see it in action as well. A friend of mine is working on a 1D diffusion PDE via method of lines in Stan. The number of states is really big, so the forward sensitivity problem gets big kinda quickly too and I think adjoint sensitivity might help. You're the most qualified person here to do this, though I figure you work more on what Metrum asks of you rather than what me or Arya do :P. I figured I'd ask though.

I'm gonna go ahead and check the memory allocation and docs more closely. I like the tests. This is close to being through.

Copy link
Member

@bbbales2 bbbales2 left a comment

Choose a reason for hiding this comment

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

Here's the latest set of changes. I just traced through a call of integrate_dae and tried to pay close attention to the memory. I read docs when I remembered to. It seems fine, and the code is readable.

const double rtol, const double atol,
const int64_t max_num_steps = idas_integrator::IDAS_MAX_STEPS,
std::ostream* msgs = nullptr) {
const std::vector<int> dummy_eq_id(yy0.size(), 0);
Copy link
Member

Choose a reason for hiding this comment

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

This says every equation is an algebraic equation. Shouldn't this be an argument to the function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't matter. eq_id only works when yy0 is var. But I've added comments to clarify.

* @param[in] theta parameter
* @param[in] x_r real data
* @param[in] x_i int data
* @param[in] rtol relative tolerance passed to IDAS, requred <10^3
Copy link
Member

Choose a reason for hiding this comment

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

<10^-3, though I guess <10^3 is true too haha

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

* @param[in] f functor for the base ordinary differential equation
* @param[in] yy0 initial state
* @param[in] yp0 initial derivative state
* @param[in] t0 initial time.
Copy link
Member

Choose a reason for hiding this comment

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

Rogue period

* given the specified consistent initial state yy0 and yp0.
*
* @tparam DAE type of DAE system
* @tparam Tpar type of parameter theta
Copy link
Member

Choose a reason for hiding this comment

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

scalar type of parameters in theta

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

* @param[in] t0 initial time.
* @param[in] ts times of the desired solutions, in strictly
* increasing order, all greater than the initial time
* @param[in] theta parameter
Copy link
Member

Choose a reason for hiding this comment

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

parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed


/**
* Solve Dae system with forward sensitivty, return a
* vector of var with recomputed gradient as sensitivity value
Copy link
Member

Choose a reason for hiding this comment

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

precomputed

#include <stan/math/rev/scal/meta/is_var.hpp>
#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/rev/mat/functor/idas_forward_system.hpp>
// #include <stan/math/rev/arr/fun/decouple_ode_states.hpp>
Copy link
Member

Choose a reason for hiding this comment

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

Remove this. Also value_of, is_var, return_type, not used. Is algorithm used?

f, eq_id, yy0, yp0, theta, x_r, x_i, msgs};
};

ASSERT_NO_THROW(build_double(eq_id, yy0, yp0, theta, x_r));
Copy link
Member

Choose a reason for hiding this comment

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

Add tests to verify things throw when length(yy0), length(yp0), and length(eq_id) aren't all equal

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added test

"times");
bad_t0 = 0;
bad_ts[0] = -1;
EXPECT_THROW_MSG(solver.integrate(dae, bad_t0, bad_ts), std::domain_error,
Copy link
Member

Choose a reason for hiding this comment

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

Add a test that throws error if ts isn't strictly ordered. So like {0.0, -1.0, 2.0} and {0.0, 0.0, 2.0} should fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added test

namespace math {
/**
* Return the solutions for a semi-explicit DAE system with residual
* specified by functor F,
Copy link
Member

Choose a reason for hiding this comment

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

I think the functor F should be documented at least somewhere, and I think this is the right place. This is what we did for integrate_1d

* f should be compatible with reverse mode autodiff and have the signature:
(rev) and
* The signature for f should be:
(prim)

@bbbales2
Copy link
Member

bbbales2 commented Aug 7, 2018

@yizhang-cae Looks good to me. Thanks Yi! Lemme know when the stan-dev/stan pull is ready. I'll tell my DAE solvin' buddy they're coming soon.

@syclik This touches one line of one makefile in what looks like a very innocuous way. Is the hold still in place for makefile-touching pulls? merge this if that change looks okay to you.

@syclik
Copy link
Member

syclik commented Aug 7, 2018 via email

@syclik
Copy link
Member

syclik commented Aug 7, 2018

I just saw the change to the makefile. If someone makes that change on the branch with the make updates, we can merge this.

@yizhang-yiz yizhang-yiz merged commit 4a13fe1 into stan-dev:develop Aug 7, 2018
@syclik
Copy link
Member

syclik commented Aug 7, 2018

@yizhang-cae, please update this pull request: #956; branch: bugfix/issue-954-make

@yizhang-yiz
Copy link
Contributor Author

@bbbales2 , thank you.

As to adjoint sensitivity, it's on my list but not priority. It's best to do ODE & DAE's adjoint together and I'd like to see DAE go in first. It doesn't hurt to create an issue specifying the problem though.

@yizhang-yiz
Copy link
Contributor Author

@syclik , one sec.

@bbbales2
Copy link
Member

bbbales2 commented Aug 7, 2018

@yizhang-cae I was talking to @bob-carpenter about adjoint vs. forward sensitivity stuff today. He said he was gonna make it a meeting agenda item for Thursday cause he wanted to talk about it some more. So definitely show up this Thursday if you can make it, cause your input will be good.

@ryan-richt
Copy link

Hello All!
My team and I would be super interested in seeing this go in. Could we kindly inquire as to it's current status?

@yizhang-yiz
Copy link
Contributor Author

@ryan-richt I'm close to a PR. I wonder what the DAE dimension your team is working on, perhaps I can use it for unit test or performance test.

@ryan-richt
Copy link

Super exciting @yizhang-yiz ! Sadly we can’t distribute the code of this particular model, but when you have a release candidate we’re happy to run it against your branch and report back metrics and the dimensionality / other meta data if that helps. (It’s pretty big/slow, like seconds per evaluation, so probably more on the perf than unit test side) Thank you again!

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.

9 participants