Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/DataLib/ALARAJOY.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ void ALARAJOYLib::loadDSVData()

// Read header containing energy group number in first entry
std::string groupName;
inTrans >> nGroups >> groupName;
std::string processingCode;
inTrans >> nGroups >> groupName >> processingCode;

// Extract Parent KZA until EOF at pKZA == -1
while ((inTrans >> row.parentKZA) && row.parentKZA != -1)
Expand Down
6 changes: 5 additions & 1 deletion tools/ALARAJOYWrapper/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Many decay data libraries are distributed in repositories containing individual
* [TENDL](https://tendl.imperial.ac.uk/)
- Usable with any TENDL release
- For FENDL3.2x processing, [TENDL 2017](https://tendl.imperial.ac.uk/tendl_2017/tendl2017.html) is the standard version.
* [PREPRO-Processed TENDL Data (FISPACT-II)](https://git.oecd-nea.org/fispact/nuclear_data)
- Nuclear data repository for use specifically with FISPACT-II.
- TENDL 2017/14 availble.
- Convertable to ALARAJOY-readable DSV file by calling `preprocess_fendl3` with `-n` flag.

- Decay Data
* EAF
Expand All @@ -55,7 +59,7 @@ ALARAJOYWrapper is designed to produce a space-delimited DSV containing cross-da

Running ALARAJOYWrapper can be done with one Python command:
```
python preprocess_fendl3.py -f /path/to/fendl3_data_dir/ -d /path/to/decay_library/ decay_library-type -g group_name -a -t -r -p
python preprocess_fendl3.py -f /path/to/fendl3_data_dir/ -d /path/to/decay_library/ decay_library-type -g group_name -a -t -r -p -n
```
To read in detail about each of these arguments, call this command:
```
Expand Down
188 changes: 145 additions & 43 deletions tools/ALARAJOYWrapper/preprocess_fendl3.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ def make_argparser():
sections from the original TENDL file.
''')
)
parser.add_argument(
'--nea_prepro', '-n', action='store_true',
help=('''
Option to convert PREPRO-formatted CCFE-709 groupwise data into
an ALARAJOY-formatted DSV. If true, must also provide the path to
the directory containing PREPRO .asc GENDF files for the `-f`
argument.
''')
)
return parser

def configure_logging(redirect_warnings=False):
Expand Down Expand Up @@ -226,7 +235,7 @@ def process_pendf(

def process_gendf(
njoy_groupr_input, material_id, MTs, mt_dict, temperature, pKZA,
isomer_dict, all_rxns, all_nucs, group_name, tendl_dir,
isomer_dict, all_rxns, all_nucs, group_name, tendl_dir, gendf_parser,
ign=17, ngn='', egn=''
):
"""
Expand Down Expand Up @@ -299,7 +308,8 @@ def process_gendf(
if gendf_path:
# Extract MT values again from GENDF file as there may be some
# difference from the original MT values in the ENDF/PENDF files
non_zero_xs, gendf_MTs, nGroups = tp.extract_gendf_data(gendf_path)
gendf_dict, nGroups, _ = gendf_parser.parse(gendf_path)
gendf_MTs = gendf_dict[3]['MTs']

# Conditionally save group bounds from NJOY/GROUPR output
if not Path(group_name.split()[-1]).is_file():
Expand All @@ -313,12 +323,13 @@ def process_gendf(
f'GENDF file missing MTs {diffs} present in the ' \
f'original TENDL file for {element}-{A}.'
)

if gendf_MTs:
all_rxns = tp.iterate_MTs(
gendf_MTs, mt_dict, non_zero_xs, pKZA,
all_rxns, all_nucs, isomer_dict, nGroups
gendf_dict, mt_dict, pKZA, all_rxns, all_nucs, nGroups,
isomer_dict=isomer_dict
)
print(f'Finished processing {element}-{A}')
notify_nuc_completion(element, A)

else:
warnings.warn(
Expand All @@ -336,6 +347,78 @@ def process_gendf(

return all_rxns, nGroups

def notify_nuc_completion(element, A):
"""
Print to output stream to notify the completion of all processing for a
single nuclide.

Arguments:
element (str): Chemical symbol of the nuclide whose data was
processed.
A (str): Mass number for the provided nuclide, including an "m" or "n"
for the first two isomeric states, if applicable.

Returns:
None
"""

print(f'Finished processing {element}-{A}')

def collect_all_prepro_TENDL_data(
prepro_tendl_dir, mt_dict, all_rxns, all_nucs
):
"""
As an alternate pathway to the standard NJOY-based processing procedure,
if the path to a directory containing PREPRO-processed groupwise TENDL
files is provided as the `-f` argument and the `-n` flag is included
when running `main()`, then the reaction data from these files are
parsed and stored directly to `all_rxns`. Nuclear data of this format
is usable by FISPACT-II and is disbtributed through the NEA GitLab
(https://git.oecd-nea.org/fispact/nuclear_data/), with options for
both TENDL-2017 and TENDL-2014.

Arguments:
prepro_tendl_dir (pathlib._local.PosixPath): Path to the directory
containing PREPRO-processed TENDL data files.
mt_dict (dict): Dictionary formatted data structure for mt_table.csv.
all_rxns (collections.defaultdict): Hierarchical dictionary keyed by
parent nuclides to store all reaction data, with structured as:
{parent:
{daughter:
{MT:
{
'emitted': (str of emitted particles)
'xsections': (array of groupwise XS)
}
}
}
}
all_nucs (dict): Dictionary keyed by all nuclide KZAs in the decay
library, with values of their half-lives (-1 for stable nuclides).

Returns:
all_rxns (collections.defaultdict): Updated dictionary for all
reactions and sub-pathways for all nuclides with TENDL files
present in `prepro_tendl_dir`.
nGroups (int): Number of energy groups into which the groupwise cross
sections were calculated.
"""

# File format from FISPACT NEA GitLab: {element}{A}g.asc
# ("g" for "groupwise")
for gendf_path in sorted(prepro_tendl_dir.glob(f'*g.asc')):
gendf_dict, nGroups, pKZA = tp.GENDFParser(
MFs=[3,10], prepro=True
).parse(gendf_path)

all_rxns |= tp.iterate_MTs(
gendf_dict, mt_dict, pKZA, all_rxns, all_nucs, nGroups,
prepro=True
)
notify_nuc_completion(*tp.interpret_KZA(pKZA))

return all_rxns, nGroups

def subtract_gas_from_totals(all_rxns):
"""
For any reaction that produces a gas daughter, subtract the individual
Expand Down Expand Up @@ -429,7 +512,8 @@ def rxn_to_str(parent, daughter, MT, rxn):
return dsv_row + ' '.join(str(xs) for xs in rxn['xsections'])

def store_results(
dsv_path, all_rxns, nGroups, tendl_dir, group_name, plotting
dsv_path, all_rxns, nGroups, tendl_dir,
group_name, processing_code, plotting
):
"""
Save groupwise-converted cross-section data to a space-delimited DSV file
Expand Down Expand Up @@ -471,6 +555,9 @@ def store_results(
group_name (str): Name of the group structure according to which
GROUPR converted continuous energy cross-sections to groupwise
cross-sections.
processing_code (str): Name of the nuclear data processing code used.
NJOY for standard ALARAJOY workflow, PREPRO if `-n` flag is
applied for FISPACT-II formatted TENDL data.
plotting (bool): Boolean to set whether to produce cross-section
plots.

Expand All @@ -479,7 +566,7 @@ def store_results(
"""

with open(dsv_path, 'w') as dsv:
dsv.write(f'{nGroups} {group_name}\n')
dsv.write(f'{nGroups} {group_name} {processing_code}\n')
for parent in sorted(all_rxns):
element, A = tp.interpret_KZA(parent)
for daughter in all_rxns[parent]:
Expand Down Expand Up @@ -577,48 +664,63 @@ def main():
all_nucs = rxd.find_nucs_from_decay_lib(decay_path)
all_rxns = defaultdict(lambda: defaultdict(dict))

unresr_err_cases = []
for file_properties in tp.search_for_files(search_dir):
element, A, pKZA, endf_path = tuple(file_properties.values())
TAPE20.write_bytes(endf_path.read_bytes())
endf_file_dict, material_id = tp.parse_endf_file_level_data(TAPE20)
MTs = set(endf_file_dict)
if args.nea_prepro:
group_name = 'CCFE-709'
processing_code = 'PREPRO'
all_rxns, nGroups = collect_all_prepro_TENDL_data(
search_dir, mt_dict, all_rxns, all_nucs
)

if len((MTs - rxd.SPEC_MTS) - endf6_MTs) > 0:
invalid_MTs = sorted((MTs - rxd.SPEC_MTS) - endf6_MTs)
warnings.warn(
f'Invalid MTs in provided TENDL file for ' \
f'{element}{A}: {invalid_MTs}'
else:
processing_code = 'NJOY'
unresr_err_cases = []
gendf_parser = tp.GENDFParser()
for file_properties in tp.search_for_files(search_dir):
element, A, pKZA, endf_path = tuple(file_properties.values())
TAPE20.write_bytes(endf_path.read_bytes())
endf_file_dict, material_id = tp.parse_endf_file_level_data(
TAPE20
)
MTs = set(endf_file_dict)

if len((MTs - rxd.SPEC_MTS) - endf6_MTs) > 0:
invalid_MTs = sorted((MTs - rxd.SPEC_MTS) - endf6_MTs)
warnings.warn(
f'Invalid MTs in provided TENDL file for ' \
f'{element}{A}: {invalid_MTs}'
)
MTs = MTs.intersection(endf6_MTs)

MTs, isomer_dict, njoy_prep_error, unresr_err_cases = (
process_pendf(
material_id, MTs, pKZA, mt_dict, temperature,
TAPE20, search_dir, unresr_err_cases
)
)
MTs = MTs.intersection(endf6_MTs)

MTs, isomer_dict, njoy_prep_error, unresr_err_cases = process_pendf(
material_id, MTs, pKZA, mt_dict, temperature,
TAPE20, search_dir, unresr_err_cases
)
if not njoy_prep_error:
all_rxns, nGroups = process_gendf(
njt.groupr_input, material_id, MTs, mt_dict,
temperature, pKZA, isomer_dict, all_rxns,
all_nucs, group_name, search_dir, gendf_parser,
ign=ign, ngn=ngn, egn=egn
)

if not njoy_prep_error:
all_rxns, nGroups = process_gendf(
njt.groupr_input, material_id, MTs, mt_dict, temperature,
pKZA, isomer_dict, all_rxns, all_nucs, group_name, search_dir,
ign=ign, ngn=ngn, egn=egn
)
else:
warnings.warn(
f'''PENDF preparation failed for {element}-{A}.
NJOY error message: {njoy_prep_error}'''
)

else:
njt.cleanup_njoy_files(element, A)

if unresr_err_cases:
warnings.warn(
f'''PENDF preparation failed for {element}-{A}.
NJOY error message: {njoy_prep_error}'''
f'A total of {len(unresr_err_cases)} TENDL files required ' \
'an increase in UNRESR fractional error tolerance for the ' \
f'following nuclides: {unresr_err_cases}'
)

njt.cleanup_njoy_files(element, A)

if unresr_err_cases:
warnings.warn(
f'A total of {len(unresr_err_cases)} TENDL files required ' \
'an increase in UNRESR fractional error tolerance for the ' \
f'following nuclides: {unresr_err_cases}'
)

# Handle gas total production cross-sections, per user specifications
gas_filtered = subtract_gas_from_totals(all_rxns)

Expand All @@ -627,8 +729,8 @@ def main():

dsv_path = dir / 'cumulative_gendf_data.dsv'
store_results(
dsv_path, gas_filtered, nGroups,
search_dir, group_name, args.xs_plotting
dsv_path, gas_filtered, nGroups, search_dir,
group_name, processing_code, args.xs_plotting
)
print(
f'Neutron activation cross-sections converted to {nGroups} groups ' \
Expand Down
Loading
Loading