diff --git a/README.md b/README.md
index 78b921b..cd4432a 100644
--- a/README.md
+++ b/README.md
@@ -73,6 +73,7 @@ A few categories of scripts are available:
| generate_endf | ENDF/B | VII.1
VIII.0 | NNDC |
| generate_fendl | FENDL | 3.2b
3.2a
3.2
3.1d
3.1a
3.0 | |
| generate_jendl | JENDL | 4.0
5.0 | |
+| generate_tendl | TENDL | 2023 | |
### Download cross sections
diff --git a/pyproject.toml b/pyproject.toml
index 01a7eb7..000c2d3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -59,6 +59,7 @@ generate_endf = "openmc_data.generate.generate_endf:main"
generate_jeff33 = "openmc_data.generate.generate_jeff33:main"
generate_jendl = "openmc_data.generate.generate_jendl:main"
generate_fendl = "openmc_data.generate.generate_fendl:main"
+generate_tendl = "openmc_data.generate.generate_tendl:main"
generate_endf71_chain_casl = "openmc_data.depletion.generate_endf71_chain_casl:main"
generate_endf_chain = "openmc_data.depletion.generate_endf_chain:main"
diff --git a/src/openmc_data/generate/generate_tendl.py b/src/openmc_data/generate/generate_tendl.py
new file mode 100644
index 0000000..54cc0fc
--- /dev/null
+++ b/src/openmc_data/generate/generate_tendl.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+
+"""
+Download TENDL data from PSI and convert it to a HDF5 library for
+use with OpenMC.
+"""
+
+import argparse
+import ssl
+from multiprocessing import Pool
+from pathlib import Path
+from urllib.parse import urljoin
+
+import openmc.data
+from openmc_data import download, extract, process_neutron, state_download_size, all_release_details
+
+
+class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter,
+ argparse.RawDescriptionHelpFormatter):
+ pass
+
+
+parser = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=CustomFormatter
+)
+parser.add_argument('-d', '--destination', type=Path, default=None,
+ help='Directory to create new library in')
+parser.add_argument('--download', action='store_true',
+ help='Download files')
+parser.add_argument('--no-download', dest='download', action='store_false',
+ help='Do not download files')
+parser.add_argument('--extract', action='store_true',
+ help='Extract tar/zip files')
+parser.add_argument('--no-extract', dest='extract', action='store_false',
+ help='Do not extract tar/zip files')
+parser.add_argument('--libver', choices=['earliest', 'latest'],
+ default='latest', help="Output HDF5 versioning. Use "
+ "'earliest' for backwards compatibility or 'latest' for "
+ "performance")
+parser.add_argument('-r', '--release', choices=["2023"], default="2023",
+ help="The nuclear data library release version. "
+ "The options currently supported are 2023")
+parser.add_argument('--cleanup', action='store_true',
+ help="Remove download directories when data has "
+ "been processed")
+parser.add_argument('--no-cleanup', dest='cleanup', action='store_false',
+ help="Do not remove download directories when data has "
+ "been processed")
+parser.set_defaults(download=True, extract=True, cleanup=False)
+args = parser.parse_args()
+
+
+def main():
+
+ library_name = 'tendl'
+
+ cwd = Path.cwd()
+
+ endf_files_dir = cwd.joinpath('-'.join([library_name, args.release, 'endf']))
+ download_path = cwd.joinpath('-'.join([library_name, args.release, 'download']))
+ # the destination is decided after the release is known
+ # to avoid putting the release in a folder with a misleading name
+ if args.destination is None:
+ args.destination = Path('-'.join([library_name, args.release, 'hdf5']))
+
+ # This dictionary contains all the unique information about each release.
+ # This can be exstened to accommodated new releases
+ details = all_release_details[library_name][args.release]['neutron']['endf']
+
+ # ==============================================================================
+ # DOWNLOAD FILES FROM WEBSITE
+
+ if args.download:
+ state_download_size(details['compressed_file_size'], details['uncompressed_file_size'], 'GB')
+ for f in details['compressed_files']:
+ # Establish connection to URL
+ download(
+ urljoin(details['base_url'], f),
+ context=ssl._create_unverified_context(),
+ output_path=download_path,
+ as_browser=True
+ )
+
+ # ==============================================================================
+ # EXTRACT FILES FROM TGZ
+ if args.extract:
+ extract(
+ compressed_files=[download_path/ f for f in details['compressed_files']],
+ extraction_dir=endf_files_dir,
+ del_compressed_file=args.cleanup
+ )
+
+ # ==============================================================================
+ # GENERATE HDF5 LIBRARY -- NEUTRON FILES
+
+ # Get a list of all ENDF files
+ neutron_files = endf_files_dir.glob('*.tendl')
+
+ # Create output directory if it doesn't exist
+ args.destination.mkdir(parents=True, exist_ok=True)
+
+ library = openmc.data.DataLibrary()
+
+ with Pool() as pool:
+ results = []
+ for filename in sorted(neutron_files):
+ func_args = (filename, args.destination, args.libver)
+ r = pool.apply_async(process_neutron, func_args)
+ results.append(r)
+
+ for r in results:
+ r.wait()
+
+ # Register with library
+ for p in sorted((args.destination).glob('*.h5')):
+ library.register_file(p)
+
+ # Write cross_sections.xml
+ library.export_to_xml(args.destination / 'cross_sections.xml')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/openmc_data/urls.py b/src/openmc_data/urls.py
index 47669ef..c87cba8 100644
--- a/src/openmc_data/urls.py
+++ b/src/openmc_data/urls.py
@@ -48,6 +48,18 @@
}
}
},
+ "2023": {
+ "neutron": {
+ "endf": {
+ "base_url": "https://tendl.web.psi.ch/tendl_2023/tar_files/",
+ "compressed_files": ["TENDL-n.2024new.tgz"],
+ "neutron_files": "tendl24c/*",
+ "metastables": "tendl24c/*m",
+ "compressed_file_size": 3.1,
+ "uncompressed_file_size": 20,
+ }
+ }
+ },
},
"fendl": {
"3.2c": {