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

Refactor Axial Expansion #1435

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open

Conversation

albeanth
Copy link
Member

@albeanth albeanth commented Oct 16, 2023

What is the change?

This PR does a fairly large refactor of the axial expansion functionality in ARMI. A new directory is structure is created to enable better traceability with testing and general maintainability.

Original:

armi/reactor/converters/
|-- axialExpansionChanger.py

and unit tests:

armi/reactor/converters/tests
|-- test_axialExpansionChanger.py

New:

armi/reactor/converters/axialExpansion
|
|-- assemblyAxialLinkage.py
|-- axialExpansionChanger.py
|-- expansionData.py

and unit tests

armi/reactor/converters/axialExpansion/tests
|
|-- test_assemblyAxialLinkage.py
|-- test_axialExpansionChanger.py
|-- test_expansionData.py

Notes:

  1. though there are a lot of diffs in the "Files Changed" tab, no new functionality is added.
  2. the original testing file had lots of "integration" tests within it. Those are kept and smaller accompanying unit tests are added here.
  3. to reviewers: if you want me to try and interactive rebase this or split it up into multiple PRs, let me know.

This does include the changes from PR #1427.

Why is the change being made?

  1. The original axialExpansionChanger.py file was responsible for too many things. It was ready to be split up to improve maintainability.
  2. The original test_axialExpansionChanger.py was likewise too big and doing too much. It has now been split up and is easier to maintain.

Checklist

  • This PR has only one purpose or idea.
  • Tests have been added/updated to verify that the new/changed code works.
  • The release notes (location doc/release/0.X.rst) are up-to-date with any important changes.
  • The documentation is still up-to-date in the doc folder.
  • The dependencies are still up-to-date in pyproject.toml.

@john-science john-science added the feature request Smaller user request label Oct 16, 2023
@john-science
Copy link
Member

  1. I think this needs a release note. It's a non-trivial re-write.
  2. How much does the Axial Expansion API change? (For people writing code downstream, does this change the API at all?)

@albeanth
Copy link
Member Author

  1. I think this needs a release note. It's a non-trivial re-write.

Yes. I will add one once we get further into the review.

  1. How much does the Axial Expansion API change? (For people writing code downstream, does this change the API at all?)

The API actually should not have changed at all actually. At least not to that I can remember off the top of my head. I am going to run this on the slough of internal tests though to confirm.

@albeanth
Copy link
Member Author

The API actually should not have changed at all actually. At least not to that I can remember off the top of my head. I am going to run this on the slough of internal tests though to confirm.

The API for unit testing did change. And the refactor changed some imports downstream. So there is an another (minor) downstream PR.

@albeanth
Copy link
Member Author

@john-science @keckler giving a bump on this.

just started doing QA work for the axial expansion changer and it would be really nice to push this through. the improved unit testing and accompanying refactor will help keep things clean imo.

happy to chat offline too.

@john-science
Copy link
Member

Put something on my calendar for this, @albeanth

@albeanth
Copy link
Member Author

albeanth commented Nov 2, 2023

Put something on my calendar for this, @albeanth

I'll put something on your calendar for next week. Some of the downstream testing is freaking out. I have no idea why and don't have enough time to figure it out this week unfortunately...

@albeanth albeanth marked this pull request as draft November 25, 2023 16:12
Co-authored-by: Chris Keckler <kecklerct@gmail.com>
@albeanth
Copy link
Member Author

albeanth commented Jul 8, 2024

@john-science / @keckler / @opotowsky also, if you guys merge this PR while I'm out this week, make sure it is coordinated with other downstream PRs. Otherwise we'll end up with Christmas in July.

# See the License for the specific language governing permissions and
# limitations under the License.

"""Particles! Expand axially!."""
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"""Particles! Expand axially!."""
"""The top-level axial expansion module, and a small set of assembly expansion utilities."""

Comment on lines +26 to +41
a : :py:class:`Assembly <armi.reactor.assemblies.Assembly>`
reference to original assembly; is directly modified/changed during expansion.

linkedBlocks : dict
keys --> :py:class:`Block <armi.reactor.blocks.Block>`

values --> list of axially linked blocks; index 0 = lower linked block; index 1: upper linked block.

see also: self._getLinkedBlocks()

linkedComponents : dict
keys --> :py:class:`Component <armi.reactor.components.component.Component>`

values --> list of axially linked components; index 0 = lower linked component; index 1: upper linked component.

