-
-
Notifications
You must be signed in to change notification settings - Fork 349
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
Adding adaptive preconditioner functionality to Cantera #1010
Conversation
@bryanwweber and @ischoegl, I have updated the pull request to be from my "ap-dev" branch. I will use this in the future. |
Tagging #951. |
Codecov Report
@@ Coverage Diff @@
## main #1010 +/- ##
==========================================
+ Coverage 67.93% 68.01% +0.08%
==========================================
Files 316 327 +11
Lines 41948 42603 +655
Branches 16853 17143 +290
==========================================
+ Hits 28498 28978 +480
- Misses 11186 11345 +159
- Partials 2264 2280 +16
📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more |
@anthony-walker ... thanks for adding the tests. As a quick heads-up, please avoid |
65924db
to
2d77873
Compare
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.
@anthony-walker, thanks for the work on this. I think a lot of people are looking forward to this feature. I have some (hopefully helpful) questions about the mathematical / algorithmic issues and suggestions about coding style.
First, as a point of clarification, at the end of AdaptivePreconditioner::setup
, it looks like the m_matrix
variable is meant to represent the Jacobian. Is this correct? Assuming that it is, I tried printing out the Jacobian for the initial timestep of the Python test problem, and what I saw didn't make a lot of sense. For instance, there are a lot of zeros on the diagonal, entire rows of zeros, and every value is positive. Just as a general sanity check, I would expect the diagonal elements to all be negative (except for a species with no reactions), and the matrix to have a mix of positive and negative values. I tried comparing this Jacobian to a simple finite difference approximation for just the species equation, and saw basically no correspondence.
Also, I don't see anywhere where the preconditioner matrix P = I - gamma * J gets formed. Are you just using the Jacobian directly as the preconditioner? There are places where the two seem to be conflated in the code, but the Jacobian itself presumably isn't what you want to use as the preconditioner.
As a more minor point, I see that the factorization step is being done as part of the "AdaptivePreconditioner::solve" function. To improve performance, the usual strategy is to factorize the preconditioner as part of the "setup" function, so that the repeated calls to "solve" can re-use the LU factors and solving is just a matter of backsubstitution. Later, once this is all working, you might also want to use one of the "incomplete" LU factorization algorithms that Eigen as a way of speeding things up even more, since the preconditioner doesn't need to be exact.
I also had a couple of suggestions on coding style and structure, which will hopefully make the code easier to read, review, and maintain:
- There's a lot of manual memory management going on, which I think should be avoided. This means using
std::vector
instead ofnew[]
,std::unique_ptr
orstd::shared_ptr
in other cases where you can't allocate an object on the stack. Basically, you want to avoid ever having to directly usedelete
. - Inside a member function, it is almost never necessary to prefix access to a member function or variable with
this->
. - Please take a look at some of the other source code, e.g.
Reactor.cpp
for typical style and try to write your code to be consistent with this. Take a look at things like indentation (4 spaces, but none for the initialnamespace
declaration); spacing and placement of brackets inif / else
blocks,for
loops, etc.; spacing around operators (one on each side of+
,=
and others).
ca2294a
to
37ccaf5
Compare
8666869
to
9f28061
Compare
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.
@anthony-walker ... great to see this moving along. I have one (tangential) comment at the moment.
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.
Another question.
866016c
to
cfd6b43
Compare
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.
Thanks for making the previous round of updates, @anthony-walker. I think this is looking pretty good from a structural standpoint. Most (though not all) of the issues I've commented on here are just formatting and documentation concerns.
394bc7f
to
71fdb1c
Compare
interfaces/cython/cantera/examples/reactors/preconditioned_integration.py
Outdated
Show resolved
Hide resolved
Adds PreconditionerBase and derives AdaptivePreconditioner from this base class. PreconditionerBase is intended to be an abstract class so other types of preconditioners can be extended. AdaptivePreconditioner is a specific type of preconditioning based on a tolerance. The preconditioned integrator works with all Sundials versions supported by Cantera. The ILUT algorithm is used to limit fill-in when factorizing the preconditioner. Adds access to CVODES integrator statistics in C++ and Python Adds reactor classes "IdealGasConstPressureMoleReactor" and "IdealGasMoleReactor" that use a mole-based state vector to increase the sparsity of the preconditioner.
@anthony-walker - Thanks for the updates. I think this has reached a state where it's ready to be merged, even though there are a few things that need to be done to improve robustness. I just pushed to your branch to squash some of the commits together because there was a lot of churn related to the several times that this PR has been rebased, and the intermediate commits had become impossible to even compile. @ischoegl - This is awaiting your approval before I can merge it. |
@speth I agree that it could still use some work to improve robustness. I think said work will be better suited to smaller pull requests now that the core functionality is present. |
@anthony-walker ... could you add what is left to do to Cantera/enhancements#47 (or whatever is most appropriate) so we have a road map for remaining work? |
@ischoegl yes I will update the most appropriate enhancement. |
- Adds a check for surfaces - adds updateState and updatePreconditioner in proper locations - Fixes documentation and makes other formatting changes - Adds utilities tests and expected failures tests for the preconditioner
@speth is there anything else that needs done before this is merged? |
@anthony-walker - Just the requested update to Cantera/enhancements#47. |
This code is adding preconditioning capabilities to Cantera/CVODEs solver interface for reactor networks. It is focused on a specific type of preconditioning but the code is being written with extensibility in mind. It adds Preconditioning capabilities to the numerics portion of cantera which contains a "PreconditionerBase" that is used to write future preconditioners. It also contains a class derived from this called "AdaptivePreconditioner" which is the aforementioned specific preconditioner.
There are also a couple of functions added to specific reactors. IdealGasReactor is one example. Currently, I added a function to evaluate the energy equation which is also done inside of evalEqs but I wanted to avoid touching core Cantera code as much as possible. In the future, I would like to collaborate with the appropriate people to stream line this.
Checklist
scons build
&scons test
) and unit tests address code coverage