-
Notifications
You must be signed in to change notification settings - Fork 503
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 methods to automatically apply results to existing Tally objects. #2671
base: develop
Are you sure you want to change the base?
Conversation
02d7f3d
to
1838375
Compare
1838375
to
f72b96f
Compare
f72b96f
to
54c938e
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 like this feature. My one concern is that right now this PR drops coverage.
bc86858
to
5e249a9
Compare
0690457
to
25dd302
Compare
After a good amount of massaging related to the When the I've updated the documentation about the With that, I think I'm pretty happy with the state of this pending further review or something I've missed (impossible); I'll be looking forward to updating tutorials/notebooks to use this feature as I think it will make setup and post-processing in a single script/notebook more intuitive. @MicahGale @paulromano @jtramm I'd be curious to hear your thoughts in particular! |
…ifferent than an explicity specified estimator
…n Tally.__eq__. The default value of None for the `Tally.estimator` attribute allows the C++ code to provide additional warnings/errors if a user explicitly specifies an estimator that is incompatible with the tally filters/scores. When this value is None, no entry appears in the XML inputs and OpenMC is free to choose an appropriate estimator without error.
8466fb4
to
2fb7e3d
Compare
I still need to pull this branch and play around with it a bit. My first inclination for the equality of |
Yeah I agree that an explicit default might be more clear in terms of intention, but I think the equivalence logic would mainly remain the same. We can't really rely on 'tracklength' as the default value because there are restrictions for estimators on certain scores/filters, but the C++ will try to respect an explicitly set estimator on the Line 283 in dcb2557
Explicitly setting tracklength is going to cause a lot of problems in the test suite and a lot of this implicit default is already baked into that in one way or another. I actually tried this out earlier in this PR but it was clear that it's sort of its own mess to untangle if we want to change that behavior. Another option is on the C++ side, the calls to |
Sorry for the delay, yes that makes sense for now. Long term it would be nice it the default were automatically changed as needed, but that's beyond this scope. |
@@ -644,6 +645,11 @@ def run(self, particles=None, threads=None, geometry_debug=False, | |||
to True. | |||
|
|||
.. versionadded:: 0.13.3 | |||
apply_tally_results : bool | |||
Whether or not to apply results of the final statepoint file to the |
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.
@tjlaboss would say:
Whether or not to apply results of the final statepoint file to the | |
Whether to apply results of the final statepoint file to the | |
model's tally objects. |
group = tallies_group[f'tally {tally_id}'] | ||
|
||
# Check if tally is internal and therefore has no data |
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.
This seems to have moved to _populate_tally
, but it doesn't seem like that's always ran. Is that ok that this won't always be ran?
sp_tally = self.get_tally(tally.scores, | ||
tally.filters, | ||
tally.nuclides, | ||
tally.name, | ||
tally.id, | ||
tally.estimator, | ||
exact_filters=True, | ||
exact_nuclides=True, | ||
exact_scores=True, | ||
multiply_density=True, | ||
derivative=tally.derivative) |
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.
This doesn't feel PEP8. With such a long arguments list keyword arguments should be used to avoid off-by-1 errors.
@@ -564,6 +611,12 @@ def get_tally(self, scores=[], filters=[], nuclides=[], | |||
If True, the number of scores in the parameters must be identical | |||
to those in the matching Tally. If False (default), the scores | |||
in the parameters may be a subset of those in the matching Tally. | |||
Default is None (no check). | |||
multiply_density : bool, optional |
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.
This feels more like an enforce_multipl_dens
than a multiply_density
@@ -591,17 +644,25 @@ def get_tally(self, scores=[], filters=[], nuclides=[], | |||
if id and id != test_tally.id: | |||
continue | |||
|
|||
# Determine if Tally has queried estimator |
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.
This is a bit out of scope, but why iterate over self.tallies.values()
? This seems like its a dictionary, and doing it this makes it an O(N^2) operation to find all tallies.
@@ -33,7 +33,7 @@ | |||
_FILTER_CLASSES = (openmc.Filter, openmc.CrossFilter, openmc.AggregateFilter) | |||
|
|||
# Valid types of estimators | |||
ESTIMATOR_TYPES = ['tracklength', 'collision', 'analog'] | |||
ESTIMATOR_TYPES = ('tracklength', 'collision', 'analog') |
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.
Might as well just do a set for slightly better performance.
other_nuclides.remove('total') | ||
if 'total' in self_nuclides: | ||
self_nuclides.remove('total') | ||
if other_nuclides != self_nuclides: |
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.
What dataset is nuclides? Does this require proper sorting? Maybe sets?
self_nuclides.remove('total') | ||
if other_nuclides != self_nuclides: | ||
return False | ||
if other.scores != self.scores: |
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.
A lot of this is repeated code.
Is
for attr_name in {"scores", "triggers"...}:
if getattr(other, attr_name) != getattr(self, attr_name):
return False
too clever?
Description
One thing I've always found a bit clunky when working with our simulation results is the process of extracting user-specified tally results from the statepoint file. It seems to me that finding a match is left to the user, but it should be possible to automate that in the majority of cases.
The idea here is that we can now apply results from our statepoint file to the original tally objects created as inputs to the simulation. This simplifies situations like:
to
or even
Keeping this as a draft for now as I'm kind of workshopping it. But I'll take care of the following dev tasks soon if there aren't any objections to heading this direction.