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

Improving efficiency of reaction rate calcs #1887

Merged
merged 49 commits into from
Oct 24, 2024
Merged

Improving efficiency of reaction rate calcs #1887

merged 49 commits into from
Oct 24, 2024

Conversation

mgjarrett
Copy link
Contributor

@mgjarrett mgjarrett commented Sep 16, 2024

What is the change?

Improve the efficiency of reaction rate calculations.

Why is the change being made?

A common post-processing step for a GlobalFluxInterface is to compute reaction rates from the flux solution and the microscopic cross sections that exist on the reactor model. The implementation of this calculation is done in a straightforward way, but it is naive with-respect-to the typical data structure in an ARMI simulation. The efficiency for typical problems can be greatly improved by refactoring the loops so that the outermost loop is over cross section type.

Often, there are thousands of blocks in a reactor model but only a handful of unique microscopic cross section types; each set of microscopic cross sections might be shared across several hundred blocks. An outer iteration over cross section types with an inner iteration over blocks can significantly reduce the number of times a microscopic cross section set needs to be retrieved.


Checklist

  • The release notes have been updated if necessary.
  • The documentation is still up-to-date in the doc folder.
  • The dependencies are still up-to-date in pyproject.toml.

@mgjarrett mgjarrett marked this pull request as draft September 16, 2024 17:19
@keckler keckler self-requested a review October 17, 2024 20:48
Copy link
Member

@keckler keckler left a comment

Choose a reason for hiding this comment

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

I think the PR probably does what you want it to do, but just added some suggestions to maybe make things more clear.

armi/reactor/converters/uniformMesh.py Outdated Show resolved Hide resolved
armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
Comment on lines 1350 to 1353
try:
mgFlux = np.array(obj.getMgFlux())
except TypeError:
continue
Copy link
Member

Choose a reason for hiding this comment

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

Should we allow for this function to silently continue if an object without flux is passed in? The explicit purpose of this function is to calculate reaction rates, so passing an object without flux is just a fundamentally wrong premise.

A hard error feels appropriate to me here, unless there is a common case that I am not aware of.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is more copy/paste:

image

Based on the comment, it seems like the thinking goes that if an object without flux is passed in, you can just skip calculating the reaction rates on that object. You don't have to crash the whole run.

Copy link
Member

Choose a reason for hiding this comment

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

I guess I understand what is happening, but it feels outside of the purview of this method to not fail in this scenario. If I pass a block into a method called calcReactionRates() and it can't calculate the reaction rates, I would expect that method to fail, or at least tell me that it can't do it.

Just skipping feels like an error trap, to me. This is getting a bit outside the scope of your PR, because like you said you just copy/pasted. But maybe an opportunity for improvement in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know whether we're ever actually hitting this exception. It might be good to remove it if possible, but that could probably be a separate PR where it is also removed from the original function I copied it out of.

armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
armi/physics/neutronics/globalFlux/globalFluxInterface.py Outdated Show resolved Hide resolved
armi/reactor/converters/uniformMesh.py Outdated Show resolved Hide resolved
Comment on lines +1208 to +1210
for nucName, numberDensity in numberDensities.items():
if numberDensity == 0.0:
continue
Copy link
Member

Choose a reason for hiding this comment

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

Instead of looping over numberDensities and then checking that the number density is non-zero, would it make more sense to loop over the nuclides in xsNucDict? You've already done work to screen out isotopes with zero number density from there, so the number of isotopes in there is less and you don't have to do any further checking for zero values.

I might be misinterpreting this, I'm finding the logic somewhat complex.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

xsNucDict will have an entry for any nuclide that exists at a non-zero number density in any blockin theblockList`.

This line is checking whether the nuclide has a nonzero density in a particular block or other object.

Copy link
Member

Choose a reason for hiding this comment

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

True, maybe the check cannot be removed. But I still think that looping over the other list might make more sense, no? xsNucDict is shorter without loss of needed information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

xsNucDict is not necessarily shorter than obj.getNumberDensities(). You could have a list of 500 blocks where 495 of them have 3 nuclides and 5 of them have 400 nuclides, and xsNucDict would have 400 nuclides. This is obviously an extreme situation that I've devised here that isn't realistic, but it's just hard to say that one of these lists is always going to be shorter than the other one.

If you refactored, it would be something like:

for nucName in xsNucDict:
    numberDensity = numberDensities.get(nucName, 0.0)
    if numberDensity == 0.0:
        continue

I think since you always have to get the dict value from numberDensities, it makes sense to iterate over numberDensities.items() instead of iterating over the keys and then doing numberDensities.get(key, 0.0). In general, in a group of blocks, if any of the blocks have a non-zero number density for a given nucName, then you'd have to iterate through that nuclide for every block and run numberDensities.get(nucName, 0.0) to check if that nuclide is there.

Copy link
Member

@keckler keckler left a comment

Choose a reason for hiding this comment

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

With those last couple comments, make any changes if you so desire. But I am good to approve this as-is. Thank you for this work, it will be a big improvement!

@john-science john-science marked this pull request as ready for review October 24, 2024 13:58
@john-science john-science changed the title Improve efficiency of reaction rate calculations Improving efficiency of reaction rate calcs Oct 24, 2024
Copy link
Member

@john-science john-science left a comment

Choose a reason for hiding this comment

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

Approved, barring one change.

@john-science john-science merged commit 7b595f0 into main Oct 24, 2024
19 checks passed
@john-science john-science deleted the calcRR_speedup branch October 24, 2024 15:49
drewj-tp added a commit that referenced this pull request Oct 24, 2024
…xial-linkage

* origin/main:
  Adding some missing nuclides to nuclides.dat (#1903)
  Improving efficiency of reaction rate calcs (#1887)
  Adding description of EOL time node in DB (#1967)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants