diff --git a/src/DataLib/EAFLib.C b/src/DataLib/EAFLib.C index 616843fb2..678739119 100644 --- a/src/DataLib/EAFLib.C +++ b/src/DataLib/EAFLib.C @@ -58,7 +58,7 @@ void EAFLib::extract(char* input, float* value) char section[32]; /* find beginning of exponent */ - int expStart = strcspn(input,"+-"); + int expStart = strcspn(input+1,"+-") + 1; /* extract mantissa portion to string variable */ strncpy(section,input,expStart); @@ -393,18 +393,45 @@ int EAFLib::getTransData() /* read the head of the file and get the following info: * - Title * and then advance to first isotope */ -void EAFLib::getDecayInfo() +int EAFLib::parse_MT(const char* buffer) { + int MT_start = 72; + int MT_length = 3; + + if (strlen(buffer) < MT_start + MT_length) return -1; + + char mtField[4] = {0}; + strncpy(mtField, buffer + MT_start, MT_length); + return atoi(mtField); +} + + void EAFLib::getDecayInfo() { char buffer[MAXLINELENGTH]; - int junkInt,i; + int MT = -1; - /* read number of initial comment lines */ - inDecay >> junkInt; + std::streampos lineStart; - /* read end of this line and comment lines */ - for (i=0;i<=junkInt;i++) - inDecay.getline(buffer,MAXLINELENGTH); + lineStart = inDecay.tellg(); + if (inDecay.getline(buffer, MAXLINELENGTH)) + { + MT = parse_MT(buffer); + } + + while (inDecay && MT != 457) + { + lineStart = inDecay.tellg(); + + if (!inDecay.getline(buffer, MAXLINELENGTH)) + break; + + MT = parse_MT(buffer); + } + + if (MT == 457) + { + inDecay.seekg(lineStart); + } decayKza = new int[MAXEAFDCYMODES]; memCheck(decayKza,"EAFLib::getDecayInfo(...): decayKza"); @@ -433,14 +460,22 @@ int EAFLib::getDecayData() float pBranch, aBranch, dIsoFlag; - do - { - /* scan for first 457 card */ - inDecay.getline(buffer,MAXLINELENGTH); - /* extract the MT number of this line */ - buffer[75] = '\0'; - MT = atoi(buffer+72); - } while (MT != 457 && !inDecay.eof()); + MT = -1; + + /* prime loop with first MT value */ + if (inDecay.getline(buffer, MAXLINELENGTH)) + { + MT = parse_MT(buffer); + } + + /* scan for first 457 card */ + while (MT != 457 && !inDecay.eof()) + { + if (!inDecay.getline(buffer, MAXLINELENGTH)) + break; + + MT = parse_MT(buffer); + } if (inDecay.eof()) { @@ -552,15 +587,18 @@ int EAFLib::getDecayData() numSpec = getGammaData(); /* skip to end of this file section */ - do - { - /* scan for last 457 card */ - inDecay.getline(buffer,MAXLINELENGTH); - /* extract the MT number of this line */ - buffer[75] = '\0'; - MT = atoi(buffer+72); - } while (MT == 457 && !inDecay.eof()); + if (inDecay.getline(buffer, MAXLINELENGTH)) + { + MT = parse_MT(buffer); + } + while (MT == 457 && !inDecay.eof()) + { + if (!inDecay.getline(buffer, MAXLINELENGTH)) + break; + + MT = parse_MT(buffer); + } debug(6,"Returning %d decay branches for %d.",nDRxns,zak); diff --git a/src/DataLib/EAFLib.h b/src/DataLib/EAFLib.h index 528277f28..74136e0bc 100644 --- a/src/DataLib/EAFLib.h +++ b/src/DataLib/EAFLib.h @@ -120,6 +120,7 @@ class EAFLib : public ASCIILib void readDiscreteGammas(int, int, float, char*); void readContGammas(int, float, char*); int getGammaData(); + int parse_MT(const char* ); /* Interface from ASCIILib */ void getTransInfo(); @@ -127,7 +128,6 @@ class EAFLib : public ASCIILib int getTransData(); int getDecayData(); - public: /* Service */ diff --git a/tools/ALARAJOYWrapper/README.md b/tools/ALARAJOYWrapper/README.md index 77c5f30fb..8d0806e74 100644 --- a/tools/ALARAJOYWrapper/README.md +++ b/tools/ALARAJOYWrapper/README.md @@ -1,6 +1,6 @@ -# FENDL3 Preprocessor with NJOY Wrapping for ALARA (*ALARAJOYWrapper*) +# FENDL3.2x Preprocessor with NJOY Wrapping for ALARA (*ALARAJOYWrapper*) -This preprocessor is designed to update ALARA's data input capabilities for updated FENDL3.2x data sets formatted as TENDL (ENDF-6) files. Unlike previous versions of [FENDL](https://www-nds.iaea.org/fendl_library/websites/fendl32b/) (Fusion Evaluated Nuclear Data Library), which have available groupwise cross-section data for neutron activation, as is required for ALARA's functionality, FENDL3 data requires conversion to that format. +This preprocessor is designed to update ALARA's data input capabilities for updated FENDL3.2x data sets formatted as TENDL (ENDF-6) files. Unlike previous versions of [FENDL](https://www-nds.iaea.org/fendl/) (Fusion Evaluated Nuclear Data Library), which have available groupwise cross-section data for neutron activation, as is required for ALARA's functionality, FENDL3.2x data requires conversion to that format. This preprocessor uses [NJOY 2016](https://github.com/njoy/NJOY2016) Nuclear Data Processing System to produce requisite pointwise data (PENDF) to subsequntly convert to the Vitamin-J 175 energy group groupwise format (GENDF) for activation cross-sections and to handle the processed data to be fed back to ALARA. For pointwise conversion, ALARAJOYWrapper uses the NJOY modules MODER, RECONR, BROADR, UNRESR, and GASPR, and for the ultimate conversion to the groupwise format, GROUPR. Note that in order to properly handle isomeric reactions, NJOY 2016 has to be built with from the commit `1dbce787` or newer of the `develop` branch, which includes the necessary support for holistic isomer handling. @@ -21,19 +21,38 @@ This preprocessor uses [NJOY 2016](https://github.com/njoy/NJOY2016) Nuclear Dat * [Pandas](https://pandas.pydata.org/docs/getting_started/install.html) - Domain-specific packages * [ENDFtk](https://github.com/njoy/ENDFtk) - * [NJOY 2016](https://github.com/njoy/NJOY2016) (built with `develop` branch) + * [NJOY 2016](https://github.com/njoy/NJOY2016) (at Git hash `1dbce787`) -## Usage -This preprocessor can and should be used independently of any ALARA run. While the data format produced from ALARAJOYWrapper is necessary to run `convert_lib` on ALARA to convert TENDL data to an ALARA binary, once the user has a space-delimited DSV file produced from this preprocessor, usage of this preprocessor is not strictly necessary for the particular isotopes processed by the user. -ALARAJOYWrapper is designed to produce a space-delimited DSV containing data that can be directly read by the ALARA data library, ALARAJOY, without any further processing. +## Data Acquisition + +Activation/inventory solvers such as ALARA require both neutron activation cross-sections and decay data. ALARAJOYWrapper is designed with the specific intent for processing FENDL3.2x data in a format readable by ALARA, corresponding to TENDL-2017 activation cross-sections and UKDD-2020 decay data. Nevertheless, to create custom ALARA libraries, any combination of TENDL and EAF or UKDD data can be supplied to ALARAJOYWrapper. + +Many decay data libraries are distributed in repositories containing individual data files for each nuclide in the library. ALARA requires a single decay data file, so ALARAJOYWrapper can also compile these data libraries into a single file referable by `decayFname` (see _Application of Processed Data to ALARA Data Conversion Methods_ below). + +- Activation Cross-Sections + * [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. + +- Decay Data + * EAF + - [EAF-2010](https://git.oecd-nea.org/fispact/nuclear_data/EAF2010data.tar.bz2) (Must separate out ` eaf_dec_20100.0*` from the rest of the files after unzipping) + - [EAF-4.1](https://nds.iaea.org/fendl20/fen-decay.htm) (FENDL2.x decay library) + * UKDD + - [UKDD-20](https://www.oecd-nea.org/dbdata/fispact/decay2020.tar.bz2) (FENDL3.2x decay library) + - [UKDD-12](https://git.oecd-nea.org/fispact/nuclear_data/decay.tar.bz2) + + +## Usage +This preprocessor can and should be used independently of any ALARA run. While the data format produced from ALARAJOYWrapper is necessary to run `convert_lib` on ALARA to convert TENDL data to an ALARA binary, once the user has a space-delimited DSV file produced from this preprocessor, usage of this script is not strictly necessary for the particular isotopes processed by the user. -To run this preprocessor, the user must first have acquired TENDL files for each isotope from a selected [TENDL distribution](https://tendl.imperial.ac.uk/). While this tool is designed specifically for the purpose of making FENDL3.2x activation data available to be used in ALARA, the formatting of TENDL 2017 is not unique to that release, and users can apply any version of TENDL desired from the Imperial College London TENDL database to be processed in the ALARAJOY format. Otherwise, [TENDL 2017](https://tendl.imperial.ac.uk/tendl_2017/tendl2017.html) is the source for FENDL3.2x neutron activation data and is the standard intended input for this tool. All TENDL files to be processed must be in the same directory as each other to be properly identified by ALARAJOYWrapper. +ALARAJOYWrapper is designed to produce a space-delimited DSV containing cross-data that can be directly read by the ALARA data library, ALARAJOY, without any further processing. Running ALARAJOYWrapper can be done with one Python command: ``` -python preprocess_fendl3.py -f /path/to/fendl3_data_dir/ -d /path/to/eaf_decay_library/ -a +python preprocess_fendl3.py -f /path/to/fendl3_data_dir/ -d /path/to/eaf_decay_library/ decay_library_type -a ``` To read in detail about each of these arguments, call this command: ``` @@ -42,7 +61,7 @@ python preprocess_fendl3.py -h ## Data Output -Running `preprocess_fendl3.py` will return the file path to the resultant space-delimited DSV file containing transmutation reaction pathways for the neutron activation of the given isotope(s). Each row in the DSV represents a different reaction, and contains the following data needed by ALARA for a library conversion: +Running `preprocess_fendl3.py` will produce two file paths. The first is to the compiled decay data file, which will either be identical to the input for the first argument in `-d` if a pre-compiled decay library is being used or to the newly produced compiled decay library. The second is to the resultant space-delimited DSV file containing transmutation reaction pathways for the neutron activation of the given isotope(s). Each row in the DSV represents a different reaction, and contains the following data needed by ALARA for a library conversion: - Parent KZA: Unique isotope identifier for the parent isotope in the format **ZZAAAM**, where ZZ is the isotope's atomic number, AAA is the mass number, and M is the isomeric state (0 if non-excited). - Daughter KZA: Unique isotope identifier of the daughter isotope produced from a particular transmutation reaction in the format **ZZAAAM**. @@ -69,7 +88,7 @@ Data library conversion to ALARA binary libraries is done with the `convert_lib` wherein: - `ajoylib` is the library value for ALARAJOY - `transFname` is the file path to the DSV containing the preprocessed FENDL3 transmutation data -- `decayFname` is the file path to EAF decay data. +- `decayFname` is the file path to the compiled EAF or UKDD decay library, which may be produced by ALARAJOYWrapper. - `alaraFname` is the file path template for resultant ALARA data libraries (.lib, .idx. .gam, .gdx) The ALARA run for library conversion should precede and be independent from subsequent activation calculations with ALARA, as specified in the [ALARA Users' Guide](https://svalinn.github.io/ALARA/usersguide/index.html): diff --git a/tools/ALARAJOYWrapper/preprocess_fendl3.py b/tools/ALARAJOYWrapper/preprocess_fendl3.py index c195d6576..08d866f90 100644 --- a/tools/ALARAJOYWrapper/preprocess_fendl3.py +++ b/tools/ALARAJOYWrapper/preprocess_fendl3.py @@ -11,15 +11,14 @@ def args(): parser = argparse.ArgumentParser() parser.add_argument( - '--decay_lib', '-d', required=True, nargs=1, + '--decay_lib', '-d', required=True, nargs=2, help=(''' - Required argument to direct ALARAJOYWrapper to an EAF decay - library or directory containing EAF decay files for - individual nuclides. Necessary for cross-referencing short- - lived isomeric daughters against known half-life data. - - Note: If using --decay_lib to direct to a directory of EAF - decay files, all files must have the extension ".dat". + Required argument pair to direct ALARAJOYWrapper to a decay data + library. The first part of the argument is the path to either + an EAF or UKDD pre-compiled decay file or a repository + containing multiple decay files to be compiled internally. See + the README.md for access to various decay library + distributions. ''') ) parser.add_argument( @@ -99,7 +98,7 @@ def process_pendf( def process_gendf( njoy_groupr_input, material_id, MTs, mt_dict, - temperature, pKZA, isomer_dict, all_rxns, eaf_nucs + temperature, pKZA, isomer_dict, all_rxns, all_nucs ): """ Prepare and run NJOY run with GROUPR and iteratively extract cross-section @@ -134,8 +133,8 @@ def process_gendf( } } } - eaf_nucs (dict): Dictionary keyed by all radionuclides in the EAF - decay library, with values of their half-lives. + 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 @@ -165,7 +164,7 @@ def process_gendf( if gendf_MTs: all_rxns = tp.iterate_MTs( gendf_MTs, mt_dict, xs_line_dict, pKZA, - all_rxns, eaf_nucs, isomer_dict, gendf_path + all_rxns, all_nucs, isomer_dict ) print(f'Finished processing {element}-{A}') @@ -331,7 +330,22 @@ def main(): temperature = args().temperature[0] mt_dict = rxd.process_mt_data(rxd.load_mt_table(dir / 'mt_table.csv')) - eaf_nucs = rxd.find_eaf_ref_data(Path(args().decay_lib[0])) + decay_path, decay_lib_type = args().decay_lib + ukdd_options = ['ukdd', 'ukaeadd', 'decay_2020', 'decay_2012'] + if decay_lib_type.lower() in ukdd_options: + decay_lib_type = 'ukdd' + + if decay_lib_type.lower() not in ['ukdd', 'eaf']: + raise ValueError( + 'Invalid library type. Must be either an EAF or UKDD release.' + ) + + decay_path = Path(decay_path) + if decay_path.is_dir(): + rxd.resolve_decay_file_formatting_issues(decay_path, decay_lib_type) + decay_path = rxd.compile_decay_lib(decay_path, decay_lib_type, dir) + + all_nucs = rxd.find_nucs_from_decay_lib(decay_path) all_rxns = defaultdict(lambda: defaultdict(dict)) for file_properties in tp.search_for_files(search_dir): @@ -356,7 +370,7 @@ def main(): if not njoy_prep_error: all_rxns = process_gendf( njt.groupr_input, material_id, MTs, mt_dict, - temperature, pKZA, isomer_dict, all_rxns, eaf_nucs + temperature, pKZA, isomer_dict, all_rxns, all_nucs ) else: @@ -375,7 +389,10 @@ def main(): dsv_path = dir / 'cumulative_gendf_data.dsv' write_dsv(dsv_path, gas_filtered) - print(f'Reaction data saved to: {dsv_path}') + + print('-' * 20) + print(f'Compiled decay data: {decay_path}') + print(f'Reaction cross-sections: {dsv_path}') if __name__ == '__main__': main() \ No newline at end of file diff --git a/tools/ALARAJOYWrapper/reaction_data.py b/tools/ALARAJOYWrapper/reaction_data.py index aa590d335..3d78fea9f 100644 --- a/tools/ALARAJOYWrapper/reaction_data.py +++ b/tools/ALARAJOYWrapper/reaction_data.py @@ -21,6 +21,9 @@ 'kza' : [10010, 10020, 10030, 20030, 20040], 'total_mt' : range(203, 207 + 1) }) +DECAY_MF = 8 +DECAY_MT = 457 +TEND_RECORD = ' ' * 68 + '-1 0 0 0' # Track edge cases of unquantifiable MT reaction types spec_reactions = [ @@ -252,13 +255,111 @@ def process_mt_data(mt_dict): return mt_dict -def eaf_float(num_str): +def resolve_decay_file_formatting_issues(decay_dir, decay_lib_type): + """ + Check a decay file to identify and resolve formatting inconsistencies, + which include blank lines, missing TEND records, and files not ending + in newlines. For single-nuclide decay files contained in UKDD decay + data distributions, rename files by their KZA so that they can be + later compiled by ascending KZA value, as expected by EAFLib for decay + library processing. + + Arguments: + decay_dir (pathlib._local.PosixPath): Filepath to the directory + exclusively containing decay data files for either an EAF or UKDD + decay library. + decay_lib_type (str): Identifier tag for either EAF or UKDD data. + + Returns: + None + """ + + from tendl_processing import calculate_KZA_from_ENDF + + ukdd_options = ['ukdd', 'ukaeadd', 'decay_2020', 'decay_2012'] + if decay_lib_type.lower() in ukdd_options: + decay_lib_type = 'ukdd' + + for decay_file in decay_dir.iterdir(): + if '.DS_Store' in str(decay_file): + decay_file.unlink() + continue + + with open(decay_file, 'r') as f: + lines = f.readlines() + + # Remove blank lines + updated_lines = [line for line in lines if line.strip()] + + # Include missing TEND Records + if TEND_RECORD.strip().rstrip('0').strip() not in updated_lines[-1]: + tend_line = TEND_RECORD + if not updated_lines[-1].endswith('\n'): + tend_line = '\n' + tend_line + updated_lines.append(tend_line) + + # Ensure file ends with a newline + if not updated_lines[-1].endswith('\n'): + updated_lines[-1] += '\n' + + # Overwrite file if changes were made + if lines != updated_lines: + with open(decay_file, 'w') as f: + f.writelines(updated_lines) + + # Rename decay file to the KZA value so that a sorted decay directory + # iteration will go in order of ascending KZA + if decay_lib_type == 'ukdd': + kza = calculate_KZA_from_ENDF(decay_file, DECAY_MF, DECAY_MT) + decay_file.rename(decay_dir / str(kza)) + +def compile_decay_lib(decay_dir, decay_lib_type, dir): + """ + Iteratively compile the data from individual-nuclide decay files into a + single file in ascending order of KZA. Can either be an EAF or UKDD + decay library. + + Arguments: + decay_dir (pathlib._local.PosixPath): Filepath to the directory + exclusively containing decay data files for either an EAF or UKDD + decay library. + decay_lib_type (str): Identifier tag for either EAF or UKDD data. + dir (pathlib._local.PosixPath): Path to the current working directory + (CWD) from which the command was called. + + Returns: + compiled_file (pathlib._local.PosixPath): Path to the compiled decay + library file. + """ + + compiled_file = dir / f'{decay_dir}_compiled' + compiled_file.unlink(missing_ok=True) + + sorted_filepaths = sorted(decay_dir.iterdir()) + if decay_lib_type == 'ukdd': + sorted_KZAs = sorted([int(p.stem) for p in sorted_filepaths]) + sorted_filepaths = [decay_dir / str(kza) for kza in sorted_KZAs] + + for decay_file in sorted_filepaths: + with open(decay_file, 'r') as f: + lines = f.readlines() + + with open(compiled_file, 'a') as f: + f.writelines(lines) + + print( + f'Compiled {decay_lib_type.upper()} decay libary to {compiled_file}.' + ) + + return compiled_file + +def standardize_float(num_str): """ Process non-uniformly formatted scientific notation numbers from parsed - EAF data to standard floating point numbers. + decay data to standard floating point numbers. Arguments: - num_str (str): Number from an EAF file with non-uniform formatting. + num_str (str): Number from an decay file with non-uniform formatting. Returns: num (float): Reformatted number to be able to be properly converted to @@ -293,63 +394,62 @@ def get_MT_from_line(line): return int(line[72:75]) -def find_eaf_ref_data(eaf_path): +def find_nucs_from_decay_lib(compiled_decay_lib): """ - Parse through an EAF file to build a dictionary keyed by all radionuclides - with their respective half-lives as the values. Modeled after the - file parsing methods in ALARA/src/DataLib/EAFLib.C. + Parse through an pre-compiled decay library file to build a dictionary + keyed by all radionuclides with their respective half-lives as the + values. Modeled after the file parsing methods in + ALARA/src/DataLib/EAFLib.C. Arguments: - eaf_path (pathlib._local.PosixPath): Filepath to an EAF decay library - or directory containing individual nuclide-decay data files - formatted with a ".dat" extension. + compiled_decay_lib (pathlib._local.PosixPath): Filepath to a pre- + compiled decay library. Must be either an EAF decay library (i.e. + EAF4.1, EAF2010, etc.) or a UKDD decay library (UKDD-12, UKDD-20). Returns: - eaf_nucs (dict): Dictionary keyed by all radionuclides in the EAF - decay library, with values of their half-lives. + all_nucs (dict): Dictionary keyed by all nuclide KZAs in the decay + library, with values of their half-lives (-1 for stable nuclides). """ - radionucs = {} - decay_MT = 457 + all_nucs = {} + with open(compiled_decay_lib, 'r') as f: + + # Read header and skip introductory comment lines + first_line = f.readline().strip() + try: + n_comment_lines = int(first_line.split()[0]) + except ValueError: + n_comment_lines = 1 + + for _ in range(n_comment_lines): + f.readline() + + _in_decay_block = False + line = f.readline() + + while line: + MT = get_MT_from_line(line) + if not _in_decay_block and MT == DECAY_MT: + _in_decay_block = True + + # Parse nuclide KZA + za = int(standardize_float(line[:11])) + M = int(line[33:44].strip()) + kza = za * 10 + M + stability = int(line[44:56].strip()) # 0->unstable , 1->stable + + # Read half-life (next line) + line = f.readline() + if stability == 0: + thalf = standardize_float(line[:11]) + all_nucs[kza] = thalf - for eaf in (eaf_path.glob('*.dat') if eaf_path.is_dir() else [eaf_path]): - with open(eaf, 'r') as f: - - # Read header and skip introductory comment lines - first_line = f.readline().strip() - try: - n_comment_lines = int(first_line.split()[0]) - except ValueError: - n_comment_lines = 1 + else: + all_nucs[kza] = -1 - for _ in range(n_comment_lines): - f.readline() + elif MT != DECAY_MT: + _in_decay_block = False - _in_decay_block = False line = f.readline() - while line: - - # Radionuclide processing - MT = get_MT_from_line(line) - - if not _in_decay_block and MT == decay_MT: - _in_decay_block = True - - # Parse nuclide KZA - za = int(eaf_float(line[:11])) - M = int(line[33:44].strip()) - kza = za * 10 + M - - # Read half-life (next line) - line = f.readline() - thalf = eaf_float(line[:11]) - if thalf > 0: - radionucs[kza] = thalf - - elif MT != decay_MT: - _in_decay_block = False - - line = f.readline() - - return radionucs \ No newline at end of file + return all_nucs \ No newline at end of file diff --git a/tools/ALARAJOYWrapper/tendl_processing.py b/tools/ALARAJOYWrapper/tendl_processing.py index c8bfe8b93..0f25f26f2 100644 --- a/tools/ALARAJOYWrapper/tendl_processing.py +++ b/tools/ALARAJOYWrapper/tendl_processing.py @@ -384,16 +384,16 @@ def incrementally_deexcite_isomer(M, dKZA, eaf_nucs): return dKZA + trial_M def iterate_MTs( - MTs, mt_dict, xs_line_dict, pKZA, all_rxns, eaf_nucs, isomer_dict, gendf_path + MTs, mt_dict, xs_line_dict, pKZA, all_rxns, all_nucs, isomer_dict ): """ Iterate through all of the MTs present in a given GENDF file to extract the necessary data to be able to run ALARA. For isomeric daughters with an excited state less than 10 that do not have known half-lives (determined by the keys of radionucs, itself derived from the provided - EAF decay library), this function assumes a infinitesimal half-life - with discrete deexcitations to the next lowest isomeric state, until - reaching a level with a known half-life. As such, the cross-sections + decay library), this function assumes a infinitesimal half-life with + discrete deexcitations to the next lowest isomeric state, until + reaching a level with a known half-life or the ground state. As such, the cross-sections for these isomer daughters are accumulated to the appropriate isomeric state cross-sections by energy group. @@ -415,16 +415,14 @@ def iterate_MTs( } } } - eaf_nucs (dict): Dictionary keyed by all radionuclides in the EAF - decay library, with values of their half-lives. + all_nucs (dict): Dictionary keyed by all nuclide KZAs in the decay + library, with values of their half-lives (-1 for stable nuclides). isomer_dict (collections.defaultdict): Dictionary keyed by reaction type (MT), with each MT containing a subdictionary of the MF from which the isomeric pathways are extracted. At the lowest MT/MF level has a list of all isomeric states of possible daughter nuclides for which there are cross-section data in the original TENDL file. - gendf_path (pathlib._local.PosixPath): Path to the GENDF file from - which to extract groupwise cross-sections. Returns: all_rxns (collections.defaultdict): Updated dictionary for all @@ -460,7 +458,7 @@ def iterate_MTs( if M > 0: emitted += '*' - if dKZA in eaf_nucs or M == 0: + if dKZA in all_nucs: all_rxns[pKZA][dKZA][str(MT) + '*' * M] = { 'emitted' : emitted, 'xsections' : sigmas @@ -472,9 +470,13 @@ def iterate_MTs( if M > 1: dKZA = incrementally_deexcite_isomer( - M, dKZA, eaf_nucs + M, dKZA, all_nucs ) + # Skip daughters without decay data + if dKZA not in all_nucs: + continue + if dKZA not in all_rxns[pKZA]: all_rxns[pKZA][dKZA] = defaultdict(dict)