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

Adding support for ex-core structures #1891

Merged
merged 51 commits into from
Oct 7, 2024
Merged

Adding support for ex-core structures #1891

merged 51 commits into from
Oct 7, 2024

Conversation

john-science
Copy link
Member

@john-science john-science commented Sep 17, 2024

What is the change?

Added initial support for ex-core structures in ARMI.

  • Blueprints can now easily define ex-core structures on their own grids.
  • The old SpentFuelPool logic was rolled into the new ExcoreStructure class.
  • The old AssemblyList class was removed.
  • Reporting tools were updated to match.
  • Docs were updated to match.

The ARMI Reactor class used to have two children that were also attributes: r.core and r.sfp. Now it has two children that are also attributes: r.core and r.excore. And r.excore is currently a dictionary where keys map to an arbitrary set of ex-core objects:

  • r.excore["sfp"]
  • r.excore["ivs"]
  • r.excore["evst1"]

But, for convivence, you can also access these like attributes:

  • r.excore.sfp
  • r.excore.ivs
  • r.excore.evst1

Why is the change being made?

Thus far, ARMI has really only provided a data object model for the Reactor core (and also a default spent fuel pool). The large teams that model and analyze nuclear reactors will also want to model ex-core structures for fuel handling and mechanical analysis reasons.


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.

@john-science john-science added the feature request Smaller user request label Sep 17, 2024
@alexhjames
Copy link
Contributor

I think I was going along the lines of more general would be more flexible. If you have a crazy reactor setup with two cores, then you would be forced into modeling one core as the core and one as excore.core2. Or similarly, if someone wanted to run analysis on the spent fuel pool like it was a reactor to verify things, then they could... Seems like it's on the plugins to know what container to look at and run analysis on.

@john-science
Copy link
Member Author

Sure, we could do something more like this:

class Recctor:
    # ...

    def __getattr__(self, key):                                                                                                                                                                                    
        try:                                                                                                                                                                                                       
            return self.__dict__[key]                                                                                                                                                                              
        except KeyError:                                                                                                                                                                                           
            if key in self.excore:                                                                                                                                                                                      
                return self.excore[key]                                                                                                                                                                                 
            else:                                                                                                                                                                                                  
                raise                                                                                                                                                                                              
                                                                                                                                                                                                                   
    def __setattr__(self, key, value):                                                                                                                                                                             
        try:                                                                                                                                                                                                       
            self.__dict__[key] = value                                                                                                                                                                             
        except KeyError:                                                                                                                                                                                           
            if key in self.excore:                                                                                                                                                                                      
                self.excore[key] = value                                                                                                                                                                                
            else:                                                                                                                                                                                                  
                raise   

This allows r.sfp and r.evst1, if that's just super important to everyone.

Though I still think r.excore.sfp and r.excore.evst is more clear.

@drewj-tp
Copy link
Contributor

Want to clarify that I am not likely going to be an immediate user nor stakeholder of this feature so take my suggestion w/ a grain of salt. Not a requirement

@john-science
Copy link
Member Author

@drewj-tp @jakehader @alexhjames

I guess encapsulation is my goal here:

r.core - core physical object
r.excore - ex-core physical object
r.o - operator
r.id - number
r.p - parameter collection
r.cached - tooling
r.spatialGrid - tooling
r.factory - method
r.add - method
r.isFuel - method
r.backUp - method

I mean, I can make r.sfp a thing, and r.ivs, but it will mean a metric TON of error checking to make sure people don't name their excore structures id or p or o or cached or factory, because that would break the Reactor class.

And I'll have to check that no one tries to over-write the method r.factory() by doing r.factory = ExcoreStructure().

Or, in code you could set r.ivs = ExcoreStructure() , but I need to make sure you don't do r.o = ExcoreStructure().

There would just be so much error checking where I need to list every single time anyone adds or touches any method or attribute on a Reactor object. I would have to keep a full list of all attributes and methods in Reactor and it's parents Composite and ArmiObject.

@keckler
Copy link
Member

keckler commented Sep 26, 2024

There is at least one place in our benchmarks that will need to be migrated due to this change. We used to allow r.sfp, but now it is r.excore["sfp"].

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.

First off, thank you for all of this effort. This is definitely a step in the right direction. A few comments beyond those left in the code:

  1. This implementation seems to assume that any ex-core thing will be grid-like. But probably there are only so many things that might actually be like that, and something more flexible might be needed in the future. This is not a problem for this PR, more so a seed for future work.
  2. There are a lot of places where we do a check to make sure that an SFP exists. But as noted by one of the comments that you added, ARMI right now is adding an SFP by default. So maybe those checks are unnecessary?
  3. I support the decision to stash everything under r.excore instead of making them attributes on r directly. I think this makes sense. One comment that Alex brought up is about the possibility of having two Cores, and then one of them would have to live under excore which is weird. While I agree with this, I also think that storing two Core objects on a single Reactor doesn't make much sense from a traditional viewpoint. If Reactor were instead Plant, then maybe I'd agree more with Alex.
  4. There is a lot going on here. While everything appears to look good, I will not be at all surprised if this breaks some stuff in my workflow. Oh well.

armi/bookkeeping/report/reportInterface.py Show resolved Hide resolved
armi/bookkeeping/report/reportInterface.py Outdated Show resolved Hide resolved
armi/bookkeeping/report/reportInterface.py Outdated Show resolved Hide resolved
armi/bookkeeping/report/reportInterface.py Show resolved Hide resolved
armi/bookkeeping/report/reportInterface.py Show resolved Hide resolved
armi/reactor/excoreStructure.py Show resolved Hide resolved
armi/reactor/reactors.py Outdated Show resolved Hide resolved
armi/reactor/reactors.py Show resolved Hide resolved
armi/reactor/reactors.py Outdated Show resolved Hide resolved
armi/reactor/excoreStructure.py Show resolved Hide resolved
@john-science
Copy link
Member Author

@john-science Test this downstream before merging.

@john-science john-science merged commit 60b0dbf into main Oct 7, 2024
19 checks passed
@john-science john-science deleted the excore branch October 7, 2024 23:52
drewj-tp added a commit that referenced this pull request Oct 8, 2024
…xial-linkage

* origin/main:
  Adding support for ex-core structures (#1891)
  Fixing edge case in assemblyBlueprint._checkParamConsistency (#1929)
  Improving the robustness of  HexBlock._rotatePins() (#1859)
  Removing unnecessary column in print-out (#1925)
  Updating parameter-related docs (#1919)
drewj-tp added a commit that referenced this pull request Oct 11, 2024
* origin/main:
  Relaxing copyInterfaceInputs to not require a valid Setting (#1934)
  Moving C5G7 into its own test dir (#1941)
  Transposing pinMgFluxes so that the leading dimension represents pin index (#1937)
  Moving Core class to its own module (#1938)
  Removing unusable buildEqRingSchedule (#1928)
  Raising Error when loading inconsistent data from DB (#1940)
  Ensuring we only calculate smear density for pinned blocks (#1933)
  Update rotation requirement impl, tag links: Hex specific (#1936)
  Adding support for ex-core structures (#1891)
  Fixing edge case in assemblyBlueprint._checkParamConsistency (#1929)
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.

4 participants