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 armi.reactor.grids to wider submodule; Grids as ABC #1373

Conversation

drewj-usnctech
Copy link
Contributor

What is the change?

Mainly two changes here, one largely invisible to users/developers, one maybe controversial (in a312849)

Refactor

Refactoring armi/reactor/grids.py into "wider" submodule armi.reactor.grids. Dedicated files for specific grid types, e.g., armi.reactor.grids.hexagonal provides HexGrid. All classes and utilities are imported into armi/reactor/grids/__init__.py so there should be no API-breaking changes up to a312849.

I tried to keep the commits small so you could see the process was essentially

  • git mv armi/reactor/grids.py armi/reactor/grids/__init__.py
  • copy some class from armi/reactor/grids/__init__.py to new file armi/reactor/grids/class.py
  • reimport class from armi/reactor/grids/class.py into armi/reactor/grids/__init__.py so there are no API changes

In this process, I also added an AxialGrid class, the return type from the (proposed deprecated) armi.reactor.grids.axialUnitGrid function.

Abstraction

Introduced in a312849

Heavier lift, but the classes defined in armi.reactor.gridsfollow this inheritance pattern

  • Grid(abc.ABC) :: abstract interface for a grid, or things that reside in
    space
    • StructuredGrid(Grid) :: still abstract, but for things that have
      some structure, known to ARMI as unit steps and bounds
      • HexGrid(StructuredGrid)
      • CartesianGrid(StructuredGrid)
      • ThetaRZGrid(StructuredGrid) - though how "structured" is this
        really?
      • AxialGrid(StructuredGrid)

In some cases, the shared interface between structured grids falls
apart. For example, HexGrid.pitch returns a single float, while
CartesianGrid.pitch is a 2-ple of float, one for x and one for y.
And the concept of ring and position appears to be stressed since the
inception of cartesian grids. But parts of ARMI require an interface
and so an attempt was made to define that interface.

The decision was made to not have StructuredGrid the base class, and
to introduce Grid as the base intentionally. There are cases for some
multiphysics codes where a grid may still be "structured" but not with
the level of structure the previous Grid implementations expect. One
example would be an irregular cartesian grid, where the unit cell
spacing in one or more dimensions may change. So the cell spacing is a
function of the cell position in that dimension.

This is more a breaking change because classes that used to inherit from armi.reactor.grids.Grid may not have the same unit stepping / bounds behavior they would get instead by subclassing the new armi.reactor.grids.StructuredGrid

Why is the change being made?

Primary motivation is #1278 : fixing orientation of tips up hex grids. My proposed plan, introduced in this comment is to have HexGrid be "orientation agnostic" and instead provide two subclasses, e.g., FlatsUpHexGrid and TipsUpHexGrid.

Looking through the code, it seems the spatial locators attached to these components have correct (i, j) indices. But the problem falls through HexGrid.getRingPos as that seems (after minor investigation) to assume a flats-up orientation.

Looking through more of the HexGrid implementation, making HexGrid.getRingPos more aware of the orientation seems to be the tip of the iceberg. It seems like multiple methods make this assumption

This also helps clients understand more simply the hex grid orientation, something that isn't really feasible now (see this comment)

Checklist

  • This PR has only one purpose or idea.
    • maybe 1.5 ideas? it's a refactor, but like a refactor+
  • 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.
    • TBD depending on acceptance of ABC grid. Otherwise it's relatively transparent from an API perspective
  • The documentation is still up-to-date in the doc folder.
  • The dependencies are still up-to-date in setup.py.

Goal is to introduce separate files for each grid type, but still
make those importable from armi.reactor.grids
Intended to share some constants and type hints across the
`armi.reactor.grids` submodule. Intentionally sparse.

Items will be imported into `armi.reactor.grids` to help with
back compatibility.
Provides abstract `LocationBase` as the interface defining base class.
Concrete subclasses `IndexLocation`, `MultiIndexLocation`, and
`CoordinateLocation` are also defined.

