D1S-UNED files#

Reaction file#

The complete API can be found at f4enix.input.d1suned.ReactionFile

Reaction files (default name ‘reac’) contain all the reaction pathways that should be considered during a D1S-UNED simulation. They are implemented in F4Enix as a simple list of single reactions.

from f4enix.input.d1suned import Reaction, ReactionFile
from f4enix.core.irradiation import Nuclide

# Generate a single reaction
reac = Reaction(Nuclide(1001, lib="91c"), 102, Nuclide(1002, lib="91c"), comment='fake reaction')
print(reac)

# It can also be generated from a formatted string
reac_str = "1001.92c 102 1002.92c # fake reaction"
reac2 = Reaction.from_text(reac_str)
print(reac2)
/home/docs/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
parent: H1.91c
MT channel: 102
daughter: H2.91c
comment: fake reaction


parent: H1.92c
MT channel: 102
daughter: H2.92c
comment: # fake reaction
import tempfile

# A reaction file can be generated from a list of reactions and saved
reac_file = ReactionFile([reac])
outpath = tempfile.gettempdir()
reac_file.write(outpath)

# But more often is instantiated directly from an exisiting file
# Note that metastable elements have a '900' added to their zaid number
reac_file = ReactionFile.from_text('reac_fe')
reac_file
       Parent     MT    Daughter                                 Comment
    26054.99c    102       26055                                    Fe55
    26054.99c    103       25054                                    Mn54
    26054.99c    107       24051                                    Cr51
    26056.99c    105       25054                                    Mn54
    26056.99c    103       25056                                    Mn56
    26056.99c     16       26055                                    Fe55
    26057.99c     28       25056                                    Mn56
    26057.99c    104       25056                                    Mn56
    26058.99c    102       26059                                    Fe59
    26058.99c    105       25056                                    Mn56
    78195.99c    304    78195900                                  Pt195m
# a convenient method is also provided to change the activation library to use
reac_file.change_lib('98c')
print(reac_file)

# and it is also possible to get a list of parents
print('Parent list:')
reac_file.get_parents()
       Parent     MT    Daughter                                 Comment
    26054.98c    102       26055                                    Fe55
    26054.98c    103       25054                                    Mn54
    26054.98c    107       24051                                    Cr51
    26056.98c    105       25054                                    Mn54
    26056.98c    103       25056                                    Mn56
    26056.98c     16       26055                                    Fe55
    26057.98c     28       25056                                    Mn56
    26057.98c    104       25056                                    Mn56
    26058.98c    102       26059                                    Fe59
    26058.98c    105       25056                                    Mn56
    78195.98c    304    78195900                                  Pt195m

Parent list:
[Fe54.98c, Fe56.98c, Fe57.98c, Fe58.98c, Pt195.98c]

Note that the parents are Nuclide objects

parents = reac_file.get_parents()
print(type(parents[0]))
<class 'f4enix.core.irradiation.Nuclide'>

Irradiation file#

