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

Modeling ex-core structures: RPV, shielding, etc. #262

Closed
drewejohnson opened this issue Mar 1, 2021 · 11 comments
Closed

Modeling ex-core structures: RPV, shielding, etc. #262

drewejohnson opened this issue Mar 1, 2021 · 11 comments
Labels
architecture Issues related to big picture system architecture enhancement New feature or request

Comments

@drewejohnson
Copy link
Contributor

Wanted to start a discussion / propose a new feature: ex-core structures in ARMI

The base system I'd like to model is one or more concentric right cylinders defining ex-core structures like core barrel, reactor pressure vessel (RPV) and shielding. I had a thought of adding some features to the blueprints file, like a block that doesn't make it's way into the core, but still utilizes material resolution and dimension linking. A new ComplexShape could be added to model the various aspects of the canning like

excore:
    nshield:
        shape: RightCylinder
        id: 70
        od: 72
        bottomStart: 0
        bottomExtent: -5
        topStart: 100
        topExtent: 105
    RPV:
        shape: RightCylinder
        id: nshield.od
        od: 80
        bottomStart: nshield.bottomExtent
        bottomExtent: -20
        topStart: nshield.topExtent
        topExtent: 115

(dimensions made up) This information could be provided in the blocks section using circles rather than cylinders, and not placed in the core facemap. Maybe given a unique Flag to show it's part of the ex-core for bookkeeping and other checks, e.g., getFirstBlock(Flags.EXCORE)

I guess you could also model the upper / lower ex-core structures with dedicated axial layers. But you could run into a position like
rpv-gap
where the vertical ex-core structures that make up the radial shielding don't form a connection with the two lowest levels. Or they would, but the green and blue materials don't line up correctly
rpv-gap

Another consideration would be "clipped" assemblies. In modeling the MHTGR in ARMI (#224), we'd likely have extra rings around the outside making up the "permanent reflector" which would then be clipped by the barrel to make up those complex outer shapes.
mhtgr

I've dropped a proxy barrel over the FFTF facemap as another example
hex-with-intersecting-rpv
This will likely also have knock-on effects for tallying (full hex volume won't actually see neutrons) and visualization

The MHTGR also has some repeating arc-segments that make up coolant channels. The BEAVRS model has similar arcs for neutron shields between the core barrel and the RPV
beavrs
The region between the barrel, shield segments, and RPV could be filled with a DerivedShape to help model the down-comer region

@youngmit
Copy link
Contributor

youngmit commented Mar 1, 2021

This response got a little longer than I originally thought, so TL;DR:

Lots of this stuff might be possible now. The main thing in your way is the Blueprints, which lacks the flexibility to define more complicated things easily, and things like clipped hexes, which will need some head scratching. I would recommend trying to drive the Composites/Grids in code to prototype a model that you think works. See some recommendations below. From there we can talk about where to go from the input processing/blueprints side.

Glad to start a discussion about how this could be done in earnest! My main input from reading through the above is that we should try to think through what the reactor model should like like in terms of the ARMI Composite tree before we attempt to tackle the blueprints side of things. For some of these ex-core structures, i would imagine using Block/Assembly objects would make sense, but for many others, it would not (instead being a bare Component of some sort, or a general-purpose Composite, or a custom-defined Composite). All of these are technically possible today, but for a couple of things:

  • linked-dimensions are ideally a Composite level concept, so long as you are using Components that link to dimensions in their sibling Components. This is pretty flexible, but not totally general. I would also expect to bump into some bugs along the way due to the erroneous assumption that Composite really means Block. This kind of thing is sort of common in ARMI, since until recently Block and Composite were pretty much synonymous.
  • the permanent shield/clipped hex thing looks kind of hard, and i'm still trying to think of a good way to address that. One of those things that in CSG it's baby-town frolics, but when you have to name a shape to all blobs of material it gets kind of hard. hmmm...
  • axial ex-core stuff actually is something we have talked a lot about in the past. This is actually possible now, but for the blueprints not really supporting it. The current pain point for us right now w.r.t. that is things like grid plates. if you look at the fuel handler code, some of the most useful code in there now are the functions that will shuffle Assemblies in a Core, but leave the GRID_PLATE Blocks alone. An alternative that we have talked about quite a bit (and grids was implemented with an eye towards) is to represent the movable-assembly portion of the core as one Core-like object (remember, these are governed by a 2-D grid), which we can call "active core". This would be a child of another Composite, which we can call "core". The "grid plate" would then be represented as another Composite object as "active core"'s sibling in "core". "Core" itself would hold the two in a 1-D grid, placing the "active core" above the "grid plate". Other stuff above or below the active/fuelled core region can be represented in much the same way. This give a reactor model something like this:
    image

Historically, we have been sticking to a single Core object because A) input processing gets harder the more general it becomes and B) sticking to a more rigid Core->Assembly->Block->Component structure has made writing interfaces to external physics code a lot easier, since it gives you some guarantees about the tree structure. Adding extra children to the Reactor or more depth to the Core would mean the the interfaces need to know how to handle those extra structures properly. In something like MCNP that might not be too bad, but for a code that expects prisms all the way through, handling anything below, say, the grid plate requires more nuance.

