OpenMC/openmc/data/njoy.py
GuySten 61c8a59cff
Some checks are pending
Tests and Coverage / filter-changes (push) Waiting to run
Tests and Coverage / Python 3.13 (omp=n, mpi=n, dagmc=, libmesh=, event= (push) Blocked by required conditions
Tests and Coverage / Python 3.14 (omp=n, mpi=n, dagmc=, libmesh=, event= (push) Blocked by required conditions
Tests and Coverage / Python 3.14t (omp=n, mpi=n, dagmc=, libmesh=, event= (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=n, mpi=n, dagmc=n, libmesh=n, event=n (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=n, dagmc=n, libmesh=n, event=n (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=n, mpi=y, dagmc=n, libmesh=n, event=n (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=y, dagmc=n, libmesh=n, event=n (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=n, dagmc=, libmesh=y, event= (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=n, dagmc=, libmesh=, event=y (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=y, dagmc=y, libmesh=, event= (push) Blocked by required conditions
Tests and Coverage / Python 3.12 (omp=y, mpi=y, dagmc=, libmesh=y, event= (push) Blocked by required conditions
Tests and Coverage / coverage (push) Blocked by required conditions
Tests and Coverage / Check CI status (push) Blocked by required conditions
dockerhub-publish-develop / main (push) Waiting to run
dockerhub-publish-develop-dagmc-libmesh / main (push) Waiting to run
dockerhub-publish-develop-dagmc / main (push) Waiting to run
dockerhub-publish-develop-libmesh / main (push) Waiting to run
Override NJOY default damage energy threshold (#4022)
Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
2026-07-20 14:52:30 +00:00

775 lines
33 KiB
Python

from collections import namedtuple
from io import StringIO
import os
import shutil
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
import tempfile
from pathlib import Path
import warnings
from . import endf
import openmc.data
# For a given material, give a name for the ACE table and a list of ZAID
# identifiers.
ThermalTuple = namedtuple('ThermalTuple', ['name', 'zaids', 'nmix'])
_THERMAL_DATA = {
'c_Ag': ThermalTuple('ag', [47107, 47109], 1),
'c_Al27': ThermalTuple('al27', [13027], 1),
'c_Al_in_Al2O3': ThermalTuple('asap00', [13027], 1),
'c_Al_in_Y3Al5O12': ThermalTuple('alyag', [13027], 1),
'c_Au': ThermalTuple('au', [79197], 1),
'c_Be': ThermalTuple('be', [4009], 1),
'c_Be_distinct': ThermalTuple('besd', [4009], 1),
'c_Be_in_BeO': ThermalTuple('bebeo', [4009], 1),
'c_Be_in_Be2C': ThermalTuple('bebe2c', [4009], 1),
'c_Be_in_BeF2': ThermalTuple('bebef2', [4009], 1),
'c_Be_in_FLiBe': ThermalTuple('beflib', [4009], 1),
'c_BeO': ThermalTuple('beo', [4009, 8016, 8017, 8018], 2),
'c_Bi': ThermalTuple('bi', [83209], 1),
'c_Bi_in_Ge3Bi4O12': ThermalTuple('bigbo', [83209], 1),
'c_C6H6': ThermalTuple('benz', [1001, 6000, 6012], 2),
'c_C_in_Be2C': ThermalTuple('cbe2c', [6000, 6012, 6013], 1),
'c_C_in_C5O2H8': ThermalTuple('clucit', [6000, 6012, 6013], 1),
'c_C_in_C8H8': ThermalTuple('cc8h8', [6000, 6012, 6013], 1),
'c_C_in_C19H16_liquid': ThermalTuple('c19liq', [6000, 6012, 6013], 1),
'c_C_in_C19H16_solid': ThermalTuple('c19sol', [6000, 6012, 6013], 1),
'c_C_in_C2H6O_liquid': ThermalTuple('ethliq', [6000, 6012, 6013], 1),
'c_C_in_C2H6O_solid': ThermalTuple('ethsol', [6000, 6012, 6013], 1),
'c_C_in_C6H6_liquid': ThermalTuple('benzlq', [6000, 6012, 6013], 1),
'c_C_in_C6H6_solid': ThermalTuple('benzsl', [6000, 6012, 6013], 1),
'c_C_in_C7H8_liquid': ThermalTuple('tolliq', [6000, 6012, 6013], 1),
'c_C_in_C7H8_solid': ThermalTuple('tolsol', [6000, 6012, 6013], 1),
'c_C_in_C8H10_liquid': ThermalTuple('xylliq', [6000, 6012, 6013], 1),
'c_C_in_C8H10_solid': ThermalTuple('xylsol', [6000, 6012, 6013], 1),
'c_C_in_C9H12_liquid': ThermalTuple('mesliq', [6000, 6012, 6013], 1),
'c_C_in_C9H12_solid': ThermalTuple('messol', [6000, 6012, 6013], 1),
'c_C_in_CF2': ThermalTuple('ccf2', [6000, 6012, 6013], 1),
'c_C_in_CH2': ThermalTuple('cch2', [6000, 6012, 6013], 1),
'c_C_in_CH4_liquid': ThermalTuple('cch4lq', [6000, 6012, 6013], 1),
'c_C_in_CH4_solid': ThermalTuple('cch4sl', [6000, 6012, 6013], 1),
'c_C_in_Diamond': ThermalTuple('cdiam', [6000, 6012, 6013], 1),
'c_C_in_SiC': ThermalTuple('csic', [6000, 6012, 6013], 1),
'c_C_in_UC_100p': ThermalTuple('cuc100', [6000, 6012, 6013], 1),
'c_C_in_UC_10p': ThermalTuple('cuc10', [6000, 6012, 6013], 1),
'c_C_in_UC_5p': ThermalTuple('cuc5', [6000, 6012, 6013], 1),
'c_C_in_UC': ThermalTuple('cinuc', [6000, 6012, 6013], 1),
'c_C_in_UC_HALEU': ThermalTuple('cuchal', [6000, 6012, 6013], 1),
'c_C_in_UC_HEU': ThermalTuple('cucheu', [6000, 6012, 6013], 1),
'c_C_in_ZrC': ThermalTuple('czrc', [6000, 6012, 6013], 1),
'c_Ca': ThermalTuple('ca', [20040, 20042, 20043, 20044, 20046, 20048], 1),
'c_Ca_in_CaH2': ThermalTuple('cacah2', [20040, 20042, 20043, 20044, 20046, 20048], 1),
'c_Ca_in_CaO2H2': ThermalTuple('cacaoh', [20040, 20042, 20043, 20044, 20046, 20048], 1),
'c_Cr': ThermalTuple('cr', [24050, 24052, 24053, 24054], 1),
'c_Cu': ThermalTuple('cu', [29063, 29065], 1),
'c_D_in_7LiD': ThermalTuple('dlid', [1002], 1),
'c_D_in_D2O': ThermalTuple('dd2o', [1002], 1),
'c_D_in_D2O_solid': ThermalTuple('dice', [1002], 1),
'c_D_in_MgD2': ThermalTuple('dmgd2', [1002], 1),
'c_F_in_Be2': ThermalTuple('fbef2', [9019], 1),
'c_F_in_CF2': ThermalTuple('fcf2', [9019], 1),
'c_F_in_FLiBe': ThermalTuple('fflibe', [9019], 1),
'c_F_in_HF': ThermalTuple('f_hf', [9019], 1),
'c_F_in_LiF': ThermalTuple('flif', [9019], 1),
'c_F_in_MgF2': ThermalTuple('fmgf2', [9019], 1),
'c_Fe56': ThermalTuple('fe56', [26056], 1),
'c_Fe_in_Fe_alpha': ThermalTuple('fealph', [26054, 26056, 26057, 26058], 1),
'c_Fe_in_Fe_gamma': ThermalTuple('fegamm', [26054, 26056, 26057, 26058], 1),
'c_Ga_in_GaN': ThermalTuple('gagan', [31069, 31071], 1),
'c_Ga_in_GaSe': ThermalTuple('gagase', [31069, 31071], 1),
'c_Ge': ThermalTuple('ge', [32070, 32072, 32073, 32074, 32076], 1),
'c_Ge_in_Ge3Bi4O12': ThermalTuple('gegbo', [32070, 32072, 32073, 32074, 32076], 1),
'c_Ge_in_GeTe': ThermalTuple('gegete', [32070, 32072, 32073, 32074, 32076], 1),
'c_Graphite': ThermalTuple('graph', [6000, 6012, 6013], 1),
'c_Graphite_10p': ThermalTuple('grph10', [6000, 6012, 6013], 1),
'c_Graphite_20p': ThermalTuple('grph20', [6000, 6012, 6013], 1),
'c_Graphite_30p': ThermalTuple('grph30', [6000, 6012, 6013], 1),
'c_Graphite_distinct': ThermalTuple('grphsd', [6000, 6012, 6013], 1),
'c_H_in_7LiH': ThermalTuple('hlih', [1001], 1),
'c_H_in_C5O2H8': ThermalTuple('lucite', [1001], 1),
'c_H_in_C8H8': ThermalTuple('hc8h8', [1001], 1),
'c_H_in_C19H16_liquid': ThermalTuple('h19liq', [1001], 1),
'c_H_in_C19H16_solid': ThermalTuple('h19sol', [1001], 1),
'c_H_in_C2H6O_liquid': ThermalTuple('hetliq', [1001], 1),
'c_H_in_C2H6O_solid': ThermalTuple('hetsol', [1001], 1),
'c_H_in_C6H6_liquid': ThermalTuple('hbzliq', [1001], 1),
'c_H_in_C6H6_solid': ThermalTuple('hbzsol', [1001], 1),
'c_H_in_C7H8_liquid': ThermalTuple('htlliq', [1001], 1),
'c_H_in_C7H8_solid': ThermalTuple('htlsol', [1001], 1),
'c_H_in_C8H10_liquid': ThermalTuple('hxyliq', [1001], 1),
'c_H_in_C8H10_solid': ThermalTuple('hxysol', [1001], 1),
'c_H_in_C9H12_liquid': ThermalTuple('hmsliq', [1001], 1),
'c_H_in_C9H12_solid': ThermalTuple('hmssol', [1001], 1),
'c_H_in_CaH2': ThermalTuple('hcah2', [1001], 1),
'c_H_in_CaO2H2': ThermalTuple('hcaoh', [1001], 1),
'c_H1_in_CaH2': ThermalTuple('h1cah2', [1001], 1),
'c_H2_in_CaH2': ThermalTuple('h2cah2', [1001], 1),
'c_H_in_CH2': ThermalTuple('hch2', [1001], 1),
'c_H_in_CH4_liquid': ThermalTuple('lch4', [1001], 1),
'c_H_in_CH4_solid': ThermalTuple('sch4', [1001], 1),
'c_H_in_CH4_solid_phase_II': ThermalTuple('sch4p2', [1001], 1),
'c_H_in_H2O': ThermalTuple('hh2o', [1001], 1),
'c_H_in_H2O_solid': ThermalTuple('hice', [1001], 1),
'c_H_in_HF': ThermalTuple('hhf', [1001], 1),
'c_H_in_KOH': ThermalTuple('hkoh', [1001], 1),
'c_H_in_LiH': ThermalTuple('hlih2', [1001], 1),
'c_H_in_Mesitylene': ThermalTuple('mesi00', [1001], 1),
'c_H_in_ParaffinicOil': ThermalTuple('hparaf', [1001], 1),
'c_H_in_Toluene': ThermalTuple('tol00', [1001], 1),
'c_H_in_MgH2': ThermalTuple('hmgh2', [1001], 1),
'c_H_in_MgOH2': ThermalTuple('hmgoh', [1001], 1),
'c_H_in_NaMgH3': ThermalTuple('hnamg', [1001], 1),
'c_H_in_NaOH': ThermalTuple('hnaoh', [1001], 1),
'c_H_in_SrH2': ThermalTuple('hsrh2', [1001], 1),
'c_H_in_UH3': ThermalTuple('huh3', [1001], 1),
'c_H_in_YH2': ThermalTuple('hyh2', [1001], 1),
'c_H_in_ZrH': ThermalTuple('hzrh', [1001], 1),
'c_H_in_ZrH2': ThermalTuple('hzrh2', [1001], 1),
'c_H_in_ZrHx': ThermalTuple('hzrhx', [1001], 1),
'c_I_in_NaI': ThermalTuple('inai', [53127], 1),
'c_K': ThermalTuple('k', [19039, 19040, 19041], 1),
'c_K_in_KOH': ThermalTuple('kkoh', [19039, 19040, 19041], 1),
'c_Li_in_FLiBe': ThermalTuple('liflib', [3006, 3007], 1),
'c_Li_in_7LiD': ThermalTuple('lilid', [3007], 1),
'c_Li_in_7LiH': ThermalTuple('lilih', [3007], 1),
'c_Li_in_LiF': ThermalTuple('lilif', [3006, 3007], 1),
'c_Li_in_LiH': ThermalTuple('lilih2', [3006, 3007], 1),
'c_Mg24': ThermalTuple('mg24', [12024], 1),
'c_Mg_in_MgF2': ThermalTuple('mgmgf2', [12024, 12025, 12026], 1),
'c_Mg_in_MgO': ThermalTuple('mgmgo', [12024, 12025, 12026], 1),
'c_Mg_in_MgD2': ThermalTuple('mgmgd2', [12024, 12025, 12026], 1),
'c_Mg_in_MgH2': ThermalTuple('mgmgh2', [12024, 12025, 12026], 1),
'c_Mg_in_MgOH2': ThermalTuple('mgoh2', [12024, 12025, 12026], 1),
'c_Mg_in_NaMgH3': ThermalTuple('mgnamg', [12024, 12025, 12026], 1),
'c_Mo': ThermalTuple('mo', [42092, 42094, 42095, 42096, 42097, 42098, 42100], 1),
'c_N_in_GaN': ThermalTuple('ngan', [7014, 7015], 1),
'c_N_in_UN_100p': ThermalTuple('nun100', [7014, 7015], 1),
'c_N_in_UN_10p': ThermalTuple('nun10', [7014, 7015], 1),
'c_N_in_UN_5p': ThermalTuple('nun5', [7014, 7015], 1),
'c_N_in_UN': ThermalTuple('n-un', [7014, 7015], 1),
'c_N_in_UN_HALEU': ThermalTuple('nunhal', [7014, 7015], 1),
'c_N_in_UN_HEU': ThermalTuple('nunheu', [7014, 7015], 1),
'c_Na': ThermalTuple('na', [11023], 1),
'c_Na_in_NaI': ThermalTuple('nanai', [11023], 1),
'c_Na_in_NaMgH3': ThermalTuple('nanamg', [11023], 1),
'c_Na_in_NaOH': ThermalTuple('nanaoh', [11023], 1),
'c_Nb': ThermalTuple('nb', [41093], 1),
'c_Ni': ThermalTuple('ni', [28058, 28060, 28061, 28062, 28064], 1),
'c_O_in_Al2O3': ThermalTuple('osap00', [8016, 8017, 8018], 1),
'c_O_in_BeO': ThermalTuple('obeo', [8016, 8017, 8018], 1),
'c_O_in_C5O2H8': ThermalTuple('olucit', [8016, 8017, 8018], 1),
'c_O_in_C2H6O_liquid': ThermalTuple('oetliq', [8016, 8017, 8018], 1),
'c_O_in_C2H6O_solid': ThermalTuple('oetsol', [8016, 8017, 8018], 1),
'c_O_in_CaO2H2': ThermalTuple('ocaoh', [8016, 8017, 8018], 1),
'c_O_in_D2O': ThermalTuple('od2o', [8016, 8017, 8018], 1),
'c_O_in_H2O_solid': ThermalTuple('oice', [8016, 8017, 8018], 1),
'c_O_in_MgO': ThermalTuple('omgo', [8016, 8017, 8018], 1),
'c_O_in_Ge3Bi4O12': ThermalTuple('ogbo', [8016, 8017, 8018], 1),
'c_O_in_H2O': ThermalTuple('oh2o', [8016, 8017, 8018], 1),
'c_O_in_KOH': ThermalTuple('okoh', [8016, 8017, 8018], 1),
'c_O_in_MgOH2': ThermalTuple('omgoh', [8016, 8017, 8018], 1),
'c_O_in_NaOH': ThermalTuple('onaoh', [8016, 8017, 8018], 1),
'c_O_in_PuO2': ThermalTuple('opuo2', [8016, 8017, 8018], 1),
'c_O_in_SiO2_alpha': ThermalTuple('osio2a', [8016, 8017, 8018], 1),
'c_O_in_UO2_100p': ThermalTuple('ouo200', [8016, 8017, 8018], 1),
'c_O_in_UO2_10p': ThermalTuple('ouo210', [8016, 8017, 8018], 1),
'c_O_in_UO2_5p': ThermalTuple('ouo25', [8016, 8017, 8018], 1),
'c_O_in_UO2': ThermalTuple('ouo2', [8016, 8017, 8018], 1),
'c_O_in_UO2_HALEU': ThermalTuple('ouo2hl', [8016, 8017, 8018], 1),
'c_O_in_UO2_HEU': ThermalTuple('ouo2he', [8016, 8017, 8018], 1),
'c_O_in_Y3Al5O12': ThermalTuple('oyag', [8016, 8017, 8018], 1),
'c_ortho_D': ThermalTuple('orthod', [1002], 1),
'c_ortho_H': ThermalTuple('orthoh', [1001], 1),
'c_para_D': ThermalTuple('parad', [1002], 1),
'c_para_H': ThermalTuple('parah', [1001], 1),
'c_Pb': ThermalTuple('pb', [82204, 82206, 82207, 82208], 1),
'c_Pd': ThermalTuple('pd', [46102, 46104, 46105, 46106, 46108, 46110], 1),
'c_Pt': ThermalTuple('pt', [78190, 78192, 78194, 78195, 78196, 78198], 1),
'c_Pu_in_PuO2': ThermalTuple('puo2', [94239, 94240, 94241, 94242, 94243], 1),
'c_Si28': ThermalTuple('si00', [14028], 1),
'c_Si_in_SiC': ThermalTuple('sisic', [14028, 14029, 14030], 1),
'c_Si_in_SiO2_alpha': ThermalTuple('si_o2a', [14028, 14029, 14030], 1),
'c_SiO2_alpha': ThermalTuple('sio2-a', [8016, 8017, 8018, 14028, 14029, 14030], 3),
'c_SiO2_beta': ThermalTuple('sio2-b', [8016, 8017, 8018, 14028, 14029, 14030], 3),
'c_S_in_ZnS': ThermalTuple('szns', [16032, 16033, 16034, 16036], 1),
'c_Se_in_GaSe': ThermalTuple('segase', [34074, 34076, 34077, 34078, 34080, 34082], 1),
'c_Sn': ThermalTuple('sn', [50112, 50114, 50115, 50116, 50117, 50118, 50119, 50120, 50122, 50124], 1),
'c_Sr_in_SrH2': ThermalTuple('srsrh2', [38084, 38086, 38087, 38088], 1),
'c_Te_in_GeTe': ThermalTuple('tegete', [52120, 52122, 52123, 52124, 52125, 52126, 52128, 52130], 1),
'c_Ti': ThermalTuple('ti', [22046, 22047, 22048, 22049, 22050], 1),
'c_U_metal_100p': ThermalTuple('u-100p', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_metal_10p': ThermalTuple('u-10p', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_metal_5p': ThermalTuple('u-5p', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_metal': ThermalTuple('umetal', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_metal_HALEU': ThermalTuple('uhaleu', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_metal_HEU': ThermalTuple('u-heu', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC_100p': ThermalTuple('uc-100', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC_10p': ThermalTuple('uc-10', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC_5p': ThermalTuple('uc-5', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC': ThermalTuple('uc-nat', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC_HALEU': ThermalTuple('uc-hal', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UC_HEU': ThermalTuple('uc-heu', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN_100p': ThermalTuple('un-100', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN_10p': ThermalTuple('un-10', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN_5p': ThermalTuple('un-5', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN': ThermalTuple('u-un', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN_HALEU': ThermalTuple('un-hal', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UN_HEU': ThermalTuple('un-heu', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2_100p': ThermalTuple('uo2100', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2_10p': ThermalTuple('uo2-10', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2_5p': ThermalTuple('uo2-5', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2': ThermalTuple('uuo2', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2_HALEU': ThermalTuple('uo2hal', [92233, 92234, 92235, 92236, 92238], 1),
'c_U_in_UO2_HEU': ThermalTuple('uo2heu', [92233, 92234, 92235, 92236, 92238], 1),
'c_V': ThermalTuple('v', [23050, 23051], 1),
'c_W': ThermalTuple('w', [74180, 74182, 74183, 74184, 74186], 1),
'c_Y_in_Y3Al5O12': ThermalTuple('yyag', [39089], 1),
'c_Y_in_YH2': ThermalTuple('yyh2', [39089], 1),
'c_Zn': ThermalTuple('zn', [30064, 30066, 30067, 30068, 30070], 1),
'c_Zn_in_ZnS': ThermalTuple('znzns', [30064, 30066, 30067, 30068, 30070], 1),
'c_Zr': ThermalTuple('zr', [40090, 40091, 40092, 40094, 40096], 1),
'c_Zr_in_ZrC': ThermalTuple('zrzrc', [40000, 40090, 40091, 40092, 40094, 40096], 1),
'c_Zr_in_ZrH': ThermalTuple('zrzrh', [40000, 40090, 40091, 40092, 40094, 40096], 1),
'c_Zr_in_ZrH2': ThermalTuple('zrzrh2', [40000, 40090, 40091, 40092, 40094, 40096], 1),
'c_Zr_in_ZrHx': ThermalTuple('zrzrhx', [40000, 40090, 40091, 40092, 40094, 40096], 1),
}
_TEMPLATE_RECONR = """
reconr / %%%%%%%%%%%%%%%%%%% Reconstruct XS for neutrons %%%%%%%%%%%%%%%%%%%%%%%
{nendf} {npendf}
'{library} PENDF for {zsymam}'/
{mat} 2/
{error}/ err
'{library}: {zsymam}'/
'Processed by NJOY'/
0/
"""
_TEMPLATE_BROADR = """
broadr / %%%%%%%%%%%%%%%%%%%%%%% Doppler broaden XS %%%%%%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {npendf} {nbroadr}
{mat} {num_temp} 0 0 0. /
{error}/ errthn
{temps}
0/
"""
_TEMPLATE_HEATR = """
heatr / %%%%%%%%%%%%%%%%%%%%%%%%% Add heating kerma %%%%%%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {nheatr_in} {nheatr} /
{mat} 4 0 0 0 0 {ed}/
302 318 402 444 /
"""
_TEMPLATE_HEATR_LOCAL = """
heatr / %%%%%%%%%%%%%%%%% Add heating kerma (local photons) %%%%%%%%%%%%%%%%%%%%
{nendf} {nheatr_in} {nheatr_local} /
{mat} 4 0 0 1 0 {ed}/
302 318 402 444 /
"""
_TEMPLATE_GASPR = """
gaspr / %%%%%%%%%%%%%%%%%%%%%%%%% Add gas production %%%%%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {ngaspr_in} {ngaspr} /
"""
_TEMPLATE_PURR = """
purr / %%%%%%%%%%%%%%%%%%%%%%%% Add probability tables %%%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {npurr_in} {npurr} /
{mat} {num_temp} 1 20 64 /
{temps}
1.e10
0/
"""
_TEMPLATE_ACER = """
acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {nacer_in} 0 {nace} {ndir}
1 0 1 .{ext} /
'{library}: {zsymam} at {temperature}'/
{mat} {temperature}
1 1 {ismooth}/
/
"""
_THERMAL_TEMPLATE_THERMR = """
thermr / %%%%%%%%%%%%%%%% Add thermal scattering data (free gas) %%%%%%%%%%%%%%%
0 {nthermr1_in} {nthermr1}
0 {mat} {nbin} {num_temp} 1 0 {iform} 1 221 1/
{temps}
{error} {energy_max}
thermr / %%%%%%%%%%%%%%%% Add thermal scattering data (bound) %%%%%%%%%%%%%%%%%%
{nthermal_endf} {nthermr2_in} {nthermr2}
{mat_thermal} {mat} {nbin} {num_temp} {inelastic} {elastic} {iform} {natom} 222 1/
{temps}
{error} {energy_max}
"""
_THERMAL_TEMPLATE_ACER = """
acer / %%%%%%%%%%%%%%%%%%%%%%%% Write out in ACE format %%%%%%%%%%%%%%%%%%%%%%%%
{nendf} {nthermal_acer_in} 0 {nace} {ndir}
2 0 1 .{ext}/
'{library}: {zsymam_thermal} processed by NJOY'/
{mat} {temperature} '{data.name}' {nza} /
{zaids} /
222 64 {mt_elastic} {elastic_type} {data.nmix} {energy_max} {iwt}/
"""
def run(commands, tapein, tapeout, input_filename=None, stdout=False,
njoy_exec='njoy'):
"""Run NJOY with given commands
Parameters
----------
commands : str
Input commands for NJOY
tapein : dict
Dictionary mapping tape numbers to paths for any input files
tapeout : dict
Dictionary mapping tape numbers to paths for any output files
input_filename : str, optional
File name to write out NJOY input commands
stdout : bool, optional
Whether to display output when running NJOY
njoy_exec : str, optional
Path to NJOY executable
Raises
------
subprocess.CalledProcessError
If the NJOY process returns with a non-zero status
"""
if input_filename is not None:
with open(str(input_filename), 'w') as f:
f.write(commands)
with tempfile.TemporaryDirectory() as tmpdir:
# Copy evaluations to appropriates 'tapes'
for tape_num, filename in tapein.items():
tmpfilename = os.path.join(tmpdir, f'tape{tape_num}')
shutil.copy(str(filename), tmpfilename)
# Start up NJOY process
njoy = Popen([njoy_exec], cwd=tmpdir, stdin=PIPE, stdout=PIPE,
stderr=STDOUT, universal_newlines=True)
njoy.stdin.write(commands)
njoy.stdin.flush()
lines = []
while True:
# If process is finished, break loop
line = njoy.stdout.readline()
if not line and njoy.poll() is not None:
break
lines.append(line)
if stdout:
# If user requested output, print to screen
print(line, end='')
# Check for error
if njoy.returncode != 0:
raise CalledProcessError(njoy.returncode, njoy_exec,
''.join(lines))
# Copy output files back to original directory
for tape_num, filename in tapeout.items():
tmpfilename = os.path.join(tmpdir, f'tape{tape_num}')
if os.path.isfile(tmpfilename):
shutil.move(tmpfilename, str(filename))
def make_pendf(filename, pendf='pendf', **kwargs):
"""Generate pointwise ENDF file from an ENDF file
Parameters
----------
filename : str
Path to ENDF file
pendf : str, optional
Path of pointwise ENDF file to write
**kwargs
Keyword arguments passed to :func:`openmc.data.njoy.make_ace`. All NJOY
module arguments other than pendf default to False.
Raises
------
subprocess.CalledProcessError
If the NJOY process returns with a non-zero status
"""
for key in ('broadr', 'heatr', 'gaspr', 'purr', 'acer'):
kwargs.setdefault(key, False)
make_ace(filename, pendf=pendf, **kwargs)
def make_ace(filename, temperatures=None, acer=True, xsdir=None,
output_dir=None, pendf=False, error=0.001, broadr=True,
heatr=True, gaspr=True, purr=True, evaluation=None,
smoothing=True, displacement_energy=None, **kwargs):
"""Generate incident neutron ACE file from an ENDF file
File names can be passed to
``[acer, xsdir, pendf, broadr, heatr, gaspr, purr]``
to specify the exact output for the given module.
Otherwise, the files will be writen to the current directory
or directory specified by ``output_dir``. Default file
names mirror the variable names, e.g. ``heatr`` output
will be written to a file named ``heatr`` unless otherwise
specified.
Parameters
----------
filename : str
Path to ENDF file
temperatures : iterable of float, optional
Temperatures in Kelvin to produce ACE files at. If omitted, data is
produced at room temperature (293.6 K).
acer : bool or str, optional
Flag indicating if acer should be run. If a string is give, write the
resulting ``ace`` file to this location. Path of ACE file to write.
Defaults to ``"ace"``
xsdir : str, optional
Path of xsdir file to write. Defaults to ``"xsdir"`` in the same
directory as ``acer``
output_dir : str, optional
Directory to write output for requested modules. If not provided
and at least one of ``[pendf, broadr, heatr, gaspr, purr, acer]``
is ``True``, then write output files to current directory. If given,
must be a path to a directory.
pendf : str, optional
Path of pendf file to write. If omitted, the pendf file is not saved.
error : float, optional
Fractional error tolerance for NJOY processing
broadr : bool or str, optional
Indicating whether to Doppler broaden XS when running NJOY. If string,
write the output tape to this file.
heatr : bool or str, optional
Indicating whether to add heating kerma when running NJOY. If string,
write the output tape to this file.
gaspr : bool or str, optional
Indicating whether to add gas production data when running NJOY.
If string, write the output tape to this file.
purr : bool or str, optional
Indicating whether to add probability table when running NJOY.
If string, write the output tape to this file.
evaluation : openmc.data.endf.Evaluation, optional
If the ENDF file contains multiple material evaluations, this argument
indicates which evaluation should be used.
smoothing : bool, optional
If the smoothing option (ACER card 6) is on (True) or off (False).
displacement_energy : float, optional
Threshold displacement energy in [eV]. Used in HEATR to calculate
damage-energy cross section. When None, use NJOY defaults.
**kwargs
Keyword arguments passed to :func:`openmc.data.njoy.run`
Raises
------
subprocess.CalledProcessError
If the NJOY process returns with a non-zero status
IOError
If ``output_dir`` does not point to a directory
"""
if output_dir is None:
output_dir = Path()
else:
output_dir = Path(output_dir)
if not output_dir.is_dir():
raise IOError(f"{output_dir} is not a directory")
ev = evaluation if evaluation is not None else endf.Evaluation(filename)
mat = ev.material
zsymam = ev.target['zsymam']
# Determine name of library
library = '{}-{}.{}'.format(*ev.info['library'])
if temperatures is None:
temperatures = [293.6]
num_temp = len(temperatures)
temps = ' '.join(str(i) for i in temperatures)
# Create njoy commands by modules
commands = ""
nendf, npendf = 20, 21
tapein = {nendf: filename}
tapeout = {}
if pendf:
tapeout[npendf] = (output_dir / "pendf") if pendf is True else pendf
# reconr
commands += _TEMPLATE_RECONR
nlast = npendf
# broadr
if broadr:
nbroadr = nlast + 1
tapeout[nbroadr] = (output_dir / "broadr") if broadr is True else broadr
commands += _TEMPLATE_BROADR
nlast = nbroadr
# heatr
if heatr:
ed = displacement_energy if displacement_energy is not None else 0
nheatr_in = nlast
nheatr_local = nheatr_in + 1
tapeout[nheatr_local] = (output_dir / "heatr_local") if heatr is True \
else heatr + '_local'
commands += _TEMPLATE_HEATR_LOCAL
nheatr = nheatr_local + 1
tapeout[nheatr] = (output_dir / "heatr") if heatr is True else heatr
commands += _TEMPLATE_HEATR
nlast = nheatr
# gaspr
if gaspr:
ngaspr_in = nlast
ngaspr = ngaspr_in + 1
tapeout[ngaspr] = (output_dir / "gaspr") if gaspr is True else gaspr
commands += _TEMPLATE_GASPR
nlast = ngaspr
# purr
if purr:
npurr_in = nlast
npurr = npurr_in + 1
tapeout[npurr] = (output_dir / "purr") if purr is True else purr
commands += _TEMPLATE_PURR
nlast = npurr
commands = commands.format(**locals())
# acer
if acer:
ismooth = int(smoothing)
nacer_in = nlast
for i, temperature in enumerate(temperatures):
# Extend input with an ACER run for each temperature
nace = nacer_in + 1 + 2*i
ndir = nace + 1
ext = f'{i + 1:02}'
commands += _TEMPLATE_ACER.format(**locals())
# Indicate tapes to save for each ACER run
tapeout[nace] = output_dir / f"ace_{temperature:.1f}"
tapeout[ndir] = output_dir / f"xsdir_{temperature:.1f}"
commands += 'stop\n'
run(commands, tapein, tapeout, **kwargs)
if acer:
ace = (output_dir / "ace") if acer is True else Path(acer)
xsdir = (ace.parent / "xsdir") if xsdir is None else xsdir
with ace.open('w') as ace_file, xsdir.open('w') as xsdir_file:
for temperature in temperatures:
# Get contents of ACE file
text = (output_dir / f"ace_{temperature:.1f}").read_text()
# If the target is metastable, make sure that ZAID in the ACE
# file reflects this by adding 400
if ev.target['isomeric_state'] > 0:
mass_first_digit = int(text[3])
if mass_first_digit <= 2:
text = text[:3] + str(mass_first_digit + 4) + text[4:]
# Concatenate into destination ACE file
ace_file.write(text)
# Concatenate into destination xsdir file
xsdir_in = output_dir / f"xsdir_{temperature:.1f}"
xsdir_file.write(xsdir_in.read_text())
# Remove ACE/xsdir files for each temperature
for temperature in temperatures:
(output_dir / f"ace_{temperature:.1f}").unlink()
(output_dir / f"xsdir_{temperature:.1f}").unlink()
def make_ace_thermal(filename, filename_thermal, temperatures=None,
ace=None, xsdir=None, output_dir=None, error=0.001,
iwt=2, evaluation=None, evaluation_thermal=None,
table_name=None, zaids=None, nmix=None, nbin=16, **kwargs):
"""Generate thermal scattering ACE file from ENDF files
Parameters
----------
filename : str
Path to ENDF neutron sublibrary file
filename_thermal : str
Path to ENDF thermal scattering sublibrary file
temperatures : iterable of float, optional
Temperatures in Kelvin to produce data at. If omitted, data is produced
at all temperatures given in the ENDF thermal scattering sublibrary.
ace : str, optional
Path of ACE file to write. Default to ``"ace"``.
xsdir : str, optional
Path of xsdir file to write. Defaults to ``"xsdir"`` in the same
directory as ``ace``
output_dir : str, optional
Directory to write ace and xsdir files. If not provided, then write
output files to current directory. If given, must be a path to a
directory.
error : float, optional
Fractional error tolerance for NJOY processing
iwt : int
`iwt` parameter used in NJOY/ACER card 9
evaluation : openmc.data.endf.Evaluation, optional
If the ENDF neutron sublibrary file contains multiple material
evaluations, this argument indicates which evaluation to use.
evaluation_thermal : openmc.data.endf.Evaluation, optional
If the ENDF thermal scattering sublibrary file contains multiple
material evaluations, this argument indicates which evaluation to use.
table_name : str, optional
Name to assign to ACE table
zaids : list of int, optional
ZAIDs that the thermal scattering data applies to
nmix : int, optional
Number of atom types in mixed moderator
nbin : int, optional
Number of equi-probable angles
**kwargs
Keyword arguments passed to :func:`openmc.data.njoy.run`
Raises
------
subprocess.CalledProcessError
If the NJOY process returns with a non-zero status
"""
if output_dir is None:
output_dir = Path()
else:
output_dir = Path(output_dir)
if not output_dir.is_dir():
raise IOError(f"{output_dir} is not a directory")
ev = evaluation if evaluation is not None else endf.Evaluation(filename)
mat = ev.material
zsymam = ev.target['zsymam']
ev_thermal = (evaluation_thermal if evaluation_thermal is not None
else endf.Evaluation(filename_thermal))
mat_thermal = ev_thermal.material
zsymam_thermal = ev_thermal.target['zsymam'].strip()
# Determine name, isotopes, and number of atom types
if table_name and zaids and nmix:
data = ThermalTuple(table_name, zaids, nmix)
else:
with warnings.catch_warnings(record=True) as w:
proper_name = openmc.data.get_thermal_name(zsymam_thermal)
if w or proper_name not in _THERMAL_DATA:
raise RuntimeError(
f"Thermal scattering material {zsymam_thermal} not "
"recognized. Please contact OpenMC developers at "
"https://openmc.discourse.group.")
data = _THERMAL_DATA[proper_name]
zaids = ' '.join(str(zaid) for zaid in data.zaids)
nza = len(data.zaids)
# Determine name of library
library = '{}-{}.{}'.format(*ev_thermal.info['library'])
# Determine if thermal elastic is present
if (7, 2) in ev_thermal.section:
elastic = 1
mt_elastic = 223
# Determine whether elastic is incoherent (0) or coherent (1)
file_obj = StringIO(ev_thermal.section[7, 2])
elastic_type = endf.get_head_record(file_obj)[2] - 1
else:
elastic = 0
mt_elastic = 0
elastic_type = 0
# Determine number of principal atoms
file_obj = StringIO(ev_thermal.section[7, 4])
items = endf.get_head_record(file_obj)
items, values = endf.get_list_record(file_obj)
energy_max = values[3]
natom = int(values[5])
# Note that the 'iform' parameter is omitted in NJOY 99. We assume that the
# user is using NJOY 2012 or later.
iform = 0
inelastic = 2
# Determine temperatures from MF=7, MT=4 if none were specified
if temperatures is None:
file_obj = StringIO(ev_thermal.section[7, 4])
endf.get_head_record(file_obj)
endf.get_list_record(file_obj)
endf.get_tab2_record(file_obj)
params = endf.get_tab1_record(file_obj)[0]
temperatures = [params[0]]
for i in range(params[2]):
temperatures.append(endf.get_list_record(file_obj)[0][0])
num_temp = len(temperatures)
temps = ' '.join(str(i) for i in temperatures)
# Create njoy commands by modules
commands = ""
nendf, nthermal_endf, npendf = 20, 21, 22
tapein = {nendf: filename, nthermal_endf: filename_thermal}
tapeout = {}
# reconr
commands += _TEMPLATE_RECONR
nlast = npendf
# broadr
nbroadr = nlast + 1
commands += _TEMPLATE_BROADR
nlast = nbroadr
# thermr
nthermr1_in = nlast
nthermr1 = nthermr1_in + 1
nthermr2_in = nthermr1
nthermr2 = nthermr2_in + 1
commands += _THERMAL_TEMPLATE_THERMR
nlast = nthermr2
commands = commands.format(**locals())
# acer
nthermal_acer_in = nlast
for i, temperature in enumerate(temperatures):
# Extend input with an ACER run for each temperature
nace = nthermal_acer_in + 1 + 2*i
ndir = nace + 1
ext = f'{i + 1:02}'
commands += _THERMAL_TEMPLATE_ACER.format(**locals())
# Indicate tapes to save for each ACER run
tapeout[nace] = output_dir / f"ace_{temperature:.1f}"
tapeout[ndir] = output_dir / f"xsdir_{temperature:.1f}"
commands += 'stop\n'
run(commands, tapein, tapeout, **kwargs)
ace = (output_dir / "ace") if ace is None else Path(ace)
xsdir = (ace.parent / "xsdir") if xsdir is None else Path(xsdir)
with ace.open('w') as ace_file, xsdir.open('w') as xsdir_file:
# Concatenate ACE and xsdir files together
for temperature in temperatures:
ace_in = output_dir / f"ace_{temperature:.1f}"
ace_file.write(ace_in.read_text())
xsdir_in = output_dir / f"xsdir_{temperature:.1f}"
xsdir_file.write(xsdir_in.read_text())
# Remove ACE/xsdir files for each temperature
for temperature in temperatures:
(output_dir / f"ace_{temperature:.1f}").unlink()
(output_dir / f"xsdir_{temperature:.1f}").unlink()