The complete API can be found at f4enix.input.d1suned.IrradiationFile`

Irradiation files contain information related to the time correction factors to be used in the D1S-UNED calculation.

from f4enix.input.d1suned import Irradiation, IrradiationFile

# generate a single irradiation from scratch
irr = Irradiation(Nuclide.from_formula("Fe59"), 1.8e3, ['4e3', '5e3'], comment='Fake irr')
print(irr)
Daughter: Fe59
lambda [1/s]: 1800.0
times: ('4e3', '5e3')
comment: Fake irr
import tempfile

# More often an existing irradiation file is parsed
irrad_file = IrradiationFile.from_text('irr_test')

# eliminate the last irradiation and save
irrad_file.irr_schedules = irrad_file.irr_schedules[:-1]
irrad_file.write(tempfile.gettempdir())

# get the list of irradiation schedules
irrad_file.irr_schedules
[['24051', '2.896e-07', '5.982e+00', '5.697e+00', 'Cr51'],
 ['25054', '2.570e-08', '5.881e+00', '1.829e+00', 'Mn54'],
 ['26055', '8.031e-09', '4.487e+00', '6.364e-01', 'Fe55'],
 ['27062', '7.702e-03', '1.336e+00', '1', 'Co62'],
 ['27062900', '8.305e-04', '4.151e-01', '1', 'Co62m']]

A reaction file can also be computed directly using the TCF_Computer class to calculate the time correction factors for the different nuclides at different irradiation scenarios.

from f4enix.core.irradiation import Pulse, TIME_UNITS, IrradiationScenario, Nuclide
pulses = (
    [Pulse(1, 1e10, TIME_UNITS.DAY), Pulse(2, 0, TIME_UNITS.DAY)]*4
)
irr_scenario1 = IrradiationScenario(pulses)

pulses = (
    [Pulse(1, 1e10, TIME_UNITS.DAY), Pulse(2, 0, TIME_UNITS.DAY)]*100
)
irr_scenario2 = IrradiationScenario(pulses)

daughter_nuclides = [Nuclide.from_formula("Co60"), Nuclide.from_formula("Cr51")]

irr_file2 = IrradiationFile.from_irradiation_schedules(
    daughter_nuclides,
    [irr_scenario1, irr_scenario2],
    norm=1e10
)

irr_file2.irr_schedules
[['27060', '4.167e-09', '1.437e-03', '3.411e-02', 'Co60'],
 ['24051', '2.896e-07', '8.430e-02', '3.249e-01', 'Cr51']]

F4Enix also supports the use of IRS cards. The procedure to create an irrad file would be the same but nuclides using it should be flagged.

daughter_nuclides = [Nuclide.from_formula("irsCo60"), Nuclide.from_formula("Co60")]
irr_file3 = IrradiationFile.from_irradiation_schedules(
    daughter_nuclides,
    [irr_scenario1],
    scale_IRS={'irsCo60': [0.5, 3, 10]},  # example of scaling IRS data
    norm=1e10
)
irr_file3.irr_schedules
[['99927060', '4.167e-09', '7.183e-04', '4.310e-03', '1.437e-02', 'irsCo60'],
 ['27060', '4.167e-09', '1.437e-03', '1.437e-03', '1.437e-03', 'Co60']]
# auxiliary method to retrieve a specific irradiation
print(irrad_file.get_irrad('24051'))

# auxiliary method to get all daughters
print(irrad_file.get_daughters())
Daughter: Cr51
lambda [1/s]: 2.896e-07
times: ('5.982e+00', '5.697e+00')
comment: Cr51

[Cr51, Mn54, Fe55, Co62, Co62m]

You can also add/remove irradiation schedules and modify them:

new_times = {
    "24051": ["5.982e+00", "5.697e+00"],
    "25054": ["5.881e+00", "1.829e+00"],
    "26055": ["4.487e+00", "6.364e-01"],
    "27062": ["1.336e+00", "4.151e-01"],
    "27062900": ["4.151e-01", "4.151e-01"],
}
irrad_file.add_irradiation_times(new_times)
print(irrad_file.get_irrad('24051'))
Daughter: Cr51
lambda [1/s]: 2.896e-07
times: ('5.982e+00', '5.697e+00', '5.982e+00', '5.697e+00')
comment: Cr51
irrad_file.irr_schedules[0].modify_time_val(3, 4.56)
print(irrad_file.get_irrad('24051'))
Daughter: Cr51
lambda [1/s]: 2.896e-07
times: ('5.982e+00', '5.697e+00', '5.982e+00', '4.560e+00')
comment: Cr51
irrad_file.remove_irradiation_time(3)
print(irrad_file.get_irrad('24051'))
Daughter: Cr51
lambda [1/s]: 2.896e-07
times: ('5.982e+00', '5.697e+00', '5.982e+00')
comment: Cr51

D1S MCNP input#

The D1S-UNED MCNP input is exactly the same as a normal MCNP input with a few additional cards. In F4Enix is implemented as a child of the Input class and it includes as attributes also an IrradiationFile and ReactionFile objects. There are many ways to initialize this object and the simplest one is when all text input files are aleady available and can be parsed.

from f4enix.input.d1suned import ReactionFile, IrradiationFile
from f4enix.input.MCNPinput import D1S_Input

# Simplest case, all text input are already present and can be parsed
d1s_inp = D1S_Input.from_input('d1stest.i', irrad_file='irr_test',
                               reac_file='reac_fe')
print(type(d1s_inp.reac_file))
print(type(d1s_inp.irrad_file))
<class 'f4enix.input.d1suned.ReactionFile'>
<class 'f4enix.input.d1suned.IrradiationFile'>

Nevertheless, F4Enix can also help in the automatic generation of irrad and react file. An example can be the following: let’s suppose that a number of daughters have been identified as the most important radioactive isotopes of interest for a specific SDDR computation. A reaction file can be built automatically that will include all the reactions available in a specific activation library that lead to one of the listed daughters. Only parents that are included in the materials of the MCNP input will be considered.

from f4enix.input.libmanager import LibManager

# Parse only the MCNP input and the irrad file containing the list of daughters
# to be considered
d1s_inp = D1S_Input.from_input('d1stest.i', irrad_file='irr_test')
print('Daughters:')
print(d1s_inp.irrad_file.get_daughters())

# generate the reaction file with the default Library Manager and the 99c lib.
lm = LibManager()
d1s_inp.get_reaction_file(lm, '99c')
d1s_inp.reac_file
Daughters:
[Cr51, Mn54, Fe55, Co62, Co62m, Fe59]
       Parent     MT    Daughter                                 Comment
    24050.99c    102       24051                        Cr50.99c -> Cr51
    24052.99c     16       24051                        Cr52.99c -> Cr51
    25055.99c     16       25054                        Mn55.99c -> Mn54
    26054.99c    102       26055                        Fe54.99c -> Fe55
    26054.99c    103       25054                        Fe54.99c -> Mn54
    26054.99c    107       24051                        Fe54.99c -> Cr51
    26056.99c    105       25054                        Fe56.99c -> Mn54
    26056.99c     16       26055                        Fe56.99c -> Fe55
    26058.99c    102       26059                        Fe58.99c -> Fe59
    27059.99c    103       26059                        Co59.99c -> Fe59
    28058.99c    112       25054                        Ni58.99c -> Mn54
    28062.99c    107       26059                        Ni62.99c -> Fe59

If no decision has been taken on which daughters should be considered, F4Enix also allows to have a list of all the possible reactions that are foreseen from a specified activation library where the parent isotope is listed an at least one material of the MCNP input.

# parse only the MNCP input
d1s_inp = D1S_Input.from_input('d1stest.i')
lm = LibManager()
# this is a list of reactions and can be directly used to initialize a reaction
# file if needed.
d1s_inp.get_potential_paths(lm, '98c')[:3]
[
 parent: Al27.98c
 MT channel: 107
 daughter: Na24
 comment: Al27.98c -> Na24,
 
 parent: Cr50.98c
 MT channel: 102
 daughter: Cr51
 comment: Cr50.98c -> Cr51,
 
 parent: Cr52.98c
 MT channel: 16
 daughter: Cr51
 comment: Cr52.98c -> Cr51]

Another common task could be to translate a d1s input (and reaction file) from a library to another. The first method to do this is a 1 to 1 conversion. This is also available also in a standard MCNP input. This works if the decay pathways of interest (reactions) are available in both libraries. This check is not performed by F4Enix!

d1s_inp = D1S_Input.from_input('d1stest.i', irrad_file='irr_test',
                               reac_file='reac_fe')

print('before:')
print(d1s_inp.materials['M1'].to_text()[-500:])

# this translates all activated zaid with old library 99c to the new 98c. Also
# the transport library is changed here, from 21c to 31c
new_lib = {'99c': '98c', '21c': '31c'}
lm = LibManager()
d1s_inp.translate(new_lib, lm)

# Check the translation (only a piece of a material)
print('\nafter:')
print(d1s_inp.materials['M1'].to_text()[-500:])

# Manually change also the library in the reaction file
d1s_inp.reac_file.change_lib('98c')
print('\nreac file:')
d1s_inp.reac_file
before:
AB(%)     
      74183.21c        3.377160E-7     $        WEIGHT(%)  AB(%)     
      74184.21c        7.231040E-7     $        WEIGHT(%)  AB(%)     
      74186.99c        6.709480E-7     $        WEIGHT(%)  AB(%)     
      82206.21c        4.048800E-7     $        WEIGHT(%)  AB(%)     
      82207.21c        3.712800E-7     $        WEIGHT(%)  AB(%)     
      82208.21c        8.803200E-7     $        WEIGHT(%)  AB(%)     
      83209.21c        1.660000E-6     $        WEIGHT(%)  AB(%)     
after:
%) 14.327
      74184.31c        7.231040E-7     $ W-184  WEIGHT(%) 0.00096798 AB(%) 30.677
      74186.98c        6.709480E-7     $ W-186  WEIGHT(%) 0.00096798 AB(%) 28.464
      82206.31c        4.048800E-7     $ Pb-206 WEIGHT(%) 0.00076688 AB(%) 24.442
      82207.31c        3.712800E-7     $ Pb-207 WEIGHT(%) 0.00076688 AB(%) 22.414
      82208.31c        8.803200E-7     $ Pb-208 WEIGHT(%) 0.00076688 AB(%) 53.144
      83209.31c        1.660000E-6     $ Bi-209 WEIGHT(%) 0.00077488 AB(%) 100.0

reac file:
       Parent     MT    Daughter                                 Comment
    26054.98c    102       26055                                    Fe55
    26054.98c    103       25054                                    Mn54
    26054.98c    107       24051                                    Cr51
    26056.98c    105       25054                                    Mn54
    26056.98c    103       25056                                    Mn56
    26056.98c     16       26055                                    Fe55
    26057.98c     28       25056                                    Mn56
    26057.98c    104       25056                                    Mn56
    26058.98c    102       26059                                    Fe59
    26058.98c    105       25056                                    Mn56
    78195.98c    304    78195900                                  Pt195m

In addition to this, a new translating method has been defined for the D1S_Input object. Let’s suppose that this is the first time a D1S-INPUT is generated for a specific application. Once irradiation and reaction files have been defined, the MCNP input can be translated specifying an activation and a transport lib. The activation lib will be automatically assigned to all parents indicated the reac file.

# reset everything to just one lib
d1s_inp.translate('31c', lm)
print('before:')
print(d1s_inp.materials['M1'].to_text()[2000:2500])

# smart translate
d1s_inp.smart_translate('99c', '00c', lm)
print('\nafter:')
print(d1s_inp.materials['M1'].to_text()[2000:2500])
before:
      23050.31c        3.400000E-6     $ V-50   WEIGHT(%) 0.15475 AB(%) 0.25
      23051.31c        1.356600E-3     $ V-51   WEIGHT(%) 0.15475 AB(%) 99.75
      24050.31c        6.343700E-3     $ Cr-50  WEIGHT(%) 16.957 AB(%) 4.345
      24052.31c        1.223320E-1     $ Cr-52  WEIGHT(%) 16.957 AB(%) 83.789
      24053.31c        1.387150E-2     $ Cr-53  WEIGHT(%) 16.957 AB(%) 9.501
      24054.31c        3.452900E-3     $ Cr-54  WEIGHT(%) 16.957 AB(%) 2.365
      25055.31c        1.420000E-2  
after:
      23050.00c        3.400000E-6     $ V-50   WEIGHT(%) 0.15475 AB(%) 0.25
      23051.00c        1.356600E-3     $ V-51   WEIGHT(%) 0.15475 AB(%) 99.75
      24050.00c        6.343700E-3     $ Cr-50  WEIGHT(%) 16.957 AB(%) 4.345
      24052.00c        1.223320E-1     $ Cr-52  WEIGHT(%) 16.957 AB(%) 83.789
      24053.00c        1.387150E-2     $ Cr-53  WEIGHT(%) 16.957 AB(%) 9.501
      24054.00c        3.452900E-3     $ Cr-54  WEIGHT(%) 16.957 AB(%) 2.365
      25055.00c        1.420000E-2  
/home/docs/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/f4enix/input/libmanager.py:446: UserWarning:  The Default library 81c was used for zaid 1001
  warnings.warn(MSG_DEFLIB.format(self.defaultlib, zaid))

To conclude, two other cards that are needed for a D1S-UNED run can be automatically generated using F4Enix. The PIKMT card and the FU card to track the contribution of parents/daughters/cells to a specific tally. If you provided irradiation/reaction files, you can automatically generate the daughters/fathers contribution in a tally respectively. You can also automatically add the SDDR dose function to an existing tally.

d1s_inp = D1S_Input.from_input('d1stest.i', irrad_file='irr_test',
                               reac_file='reac_fe')

# add a PIKMT card to the input based on reac file
d1s_inp.add_PIKMT_card()
print(d1s_inp.other_data['PIKMT'].card())

# Add a FU card to a tally
d1s_inp.add_track_contribution('F124', [26054, 74186], who='parent')
print(d1s_inp.other_data['F124'].card())

# Add a FU card to a tally for cell contributions
d1s_inp.add_track_contribution('F14', [200, 400], who='cell')
print(d1s_inp.other_data['F14'].card())
print(d1s_inp.other_data['FT14'].card())

# Add a FU card to a tally for daughter contributions
d1s_inp.add_track_contribution('F34', [28058, 28060, 73182], who='daughter')
# Add the DE/DF function for SDDR
d1s_inp.add_SDDR_dose_function("F34")
print(d1s_inp.other_data['F34'].card())
print(d1s_inp.other_data['DE34'].card())
print(d1s_inp.other_data['DF34'].card())

# Take all daugthers from the irradiation file and add them to a tally as userbins
d1s_inp.add_daughter_contribution_from_irr("F44")
print(d1s_inp.other_data['F44'].card())

# Take all parents from the reaction file and add them to a tally as userbins
d1s_inp.add_parent_contribution_from_reac("F54")
print(d1s_inp.other_data['F54'].card())
PIKMT
         26054    0
         26056    0
         26057    0
         26058    0
         78195    0

c
C ---------------- Dose Calculation --------------------------------------------
C    tally  *    ICF           *      DF        *   Sv/pSv       *     s/h    
C [p/cm^2/#]* 1.0714e17 [#/s]) * [pSv/(p/cm^2)] * 1e-12 [Sv/pSv] * 3600 [s/h] 
C ------------------------------------------------------------------------------
F124:p 10 11 12 13
FU124 0
         -26054
         -74186

c
c
C ---------------------- Gamma Flux Tallies ------------------------------------
C     Tally * FM -> [p/cm^2/#] * [#/s] = [p/cc/s]
C ------------------------------------------------------------------------------
c Control gamma flux tally
F14:p 10
FU14 0
         200
         400

FT14 SCD

C 
F34:p 11
FU34 0
         28058
         28060
         73182

DE34 0.01 0.015 0.02 0.03 0.04 0.05
        0.06 0.07 0.08 0.10 0.15 0.20
        0.3 0.40.5 0.6 0.8 1.0
        2.0 4.0 6.0 8.0 10.0

DF34 0.0485 0.1254 0.2050 0.2999 0.3381 0.3572
        0.3780 0.4066 0.4399 0.5172 0.7523 1.0041
        1.5083 1.9958 2.4657 2.9082 3.7269 4.4834
        7.4896 12.0153 15.9873 19.9191 23.7600

C 
F44:p 12
FU44 0
         24051
         25054
         26055
         27062
         27062900
         26059

C 
F54:p 13
FU54 0
         -26054.99c
         -26056.99c
         -26057.99c
         -26058.99c
         -78195.99c