I hope this helps! Its a big topic, so might be worth a little workshop or something to hash out some more ideas.

@drewejohnson
Copy link
Contributor Author

@youngmit thank you for the detailed explanation. I do appreciate getting a look at the design and inheritance model 👍

My main input from reading through the above is that we should try to think through what the reactor model should like like in terms of the ARMI Composite tree before we attempt to tackle the blueprints side of things.

Definitely agree

the permanent shield/clipped hex thing looks kind of hard

but for a code that expects prisms all the way through, handling anything below, say, the grid plate requires more nuance.

I wonder if an extra ring of some homogenized reflector + RPV might be a good workaround / substitute. Then it's still a regular structure. But the homogenzation would have to be block specific since the fraction of reflector + rpv + void varies by block... yikes

axial ex-core stuff actually is something we have talked a lot about in the past. This is actually possible now, but for the blueprints not really supporting it.

exciting! by blueprints not really supporting axial ex-core stuff, do you mean that's something that has to be made w/ a driver script, not the plain yaml file?

Adding extra children to the Reactor or more depth to the Core ...

If instead of adding the RPV to the Core, would it be easier w.r.t. existing interfaces to have the RPV and ex-core stuff be a child of the Reactor and a sibling to Core? Then anything that works on o.r.core should be fine. Maybe?

I'll try and kick some stuff around and see what I can come up with.

@youngmit
Copy link
Contributor

youngmit commented Mar 3, 2021

I wonder if an extra ring of some homogenized reflector + RPV might be a good workaround / substitute. Then it's still a regular structure. But the homogenzation would have to be block specific since the fraction of reflector + rpv + void varies by block... yikes

You should see how we model molten salt reactors :) This essentially becomes a mesh overlay problem, which is super doable, but does erode some of the value-add of ARMI, since it is no longer possible to, say, thermally expand components. You could do that on the higher-level meshes that you are shoehorning into the ARMI model and re-map everything, but its definitely less nice :/ Still, having a prismatic, block-y thing with well-represented volume fractions is still mighty useful.

exciting! by blueprints not really supporting axial ex-core stuff, do you mean that's something that has to be made w/ a driver script, not the plain yaml file?

Yup, some sort of driver script. We actually had experimented with a plugin API that would let a plugin provide custom strategies for creating the reactor model itself (see below). In this way, from Blueprints would become the default method, but one could write some custom code that largely eschews Blueprints and just whips up a Reactor on it's own (perhaps parameterized on some custom input). Making this a plugin hook is necessary to make things like [armiapp] run [case settings] work. However, if we are just spitballing how best to represent a Reactor model with these sorts of bells and whistles, I think a one-off driver script is the best place to start. Note that Blueprints are still needed to provide nuclide flags. This is pretty high on my list of priorities to resolve, since the supremacy of Blueprints has always rubbed me the wrong way, and this discussion is a perfect object lesson into why :)

