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

AM242 specification in the blueprints #1757

Open
keckler opened this issue Jun 30, 2024 · 6 comments
Open

AM242 specification in the blueprints #1757

keckler opened this issue Jun 30, 2024 · 6 comments
Assignees
Labels
bug Something is wrong: Highest Priority

Comments

@keckler
Copy link
Member

keckler commented Jun 30, 2024

There is a bit of an inconsistency in the different sections of the blueprints when it comes to specifying the isotope AM242.

The nuclide flags portion of the blueprints allows you to put AM242 without complaining. But then if you put AM242 into one of your components, the run will fail during blueprints instantiation. For instance, using the attached input files which have AM242 in both the nuclide flags and a custom material:

> from armi.reactor.blueprints import Blueprints
> from armi.settings.caseSettings import Settings
> with open("example-blueprints.yaml",'r') as f:
    bp = Blueprints.load(f)
> cs = Settings("example.yaml")
> bp._prepConstruction(cs)

ValueError: The nuclides {'AM242'} are present in material <Material: Custom> by compositions, but are not specified in the `nuclide flags` section of the input file. They need to be added, or custom isotopics need to be applied.

To get this error to go away, you have to change the AM242 in the custom material into either AM242M or AM242G.

The error is raised here:

def _constructMaterial(self, blueprint, matMods):
nucsInProblem = blueprint.allNuclidesInProblem
# make material with defaults
mat = materials.resolveMaterialClassByName(self.material)()
if self.isotopics is not None:
# Apply custom isotopics before processing input mods so
# the input mods have the final word
blueprint.customIsotopics.apply(mat, self.isotopics)
# add mass fraction custom isotopics info, since some material modifications need
# to see them e.g. in the base Material.applyInputParams
matMods.update(
{
"customIsotopics": {
k: v.massFracs for k, v in blueprint.customIsotopics.items()
}
}
)
if len(matMods) > 1:
# don't apply if only customIsotopics is in there
try:
# update material with updated input params from blueprints file.
mat.applyInputParams(**matMods)
except TypeError:
# This component does not accept material modification inputs of the names passed in
# Keep going since the modification could work for another component
pass
expandElementals(mat, blueprint)
missing = set(mat.massFrac.keys()).difference(nucsInProblem)
if missing:
raise ValueError(
"The nuclides {} are present in material {} by compositions, but are not "
"specified in the `nuclide flags` section of the input file. "
"They need to be added, or custom isotopics need to be applied.".format(
missing, mat
)
)
return mat

If you look into that nucsInProblem set, which is derived from the nuclide flags in the blueprints, you'll find that it has AM242G and AM242M in it, but not plain old AM242 like was specified by the user:

> nucsInProblem
OrderedSet(['AC225', 'AC226', 'AC227', 'AG107', 'AG109', 'AG110M', 'AG111', 'AL27', 'AM241', 'AM242G', 'AM242M', 'AM243', 'AM244', 'AM244M', 'AR36', 'AR38', 'AR40', 'AS75', 'AU197', 'B10', 'B11', 'BA130', 'BA132', 'BA133', 'BA134', 'BA135', '
BA136', 'BA137', 'BA138', 'BA140', 'BE7', 'BE9', 'BI209', 'BK249', 'BK250', 'BR79', 'BR81', 'C', 'CA40', 'CA42', 'CA43', 'CA44', 'CA46', 'CA48', 'CD106', 'CD108', 'CD110', 'CD111', 'CD112', 'CD113', 'CD114', 'CD115M', 'CD116', 'CE136', 'CE138
', 'CE139', 'CE140', 'CE141', 'CE142', 'CE143', 'CE144', 'CF249', 'CF250', 'CF251', 'CF252', 'CF253', 'CF254', 'CL35', 'CL37', 'CM241', 'CM242', 'CM243', 'CM244', 'CM245', 'CM246', 'CM247', 'CM248', 'CM249', 'CM250', 'CO58', 'CO58M', 'CO59',
'CR50', 'CR52', 'CR53', 'CR54', 'CS133', 'CS134', 'CS135', 'CS136', 'CS137', 'CU63', 'CU65', 'DUMP1', 'DUMP2', 'DY156', 'DY158', 'DY160', 'DY161', 'DY162', 'DY163', 'DY164', 'ER162', 'ER164', 'ER166', 'ER167', 'ER168', 'ER170', 'ES253', 'ES25
4', 'ES255', 'EU151', 'EU152', 'EU153', 'EU154', 'EU155', 'EU156', 'EU157', 'F19', 'FE54', 'FE56', 'FE57', 'FE58', 'FM255', 'GA69', 'GA71', 'GD152', 'GD153', 'GD154', 'GD155', 'GD156', 'GD157', 'GD158', 'GD160', 'GE70', 'GE72', 'GE73', 'GE74'
, 'GE76', 'H1', 'H2', 'H3', 'HE3', 'HE4', 'HF174', 'HF176', 'HF177', 'HF178', 'HF179', 'HF180', 'HG196', 'HG198', 'HG199', 'HG200', 'HG201', 'HG202', 'HG204', 'HO165', 'HO166M', 'I127', 'I129', 'I130', 'I131', 'I135', 'IN113', 'IN115', 'IR191
', 'IR193', 'K39', 'K40', 'K41', 'KR78', 'KR80', 'KR82', 'KR83', 'KR84', 'KR85', 'KR86', 'LA138', 'LA139', 'LA140', 'LFP35', 'LFP38', 'LFP39', 'LFP40', 'LFP41', 'LI6', 'LI7', 'LU175', 'LU176', 'MG24', 'MG25', 'MG26', 'MN55', 'MO100', 'MO92',
'MO94', 'MO95', 'MO96', 'MO97', 'MO98', 'MO99', 'N14', 'N15', 'NA22', 'NA23', 'NB93', 'NB94', 'NB95', 'ND142', 'ND143', 'ND144', 'ND145', 'ND146', 'ND147', 'ND148', 'ND150', 'NI58', 'NI59', 'NI60', 'NI61', 'NI62', 'NI64', 'NP235', 'NP236', 'N
P237', 'NP238', 'NP239', 'O16', 'O17', 'P31', 'PA231', 'PA232', 'PA233', 'PB204', 'PB206', 'PB207', 'PB208', 'PD102', 'PD104', 'PD105', 'PD106', 'PD107', 'PD108', 'PD110', 'PM147', 'PM148', 'PM148M', 'PM149', 'PM151', 'PR141', 'PR142', 'PR143
', 'PU236', 'PU237', 'PU238', 'PU239', 'PU240', 'PU241', 'PU242', 'PU243', 'PU244', 'PU246', 'RA223', 'RA224', 'RA225', 'RA226', 'RB85', 'RB86', 'RB87', 'RE185', 'RE187', 'RH103', 'RH105', 'RU100', 'RU101', 'RU102', 'RU103', 'RU104', 'RU105',
 'RU106', 'RU96', 'RU98', 'RU99', 'S32', 'S33', 'S34', 'S36', 'SB121', 'SB123', 'SB124', 'SB125', 'SB126', 'SC45', 'SE74', 'SE76', 'SE77', 'SE78', 'SE79', 'SE80', 'SE82', 'SI28', 'SI29', 'SI30', 'SM144', 'SM147', 'SM148', 'SM149', 'SM150', 'S
M151', 'SM152', 'SM153', 'SM154', 'SN112', 'SN113', 'SN114', 'SN115', 'SN116', 'SN117', 'SN118', 'SN119', 'SN120', 'SN122', 'SN123', 'SN124', 'SN125', 'SN126', 'SR84', 'SR86', 'SR87', 'SR88', 'SR89', 'SR90', 'TA181', 'TA182', 'TB159', 'TB160'
, 'TC99', 'TE120', 'TE122', 'TE123', 'TE124', 'TE125', 'TE126', 'TE127M', 'TE128', 'TE129M', 'TE130', 'TE132', 'TH227', 'TH228', 'TH229', 'TH230', 'TH232', 'TH233', 'TH234', 'TI46', 'TI47', 'TI48', 'TI49', 'TI50', 'U232', 'U233', 'U234', 'U23
5', 'U236', 'U237', 'U238', 'U239', 'U240', 'U241', 'V', 'W182', 'W183', 'W184', 'W186', 'XE123', 'XE124', 'XE126', 'XE128', 'XE129', 'XE130', 'XE131', 'XE132', 'XE133', 'XE134', 'XE135', 'XE136', 'Y89', 'Y91', 'ZN', 'ZR90', 'ZR91', 'ZR92', '
ZR93', 'ZR94', 'ZR95', 'ZR96'])

So somewhere in the problem initialization, the AM242 nuclide flag is converted into AM242G and AM242M. But this makes is confusing if one tries to simply enter nuclide flags for the isotopes corresponding to their materials.

If we are going to force users to use AM242M and AM242G, then we should do so consistently.

example-blueprints.yaml.txt
example.yaml.txt

@john-science john-science added the bug Something is wrong: Highest Priority label Jul 3, 2024
@john-science
Copy link
Member

@keckler It appears to me that AM242 and AM242M are the exact same thing, just with a different name:

am242m = nuclideBases.byName["AM242"]
self.assertEqual(am242m, nuclideBases.byName["AM242M"])

It appears am242m is the preferred name, to differentiate it from am242g. The logic really looks like we won't want to use the name am242 because then people won't know if it is m or g, as that would not be clear.

Thoughts?

@keckler
Copy link
Member Author

keckler commented Aug 23, 2024

Yeah, I think that is fine. But then we should not allow AM242 in the nuclide flags. We should make people enter AM242M to avoid the ambiguity and the inconsistency between the nuclide flags and the isotopic definitions.

@john-science
Copy link
Member

Yeah, I think that is fine. But then we should not allow AM242 in the nuclide flags. We should make people enter AM242M to avoid the ambiguity and the inconsistency between the nuclide flags and the isotopic definitions.

I could do that.

We could also throw a loud warning that the nuclide you entered is being renamed, and loudly inform people this is just a convenience pass-through for them.

@john-science john-science self-assigned this Aug 23, 2024
@john-science
Copy link
Member

A little research showed me that "AM242" is used extensively in our downstream projects. (I gave up counting after a dozen.)

While many projects are already correctly using AM242G and AM242M, just dropping AM242 will be quite a big set of changes in the ecosystem.

Thoughts?

@keckler
Copy link
Member Author

keckler commented Aug 30, 2024

Interesting. I know that I am responsible for at least some of that. I would be willing to migrate anytime that a change is made here.

I think a good path here is to move towards deprecation, starting with a warning. Maybe in the next-next release, we drop it?

@john-science
Copy link
Member

So, this whole situation is, it turns out, extremely well documented in the code:

if z == 95 and a == 242:
# Am242 has special rules
if self.state != 1:
# MCNP uses base state for the common metastable state AM242M, so AM242M is just 95242
# AM242 base state is called 95642 (+400) in mcnp.
# see https://mcnp.lanl.gov/pdf_files/la-ur-08-1999.pdf
# New ACE-Formatted Neutron and Proton Libraries Based on ENDF/B-VII.0
a += 300 + 100 * max(self.state, 1)

def updateNuclideBasesForSpecialCases():
"""
Update the nuclide bases for special case name changes.
.. impl:: The special case name Am242g is supported.
:id: I_ARMI_ND_ISOTOPES6
:implements: R_ARMI_ND_ISOTOPES
This function updates the keys for the :py:class:`NuclideBase
<armi.nucDirectory.nuclideBases.NuclideBase>` instances for Am-242m and
Am-242 in the ``byName`` and ``byDBName`` global dictionaries. This
function associates the more common isomer Am-242m with the name
"AM242", and uses "AM242G" to denote the ground state.
Notes
-----
This function is specifically added to change the definition of
`AM242` to refer to its metastable isomer, `AM242M` by default. `AM242M`
is most common isomer of `AM242` and is typically the desired isomer
when being requested rather than than the ground state (i.e., S=0) of
`AM242`.
"""
# Change the name of `AM242` to specific represent its ground state.
am242g = byName["AM242"]
am242g.name = "AM242G"
byName["AM242G"] = am242g
byDBName[byName["AM242G"].getDatabaseName()] = am242g
# Update the pointer of `AM242` to refer to `AM242M`.
am242m = byName["AM242M"]
byName["AM242"] = am242m
byDBName["nAm242"] = am242m
byDBName[byName["AM242"].getDatabaseName()] = am242m

But there isn't any (good or pleasant) way to inject a DeprecationWarning only when people use AM242. They would have to see it every time they run any ARMI simulation. #shrug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is wrong: Highest Priority
Projects
None yet
Development

No branches or pull requests

2 participants