-
-
Notifications
You must be signed in to change notification settings - Fork 350
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
Extensible rate: unit handling, serialization, and validation #1478
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1478 +/- ##
==========================================
+ Coverage 70.06% 70.14% +0.08%
==========================================
Files 377 377
Lines 57789 58001 +212
Branches 19410 19422 +12
==========================================
+ Hits 40489 40687 +198
- Misses 14740 14752 +12
- Partials 2560 2562 +2
... and 2 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
2c05b1a
to
659df28
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.
@speth … changes look good to me; while I did spend a fair amount of time figuring out units when I refactored the rate calculators, your simplifications make sense to me. Good to see the fixes also: for falloff reactions, I was mainly concerned about getting the final units right and making sure that everything matched the CTI implementation; regarding sticking coefficients, they weren’t meant to have units, but I may have adopted/duplicated infrastructure that brought them in the back door.
My main observation in this PR is about the broadening units interface in Python. It is apparent that extensible objects make exposing C++ units a requirement (some bare bones units functionality I had put in place before was merely a narrow interface that allowed for testing). At this point some potential overlaps with pint
capabilities start to appear. While the motivations for these unit system interfaces are certainly different, I am wondering about where this would lead eventually? I don’t have a satisfactory answer to this myself at the moment …
PS: from a technical viewpoint, it makes little to no sense to run things through pint
for what is proposed here. So my main question is about how the unit handling approaches are differentiated from the user-facing perspective.
interfaces/cython/cantera/_utils.pyx
Outdated
@@ -151,8 +153,75 @@ cdef comp_map_to_dict(Composition m): | |||
class CanteraError(RuntimeError): | |||
pass | |||
|
|||
DimensionalValue = namedtuple('DimensionalValue', |
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.
Looks like there is starting to be overlap with what pint
can do. I am personally on the fence about where this can/should go, so this is mostly an observation at this point.
|
||
cdef class AnyMap(dict): | ||
""" | ||
A key-value store representing objects defined in Cantera's YAML input format. |
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.
See above. We potentially have the option to use pint
here, instead of grafting it on at a later point?
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.
Apart from the questions I had in my comment, the changes themselves look good to me.
Previously, accessing an ExtensibleRate object from a Reaction object would create a new wrapper object rather than providing access to the "original" object that is used by the ReactionRateDelegator, and this wrapper object would not behave the same as the original object except for methods that passed through via the Delegator. Now, we return the underlying object, ensuring consistency. This requires more complex memory management because the ExtensibleRate/Delegator pair form a reference cycle that can be attached to other objects either from the C++ or the Python side.
Handling this centrally simplifies the implementation of user-defined rate functions
The forward rate constants for falloff and chemically activated reactions already incorporate the third-body dependency, so the units should only reflect the explicit reactants. This was being compensated for when setting the units of the high/low pressure rate expressions, so it did not affect any results.
These differ specifically in the case of sticking reactions, where the rate coefficient has units like m^3/kmol/s, depending on the reactant orders while the sticking coefficient itself is dimensionless.
659df28
to
dffa5cb
Compare
You're right that there is some significant overlap in what pint can be configured to do and what the C++ I think that even if we eventually expand the use of units as in #991 and that becomes a popular way to use Cantera, I'd still expect to retain a lower-level interface that worked in plain mks+kmol values, and you'd probably always want to use that interface for things like I updated the PR to (a) hide the |
Changes proposed in this pull request
AnyMap
units in PythonExtensibleRate.get_parameters
to enable serialization of user-defined rate typesExtensibleRate.validate
to enable validation checks for user-defined typesReaction.rate_units
If applicable, fill in the issue number this pull request is fixing
Contributes to implementing Cantera/enhancements#79
If applicable, provide an example illustrating new features this pull request is introducing
From the
custom_reactions.py
example:Checklist
scons build
&scons test
) and unit tests address code coverage