ACE files and XS#
F4Enix leverages the endf python package to parse ACE files. Building on this, F4Enix allow to compute xs for materials (i.e. any collection of zaids) and to collapse xs into pre-defined energy groups.
Retrieve a continous or collapsed XS#
Single nuclides#
A number of pre-defined energy groups are available and can be explored with the following code. All energies are expressed in [eV].
from f4enix.core.egroups import GROUP_STRUCTURES
print(f'Avaialble groups: {GROUP_STRUCTURES.keys()}')
print('\nCASMO-8 energies in eV:')
print(GROUP_STRUCTURES['CASMO-8'])
/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
Avaialble groups: dict_keys(['CASMO-2', 'CASMO-4', 'CASMO-8', 'CASMO-16', 'CASMO-25', 'CASMO-40', 'VITAMIN-J-42', 'SCALE-44', 'MPACT-51', 'MPACT-60', 'MPACT-69', 'CASMO-70', 'XMAS-172', 'VITAMIN-J-175', 'SCALE-252', 'TRIPOLI-315', 'SHEM-361', 'CCFE-709', 'UKAEA-1102', 'ECCO-1968'])
CASMO-8 energies in eV:
[0.00e+00 5.80e-02 1.40e-01 2.80e-01 6.25e-01 4.00e+00 5.53e+03 8.21e+05
2.00e+07]
The following is an example where both continous and collapsed cross sections for C-12 are requested. More than one xs can be requested at the same tieme. Note that the path to ace files can be either given with a dictionary as demonstrated here or giving the path to an MCNP xsdir file.
import matplotlib.pyplot as plt
from f4enix.input.ace import get_xs
# use a dictionary for custom paths to the ace files
local_ace = {
("1001", "FENDL32"): {"path": "ace/01H_001"},
("1002", "FENDL32"): {"path": "ace/01H_002"},
("6012", "FENDL32"): {"path": "ace/06C_012"},
}
# Get the continous xs
xs_continuous, ys_continuous = get_xs(
this='6012',
types=[1, 102],
library="FENDL32",
ace_filepaths=local_ace,
)
# Plot the continuous xs
fig, (ax1, ax2) = plt.subplots(nrows=2)
ax1.plot(xs_continuous, ys_continuous[0], label="MT=1 - Continuous")
ax2.plot(xs_continuous, ys_continuous[1], label="MT=102 - Continuous")
# Get the collapsed xs in two differen groups
for group in ["VITAMIN-J-175", "SCALE-44"]:
xs_collapsed, ys_collapsed = get_xs(
this='6012',
types=[1, 102],
library="FENDL32",
ace_filepaths=local_ace,
group_structure=group,
)
# plot the collapsed xs
ax1.step(xs_collapsed, ys_collapsed[0], label=f"MT=1 - {group}", linestyle="--")
ax2.step(xs_collapsed, ys_collapsed[1], label=f"MT=102 - {group}", linestyle="--")
# make the plot more informative
for ax in (ax1, ax2):
ax.set_xlabel("Energy [eV]")
ax.set_ylabel("Cross section [barn]")
ax.set_xscale("log")
ax.set_yscale("log")
ax.legend()
ax.grid()
ax.set_xlim(1e-2)
ax1.set_ylim(top=10)
ax2.set_ylim(top=1e-2)
ax1.set_title("C-12")
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[2], line 27
25 # Get the collapsed xs in two differen groups
26 for group in ["VITAMIN-J-175", "SCALE-44"]:
---> 27 xs_collapsed, ys_collapsed = get_xs(
28 this='6012',
29 types=[1, 102],
30 library="FENDL32",
31 ace_filepaths=local_ace,
32 group_structure=group,
33 )
34 # plot the collapsed xs
35 ax1.step(xs_collapsed, ys_collapsed[0], label=f"MT=1 - {group}", linestyle="--")
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/f4enix/input/ace.py:380, in get_xs(this, types, library, ace_filepaths, group_structure, temperature, integral_points)
377 for submat in mat.submaterials:
378 zaids.extend(submat.zaidList)
--> 380 energy_grid, data = _get_xs_zaid_list(
381 zaids,
382 types,
383 library,
384 ace_filepaths,
385 temp=temperature,
386 group_structure=group_structure,
387 integral_points=integral_points,
388 )
390 return energy_grid, data
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/f4enix/input/ace.py:317, in _get_xs_zaid_list(zaids, types, library, ace_filepaths, temp, group_structure, integral_points)
315 x = np.logspace(np.log10(e_0), np.log10(e), integral_points)
316 y = table(x)
--> 317 values.append(np.trapezoid(y, x) / (e - e_0))
318 values = np.array(values)
320 else:
321 # if continous, the simple interpolation is ok
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/numpy/__init__.py:333, in __getattr__(attr)
330 "Removed in NumPy 1.25.0"
331 raise RuntimeError("Tester was removed in NumPy 1.25.")
--> 333 raise AttributeError("module {!r} has no attribute "
334 "{!r}".format(__name__, attr))
AttributeError: module 'numpy' has no attribute 'trapezoid'
The average xs value in an energy bin is obtained as the integral of the xs value in the bin divided by the bin width. The integral is performed numerically, hence, the number of integration point may influence the result. This is especially true:
if the energy bins are wide
if many resonances are present in the energy bin.
By default F4Enix uses 100 points in each energy bin, which should be sufficient to reach convergence for most applications. This parameter can be changed though and it is the responsability of the user to verify it suitability for its specific application.
Let’s see an example of this effect in the resonance region of C-12 total cross section:
# Plot the continuous xs
fig, ax = plt.subplots()
ax.plot(xs_continuous, ys_continuous[0], label="MT=1 - Continuous", alpha=0.5)
# Get the collapsed xs with different number of integration points
for integral_points in [2, 10, 100, 1000]:
xs_collapsed, ys_collapsed = get_xs(
this='6012',
types=['total'],
library="FENDL32",
ace_filepaths=local_ace,
group_structure="SCALE-44",
integral_points=integral_points,
)
ax.step(xs_collapsed, ys_collapsed[0],
label=f"integration points: {integral_points}", linestyle="--")
# plot parameters
ax.set_xlabel("Energy [eV]")
ax.set_ylabel("Cross section [barn]")
ax.set_xlabel("Energy [eV]")
ax.set_ylabel("Cross section [barn]")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlim(1e4, 5e7)
ax.set_ylim(1, 1e1)
ax.legend()
ax.grid()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[3], line 7
5 # Get the collapsed xs with different number of integration points
6 for integral_points in [2, 10, 100, 1000]:
----> 7 xs_collapsed, ys_collapsed = get_xs(
8 this='6012',
9 types=['total'],
10 library="FENDL32",
11 ace_filepaths=local_ace,
12 group_structure="SCALE-44",
13 integral_points=integral_points,
14 )
15 ax.step(xs_collapsed, ys_collapsed[0],
16 label=f"integration points: {integral_points}", linestyle="--")
18 # plot parameters
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/f4enix/input/ace.py:380, in get_xs(this, types, library, ace_filepaths, group_structure, temperature, integral_points)
377 for submat in mat.submaterials:
378 zaids.extend(submat.zaidList)
--> 380 energy_grid, data = _get_xs_zaid_list(
381 zaids,
382 types,
383 library,
384 ace_filepaths,
385 temp=temperature,
386 group_structure=group_structure,
387 integral_points=integral_points,
388 )
390 return energy_grid, data
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/f4enix/input/ace.py:317, in _get_xs_zaid_list(zaids, types, library, ace_filepaths, temp, group_structure, integral_points)
315 x = np.logspace(np.log10(e_0), np.log10(e), integral_points)
316 y = table(x)
--> 317 values.append(np.trapezoid(y, x) / (e - e_0))
318 values = np.array(values)
320 else:
321 # if continous, the simple interpolation is ok
File ~/checkouts/readthedocs.org/user_builds/f4enix/envs/developing/lib/python3.10/site-packages/numpy/__init__.py:333, in __getattr__(attr)
330 "Removed in NumPy 1.25.0"
331 raise RuntimeError("Tester was removed in NumPy 1.25.")
--> 333 raise AttributeError("module {!r} has no attribute "
334 "{!r}".format(__name__, attr))
AttributeError: module 'numpy' has no attribute 'trapezoid'
Material or elements#
It is also possible to compute (and collapse) the xs of a material or of an element.
from f4enix.input.libmanager import LibManager
from f4enix.input.materials import Material
lm = LibManager(xsdir_path='ace/xsdir_test', defaultlib='32c')
# Create a material object (Methane - CH4)
mat = Material.from_zaids([(6012, 1), (1000, 4)], lm, '32c', name='Methane')
# elements can be simply obtained as material with only one element
elem = Material.from_zaids([(1000, 1)], lm, '32c', name='Hydrogen')
# a material of only one zaid is also equivalent
elem2 = Material.from_zaids([(6012, 1)], lm, '32c', name='Carbon')
fig, ax = plt.subplots()
# Get the total cross section
for this in [mat, elem, elem2]:
xs_continuous, ys_continuous = get_xs(
this=this,
types=['total'], # main xs can also be requested by strings
# let's use an xsdir this time instead of the dictionary
library="32c", # need to use the same suffix as per xsdir
ace_filepaths='ace/xsdir_test',
)
# Plot the continuous xs
ax.plot(xs_continuous, ys_continuous[0], label=f"MT=1 - {this.header}")
# plot parameters
ax.set_xlabel("Energy [eV]")
ax.set_ylabel("Cross section [barn]")
ax.set_xlabel("Energy [eV]")
ax.set_ylabel("Cross section [barn]")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlim(1e4, 5e7)
ax.set_ylim(1, 1e1)
ax.legend()
ax.grid()