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

Add variable to specify ZAID-format #187

Merged
merged 8 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/fileformatspec/depcode_input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,22 @@ Serpent-specific properties
:pattern:
``^(.\\/)*(.*)$``

``zaid_convention``
~~~~~~~~~~~~~~~~~~~

:description:
ZAID naming convention for nuclide codes. 'serpent': The third digit in ZA for nuclides in isomeric states is 3 (e.g. 47310 for for Ag-110m). 'mcnp': ZA = Z*1000 + A + (300 + 100*m). where m is the mth isomeric state (e.g. 47510 for Ag-110m). 'nndc': Identical to 'mcnp', except Am242m1 is 95242 and Am242 is 95642


:type:
``string``

:enum:
"serpent", "mcnp", "nndc"

:default:
"mcnp"


.. _openmc_specific_properties:

Expand Down
4 changes: 4 additions & 0 deletions doc/releasenotes/v0.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ Bug Fixes
..
Describe any bug fixes.

- `Fix bug where Serpent2 material temperatures are hardcoded to 900K in the JEFF 3.1.2 library format. <https://github.com/arfc/saltproc/pull/178>`
- `Fix bug where using MCNP-style ZAID codes results in an error in various SerpentDepcode functions <https://github.com/arfc/saltproc/issues/187>`



Expand Down Expand Up @@ -98,6 +100,7 @@ Python API Changes
- Input file format changes:

- Added default values for certain input parameters
- Adds a ``zaid_convention`` input parameter
- Added depletion settings for OpenMC
- ``num_depsteps`` → ``n_depletion_steps``
- ``depcode['template_inputfile_path']`` → ``depcode['template_input_file_path']``
Expand Down Expand Up @@ -167,6 +170,7 @@ Python API Changes
- (new function) → ``get_neutron_settings()``
- (new function) → ``_get_burnable_materials_file()``
- (new function) → ``_get_burnable_material_card_data()``
- (new parameter) → ``zaid_convention``