see also: self._getLinkedComponents
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
a : :py:class:`Assembly <armi.reactor.assemblies.Assembly>`
reference to original assembly; is directly modified/changed during expansion.
linkedBlocks : dict
keys --> :py:class:`Block <armi.reactor.blocks.Block>`
values --> list of axially linked blocks; index 0 = lower linked block; index 1: upper linked block.
see also: self._getLinkedBlocks()
linkedComponents : dict
keys --> :py:class:`Component <armi.reactor.components.component.Component>`
values --> list of axially linked components; index 0 = lower linked component; index 1: upper linked component.
see also: self._getLinkedComponents
a : :py:class:`Assembly <armi.reactor.assemblies.Assembly>`
reference to original assembly; is directly modified/changed during expansion.
linkedBlocks : dict
keys --> :py:class:`Block <armi.reactor.blocks.Block>`
values --> list of axially linked blocks; index 0 = lower linked block; index 1: upper linked block.
see also: self._getLinkedBlocks()
linkedComponents : dict
keys --> :py:class:`Component <armi.reactor.components.component.Component>`
values --> list of axially linked components; index 0 = lower linked component; index 1: upper linked component.
see also: self._getLinkedComponents

Copy link
Member

Choose a reason for hiding this comment

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

At your discretion, but for whatever reason, I found this hard to read with all the whitespace.

and isinstance(componentA, type(componentB))
and (componentA.getDimension("mult") == componentB.getDimension("mult"))
):
if isinstance(componentA, UnshapedComponent):
Copy link
Member

Choose a reason for hiding this comment

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

What about NullComponent?

"""
blkLst = self.linked.a.getBlocks()
if not blkLst[-1].hasFlags(Flags.DUMMY):
runLog.warning(
Copy link
Member

Choose a reason for hiding this comment

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

Do we have a unit test that covers the warnings and errors in this method?

(The primary cause of code coverage being low in ARMI right now is people adding a near infinite number of warnings, but not testing them. In the future, I am wondering if all need warnings and exceptions should be covered by tests. Though I haven't made that rule yet, obviously.)

Copy link
Member Author

Choose a reason for hiding this comment

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

These should have testing, yes. I made a concerted effort a year or two ago to make sure that each of these had coverage and that axial expansion had 100% testing coverage. It should be the same...!

Comment on lines +290 to +295
runLog.debug(
"Printing component expansion information (growth percentage and 'target component')"
f"for each block in assembly {self.linked.a}."
)
for ib, b in enumerate(self.linked.a):
runLog.debug(msg=f" Block {b}")
Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, do you think anyone but you will ever want to see these debug lines?

My concern is that they look like something you added because they were useful to you developing axial expansion?


class AxialExpansionChanger:
"""
Axially expand or contract assemblies or an entire core.
Copy link
Member

Choose a reason for hiding this comment

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

It appears to me (tell me if I'm wrong!) that axial expansion only works on a pin-type (assembly-type) reactor.

Assuming that's true, I think this might be something more like:

Axially expand or contract assemblies or an entire core of assemblies.

But more so, I wonder if there is another high-level place or two we should call out that this feature only works on assemblies. Thoughts?

return b


def buildDummySodium(hotTemp: float, height: float):
Copy link
Member

Choose a reason for hiding this comment

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

For some reason, this name seems too short to me. Maybe add "Block"?

buildDummySodiumBlock

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if it's documented somewhere, but maybe explaining the significance of a DUMMY name would be valuable as a test with the flag system. Essentially you might want a test that demonstrates this method is returning the expected thing if not already checked by itself in a test just in case this flag gets broken later by accident.

Comment on lines +28 to +31
"""Runs through AssemblyAxialLinkage::_determineAxialLinkage() and does full linkage.

The individual methods, _getLinkedBlocks, _getLinkedComponents, and _determineLinked are then
tested in individual tests by asserting that the linkage is as expected.
Copy link
Member

Choose a reason for hiding this comment

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

Just trying to fix the RST / Sphinx formatting.

albeanth and others added 2 commits July 8, 2024 19:26
Co-authored-by: John Stilley <1831479+john-science@users.noreply.github.com>
Co-authored-by: John Stilley <1831479+john-science@users.noreply.github.com>
@jakehader
Copy link
Member

jakehader commented Jul 9, 2024

@albeanth - I'm curious if you've tried different ways to use the axial expansion code in an unintended way, like calling methods out of order or with different, unexpected block types or geometries. Essentially, I'm wondering if there are sufficient checks on the Assembly design (e.g., hex, Cartesian, RZ, etc.) to guard against excepted behavior. If so, would you be able to point out some of those unit tests or if not, could you add some? For example, what about an assembly with custom ISO topics as the materials? What about homogeneous blocks with no components?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Smaller user request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants