From cb8914ef3ec1eead55d8d2cda0bc3948af8fb85d Mon Sep 17 00:00:00 2001 From: Grego01 Date: Thu, 5 Feb 2026 10:40:48 -0500 Subject: [PATCH 1/3] sample sandy --- sample_sandy.py | 77 ++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/sample_sandy.py b/sample_sandy.py index 7340aa4d..11aa1538 100755 --- a/sample_sandy.py +++ b/sample_sandy.py @@ -7,6 +7,8 @@ import re import shutil from pathlib import Path +import sandy.sampling +import subprocess import openmc.data @@ -24,6 +26,23 @@ class CustomFormatter( pass +def process_neutron_random(nuc, i, out_dir, in_dir, file_num): # Need to add temperatures + """Process ENDF neutron sublibrary file into HDF5 and write into a + specified output directory.""" + + #fileIn = in_dir / f"{nuc}_{i-1}.endf" + fileIn = in_dir / f"{nuc}_{i-1}.03c" + fileOut = out_dir / f"{nuc}_{i}.h5" + + #data = openmc.data.IncidentNeutron.from_njoy(fileIn) + data = openmc.data.IncidentNeutron.from_ace(fileIn) + data.name = f"{nuc}_{i}" + data.export_to_hdf5(fileOut, "w") + if i % 40 == 0: + print(f"Nuclide {nuc} {i+1}/{file_num} finished") + + + def main(): parser = argparse.ArgumentParser( description=description, formatter_class=CustomFormatter) @@ -75,13 +94,14 @@ def main(): # CHECK IF REQUEST IS VALID AND IF ENDF FILES EXIST prefix = "n-" - suffix = ".endf" + suffix = ".tendl" + #suffix = ".endf" atomic_dict = openmc.data.ATOMIC_NUMBER nuc_dict = {} for nuc in nuclides: - mass_num = int(re.findall("(\d+)", nuc)[0]) + mass_num = int(re.findall(r"(\d+)", nuc)[0]) atomic_sym = "".join([i for i in nuc if not i.isdigit()]) if atomic_sym not in atomic_dict.keys(): print(f"Entered nuclide {nuc} does not have a valid atomic symbol") @@ -89,12 +109,13 @@ def main(): atomic_num = atomic_dict[atomic_sym] file_mass = f"{mass_num:03}" - file_atomic = f"{atomic_num:03}" + #file_atomic = f"{atomic_num:03}" - file_name = f"{prefix}{file_atomic}_{atomic_sym}_{file_mass}{suffix}" + #file_name = f"{prefix}{file_atomic}_{atomic_sym}_{file_mass}{suffix}" + file_name = f"{prefix}{atomic_sym}{file_mass}{suffix}" - if not (libdir / "neutron" / file_name).is_file(): - print(f"File {libdir / 'neutron' / file_name} does not exist") + if not (libdir / "neutrons" / file_name).is_file(): + print(f"File {libdir / 'neutrons' / file_name} does not exist") sys.exit() nuc_dict[nuc] = { "sym": atomic_sym, @@ -116,33 +137,30 @@ def main(): nuc_dir_endf.mkdir(exist_ok=True) shutil.copyfile( - libdir / "neutron" / nuc_dict[nuc]["file_name"], + libdir / "neutrons" / nuc_dict[nuc]["file_name"], nuc_dir_endf / nuc_dict[nuc]["file_name"], ) os.chdir(nuc_dir_endf) - sandy_command = f"sandy {nuc_dict[nuc]['file_name']} --samples {args.samples} --outname {nuc} --processes {args.processes}" - os.system(sandy_command) - + sandy_args = [ + nuc_dict[nuc]["file_name"], + "--acer", "True", + "--temperature", "294.0", + "--samples", str(args.samples), + "--outname", f"{nuc}_{{SMP}}", + "--processes", str(args.processes), + "--verbose" + ] + sandy_cmd = ["python", "-m", "sandy.sampling"] + sandy_args + try: + subprocess.run(sandy_cmd, check=True) + except Exception as e: + print(f"Error sampling {nuc}: {e}") + raise os.chdir(script_dir) # ============================================================================== # CONVERT RANDOM EVALUATIONS TO HDF5 - - def process_neutron_random(nuc, i, out_dir, in_dir, file_num): # Need to add temperatures - """Process ENDF neutron sublibrary file into HDF5 and write into a - specified output directory.""" - - fileIn = in_dir / f"{nuc}-{i}" - fileOut = out_dir / f"{nuc}-{i}.h5" - - data = openmc.data.IncidentNeutron.from_njoy(fileIn) - data.name = f"{nuc}-{i}" - data.export_to_hdf5(fileOut, "w") - if i % 40 == 0: - print(f"Nuclide {nuc} {i+1}/{file_num} finished") - - print("Beginning NJOY processing") with Pool() as pool: results = [] @@ -156,14 +174,13 @@ def process_neutron_random(nuc, i, out_dir, in_dir, file_num): # Need to add te out_dir.mkdir(exist_ok=True) print(f"Beginning nuclide {nuc} ...") - for i in range(1, file_num + 1): + for i in range(1, file_num+1): func_args = (nuc, i, out_dir, in_dir, file_num) r = pool.apply_async(process_neutron_random, func_args) results.append(r) for r in results: - r.wait() - + r.get() # ============================================================================== # Create xml library @@ -174,7 +191,7 @@ def process_neutron_random(nuc, i, out_dir, in_dir, file_num): # Need to add te for nuc in nuclides: out_dir = hdf5_files_dir / nuc for i in range(1, file_num + 1): - fileOut = out_dir / f"{nuc}-{i}.h5" + fileOut = out_dir / f"{nuc}_{i}.h5" lib.register_file(fileOut) pre = output_dir / "cross_sections_pre.xml" @@ -187,7 +204,7 @@ def process_neutron_random(nuc, i, out_dir, in_dir, file_num): # Need to add te else: lib.export_to_xml(post) - pre.unlink() + pre.unlink() if __name__ == '__main__': From 5d6fe4ac995a08c771ef10e3f4ca79a7e89203c5 Mon Sep 17 00:00:00 2001 From: Grego01 Date: Tue, 14 Apr 2026 14:29:30 -0400 Subject: [PATCH 2/3] new file to generate full nuclear data library with covariance data included --- generate_endf_covariance.py | 599 ++++++++++++++++++++++++++++++++++++ 1 file changed, 599 insertions(+) create mode 100644 generate_endf_covariance.py diff --git a/generate_endf_covariance.py b/generate_endf_covariance.py new file mode 100644 index 00000000..fef86024 --- /dev/null +++ b/generate_endf_covariance.py @@ -0,0 +1,599 @@ +#!/usr/bin/env python3 + +""" +generate_endf_with_cov.py + +Download and process an ENDF/B library for use in OpenMC, then attach +multigroup MF=33 cross-section covariances (1500-group uniform-lethargy grid) +produced by NJOY/ERRORR to every incident-neutron HDF5 file. +""" + +from __future__ import annotations + +import argparse +import importlib.util +import logging +import sys +import tarfile +import traceback +import zipfile +from multiprocessing import Pool +from pathlib import Path +from shutil import rmtree, copy, copyfileobj +from typing import Optional, Sequence + +import numpy as np +import h5py +import openmc.data + +from utils import download, process_neutron, process_thermal + +logging.basicConfig(level=logging.INFO, format="%(levelname)s [%(name)s] %(message)s") +log = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Fixed 1500-group uniform-lethargy energy grid +# --------------------------------------------------------------------------- +ENERGY_GRID_EV = np.logspace(np.log10(1e-5), np.log10(150e6), 1501) +COV_TEMPERATURE = 294.0 +EIG_TOL = 1e-10 + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + + +def _import_module_as(mod_qualname: str, path: Path): + spec = importlib.util.spec_from_file_location(mod_qualname, str(path)) + if spec is None or spec.loader is None: + raise ImportError(f"Could not load spec for {mod_qualname} from {path}") + module = importlib.util.module_from_spec(spec) + sys.modules[mod_qualname] = module + spec.loader.exec_module(module) + return module + + +def _load_neutron_xs_covariances(cov_mod_dir: Path): + try: + from openmc.data.xs_covariance_njoy import NeutronXSCovariances + return NeutronXSCovariances + except Exception: + cov_mod_dir = cov_mod_dir.resolve() + _import_module_as("openmc.data.mf33_njoy", cov_mod_dir / "mf33_njoy.py") + mod = _import_module_as("openmc.data.xs_covariance_njoy", + cov_mod_dir / "xs_covariance_njoy.py") + return mod.NeutronXSCovariances + + +def _attach_mf33(h5_path: Path, cov) -> None: + with h5py.File(h5_path, "r+") as f: + nuc_name = next(iter(f.keys())) + cov_root = f[nuc_name].require_group("covariance") + cov.write_mf33_group(cov_root, store_raw_covariance=True) + + +def _build_release_details(endf_files_dir, neutron_dir, thermal_dir): + return { + 'vii.1': { + 'neutron': { + 'base_url': 'http://www.nndc.bnl.gov/endf-b7.1/zips/', + 'compressed_files': ['ENDF-B-VII.1-neutrons.zip'], + 'checksums': ['e5d7f441fc4c92893322c24d1725e29c'], + 'file_type': 'endf', + 'endf_files': neutron_dir.rglob('n-*.endf'), + }, + 'thermal': { + 'base_url': 'http://www.nndc.bnl.gov/endf-b7.1/zips/', + 'compressed_files': ['ENDF-B-VII.1-thermal_scatt.zip'], + 'checksums': ['fe590109dde63b2ec5dc228c7b8cab02'], + 'file_type': 'endf', + 'sab_files': [ + ('n-001_H_001.endf', 'tsl-HinH2O.endf'), + ('n-001_H_001.endf', 'tsl-HinCH2.endf'), + ('n-001_H_001.endf', 'tsl-HinZrH.endf'), + ('n-001_H_001.endf', 'tsl-ortho-H.endf'), + ('n-001_H_001.endf', 'tsl-para-H.endf'), + ('n-001_H_001.endf', 'tsl-benzine.endf'), + ('n-001_H_001.endf', 'tsl-l-CH4.endf'), + ('n-001_H_001.endf', 'tsl-s-CH4.endf'), + ('n-001_H_002.endf', 'tsl-DinD2O.endf'), + ('n-001_H_002.endf', 'tsl-ortho-D.endf'), + ('n-001_H_002.endf', 'tsl-para-D.endf'), + ('n-004_Be_009.endf', 'tsl-BeinBeO.endf'), + ('n-004_Be_009.endf', 'tsl-Be-metal.endf'), + ('n-006_C_000.endf', 'tsl-graphite.endf'), + ('n-008_O_016.endf', 'tsl-OinBeO.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2.endf'), + ('n-013_Al_027.endf', 'tsl-013_Al_027.endf'), + ('n-026_Fe_056.endf', 'tsl-026_Fe_056.endf'), + ('n-014_Si_028.endf', 'tsl-SiO2.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrH.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2.endf'), + ], + }, + 'photon': { + 'base_url': 'http://www.nndc.bnl.gov/endf-b7.1/zips/', + 'compressed_files': ['ENDF-B-VII.1-photoat.zip', 'ENDF-B-VII.1-atomic_relax.zip'], + 'checksums': ['5192f94e61f0b385cf536f448ffab4a4', 'fddb6035e7f2b6931e51a58fc754bd10'], + 'file_type': 'endf', + 'photo_files': endf_files_dir.joinpath('photon').rglob('photoat*.endf'), + 'atom_files': endf_files_dir.joinpath('photon').rglob('atom*.endf'), + }, + 'wmp': { + 'base_url': 'https://github.com/mit-crpg/WMP_Library/releases/download/v1.1/', + 'compressed_files': ['WMP_Library_v1.1.tar.gz'], + 'file_type': 'wmp', + }, + }, + 'viii.0': { + 'neutron': { + 'base_url': 'https://www.nndc.bnl.gov/endf-b8.0/', + 'compressed_files': ['zips/ENDF-B-VIII.0_neutrons.zip', 'erratafiles/n-005_B_010.endf'], + 'checksums': ['90c1b1a6653a148f17cbf3c5d1171859', 'eaf71eb22258f759abc205a129d8715a'], + 'file_type': 'endf', + 'endf_files': neutron_dir.rglob('n-*.endf'), + }, + 'thermal': { + 'base_url': 'https://www.nndc.bnl.gov/endf-b8.0/zips/', + 'compressed_files': ['ENDF-B-VIII.0_thermal_scatt.zip'], + 'checksums': ['ecd503d3f8214f703e95e17cc947062c'], + 'file_type': 'endf', + 'sab_files': [ + ('n-001_H_001.endf', 'tsl-HinC5O2H8.endf'), + ('n-001_H_001.endf', 'tsl-HinH2O.endf'), + ('n-001_H_001.endf', 'tsl-HinCH2.endf'), + ('n-001_H_001.endf', 'tsl-HinZrH.endf'), + ('n-001_H_001.endf', 'tsl-HinIceIh.endf'), + ('n-001_H_001.endf', 'tsl-HinYH2.endf'), + ('n-001_H_001.endf', 'tsl-ortho-H.endf'), + ('n-001_H_001.endf', 'tsl-para-H.endf'), + ('n-001_H_001.endf', 'tsl-benzene.endf'), + ('n-001_H_001.endf', 'tsl-l-CH4.endf'), + ('n-001_H_001.endf', 'tsl-s-CH4.endf'), + ('n-001_H_002.endf', 'tsl-DinD2O.endf'), + ('n-001_H_002.endf', 'tsl-ortho-D.endf'), + ('n-001_H_002.endf', 'tsl-para-D.endf'), + ('n-004_Be_009.endf', 'tsl-BeinBeO.endf'), + ('n-004_Be_009.endf', 'tsl-Be-metal.endf'), + ('n-006_C_012.endf', 'tsl-CinSiC.endf'), + ('n-006_C_012.endf', 'tsl-crystalline-graphite.endf'), + ('n-006_C_012.endf', 'tsl-reactor-graphite-10P.endf'), + ('n-006_C_012.endf', 'tsl-reactor-graphite-30P.endf'), + ('n-007_N_014.endf', 'tsl-NinUN.endf'), + ('n-008_O_016.endf', 'tsl-OinBeO.endf'), + ('n-008_O_016.endf', 'tsl-OinD2O.endf'), + ('n-008_O_016.endf', 'tsl-OinIceIh.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2.endf'), + ('n-013_Al_027.endf', 'tsl-013_Al_027.endf'), + ('n-026_Fe_056.endf', 'tsl-026_Fe_056.endf'), + ('n-014_Si_028.endf', 'tsl-SiinSiC.endf'), + ('n-014_Si_028.endf', 'tsl-SiO2-alpha.endf'), + ('n-014_Si_028.endf', 'tsl-SiO2-beta.endf'), + ('n-039_Y_089.endf', 'tsl-YinYH2.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrH.endf'), + ('n-092_U_238.endf', 'tsl-UinUN.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2.endf'), + ], + }, + 'photon': { + 'base_url': 'https://www.nndc.bnl.gov/endf-b8.0/', + 'compressed_files': ['zips/ENDF-B-VIII.0_photoat.zip', 'erratafiles/atomic_relax.tar.gz'], + 'checksums': ['d49f5b54be278862e1ce742ccd94f5c0', '805f877c59ad22dcf57a0446d266ceea'], + 'file_type': 'endf', + 'photo_files': endf_files_dir.joinpath('photon').rglob('photoat*.endf'), + 'atom_files': endf_files_dir.joinpath('photon').rglob('atom*.endf'), + }, + }, + 'viii.1': { + 'neutron': { + 'base_url': 'https://www.nndc.bnl.gov/endf-releases/releases/B-VIII.1/neutrons/', + 'compressed_files': ['neutrons-version.VIII.1.tar.gz'], + 'checksums': ['dc622c0f1c3c4477433e698266e0fc80'], + 'file_type': 'endf', + 'endf_files': neutron_dir.rglob('n-*.endf'), + }, + 'thermal': { + 'base_url': 'https://www.nndc.bnl.gov/endf-releases/releases/B-VIII.1/thermal_scatt/', + 'compressed_files': ['thermal_scatt-version.VIII.1.tar.gz'], + 'checksums': ['f7bcae02b2da577e28a3a083e07a3a3a'], + 'file_type': 'endf', + 'sab_files': [ + ('n-001_H_001.endf', 'tsl-H1inCaH2.endf'), + ('n-001_H_001.endf', 'tsl-H2inCaH2.endf'), + ('n-001_H_001.endf', 'tsl-Hin7LiH-mixed.endf'), + ('n-001_H_001.endf', 'tsl-HinC5O2H8.endf'), + ('n-001_H_001.endf', 'tsl-HinC8H8.endf'), + ('n-001_H_001.endf', 'tsl-HinCH2.endf'), + ('n-001_H_001.endf', 'tsl-HinH2O.endf'), + ('n-001_H_001.endf', 'tsl-HinHF.endf'), + ('n-001_H_001.endf', 'tsl-HinIceIh.endf'), + ('n-001_H_001.endf', 'tsl-HinParaffinicOil.endf'), + ('n-001_H_001.endf', 'tsl-HinUH3.endf'), + ('n-001_H_001.endf', 'tsl-HinYH2.endf'), + ('n-001_H_001.endf', 'tsl-HinZrH2.endf'), + ('n-001_H_001.endf', 'tsl-HinZrH.endf'), + ('n-001_H_001.endf', 'tsl-HinZrHx.endf'), + ('n-001_H_001.endf', 'tsl-ortho-H.endf'), + ('n-001_H_001.endf', 'tsl-para-H.endf'), + ('n-001_H_001.endf', 'tsl-benzene.endf'), + ('n-001_H_001.endf', 'tsl-l-CH4.endf'), + ('n-001_H_001.endf', 'tsl-s-CH4.endf'), + ('n-001_H_002.endf', 'tsl-Din7LiD-mixed.endf'), + ('n-001_H_002.endf', 'tsl-DinD2O.endf'), + ('n-001_H_002.endf', 'tsl-ortho-D.endf'), + ('n-001_H_002.endf', 'tsl-para-D.endf'), + ('n-003_Li_007.endf', 'tsl-7Liin7LiD-mixed.endf'), + ('n-003_Li_007.endf', 'tsl-7Liin7LiH-mixed.endf'), + ('n-003_Li_007.endf', 'tsl-LiinFLiBe.endf'), + ('n-004_Be_009.endf', 'tsl-BeinBe2C.endf'), + ('n-004_Be_009.endf', 'tsl-BeinBeF2.endf'), + ('n-004_Be_009.endf', 'tsl-BeinBeO.endf'), + ('n-004_Be_009.endf', 'tsl-BeinFLiBe.endf'), + ('n-004_Be_009.endf', 'tsl-Be-metal.endf'), + ('n-004_Be_009.endf', 'tsl-Be-metal+Sd.endf'), + ('n-006_C_012.endf', 'tsl-CinBe2C.endf'), + ('n-006_C_012.endf', 'tsl-CinC5O2H8.endf'), + ('n-006_C_012.endf', 'tsl-CinC8H8.endf'), + ('n-006_C_012.endf', 'tsl-CinCF2.endf'), + ('n-006_C_012.endf', 'tsl-CinSiC.endf'), + ('n-006_C_012.endf', 'tsl-CinUC-100P.endf'), + ('n-006_C_012.endf', 'tsl-CinUC-10P.endf'), + ('n-006_C_012.endf', 'tsl-CinUC-5P.endf'), + ('n-006_C_012.endf', 'tsl-CinUC.endf'), + ('n-006_C_012.endf', 'tsl-CinUC-HALEU.endf'), + ('n-006_C_012.endf', 'tsl-CinUC-HEU.endf'), + ('n-006_C_012.endf', 'tsl-CinZrC.endf'), + ('n-006_C_012.endf', 'tsl-crystalline-graphite.endf'), + ('n-006_C_012.endf', 'tsl-graphiteSd.endf'), + ('n-006_C_012.endf', 'tsl-reactor-graphite-10P.endf'), + ('n-006_C_012.endf', 'tsl-reactor-graphite-20P.endf'), + ('n-006_C_012.endf', 'tsl-reactor-graphite-30P.endf'), + ('n-007_N_014.endf', 'tsl-NinUN-100P.endf'), + ('n-007_N_014.endf', 'tsl-NinUN-10P.endf'), + ('n-007_N_014.endf', 'tsl-NinUN-5P.endf'), + ('n-007_N_014.endf', 'tsl-NinUN.endf'), + ('n-007_N_014.endf', 'tsl-NinUN-HALEU.endf'), + ('n-007_N_014.endf', 'tsl-NinUN-HEU.endf'), + ('n-008_O_016.endf', 'tsl-OinAl2O3.endf'), + ('n-008_O_016.endf', 'tsl-OinBeO.endf'), + ('n-008_O_016.endf', 'tsl-OinC5O2H8.endf'), + ('n-008_O_016.endf', 'tsl-OinD2O.endf'), + ('n-008_O_016.endf', 'tsl-OinIceIh.endf'), + ('n-008_O_016.endf', 'tsl-OinMgO.endf'), + ('n-008_O_016.endf', 'tsl-OinPuO2.endf'), + ('n-008_O_016.endf', 'tsl-OinSiO2-alpha.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2-100P.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2-10P.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2-5P.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2-HALEU.endf'), + ('n-008_O_016.endf', 'tsl-OinUO2-HEU.endf'), + ('n-009_F_019.endf', 'tsl-FinBeF2.endf'), + ('n-009_F_019.endf', 'tsl-FinCF2.endf'), + ('n-009_F_019.endf', 'tsl-FinFLiBe.endf'), + ('n-009_F_019.endf', 'tsl-FinHF.endf'), + ('n-009_F_019.endf', 'tsl-FinMgF2.endf'), + ('n-012_Mg_024.endf', 'tsl-MginMgF2.endf'), + ('n-012_Mg_024.endf', 'tsl-MginMgO.endf'), + ('n-013_Al_027.endf', 'tsl-013_Al_027.endf'), + ('n-013_Al_027.endf', 'tsl-AlinAl2O3.endf'), + ('n-026_Fe_056.endf', 'tsl-026_Fe_056.endf'), + ('n-014_Si_028.endf', 'tsl-SiinSiC.endf'), + ('n-014_Si_028.endf', 'tsl-SiinSiO2-alpha.endf'), + ('n-014_Si_028.endf', 'tsl-SiO2-beta.endf'), + ('n-020_Ca_040.endf', 'tsl-CainCaH2.endf'), + ('n-039_Y_089.endf', 'tsl-YinYH2.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrC.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrH2.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrH.endf'), + ('n-040_Zr_090.endf', 'tsl-ZrinZrHx.endf'), + ('n-092_U_238.endf', 'tsl-UinUC-100P.endf'), + ('n-092_U_238.endf', 'tsl-UinUC-10P.endf'), + ('n-092_U_238.endf', 'tsl-UinUC-5P.endf'), + ('n-092_U_238.endf', 'tsl-UinUC.endf'), + ('n-092_U_238.endf', 'tsl-UinUC-HALEU.endf'), + ('n-092_U_238.endf', 'tsl-UinUC-HEU.endf'), + ('n-092_U_238.endf', 'tsl-UinUN-100P.endf'), + ('n-092_U_238.endf', 'tsl-UinUN-10P.endf'), + ('n-092_U_238.endf', 'tsl-UinUN-5P.endf'), + ('n-092_U_238.endf', 'tsl-UinUN.endf'), + ('n-092_U_238.endf', 'tsl-UinUN-HALEU.endf'), + ('n-092_U_238.endf', 'tsl-UinUN-HEU.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2-100P.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2-10P.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2-5P.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2-HALEU.endf'), + ('n-092_U_238.endf', 'tsl-UinUO2-HEU.endf'), + ('n-092_U_238.endf', 'tsl-U-metal-100P.endf'), + ('n-092_U_238.endf', 'tsl-U-metal-10P.endf'), + ('n-092_U_238.endf', 'tsl-U-metal-5P.endf'), + ('n-092_U_238.endf', 'tsl-U-metal.endf'), + ('n-092_U_238.endf', 'tsl-U-metal-HALEU.endf'), + ('n-092_U_238.endf', 'tsl-U-metal-HEU.endf'), + ('n-094_Pu_239.endf', 'tsl-PuinPuO2.endf'), + ], + }, + 'photon': { + 'base_url': 'https://www.nndc.bnl.gov/endf-releases/releases/B-VIII.1/', + 'compressed_files': [ + 'photoat/photoat-version.VIII.1.tar.gz', + 'atomic_relax/atomic_relax-version.VIII.1.tar.gz', + ], + 'checksums': ['6d5f4830f6290d6c618803a8391ba0cf', '70e9ca0c481236499b7a3e0a490f4ef2'], + 'file_type': 'endf', + 'photo_files': endf_files_dir.joinpath('photon').rglob('photoat*.endf'), + 'atom_files': endf_files_dir.joinpath('photon').rglob('atom*.endf'), + }, + }, + } + +def process_neutron_merged( + endf_file, + neutron_dest, + libver, + temperatures, + *, + njoy_exec, + cov_energy_grid_ev=None, + cov_temperature=293.6, + eig_tol=1e-10, + cov_mod_dir=None, +): + data = openmc.data.IncidentNeutron.from_njoy( + endf_file, + temperatures=temperatures, + njoy_exec=njoy_exec, + ) + + if cov_energy_grid_ev is not None: + NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) + cov = NeutronXSCovariances.from_endf( + endf_file, + cov_energy_grid_ev, + njoy_exec=njoy_exec, + temperature=cov_temperature, + name=data.name, + eig_tol=eig_tol, + ) + data.mg_covariance = cov + + h5_path = neutron_dest / f"{data.name}.h5" + data.export_to_hdf5(h5_path, 'w', libver=libver) + return h5_path + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description=__doc__, formatter_class=CustomFormatter) + parser.add_argument('-d', '--destination', type=Path, + help='Directory to create new library in') + parser.add_argument('--download', action='store_true', + help='Download files from NNDC') + parser.add_argument('--no-download', dest='download', action='store_false') + parser.add_argument('--extract', action='store_true', + help='Extract compressed files') + parser.add_argument('--no-extract', dest='extract', action='store_false') + parser.add_argument('--libver', choices=['earliest', 'latest'], default='earliest', + help="HDF5 versioning") + parser.add_argument('-r', '--release', choices=['vii.1', 'viii.0', 'viii.1'], + default='viii.1', help="ENDF/B release version") + parser.add_argument('-p', '--particles', choices=['neutron', 'thermal', 'photon', 'wmp'], + nargs='+', default=['neutron', 'thermal', 'photon']) + parser.add_argument('--cleanup', action='store_true') + parser.add_argument('--no-cleanup', dest='cleanup', action='store_false') + parser.add_argument('--temperatures', type=float, nargs='+', + default=[250.0, 293.6, 600.0, 900.0, 1200.0, 2500.0]) + parser.add_argument('--njoy', type=str, default=None, + help="NJOY executable (falls back to $NJOY)") + parser.set_defaults(download=True, extract=True, cleanup=False) + args = parser.parse_args() + + cov_mod_dir = Path(__file__).resolve().parent + + def sort_key(path): + if path.name.startswith('c_'): + return (1000, path) + else: + return openmc.data.zam(path.stem) + + library_name = 'endfb' + cwd = Path.cwd() + endf_files_dir = cwd / '-'.join([library_name, args.release, 'endf']) + neutron_dir = endf_files_dir / 'neutron' + thermal_dir = endf_files_dir / 'thermal' + download_path = cwd / '-'.join([library_name, args.release, 'download']) + if args.destination is None: + args.destination = Path('-'.join([library_name, args.release, 'hdf5'])) + + release_details = _build_release_details(endf_files_dir, neutron_dir, thermal_dir) + + # ---- Download ---- + if args.download: + for particle in args.particles: + details = release_details[args.release][particle] + for i, f in enumerate(details['compressed_files']): + url = details['base_url'] + f + kw = {} + if 'checksums' in details: + kw['checksum'] = details['checksums'][i] + download(url, output_path=download_path / particle, **kw) + + # ---- Extract ---- + if args.extract: + extract_kwargs = {'filter': 'data'} if sys.version_info >= (3, 12) else {} + for particle in args.particles: + ft = release_details[args.release][particle]['file_type'] + extraction_dir = (args.destination / particle) if ft == 'wmp' else (endf_files_dir / particle) + extraction_dir.mkdir(parents=True, exist_ok=True) + for f in release_details[args.release][particle]['compressed_files']: + fname = Path(f).name + if fname.endswith('.zip'): + print(f'Extracting {fname}...') + with zipfile.ZipFile(download_path / particle / fname) as zipf: + for member in zipf.namelist(): + filename = Path(member).name + if not filename: + continue + with zipf.open(member) as src, open(extraction_dir / filename, "wb") as dst: + copyfileobj(src, dst) + elif fname.endswith('.tar.gz'): + print(f'Extracting {fname}...') + with tarfile.open(download_path / particle / fname, 'r') as tgz: + for member in tgz.getmembers(): + if member.isreg(): + member.name = Path(member.name).name + tgz.extract(member, path=extraction_dir, **extract_kwargs) + else: + copy(download_path / particle / fname, extraction_dir / fname) + if args.cleanup and download_path.exists(): + rmtree(download_path) + + # ---- Output dirs ---- + for particle in args.particles: + (args.destination / particle).mkdir(parents=True, exist_ok=True) + + library = openmc.data.DataLibrary() + + # ================================================================ + # NEUTRON: standard processing (parallel) then covariances + # ================================================================ + if 'neutron' in args.particles: + details = release_details[args.release]['neutron'] + neutron_dest = args.destination / 'neutron' + endf_files = [f for f in details['endf_files'] + if f.name != 'n-000_n_001.endf'] + + NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) + + with Pool() as pool: + results = [] + for fn in endf_files: + r = pool.apply_async( + process_neutron_merged, + (fn, neutron_dest, args.libver, args.temperatures), + dict( + njoy_exec=args.njoy, + cov_energy_grid_ev=ENERGY_GRID_EV, + cov_temperature=COV_TEMPERATURE, + eig_tol=EIG_TOL, + cov_mod_dir=cov_mod_dir, + ), + ) + results.append((fn, r)) + + for fn, r in results: + try: + r.get() + except Exception: + log.error("Processing FAILED for %s:\n%s", + fn.name, traceback.format_exc()) + + for p in sorted(neutron_dest.glob('*.h5'), key=sort_key): + library.register_file(p) + + '''# Step 1 — standard NJOY processing in parallel + print(f"\nProcessing {len(endf_files)} neutron evaluations...") + with Pool() as pool: + results = [] + for fn in endf_files: + r = pool.apply_async(process_neutron, + (fn, neutron_dest, args.libver, args.temperatures)) + results.append((fn, r)) + for fn, r in results: + try: + r.get() + except Exception: + log.error("Processing FAILED for %s:\n%s", + fn.name, traceback.format_exc()) + + # Step 2 — attach MF=33 covariances (sequential, each calls ERRORR) + print(f"\nAttaching MF=33 covariances (1500-group lethargy grid)...") + NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) + ok, fail = 0, 0 + + for endf_file in endf_files: + try: + data_tmp = openmc.data.IncidentNeutron.from_endf(str(endf_file)) + nuc_name = data_tmp.name + except Exception: + nuc_name = endf_file.stem + + h5_path = neutron_dest / f"{nuc_name}.h5" + if not h5_path.exists(): + log.warning("HDF5 not found for %s, skipping covariance", endf_file.name) + fail += 1 + continue + + try: + cov = NeutronXSCovariances.from_endf( + endf_file, ENERGY_GRID_EV, + njoy_exec=args.njoy, + temperature=COV_TEMPERATURE, + name=nuc_name, + eig_tol=EIG_TOL, + ) + _attach_mf33(h5_path, cov) + ok += 1 + log.info("MF=33 attached -> %s", h5_path.name) + except Exception: + fail += 1 + log.warning("MF=33 FAILED for %s (HDF5 still valid):\n%s", + endf_file.name, traceback.format_exc()) + + print(f"Covariance summary: {ok} succeeded, {fail} failed / {len(endf_files)} total") + + for p in sorted(neutron_dest.glob('*.h5'), key=sort_key): + library.register_file(p)''' + + # ================================================================ + # THERMAL (unchanged) + # ================================================================ + if 'thermal' in args.particles: + details = release_details[args.release]['thermal'] + with Pool() as pool: + results = [] + for path_n, path_t in details['sab_files']: + r = pool.apply_async(process_thermal, + (neutron_dir / path_n, thermal_dir / path_t, + args.destination / 'thermal', args.libver)) + results.append(r) + for r in results: + r.wait() + for p in sorted((args.destination / 'thermal').glob('*.h5'), key=sort_key): + library.register_file(p) + + # ================================================================ + # PHOTON (unchanged) + # ================================================================ + if 'photon' in args.particles: + details = release_details[args.release]['photon'] + for photo_path, atom_path in zip(sorted(details['photo_files']), + sorted(details['atom_files'])): + print('Converting:', photo_path.name, atom_path.name) + data = openmc.data.IncidentPhoton.from_endf(photo_path, atom_path) + h5_file = args.destination / 'photon' / f'{data.name}.h5' + data.export_to_hdf5(h5_file, 'w', libver=args.libver) + library.register_file(h5_file) + + # ================================================================ + # WMP (unchanged) + # ================================================================ + if 'wmp' in args.particles: + for h5_file in sorted((args.destination / 'wmp').rglob('*.h5')): + library.register_file(h5_file) + + # ---- cross_sections.xml ---- + library.export_to_xml(args.destination / 'cross_sections.xml') + print(f"\nLibrary written to: {args.destination}") + + +if __name__ == '__main__': + main() From f6ce130a89543bb7f5efb15e249fd237cd38d33f Mon Sep 17 00:00:00 2001 From: Grego01 Date: Tue, 14 Apr 2026 14:37:47 -0400 Subject: [PATCH 3/3] cleaning up and testing --- generate_endf_covariance.py | 302 +++++++++++++++++------------------- 1 file changed, 141 insertions(+), 161 deletions(-) diff --git a/generate_endf_covariance.py b/generate_endf_covariance.py index fef86024..304da961 100644 --- a/generate_endf_covariance.py +++ b/generate_endf_covariance.py @@ -6,6 +6,14 @@ Download and process an ENDF/B library for use in OpenMC, then attach multigroup MF=33 cross-section covariances (1500-group uniform-lethargy grid) produced by NJOY/ERRORR to every incident-neutron HDF5 file. + +This script is based on the existing generate_endf.py in openmc-dev/data, +extended with covariance processing. + +Requires +-------- +- openmc (with the MF=33 covariance PR merged) +- NJOY executable (set via --njoy or $NJOY environment variable) """ from __future__ import annotations @@ -32,11 +40,11 @@ log = logging.getLogger(__name__) # --------------------------------------------------------------------------- -# Fixed 1500-group uniform-lethargy energy grid +# Default covariance settings # --------------------------------------------------------------------------- -ENERGY_GRID_EV = np.logspace(np.log10(1e-5), np.log10(150e6), 1501) -COV_TEMPERATURE = 294.0 -EIG_TOL = 1e-10 +DEFAULT_COV_GRID_EV = np.logspace(np.log10(1e-5), np.log10(20e6), 1501) +DEFAULT_COV_TEMPERATURE = 293.6 +DEFAULT_EIG_TOL = 1e-10 # --------------------------------------------------------------------------- @@ -47,36 +55,6 @@ class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): pass - -def _import_module_as(mod_qualname: str, path: Path): - spec = importlib.util.spec_from_file_location(mod_qualname, str(path)) - if spec is None or spec.loader is None: - raise ImportError(f"Could not load spec for {mod_qualname} from {path}") - module = importlib.util.module_from_spec(spec) - sys.modules[mod_qualname] = module - spec.loader.exec_module(module) - return module - - -def _load_neutron_xs_covariances(cov_mod_dir: Path): - try: - from openmc.data.xs_covariance_njoy import NeutronXSCovariances - return NeutronXSCovariances - except Exception: - cov_mod_dir = cov_mod_dir.resolve() - _import_module_as("openmc.data.mf33_njoy", cov_mod_dir / "mf33_njoy.py") - mod = _import_module_as("openmc.data.xs_covariance_njoy", - cov_mod_dir / "xs_covariance_njoy.py") - return mod.NeutronXSCovariances - - -def _attach_mf33(h5_path: Path, cov) -> None: - with h5py.File(h5_path, "r+") as f: - nuc_name = next(iter(f.keys())) - cov_root = f[nuc_name].require_group("covariance") - cov.write_mf33_group(cov_root, store_raw_covariance=True) - - def _build_release_details(endf_files_dir, neutron_dir, thermal_dir): return { 'vii.1': { @@ -333,7 +311,11 @@ def _build_release_details(endf_files_dir, neutron_dir, thermal_dir): }, } -def process_neutron_merged( +# --------------------------------------------------------------------------- +# Neutron processing with covariance attachment +# --------------------------------------------------------------------------- + +def process_neutron_with_covariance( endf_file, neutron_dest, libver, @@ -343,67 +325,91 @@ def process_neutron_merged( cov_energy_grid_ev=None, cov_temperature=293.6, eig_tol=1e-10, - cov_mod_dir=None, ): + """Process a single ENDF neutron file: standard NJOY chain + optional + MF=33 covariance attachment. + + If the covariance step fails (e.g. the evaluation lacks MF=33 data), + the HDF5 file is still written with standard cross-section data. + """ + from openmc.data.xs_covariance_njoy import NeutronXSCovariances + + # Step 1: standard NJOY processing (always runs) data = openmc.data.IncidentNeutron.from_njoy( endf_file, temperatures=temperatures, njoy_exec=njoy_exec, ) - + + # Step 2: covariance attachment (best-effort) if cov_energy_grid_ev is not None: - NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) - cov = NeutronXSCovariances.from_endf( - endf_file, - cov_energy_grid_ev, - njoy_exec=njoy_exec, - temperature=cov_temperature, - name=data.name, - eig_tol=eig_tol, - ) - data.mg_covariance = cov - + try: + cov = NeutronXSCovariances.from_endf( + endf_file, + cov_energy_grid_ev, + njoy_exec=njoy_exec, + temperature=cov_temperature, + name=data.name, + eig_tol=eig_tol, + ) + data.mg_covariance = cov + log.info("MF=33 covariance attached for %s", data.name) + except Exception: + log.warning( + "MF=33 covariance skipped for %s (no MF=33 data or " + "ERRORR failure):\n%s", + data.name, traceback.format_exc(), + ) + + # Step 3: write HDF5 (always succeeds) h5_path = neutron_dest / f"{data.name}.h5" data.export_to_hdf5(h5_path, 'w', libver=libver) return h5_path - + + # --------------------------------------------------------------------------- # Main # --------------------------------------------------------------------------- - + def main(): - parser = argparse.ArgumentParser(description=__doc__, formatter_class=CustomFormatter) - parser.add_argument('-d', '--destination', type=Path, - help='Directory to create new library in') + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=CustomFormatter, + ) + parser.add_argument( + '-d', '--destination', type=Path, + help='Directory to create new library in', + ) parser.add_argument('--download', action='store_true', help='Download files from NNDC') parser.add_argument('--no-download', dest='download', action='store_false') parser.add_argument('--extract', action='store_true', help='Extract compressed files') parser.add_argument('--no-extract', dest='extract', action='store_false') - parser.add_argument('--libver', choices=['earliest', 'latest'], default='earliest', - help="HDF5 versioning") - parser.add_argument('-r', '--release', choices=['vii.1', 'viii.0', 'viii.1'], - default='viii.1', help="ENDF/B release version") - parser.add_argument('-p', '--particles', choices=['neutron', 'thermal', 'photon', 'wmp'], + parser.add_argument('--libver', choices=['earliest', 'latest'], + default='earliest', help='HDF5 versioning') + parser.add_argument('-r', '--release', + choices=['vii.1', 'viii.0', 'viii.1'], + default='viii.1', help='ENDF/B release version') + parser.add_argument('-p', '--particles', + choices=['neutron', 'thermal', 'photon', 'wmp'], nargs='+', default=['neutron', 'thermal', 'photon']) parser.add_argument('--cleanup', action='store_true') parser.add_argument('--no-cleanup', dest='cleanup', action='store_false') parser.add_argument('--temperatures', type=float, nargs='+', default=[250.0, 293.6, 600.0, 900.0, 1200.0, 2500.0]) parser.add_argument('--njoy', type=str, default=None, - help="NJOY executable (falls back to $NJOY)") + help='NJOY executable (falls back to $NJOY)') + parser.add_argument('--no-covariance', action='store_true', + help='Skip MF=33 covariance processing') parser.set_defaults(download=True, extract=True, cleanup=False) args = parser.parse_args() - - cov_mod_dir = Path(__file__).resolve().parent - + def sort_key(path): if path.name.startswith('c_'): return (1000, path) else: return openmc.data.zam(path.stem) - + library_name = 'endfb' cwd = Path.cwd() endf_files_dir = cwd / '-'.join([library_name, args.release, 'endf']) @@ -412,9 +418,11 @@ def sort_key(path): download_path = cwd / '-'.join([library_name, args.release, 'download']) if args.destination is None: args.destination = Path('-'.join([library_name, args.release, 'hdf5'])) - - release_details = _build_release_details(endf_files_dir, neutron_dir, thermal_dir) - + + release_details = _build_release_details( + endf_files_dir, neutron_dir, thermal_dir, + ) + # ---- Download ---- if args.download: for particle in args.particles: @@ -425,13 +433,18 @@ def sort_key(path): if 'checksums' in details: kw['checksum'] = details['checksums'][i] download(url, output_path=download_path / particle, **kw) - + # ---- Extract ---- if args.extract: - extract_kwargs = {'filter': 'data'} if sys.version_info >= (3, 12) else {} + extract_kwargs = ( + {'filter': 'data'} if sys.version_info >= (3, 12) else {} + ) for particle in args.particles: ft = release_details[args.release][particle]['file_type'] - extraction_dir = (args.destination / particle) if ft == 'wmp' else (endf_files_dir / particle) + extraction_dir = ( + (args.destination / particle) if ft == 'wmp' + else (endf_files_dir / particle) + ) extraction_dir.mkdir(parents=True, exist_ok=True) for f in release_details[args.release][particle]['compressed_files']: fname = Path(f).name @@ -442,158 +455,125 @@ def sort_key(path): filename = Path(member).name if not filename: continue - with zipf.open(member) as src, open(extraction_dir / filename, "wb") as dst: + with (zipf.open(member) as src, + open(extraction_dir / filename, 'wb') as dst): copyfileobj(src, dst) elif fname.endswith('.tar.gz'): print(f'Extracting {fname}...') - with tarfile.open(download_path / particle / fname, 'r') as tgz: + with tarfile.open( + download_path / particle / fname, 'r', + ) as tgz: for member in tgz.getmembers(): if member.isreg(): member.name = Path(member.name).name - tgz.extract(member, path=extraction_dir, **extract_kwargs) + tgz.extract( + member, path=extraction_dir, + **extract_kwargs, + ) else: - copy(download_path / particle / fname, extraction_dir / fname) + copy( + download_path / particle / fname, + extraction_dir / fname, + ) if args.cleanup and download_path.exists(): rmtree(download_path) - + # ---- Output dirs ---- for particle in args.particles: (args.destination / particle).mkdir(parents=True, exist_ok=True) - + library = openmc.data.DataLibrary() - + # ================================================================ - # NEUTRON: standard processing (parallel) then covariances + # NEUTRON # ================================================================ if 'neutron' in args.particles: details = release_details[args.release]['neutron'] neutron_dest = args.destination / 'neutron' - endf_files = [f for f in details['endf_files'] - if f.name != 'n-000_n_001.endf'] - - NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) - + endf_files = [ + f for f in details['endf_files'] + if f.name != 'n-000_n_001.endf' + ] + + cov_grid = None if args.no_covariance else DEFAULT_COV_GRID_EV + + print(f"\nProcessing {len(endf_files)} neutron evaluations" + f"{' (with MF=33 covariances)' if cov_grid is not None else ''}...") + with Pool() as pool: results = [] for fn in endf_files: r = pool.apply_async( - process_neutron_merged, + process_neutron_with_covariance, (fn, neutron_dest, args.libver, args.temperatures), dict( njoy_exec=args.njoy, - cov_energy_grid_ev=ENERGY_GRID_EV, - cov_temperature=COV_TEMPERATURE, - eig_tol=EIG_TOL, - cov_mod_dir=cov_mod_dir, + cov_energy_grid_ev=cov_grid, + cov_temperature=DEFAULT_COV_TEMPERATURE, + eig_tol=DEFAULT_EIG_TOL, ), ) results.append((fn, r)) - + for fn, r in results: try: r.get() except Exception: - log.error("Processing FAILED for %s:\n%s", - fn.name, traceback.format_exc()) - + log.error( + "Processing FAILED for %s:\n%s", + fn.name, traceback.format_exc(), + ) + for p in sorted(neutron_dest.glob('*.h5'), key=sort_key): library.register_file(p) - - '''# Step 1 — standard NJOY processing in parallel - print(f"\nProcessing {len(endf_files)} neutron evaluations...") - with Pool() as pool: - results = [] - for fn in endf_files: - r = pool.apply_async(process_neutron, - (fn, neutron_dest, args.libver, args.temperatures)) - results.append((fn, r)) - for fn, r in results: - try: - r.get() - except Exception: - log.error("Processing FAILED for %s:\n%s", - fn.name, traceback.format_exc()) - - # Step 2 — attach MF=33 covariances (sequential, each calls ERRORR) - print(f"\nAttaching MF=33 covariances (1500-group lethargy grid)...") - NeutronXSCovariances = _load_neutron_xs_covariances(cov_mod_dir) - ok, fail = 0, 0 - - for endf_file in endf_files: - try: - data_tmp = openmc.data.IncidentNeutron.from_endf(str(endf_file)) - nuc_name = data_tmp.name - except Exception: - nuc_name = endf_file.stem - - h5_path = neutron_dest / f"{nuc_name}.h5" - if not h5_path.exists(): - log.warning("HDF5 not found for %s, skipping covariance", endf_file.name) - fail += 1 - continue - - try: - cov = NeutronXSCovariances.from_endf( - endf_file, ENERGY_GRID_EV, - njoy_exec=args.njoy, - temperature=COV_TEMPERATURE, - name=nuc_name, - eig_tol=EIG_TOL, - ) - _attach_mf33(h5_path, cov) - ok += 1 - log.info("MF=33 attached -> %s", h5_path.name) - except Exception: - fail += 1 - log.warning("MF=33 FAILED for %s (HDF5 still valid):\n%s", - endf_file.name, traceback.format_exc()) - - print(f"Covariance summary: {ok} succeeded, {fail} failed / {len(endf_files)} total") - - for p in sorted(neutron_dest.glob('*.h5'), key=sort_key): - library.register_file(p)''' - + # ================================================================ - # THERMAL (unchanged) + # THERMAL # ================================================================ if 'thermal' in args.particles: details = release_details[args.release]['thermal'] with Pool() as pool: results = [] for path_n, path_t in details['sab_files']: - r = pool.apply_async(process_thermal, - (neutron_dir / path_n, thermal_dir / path_t, - args.destination / 'thermal', args.libver)) + r = pool.apply_async( + process_thermal, + (neutron_dir / path_n, thermal_dir / path_t, + args.destination / 'thermal', args.libver), + ) results.append(r) for r in results: r.wait() - for p in sorted((args.destination / 'thermal').glob('*.h5'), key=sort_key): + for p in sorted( + (args.destination / 'thermal').glob('*.h5'), key=sort_key, + ): library.register_file(p) - + # ================================================================ - # PHOTON (unchanged) + # PHOTON # ================================================================ if 'photon' in args.particles: details = release_details[args.release]['photon'] - for photo_path, atom_path in zip(sorted(details['photo_files']), - sorted(details['atom_files'])): + for photo_path, atom_path in zip( + sorted(details['photo_files']), + sorted(details['atom_files']), + ): print('Converting:', photo_path.name, atom_path.name) data = openmc.data.IncidentPhoton.from_endf(photo_path, atom_path) h5_file = args.destination / 'photon' / f'{data.name}.h5' data.export_to_hdf5(h5_file, 'w', libver=args.libver) library.register_file(h5_file) - + # ================================================================ - # WMP (unchanged) + # WMP # ================================================================ if 'wmp' in args.particles: for h5_file in sorted((args.destination / 'wmp').rglob('*.h5')): library.register_file(h5_file) - + # ---- cross_sections.xml ---- library.export_to_xml(args.destination / 'cross_sections.xml') print(f"\nLibrary written to: {args.destination}") - - + + if __name__ == '__main__': - main() + main() \ No newline at end of file