-
-
Notifications
You must be signed in to change notification settings - Fork 345
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
Improve output handling in zeroD simulations #629
Conversation
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.
The fix in commit 38ab0b1 is unrelated to the pull request, and simply fixes a warning during compilation.
Codecov Report
@@ Coverage Diff @@
## master #629 +/- ##
==========================================
+ Coverage 70.74% 70.78% +0.04%
==========================================
Files 373 373
Lines 43339 43447 +108
==========================================
+ Hits 30660 30754 +94
- Misses 12679 12693 +14
Continue to review full report at Codecov.
|
I incorporated first feedback from #628 and renamed some functions for clarity (plus squashed commits). I can add unit tests once I hear back (edit: rudimentary unit tests are now added). |
c18ba53
to
fe09fcc
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.
I certainly understand the desire for control over the output interval when integrating, and the use of CVODES to extrapolate the solution in order to do so is an intriguing approach. I am a bit concerned about the complexity, however, given that you can get fairly similar control from very a very simple approach such as writing the integration loop as:
tlast = 0
Tlast = 0
while sim.time < 1e-3:
sim.step()
if sim.time > tlast + 1e-5 or abs(Tlast - r.T) > delta_T_max:
tlast = sim.time
Tlast = r.T
states.append(r.thermo.state, t=sim.time*1e3)
print('%10.3e %10.3f %10.3f %14.6e' % (sim.time, r.T,
r.thermo.P, r.thermo.u))
This doesn't do quite the same thing as the advance_towards
method (it results in having output just after either condition is exceeded, rather than just before), but the effect is similar, and I'm not sure that this is any more complicated for the end user than the new set_atol_advance
function introduced here.
One particular concern I have is that adding this would make it difficult for us to change to an alternate integrator instead of CVODES at some point in the future, by locking us into requiring an integrator which has the specific feature of being able to access information about the derivatives.
Perhaps what would make this more compelling would be to provide defaults for the tolerances such that decent performance could be obtained without the user having to do anything except replace step
with advance_towards
.
My skepticism I expressed about this change in the related issue remains. I've been thinking about this, but been swamped with other work lately. I'll try to make some time to collect my thoughts next week. Sorry for the delay! Thanks @speth for poking this back onto my radar. |
@speth ... thank you for the review, but I will wait for @bryanwweber's comments before continuing. To briefly restate my motivation for this PR: I specifically wanted to improve the behaviour of At the moment, there are three options for output handling:
Based on experience, (3) is unfortunately not something that can be expected when teaching an UG combustion class at a generic college, (1) is overkill: some students will use Excel to process data (!), leaving (2) with the stated caveats. Hence my desire to improve upon (2). Regarding the comment about default arguments: it is a reasonable idea. However, would it make sense to merge |
727a333
to
a33c08c
Compare
@speth and @bryanwweber ... at this point I resolved all but one of the requests, but am still hoping to obtain feedback. Following up on my comment from a week ago, i.e.
I defined a new method ix = sim.component_index(r.name, 'temperature') and am still suggesting to merge |
Right, thanks for your patience @ischoegl! My biggest concern with this change as implemented is that now we have yet another way for users to advance time in a simulation. Already, I see many people using I'm also not keen on adding additional optional arguments to the That said, the way I would like to see it work if optional arguments are added to Overall, I'm a soft 👎 on this change right now. If it can be merged with On a related but separate note, I think the same task could be accomplished by adding a |
I want to add some more thoughts to my last comment. I should have started by saying I think this is a valuable idea before launching into my concerns 😄 By "soft" disagreement, I mainly meant that if we could come to consensus that the cognitive overhead for users is offset by the gain in functionality, then I would be on board. My concern is that, as currently implemented, that balance is on the side of too much overhead. However, I had another thought. I think the general idea of the user saying "I want to integrate for x units" where "x" and "units" are described by the user has great utility. I think framing it in terms of limiting the time that the solver advances is somewhat confusing though, and the idea that the So what if the This could be largely the same implementation as is currently here, just presented to the user differently. That said, I would be interested in a comparison with an interpolation method rather than (or in addition to) the current gradient estimation method, i.e. similar to the one done by |
Thanks for your detailed thoughts, @bryanwweber! I believe the suggestion of Regarding One thing that I am interested in is the acceptance for creating an interface for time derivatives computed by CVODE (which my current implementation hinges on). If there is agreement that it is a useful feature to be broken out in the |
Yes, I avoided some of the difficulty in the implementation of the idea as an initial thought 😃
The idea would be that C++ would return (a pointer to) an array, and the separate implementations would decide what to do with that, e.g., Cython could turn that into a
I don't immediately see the utility of a general interface to this beyond the capability that you've shown in this PR, can you provide some other examples? Once we had converged on an idea, I was actually going to suggest removing at least |
In the current implementation, PS: one thing I have been wondering about in a loosely related context is the choice of the Feature Scaling approach in |
OK, so that may have some utility, if a user is interested in dT/dt or d[X]/dt (given the current state vectors).
Right, so how is that useful for a user? Why wouldn't they just have the integrator do the integration?
I'm not sure what you're asking, but the Users' Group is probably a better place for general questions about features (unless you think it should be an Issue on GitHub). I'd like to keep this discussion focused on the features you're proposing. Thanks 😄 |
Alright. I’ll have to think about this for some time: I don’t see a clear path forward and may just limit this PR to get_derivative. Regarding advance_to_steady_state, it really was a rhetorical question, as convergence is poorly defined in the current code. It’s a minor issue not worth raising by itself, but a more rigorous definition could build on an actual time derivative, which is why I brought it up. |
I'm not sure there's a useful, general way to implement automatic collection of integrator states. In C++, there's not an obvious, efficient container, and in Python, SolutionArray would only be useful for a network consisting of a single reactor.
Given the current state of the Matlab toolbox, how difficult adding things is, and how often ideas for improving it involve effectively starting over, I would not insist on this.
That's an interesting thought, and CVODE already provides access to this interpolation via the
While I can see that the computed derivative function does seem to behave reasonably well in your extrapolation method, I think that this polynomial is only meant to apply to the time interval between the last output time and the current time, given the way the BDF method is defined. So, I'm a little concerned about providing a method whose main purpose is to use this data outside the time interval for which it is applicable. |
@speth do you have any thoughts about my concern about adding another user interface method for integration?
I'm not sure I understand what you're saying here. Why is this a concern? |
I didn't have a good idea here either, especially as there is no good data structure candidate in C++ implemented at this point (and I am not even sure whether implementing one makes sense: it definitely goes way beyond the original intent of this PR).
Agreed.
Correct. The derivatives are accurate within the time interval of the last CVODE step, although I am not sure how they are internally calculated. What I used for the current implementation was a Taylor series expansion, with all its well known caveats. Time derivatives are, however, also of interest within other contexts: one would be my comment above about the current |
@bryanwweber This is linked to how CVODE is being called (i.e. with flags |
@speth and @bryanwweber ... I figure that the intent of my original PR was to treat the step size reduction via thresholds (with bounds estimated using a Taylor series expansion). The implementation is straight-forward, and does not bypass CVODE internals. Summarizing my other thoughts from before, I believe the following Cantera interface makes sense:
That way, not reaching the output time will not be a surprise to the user, which is really the main concern that I can see. Otherwise, I do not see a simple solution emerging from this discussion. |
I like this proposal for the interface, using an optional argument to I think I would prefer the While adding the I also agree that having a way of calculating the derivative would be helpful for fixing the flawed implementation of |
This will require some work (and affect more class definitions), but it does make sense.
I will open an issue (#654) |
@speth ... the suggested change to the interface is implemented, together with your request to implement |
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 left a couple of comments.
@bryanwweber and @speth ... I believe I took care of everything, but left the two items that were not trivial open (despite considering both as resolved). Let me know whether there is anything else. |
The last two remaining points are now addressed. |
@speth ... thanks for the review and comments: I believe everything is addressed. Also let me know if I should rebase the PR (afaik, it's not necessary). |
Fixes #628
Changes proposed in this pull request:
CVodesIntegrator
to calculate time derivatives viaCVodeGetDky
ReactorNet
objectReactorNet::advanceTowards
function as an alternative toReactorNet::advance
, which automatically reduces the time advance when excessive state differences are predicted (time advances are successively reduced by2^(-1)
until differences remain within specified limits. Internal cvode time steps remain unaffected).All functions are implemented in C++ and are accessible from the Python interface via cython. The new example
reactor3.py
illustrates differences to the standardReactorNet
examplereactor1.py
.