- ``OpenMCDepcode`` is a ``Depcode`` subclass that interfaces with ``openmc``. This class implements the following functions
Expand Down
3 changes: 2 additions & 1 deletion examples/msbr/msbr_main.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"depcode": {
"codename": "serpent",
"template_input_file_path": "msbr.serpent",
"geo_file_paths": ["geometry/msbr_full.ini"]
"geo_file_paths": ["geometry/msbr_full.ini"],
"zaid_convention": "serpent"
},
"simulation": {
"sim_name": "msbr_kl_100_simulation"
Expand Down
3 changes: 2 additions & 1 deletion examples/tap/tap_main.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"geometry/1338.ini",
"geometry/1498.ini",
"geometry/1668_all.ini"
]
],
"zaid_convention": "serpent"
},
"simulation": {
"sim_name": "tap_example_simulation",
Expand Down
8 changes: 7 additions & 1 deletion saltproc/input_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@
"exec_path": {
"default": "sss2"},
"template_input_file_path": {
"pattern": "^(.\\/)*(.*)$"}
"pattern": "^(.\\/)*(.*)$"},
"zaid_convention": {
"description": "ZAID naming convention for nuclide codes. 'serpent': The third digit in ZA for nuclides in isomeric states is 3 (e.g. 47310 for for Ag-110m). 'mcnp': ZA = Z*1000 + A + (300 + 100*m). where m is the mth isomeric state (e.g. 47510 for Ag-110m). 'nndc': Identical to 'mcnp', except Am242m1 is 95242 and Am242 is 95642",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why you included NNDC in this, when it looks like your stuff just uses Serpent and OpenMC.

Copy link
Contributor Author

@yardasol yardasol Jan 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NNDC provides cross section libraries using their own ZAID convention for metastable nuclides. It is slightly different than the convention used by cross section libraries shipped with MCNP. Notice that this variable only appears in the depcode object if codename is serpent. This is because Serpent uses ZAID codes to get cross section data for nuclides. This variable has no effect on how OpenMC will handle it's XS libraries, as that is all internally consistent within OpenMC.

LukeSeifert marked this conversation as resolved.
Show resolved Hide resolved
"type": "string",
"enum": ["serpent", "mcnp", "nndc"],
"default": "mcnp"
LukeSeifert marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
},
Expand Down
79 changes: 59 additions & 20 deletions saltproc/serpent_depcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def __init__(self,
output_path,
exec_path,
template_input_file_path,
geo_file_paths):
geo_file_paths,
zaid_convention):
"""Initialize a SerpentDepcode object.

Parameters
Expand All @@ -52,10 +53,21 @@ def __init__(self,
Path to Serpent2 executable.
template_input_file_path : str
Path to user input file for Serpent2
geo_file_paths : str or list, optional
geo_file_paths : str or list
Path to file that contains the reactor geometry.
List of `str` if reactivity control by
switching geometry is `On` or just `str` otherwise.
zaid_convention : str
ZAID naming convention for nuclide codes.

'serpent' - The third digit in ZA for nuclides in isomeric states
is 3 (e.g. 47310 for for Ag-110m).

'mcnp' - ZA = Z*1000 + A + (300 + 100*m). where m is the mth
isomeric state (e.g. 47510 for Ag-110m)

'nndc' - Identical to 'mcnp', except Am242m1 is 95242 and Am242
is 95642

"""
super().__init__("serpent",
Expand All @@ -66,6 +78,7 @@ def __init__(self,
self.runtime_inputfile = \
str((output_path / 'runtime_input.serpent').resolve())
self.runtime_matfile = str((output_path / 'runtime_mat.ini').resolve())
self.zaid_convention = zaid_convention

def get_neutron_settings(self, file_lines):
"""Get neutron settings (no. of neutrons per cycle, no. of active and
Expand Down Expand Up @@ -175,20 +188,33 @@ def convert_nuclide_code_to_name(self, nuc_code):
"""

if '.' in str(nuc_code):
nuc_code = pyname.zzzaaa_to_id(int(nuc_code.split('.')[0]))
nuc_code = int(nuc_code.split('.')[0])
if self.zaid_convention == 'serpent':
nuc_code = pyname.zzzaaa_to_id(nuc_code)
if self.zaid_convention in ('mcnp', 'nndc'):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider changing to elif here, then you could add an else statement to make sure self.zaid_convention is an expected value.

if self.zaid_convention == 'mcnp' and nuc_code in (95242, 95642):
if nuc_code == 95242:
nuc_code = 95642
else:
nuc_code = 95242
Comment on lines +195 to +199
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on your documentation I thought 95642 was for the NNDC ZAIDs, not the OpenMC ones. This function makes it seem the opposite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has nothing to do with OpenMC. It is all about where the nuclide cross section data is sourced from, since their ZAIDs will have slightly different conventions for metastable isotopes. This is a bit confusing so I'm going to go through this step-by-step.

  1. Recall that the standard nndc convention is identical to the mcnp convention, except in the case of Am-242 and Am-242m. The mcnp convention for ZAIDs of metastable isotopes is ZA = Z * 1000 + (A + 300 + 100*m). This means that Ag-110m has ZA = 47510, and Am-242m has ZA = 95642. In the nndc convention, for whatever reason, the ZA for Am-242m and Am242 are swapped, so ZA(Am242) = 95642, and ZA(Am242m) = 95242.
  2. PyNE's nucname module contains functions for handling ZAID codes. One such function is nucname.mcnp_to_id, which converts the ZAID code in mcnp convention to PyNEs internal id format. However, during testing, I noticed that this function actually converts ZAID codes in nndc convention! That is, will convert 95242 to 952420001, and 95642 to 952420000, but convert everything else normally. So if we are using the mcnp convention, we'll need to input the wrong ZAID code to get the right PyNE id. Does that make sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That all mostly makes sense (I meant to say MCNP, but had OpenMC on my mind when I made the comment, apologies). Just to make sure I understand this correctly:

In MCNP:

  • Am242 = 95242
  • Am242m = 95642
    In NNDC:
  • Am242 = 95642
  • Am242m = 95242.

Your function here says that if you are using MCNP and you give it 95242 (Am242 in MCNP), then it converts it to 95642 (Am242m in MCNP). If you give it 95642 (Am242m in MCNP), then it converts it to 95242 (Am242). So that gets switched. This assumes that you are providing NNDC nomenclature and trying to use MCNP. What if you are using MCNP nomenclature already and don't need to switch it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have the first right.

This assumes that you are providing NNDC nomenclature and trying to use MCNP. What if you are using MCNP nomenclature already and don't need to switch it?

The reason we do the swap is because PyNE assumes an nndc format for nucname.mcnp_to_id and other mcnp-related functions. That is, there is a discrepancy between our understanding of the mncp convention and what PyNE's understanding of the mcnp convention. PyNE's mcnp convention is equivalent to our nndc convention. So if we want to use our mcnp convention, we have to swap the ZAIDs for Am242 and Am242m that we input into the mcnp-related functions in PyNE to get the correct outputs (ZAIDs and nuclide names).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I'm making sure that there is no situation in which these ZAIDs would be switched when they don't have to be.

nuc_code = pyname.mcnp_to_id(nuc_code)

zz = pyname.znum(nuc_code)
aa = pyname.anum(nuc_code)
aa_str = str(aa)
if aa > 300:
if zz > 76:
aa_str = str(aa - 100) + 'm1'
aa = aa - 100
else:
aa_str = str(aa - 200) + 'm1'
aa = aa - 200
nuc_zzaaam = str(zz) + str(aa) + '1'
elif aa == 0:
aa_str = 'nat'
if self.zaid_convention == 'serpent':
if aa > 300:
if zz > 76:
aa_str = str(aa - 100) + 'm1'
else:
aa_str = str(aa - 200) + 'm1'
elif aa == 0:
aa_str = 'nat'
if self.zaid_convention in ('mcnp', 'nndc'):
mm = pyname.snum(nuc_code)
if mm != 0:
aa_str = str(aa) + f'm{mm}'

nuc_name = pyname.zz_name[zz] + aa_str
else:
meta_flag = pyname.snum(nuc_code)
Expand Down Expand Up @@ -233,10 +259,23 @@ def map_nuclide_code_zam_to_serpent(self):
line = line.split()
nuc_code = line[2]
if '.' in str(nuc_code):
nuc_code = pyname.zzzaaa_to_id(int(nuc_code.split('.')[0]))

zzaaam = \
self.convert_nuclide_code_to_zam(pyname.zzaaam(nuc_code))
nuc_code = int(nuc_code.split('.')[0])
# In MCNP format the ground state of Am-242 is 95242,
# but PyNE seems to disagree
if self.zaid_convention == 'serpent':
nuc_code = pyname.zzzaaa_to_id(nuc_code)
zzaaam = \
self.convert_nuclide_code_to_zam(pyname.zzaaam(nuc_code))
if self.zaid_convention == 'nndc' or self.zaid_convention == 'mcnp':
if self.zaid_convention == 'mcnp' and nuc_code in (95242, 95642):
if nuc_code == 95242:
nuc_code = 95642
else:
nuc_code = 95242
abachma2 marked this conversation as resolved.
Show resolved Hide resolved
nuc_code = pyname.mcnp_to_id(nuc_code)
zzaaam = pyname.zzaaam(nuc_code)
else:
zzaaam = int(nuc_code)

nuc_code_map.update({zzaaam: line[2]})
return nuc_code_map
Expand Down Expand Up @@ -436,15 +475,15 @@ def run_depletion_step(self, cores, nodes):
args = (self.exec_path, '-omp', str(cores), self.runtime_inputfile)
print('Running %s' % (self.codename))
try:
subprocess.check_output(
subprocess.run(
args,
cwd=os.path.split(self.template_input_file_path)[0],
stderr=subprocess.STDOUT)
capture_output=True)
print('Finished Serpent2 Run')
except subprocess.CalledProcessError as error:
print(error.output.decode("utf-8"))
raise RuntimeError('\n %s RUN FAILED\n see error message above'
% (self.codename))
print('Finished Serpent2 Run')

def convert_nuclide_code_to_zam(self, nuc_code):
"""Converts nuclide code from Serpent2 format to zam format.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"depcode": {
"codename": "serpent",
"template_input_file_path": "tap_template.ini",
"geo_file_paths": ["tap_geometry_base.ini"]
"geo_file_paths": ["tap_geometry_base.ini"],
"zaid_convention": "serpent"
},
"simulation": {
"sim_name": "tap_constant_reprocessing"
Expand Down
3 changes: 2 additions & 1 deletion tests/integration_tests/run_no_reprocessing/test_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"depcode": {
"codename": "serpent",
"template_input_file_path": "test_input.ini",
"geo_file_paths": ["../../serpent_data/tap_geometry_base.ini"]
"geo_file_paths": ["../../serpent_data/tap_geometry_base.ini"],
"zaid_convention": "serpent"
},
"simulation": {
"sim_name": "test_no_reprocessing",
Expand Down
3 changes: 2 additions & 1 deletion tests/serpent_data/tap_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"depcode": {
"codename": "serpent",
"template_input_file_path": "tap_template.ini",
"geo_file_paths": ["tap_geometry_base.ini"]
"geo_file_paths": ["tap_geometry_base.ini"],
"zaid_convention": "serpent"
},
"simulation": {
"sim_name": "tap_test_simulation_serpent"
Expand Down
Loading