There is little to no implementation differences in this change. Only
that `LocationBase` is a proper abstract base class, so subclasses that
don't override the necessary abstract methods will need to change. Some
other key changes

- `LocationBase.__eq__` returns `NotImplemented` if the RHS argument
  is not a tuple nor a `LocationBase`

The four main classes defined are imported into `armi.reactor.grids`
to maintain back compatibility.
Imported into `armi.reactor.grids` so still back compatible
Heavier lift, but the classes defined in `armi.reactor.grids`
follow this inheritance pattern

- `Grid(abc.ABC)` :: abstract interface for _a_ grid, or things that reside in
  space
  - `StructuredGrid(Grid)` :: still abstract, but for things that have
    some structure, known to ARMI as unit steps and bounds
    - `HexGrid(StructuredGrid)`
    - `CartesianGrid(StructuredGrid)
    - `ThetaRZGrid(StructuredGrid)` - though how "structured" is this
      really?
    - `AxialGrid(StructuredGrid)`

In some cases, the shared interface between structured grids falls
apart. For example, `HexGrid.pitch` returns a single float, while
`CartesianGrid.pitch` is a 2-ple of float, one for x and one for y.
And the concept of ring and position appears to be stressed since the
inception of cartesian grids. But parts of ARMI require an interface
and so an attempt was made to define that interface.

The decision was made to not have `StructuredGrid` the base class, and
to introduce `Grid` as the base intentionally. There are cases for some
multiphysics codes where a grid may still be "structured" but not with
the level of structure the previous `Grid` implementations expect. One
example would be an irregular cartesian grid, where the unit cell
spacing in one or more dimensions may change. So the cell spacing is a
function of the cell position in that dimension.
@drewj-usnctech
Copy link
Contributor Author

ping @keckler @john-science @ntouran for insight / review. This is a first step in closing #1278

@john-science john-science added architecture Issues related to big picture system architecture cleanup Code/comment cleanup: Low Priority labels Aug 23, 2023
@john-science
Copy link
Member

@drewj-usnctech Awesome! I love it. I have a couple of little cleanup things above, then we can merge this.

…id-refactor-pre-1278

* terrapower/main:
  Move max assembly number out of global scope (terrapower#1383)
  Ensuring we throw an error on bad YAML files (terrapower#1358)
  Removing unused settings (terrapower#1393)
  Fixing some miscellaneous TODOs (terrapower#1392)
  Removing global plugin flags (terrapower#1388)
  Update reactivity coefficient parameters (terrapower#1355)
  Fixing ruff formatting of doc gallery examples (terrapower#1389)
  Fixing broken link (terrapower#1390)
  Removing unreachable code block (terrapower#1391)
  Removing unnecessary f-strings (terrapower#1387)
  Updating documentation dependencies for Python 3.11 (terrapower#1378)
  Adding a little code coverage to the CLIs (terrapower#1371)
  Remove coveragepy-lcov dependency during CI. (terrapower#1382)
  Reconnect logger after disconnecting in test. (terrapower#1381)
  Add Python 3.11 to GH Actions (terrapower#1341)
  Removing global variable from runLog.py (terrapower#1370)
  Moving the First-Time Contributors guide to the docs (terrapower#1368)
@drewj-usnctech
Copy link
Contributor Author

Some weird pip behavior that feels like a github / docker / larger issue?

 .pkg: _exit> python /opt/hostedtoolcache/Python/3.11.4/x64/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
  cov2: FAIL code 1 (1221.10=setup[62.95]+cmd[1158.15] seconds)

@john-science
Copy link
Member

Some weird pip behavior that feels like a github / docker / larger issue?

 .pkg: _exit> python /opt/hostedtoolcache/Python/3.11.4/x64/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
  cov2: FAIL code 1 (1221.10=setup[62.95]+cmd[1158.15] seconds)

@opotowsky Is this a Python 3.11 issue?

@opotowsky
Copy link
Member

Some weird pip behavior that feels like a github / docker / larger issue?

 .pkg: _exit> python /opt/hostedtoolcache/Python/3.11.4/x64/lib/python3.11/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
  cov2: FAIL code 1 (1221.10=setup[62.95]+cmd[1158.15] seconds)

@opotowsky Is this a Python 3.11 issue?

I'm seeing an actual failure, actually

But why in only python 3.11?

image

@john-science
Copy link
Member

john-science commented Aug 24, 2023

@drewj-usnctech OR this might not be Python 3.11, this might just be a plain unit test failure:

https://github.com/terrapower/armi/actions/runs/5965597782/job/16183385153?pr=1373

  File "/home/runner/work/armi/armi/armi/reactor/grids/tests/test_grids.py", line 216, in test_ringPosFromIndicesIncorrect
    grid = grids.Grid(unitSteps=((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Can't instantiate abstract class Grid with abstract methods __len__, backUp, getCellBase, getCellTop, getCoordinates, getSymmetricEquivalents, isAxialOnly, items, locatorInDomain, overlapsWhichSymmetryLine, reduce, restoreBackup

MAYBE this is a problem by in Python 3.11 they are more hard-enforcing that you must fully implement all abstract methods in an abstract class now? And it was more soft "maybe" before?

I bet it's something like that. Though the test did fail. I don't see any changes to abc in the release notes.

@opotowsky
Copy link
Member

oh! the other tests were cancelled! prob not a py 311 problem, phew!

@drewj-usnctech
Copy link
Contributor Author

Nope that's on me. I just missed that grids.Grid in the tests 🤦

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.

I love a good refactor!

@john-science john-science merged commit 5e76197 into terrapower:main Aug 25, 2023
10 checks passed
@drewj-usnctech drewj-usnctech deleted the drewj-usnctech/grid-refactor-pre-1278 branch August 25, 2023 19:39
@john-science
Copy link
Member

@drewj-usnctech It looks like the problem above that broke the unit tests also broke the docs:

/home/runner/work/armi/armi/doc/gallery-src/framework/run_grids2_cartesian.py failed leaving traceback:
Traceback (most recent call last):
  File "/home/runner/work/armi/armi/doc/gallery-src/framework/run_grids2_cartesian.py", line 34, in <module>
    cartesian_grid = grids.Grid(
TypeError: Can't instantiate abstract class Grid with abstract methods __len__, backUp, getCellBase, getCellTop, getCoordinates, getSymmetricEquivalents, isAxialOnly, items, locatorInDomain, overlapsWhichSymmetryLine, reduce, restoreBackup

CI is currently broken in ARMI.

drewj-usnctech added a commit to drewj-usnctech/armi that referenced this pull request Sep 6, 2023
…t-mod-empty-validation

* terrapower/main: (23 commits)
  Allowing users to set powerDensity instead of power (terrapower#1395)
  Fix assemNum parameter for uniform mesh reactor. (terrapower#1398)
  Update to black v22.6.0 (terrapower#1396)
  Fixing gallery example for new working Grids (terrapower#1394)
  Refactor armi.reactor.grids to wider submodule; Grids as ABC (terrapower#1373)
  Make SFP a child of reactor. (terrapower#1349)
  Move max assembly number out of global scope (terrapower#1383)
  Ensuring we throw an error on bad YAML files (terrapower#1358)
  Removing unused settings (terrapower#1393)
  Fixing some miscellaneous TODOs (terrapower#1392)
  Removing global plugin flags (terrapower#1388)
  Update reactivity coefficient parameters (terrapower#1355)
  Fixing ruff formatting of doc gallery examples (terrapower#1389)
  Fixing broken link (terrapower#1390)
  Removing unreachable code block (terrapower#1391)
  Removing unnecessary f-strings (terrapower#1387)
  Updating documentation dependencies for Python 3.11 (terrapower#1378)
  Adding a little code coverage to the CLIs (terrapower#1371)
  Remove coveragepy-lcov dependency during CI. (terrapower#1382)
  Reconnect logger after disconnecting in test. (terrapower#1381)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture Issues related to big picture system architecture cleanup Code/comment cleanup: Low Priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants