1. The ARMI Nuclide and Element Packages
One of the key features that the ARMI framework offers is access to nuclide data across an application (recall: a nuclide is a particular isotope of an element. Iron-56, Uranium-238, and Boron-10 are all nuclides). This is specifically useful for nuclear engineers so that manual look-ups of nuclide attributes on sources like Wikipedia, Chart of the Nuclides, etc. are not needed.
The available attributes for each nuclide are:
Atomic weight/mass, in amu
Natural abundance
Atomic number, Z
Mass number, A
Half-life
Neutron yield from spontaneous fission
Accessing the nuclide data begins with importing the nuclide bases, and optionally, the elements packages:
[7]:
from armi.nucDirectory import nuclideBases
from armi.nucDirectory import elements
One these packages are imported, there are several module-level global dictionaries that are important to know about, since these are likely what you will be working with when implementing code that requires nuclide data or just when performing data look-ups:
Nuclide Bases Global Dictionaries
nuclideBases.byName
nuclideBases.DBName
nuclideBases.byLabel
nuclideBases.byMcc2Id
nuclideBases.byMcc3Id
nuclideBases.byMcnpId
nuclideBases.byAAAZZZSId
Elements Global Dictionaries
elements.byZ
elements.bySymbol
elements.byName
1.1. Accessing Individual Nuclide Data/Attributes
Here we will explore retrieving data from a couple nuclides and showing the coupling between nuclide and element definitions. For these examples, let’s try to answer the following questions:
How many total nuclides and elements are defined in the framework?
What is atomic weight of a selected nuclide?
What is the natural abundance a selected nuclide?
Are there any spontaneous fission neutrons for a selected nuclide?
What is the half-life in seconds for a selected nuclide?
How many other nuclides for the same element exist for a selected nuclide?
1.1.1. How many total nuclides and elements are defined in the framework?
[8]:
import collections
print(f"Number of elements defined in the framework: {len(elements.byZ.values())}")
print("")
print(f"Number of nuclides defined in the framework: {len(nuclideBases.instances)}")
nucsByType = collections.defaultdict(list)
for n in nuclideBases.instances:
nucsByType[type(n)].append(n)
for typ, nucs in nucsByType.items():
print(f" - Number of nuclides of type `{typ}`: {len(nucs)}")
Number of elements defined in the framework: 120
Number of nuclides defined in the framework: 4706
- Number of nuclides of type `<class 'armi.nucDirectory.nuclideBases.NuclideBase'>`: 4614
- Number of nuclides of type `<class 'armi.nucDirectory.nuclideBases.NaturalNuclideBase'>`: 84
- Number of nuclides of type `<class 'armi.nucDirectory.nuclideBases.DummyNuclideBase'>`: 2
- Number of nuclides of type `<class 'armi.nucDirectory.nuclideBases.LumpNuclideBase'>`: 6
1.1.2. Looking up nuclide and elemental data for U-235
[9]:
u235 = nuclideBases.byName['U235']
print(u235)
print(f"Atomic Weight (amu): {u235.weight}")
print(f"Natural Abundance: {u235.abundance}")
print(f"Spontaneous Fission Neutron Yield: {u235.nuSF}")
print(f"Half-life (seconds): {u235.halflife}")
print("")
print(f"Other nuclides for {elements.byZ[u235.z].name}:")
for n in elements.byZ[u235.z].nuclides:
print(f" - {n}")
<NuclideBase U235: Z:92, A:235, S:0, W:2.350439e+02, Label:U235>, HL:2.22160758861e+16, Abund:7.204000e-03>
Atomic Weight (amu): 235.043929425
Natural Abundance: 0.007204
Spontaneous Fission Neutron Yield: 1.87
Half-life (seconds): 2.22160758861e+16
Other nuclides for Uranium:
- <NaturalNuclideBase U: Z:92, W:2.380289e+02, Label:U>
- <NuclideBase U215: Z:92, A:215, S:0, W:2.150262e+02, Label:U215>, HL:7.00000000000e-04, Abund:0.000000e+00>
- <NuclideBase U216: Z:92, A:216, S:0, W:2.160240e+02, Label:U216>, HL:4.50000000000e-03, Abund:0.000000e+00>
- <NuclideBase U217: Z:92, A:217, S:0, W:2.170244e+02, Label:U217>, HL:1.60000000000e-02, Abund:0.000000e+00>
- <NuclideBase U218: Z:92, A:218, S:0, W:2.180235e+02, Label:U218>, HL:6.50000000000e-04, Abund:0.000000e+00>
- <NuclideBase U219: Z:92, A:219, S:0, W:2.190249e+02, Label:U219>, HL:6.00000000000e-05, Abund:0.000000e+00>
- <NuclideBase U220: Z:92, A:220, S:0, W:2.200247e+02, Label:U220>, HL:1.11110000000e+01, Abund:0.000000e+00>
- <NuclideBase U221: Z:92, A:221, S:0, W:2.210264e+02, Label:U221>, HL:6.60000000000e-07, Abund:0.000000e+00>
- <NuclideBase U222: Z:92, A:222, S:0, W:2.220261e+02, Label:U222>, HL:4.70000000000e-06, Abund:0.000000e+00>
- <NuclideBase U223: Z:92, A:223, S:0, W:2.230277e+02, Label:U223>, HL:1.80000000000e-05, Abund:0.000000e+00>
- <NuclideBase U224: Z:92, A:224, S:0, W:2.240276e+02, Label:U224>, HL:8.40000000000e-04, Abund:0.000000e+00>
- <NuclideBase U225: Z:92, A:225, S:0, W:2.250294e+02, Label:U225>, HL:6.90000000000e-02, Abund:0.000000e+00>
- <NuclideBase U226: Z:92, A:226, S:0, W:2.260293e+02, Label:U226>, HL:2.68000000000e-01, Abund:0.000000e+00>
- <NuclideBase U227: Z:92, A:227, S:0, W:2.270312e+02, Label:U227>, HL:6.60000000000e+01, Abund:0.000000e+00>
- <NuclideBase U228: Z:92, A:228, S:0, W:2.280314e+02, Label:U228>, HL:5.46000000000e+02, Abund:0.000000e+00>
- <NuclideBase U229: Z:92, A:229, S:0, W:2.290335e+02, Label:U229>, HL:3.48000000000e+03, Abund:0.000000e+00>
- <NuclideBase U230: Z:92, A:230, S:0, W:2.300339e+02, Label:U230>, HL:1.74787200000e+06, Abund:0.000000e+00>
- <NuclideBase U231: Z:92, A:231, S:0, W:2.310363e+02, Label:U231>, HL:3.62880000000e+05, Abund:0.000000e+00>
- <NuclideBase U232: Z:92, A:232, S:0, W:2.320372e+02, Label:U232>, HL:2.17427219965e+09, Abund:0.000000e+00>
- <NuclideBase U233: Z:92, A:233, S:0, W:2.330396e+02, Label:U233>, HL:5.02354704590e+12, Abund:0.000000e+00>
- <NuclideBase U234: Z:92, A:234, S:0, W:2.340410e+02, Label:U234>, HL:7.74722532676e+12, Abund:5.400000e-05>
- <NuclideBase U235: Z:92, A:235, S:0, W:2.350439e+02, Label:U235>, HL:2.22160758861e+16, Abund:7.204000e-03>
- <NuclideBase U235M: Z:92, A:235, S:1, W:2.350439e+02, Label:U23F>, HL:1.56000000000e+03, Abund:0.000000e+00>
- <NuclideBase U236: Z:92, A:236, S:0, W:2.360456e+02, Label:U236>, HL:7.39063206325e+14, Abund:0.000000e+00>
- <NuclideBase U237: Z:92, A:237, S:0, W:2.370487e+02, Label:U237>, HL:5.83372800000e+05, Abund:0.000000e+00>
- <NuclideBase U238: Z:92, A:238, S:0, W:2.380508e+02, Label:U238>, HL:1.40996345254e+17, Abund:9.927420e-01>
- <NuclideBase U239: Z:92, A:239, S:0, W:2.390543e+02, Label:U239>, HL:1.40700000000e+03, Abund:0.000000e+00>
- <NuclideBase U240: Z:92, A:240, S:0, W:2.400566e+02, Label:U240>, HL:5.07600000000e+04, Abund:0.000000e+00>
- <NuclideBase U241: Z:92, A:241, S:0, W:2.410603e+02, Label:U241>, HL:inf , Abund:0.000000e+00>
- <NuclideBase U242: Z:92, A:242, S:0, W:2.420629e+02, Label:U242>, HL:1.00800000000e+03, Abund:0.000000e+00>
- <NuclideBase U243: Z:92, A:243, S:0, W:2.430674e+02, Label:U243>, HL:inf , Abund:0.000000e+00>
- <NuclideBase U244: Z:92, A:244, S:0, W:2.440679e+02, Label:U244>, HL:inf , Abund:0.000000e+00>
- <NuclideBase U245: Z:92, A:245, S:0, W:2.450708e+02, Label:U245>, HL:inf , Abund:0.000000e+00>
- <NuclideBase U246: Z:92, A:246, S:0, W:2.460702e+02, Label:U246>, HL:inf , Abund:0.000000e+00>
1.1.3. Looking up nuclide and elemental data for Li-7
[10]:
li7 = nuclideBases.byName['LI7']
print(li7)
print(f"Atomic Weight (amu): {li7.weight}")
print(f"Natural Abundance: {li7.abundance}")
print(f"Spontaneous Fission Neutron Yield: {li7.nuSF}")
print(f"Half-life (seconds): {li7.halflife}")
print("")
print(f"Other nuclides for {elements.byZ[li7.z].name}:")
for n in elements.byZ[li7.z].nuclides:
print(f" - {n}")
<NuclideBase LI7: Z:3, A:7, S:0, W:7.016004e+00, Label:LI07>, HL:inf , Abund:9.241000e-01>
Atomic Weight (amu): 7.01600439548
Natural Abundance: 0.92410004
Spontaneous Fission Neutron Yield: 0.0
Half-life (seconds): inf
Other nuclides for Lithium:
- <NaturalNuclideBase LI: Z:3, W:6.940038e+00, Label:LI>
- <NuclideBase LI3: Z:3, A:3, S:0, W:3.030775e+00, Label:LI03>, HL:1.11110000000e+01, Abund:0.000000e+00>
- <NuclideBase LI4: Z:3, A:4, S:0, W:4.027185e+00, Label:LI04>, HL:inf , Abund:0.000000e+00>
- <NuclideBase LI5: Z:3, A:5, S:0, W:5.012538e+00, Label:LI05>, HL:3.70924971603e-22, Abund:0.000000e+00>
- <NuclideBase LI6: Z:3, A:6, S:0, W:6.015123e+00, Label:LI06>, HL:inf , Abund:7.590000e-02>
- <NuclideBase LI7: Z:3, A:7, S:0, W:7.016004e+00, Label:LI07>, HL:inf , Abund:9.241000e-01>
- <NuclideBase LI8: Z:3, A:8, S:0, W:8.022488e+00, Label:LI08>, HL:8.39900000000e-01, Abund:0.000000e+00>
- <NuclideBase LI9: Z:3, A:9, S:0, W:9.026789e+00, Label:LI09>, HL:1.78300000000e-01, Abund:0.000000e+00>
- <NuclideBase LI10: Z:3, A:10, S:0, W:1.003548e+01, Label:LI10>, HL:inf , Abund:0.000000e+00>
- <NuclideBase LI11: Z:3, A:11, S:0, W:1.104380e+01, Label:LI11>, HL:8.75000000000e-03, Abund:0.000000e+00>
- <NuclideBase LI12: Z:3, A:12, S:0, W:1.205378e+01, Label:LI12>, HL:inf , Abund:0.000000e+00>
- <NuclideBase LI13: Z:3, A:13, S:0, W:1.306117e+01, Label:LI13>, HL:1.11110000000e+01, Abund:0.000000e+00>
1.1.4. Exploring elemental Lithium data
[11]:
liElement = elements.bySymbol['LI']
print(liElement)
print("")
print(f"Average Atomic weight: {liElement.standardWeight}")
print(f"Is Naturally Occurring?: {liElement.isNaturallyOccurring()}")
print(f"Is a Heavy Metal Atom?: {liElement.isHeavyMetal()}")
<Element LI (Z=3), Lithium, ChemicalGroup.ALKALI_METAL, ChemicalPhase.SOLID>
Average Atomic weight: 6.940037501798687
Is Naturally Occurring?: True
Is a Heavy Metal Atom?: False
1.2. Plotting the Chart of the Nuclides
[12]:
import matplotlib.pyplot as plt
from matplotlib import colors
xyc = []
for name, base in nuclideBases.byName.items():
if not base.a:
continue
xyc.append((base.a-base.z, base.z, base.abundance or 0.5))
x,y,c = zip(*xyc)
plt.figure(figsize=(12,8))
plt.scatter(x,y,c = c, marker='s', s=6)
plt.title('Chart of the nuclides')
plt.xlabel('Number of neutrons (N)')
plt.ylabel('Number of protons (Z)')
plt.show()