If instead of adding the RPV to the Core, would it be easier w.r.t. existing interfaces to have the RPV and ex-core stuff be a child of the Reactor and a sibling to Core?

Yup! I was trying to hint at that, but probably could have made it more clear by including it in the diagram. I would imagine that the RPV would be next to the Core, not inside of it:
image

The wrinkle with treating the core as a thing that is itself a 1-D stack of things like the active core region on top of the grid plate (to take an example), is that a trivial implementation of, say, a global flux solver would probably want to model both the active core and the grid plate. If they are in one Core object with the fuel, plenum, grid plate, etc being stuffed into an Assembly, its a simple loop over Assemblies -> Blocks to form a neutronics model. If the grid plate is in some other object, that generality needs to be addressed. Not a bad thing by any means, but the main reason why we haven't gone out of our way to do it yet. The same thing goes for something like an RPV, core barrel or whatever. In your various physics interfaces (and implementing code), what object/scope do you pass in? The Core (thus ignoring RPV)? The Reactor (requiring the callee to chose which systems to include in its model)? A collection containing the Core and whatever other components are relevant (placing the burden on the caller)? All of these seem reasonable, depending on the circumstances and the desired methodology.

@youngmit
Copy link
Contributor

youngmit commented Mar 3, 2021

Regarding custom reactor model construction/initialization, I had in the past proposed the following plugin API:

@staticmethod
    @HOOKSPEC
    def defineReactorConstructionMethods():
        """
        Return new methods by which a Reactor object can be created.

        This allows for plugins to provide their own approach to Reactor model
        construction than the default, Blueprints-defined method that comes with ARMI.
        These can be useful for exotic reactor types which are not well served by the
        Blueprints mechanism.

        Returns
        -------
        methods : dict
            Implementations should return a dictionary mapping of name to method,
            where ``name`` is a unique string label for the corresponding method, and
            ``method`` is a function-like object that takes a ``Settings`` object as its
            only argument and returns a fully-constructed ``Reactor`` object.

        Note
        ----
        Reactor construction is ultimately governed by the ``reactorConstructionMethod``
        setting. To fully expose new methods, the names should also be provided as
        Options to the ``reactorConstructionMethod`` setting as well.

        See also
        --------
        defineSettings
        armi.settings.setting.Option

        Example
        -------
        In this example, we define a new function for creating a Reactor object. It uses
        a new setting that we also provide to control its behavior. We also advertise
        the method using the ``defineSettings()`` and
        ``defineReactorConstructionMethods()`` hooks::

            def fancyReactorMaker(cs):
                r = reactors.Reactor(name=cs["fancyReactorName"], blueprints=None)
                // Do more magic!
                return r

            class MyPlugin(ArmiPlugin):
                def defineSettings():
                    return [
                        # This setting is used to control/parameterize the function
                        # defined above.
                        setting.Setting("fancyReactorName", default=""),
                        setting.Option("reactorConstructionMethod", "fancyReactor")
                    ]

                def defineReactorConstructionMethods():
                    return {"fancyReactor": fancyReactorMaker}
        """

The direct motivation for this API was to make a custom reactor initializer that did some mesh overlay work to handle weirdly-shaped Blocks/Components (eerily similar to your fixed reflector situation). The intention was for this to also serve as a proving ground for more flexible Reactor model hierarchies and ex-core things that aren't yet supported by Blueprints. If you think this would be useful, I could try to get this on a branch for you to experiment with.

@drewejohnson
Copy link
Contributor Author

Thanks for the detailed response @youngmit. If you're comfortable pushing a branch of some level of usability (WIP or stable but not accepted) I could take a swing at using that hook. It might be a good way to drop in some shield / rpv-like classes

@youngmit
Copy link
Contributor

@drewejohnson finally got around from digging this up. Check out the rxConstructMethod branch. This is the result of cherry-picking a couple of commits from an old branch and some minor retrofit, so may have goofed on something. Let me know if you run into any trouble.

