armi
armi copied to clipboard
[Suspect 🕵️♀️] - "De-homogenization" of Number Densities
For a long time now, we have allowed users and developers to use the setNumberDensities method that exists on the composites to set number densities on a Component, Block, Assembly, Core directly:
https://github.com/terrapower/armi/blob/e8ddcdf774f9eb3e842ae75948f095095fc2d48b/armi/reactor/composites.py#L1546-L1564
When this is called, the updateNumberDensities method is called and for non-components, the nuclides that are updated at distributed "evenly" throughout the children of the composite:
https://github.com/terrapower/armi/blob/e8ddcdf774f9eb3e842ae75948f095095fc2d48b/armi/reactor/composites.py#L1566-L1576
This works well when the user/developer does not care about maintaining the distribution of number densities below the level that the number densities are updated on, but can lead to unintended consequences if a down-stream user of the data model needs to know the material distributions.
I do not have a public example to show at the moment, but I will create one to demonstrate the issue. There are a couple solutions:
- Be opinionated in the implementation: Only allow number densities to be set on an object that has no children. This would be a strict implementation and could lead to down-stream "breaking" changes but could also uncover hidden implementation bugs.
- Be flexible in the implementation: Allow users/developers to communicate with the data model for how they would like the number densities to be modified (i.e., provide a nuclide to children mapping as an input as optional, and default to "evenly" spreading out the nuclides as currently implemented).
- Explore another algorithm for the implementation: It's not clear to me if the current implementation of using volume fractions of the children to "evenly" spread out nuclides is correct. In some cases, after you set number densities in this way you can ask a component for its
density()and get a value that is much different than itsmaterial.density(Tc=c.temperatureInC).
CC: @john-science, @drewejohnson, @albeanth, @opotowsky
Hey @jakehader, sorry for missing this. Might have been a wrong user-name tag 😜
If I understand right, if I did something like
core.setNumberDensities(data)
does it functionally unravel to
for leaf in core.iterComponents():
leaf.updateNumberDensities(data)
Oh but only updating nuclides that exist in those leaf children... I guess the name update was a choice vs. set?
Like this is a way to quickly build a homogenized core of a single material?
I think to get to your question, we're not using this so if it gets yanked / changed we won't be impacted
I would prefer option (1) by the way. I think that we should only be setting number densities on the lowest-level composites modeled in the data model. Anything else is not technically correct. If a user wants to make a quick homogenized blob then they could make a new Component or Block and assign the number densities directly to that without any children.
Finally getting around to reading this @jakehader. I also support option 1 you outline above. Unless I've misinterpreted, we should probably only allow number densities to be set on components. I'm not sure if anything else really makes all that much sense to be honest?
I could see this formalizing into a requirement @john-science @opotowsky. Thoughts?
EDIT: After spending a little time with this, I think making the number densities live on the components would greatly simplify the number density implementation. This would be a pretty big change and would likely cause lots of knock on effects but is something worth considering, I think.
We talked about this ticket as a group and the approach we think is cleanest is to move setNumberDensities() from ArmiObject to Component. (This might mean also moving setNumberDensity() over. TBD.)
So, I will try that.
@drewj-usnctech How do you think that would affect you?