terrapower / armi

An open-source nuclear reactor analysis automation framework that helps design teams increase efficiency and quality
https://terrapower.github.io/armi/
Apache License 2.0
232 stars 90 forks source link

Allow a way to efficiently iterate over some parameters #1898

Closed drewj-tp closed 1 month ago

drewj-tp commented 1 month ago

(Pulling a discussion out of https://github.com/terrapower/armi/pull/1877#discussion_r1769233599)

We have a lot of parameters. Not all of them are used in every location. For example, in working on HexBlock.rotate, lots of things needs to be rotated. Two cases are

  1. Parameters defined on the midpoints and vertices of a hexagon (e.g., with ParamLocation.CORNERS)
  2. Parameters defined on the children of the block (e.g., with ParamLocation.CHILDREN)

For parameters meeting condition 1, we have

https://github.com/terrapower/armi/blob/3dd2763535f0a5694215a0f1f876db49eea3a11c/armi/reactor/blocks.py#L2041-L2042

ParameterDefinitions.atLocation involves iterating over all parameters, making an intermediate ParameterDefinitionCollection, extending to it, twice (once for corners, once for edges). And then iterate again over the combined names.

In #1877, I added a helper onto HexBlock that allowed a pattern like

for param in self._getParamsWhere(lambda pd: pd.atLocation(ParamLocation.CORNERS)):
    pass

This allowed for one iteration over all the parameters and used filter to only produce parameters that met the condition.

This seems more generally useful so let's add it.

Where?

I don't think it should be added to a composite. Those already have too many methods.

I'm thinking a ParameterCollection so you can do something like

assem = r.core[0]
assem.p.where(lambda pd: pd.hasCategory("neutronics"))

There could be some confusion about where needing a condition for the values of the parameter collection, not so much their definitions. The same way numpy.where and pandas.where behave.

So maybe a ParameterDefinitionCollection? Then you'd need to do

assem.p.pDefs.where(pd: pd.atLocation(ParamLocation.EDGES))

that feels a bit better? Grabbing parameters where their definition meets a certain category. Yeah, I think I like that better

john-science commented 1 month ago

I like this idea!

I would be happy with:

assem = r.core[0]
assem.p.where(lambda pd: pd.hasCategory("neutronics"))

The original idea I had something like:

assem.p.where(categories, locations)

# or

assem.p.where(categories, locations, names)

where we just allow people to add (optional/empty) sets/lists of all three. Your idea is more flexible. If the ONLY things people ever used were categories and locations, I think the second version would be better. Less flexible though.

(I'm just a chatting. I'm not planning on dying on any hills today.)