@drewejohnson
Copy link
Contributor Author

@youngmit thank you for making that available. I'll let you know how it goes on my end

@john-science john-science added architecture Issues related to big picture system architecture enhancement New feature or request labels Nov 4, 2021
@john-science
Copy link
Member

john-science commented Feb 22, 2024

One possible solution to this would be to an ExCore child to the Reactor (just as the SFP was recently made a child of the Reactor.). Then Pylot could define parameters for the objects in that structure, like we do in so many other places in ARMI and in downstream plugins:

def getNeutronicsParameterDefinitions():
"""Return ParameterDefinitionCollections for each appropriate ArmiObject."""
return {Block: _getNeutronicsBlockParams(), Core: _getNeutronicsCoreParams()}

So, we would define:

  • class ExCore(composites.Composite), to be a hierarchical data object for storing ex-core structures.
  • Reactor.excore would be added as a attribute to the Reactor class.
  • Something like an ExCoreStructure / ExCoreBlock would need to be created, so we have something to add Parameters to.

This all seems quite easy to do. And then ex-core structures would be automatically read to-and-from the ARMI Database.

Downsides on this first draft, that ARMI could improve in future versions:

  • You would have to define your ex-core structures in code (this doesn't solve the need for "3D blueprints").
  • If you wanted objects like Shielding or ContainmentVessel or Pipe, you would have to subclass our ExCoreBlock and define them yourself.

Obviously, my idea is just a starting place. Your double-cylinder would be built on top of this kind of entry-level infrastructure. I'm just thinking aloud about a place to start.

@john-science
Copy link
Member

@jakehader This is the ticket in question.

In order for something like this to work, we need:

  1. The new ex-core structures to be a child of the Reactor object
    a. Like what Michael did with the SFP
    b. Without this, the new ex-core stuff would not be in the DB.
  2. The full set of the ex-core structures defined to be flexible
    a. You suggested a Plugin hook, that seems good.

My last thought is: I don't want to have to hunt or guess at what is in the Reactor, so I would prefer if all such things (and maybe the SFP?) fell under reactor.excore, so they were easy to find and identify. SOMETHING like that.

@jakehader
Copy link
Member

jakehader commented Aug 20, 2024

I think everything under reactor could be fine. Having excore creates another layer that might not add much value. I like to think if the reactor as "a plant" so to me, having the reactor be the parent with arbitrary definitions of containers / grids that sit in a flat structure could be the easiest. While in theory we could have things like pumps, heat exchangers, vessels, and physical equipment defined, I think the ability to say where in space a container relative to one another could be a first step and then if we want the reactor or a reactor to support logic for both things are interrelated or connected then that might be by the specific plugin or plugins that implement the things.

For example, having a dry cask storage pad with dry casks that sit in the grid cylindrical grid which contain core assemblies inside in a cartesian grid of the casks themselves. In this hypothetical, the core, SFP, and StoragePad would each have independent grids and the reactor would then have it's own grid that defines the relative orientation and origin of each grid underneath. Next, for a specific reactor design, the plugin or application might want some functionality to say, core assemblies shall not go straight to the StoragePad until some conditions are met (i.e., passing through the SFP, waiting for X amount of time, until peak decay heat is below a certain value, or all the above). I think applications should be able to subclass the Reactor if needed to get some type of this behavior and the plugin hooks should support an adaptive process to register new things as needed. In this example, may be the Reactor doesn't hold the logic or constraints but maybe a FuelHandler does.

Right now I'm just thinking let's add the capability to have "N" containers that sit on the reactor that house assemblies. How they get there based on other equipment or snap to that location using a FuelHandler may be the next step. Handling fluid systems like heat exchangers, pumps, pipes, etc. is probably too ambitious at first, and would require more thought about what a Reactor object truly is and isn't

@john-science
Copy link
Member

Okay, we finally have a first pass at this in ARMI: #1891

We have two teams using this feature internally, so I fully expect if there are problems, they will be opened as smaller (less architectural) changes.

Thanks, all!

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 enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants