OpenMC Guide
Tallies in OpenMC
Understanding Tallies
Now that we understand how to create geometry and run simulations, we need to extract useful information from our model. Tallies are OpenMC's way of scoring quantities of interest during the simulation.
Key Concepts
- Filters: Define where to collect data (cells, materials, energy ranges)
- Scores: Specify what to measure (flux, reaction rates, energy deposition)
- Estimators: Determine how to collect data (track-length, collision, analog)
Basic Tally Setup
Let's start with a simple example using the geometry and materials we created earlier:
Example: Fuel Pin Flux
python
# Create a basic tally
tally = openmc.Tally(name='fuel_flux')
# Where to tally (in the fuel cell we created)
fuel_filter = openmc.CellFilter([fuel_cell])
tally.filters = [fuel_filter]
# What to tally (neutron flux)
tally.scores = ['flux']
# Add to tallies collection
tallies = openmc.Tallies([tally])
# Export with your model
model = openmc.Model(geometry, materials, settings, tallies)Note: Tallies don't affect the physics of your simulation - they just collect data as particles travel through your geometry.
Tally Basics
Components
- Filters: Where to tally
- Scores: What to tally
- Nuclides: Which isotopes
- Estimator: How to tally
Common Scores
- flux: Particle flux
- fission: Fission rate
- absorption: Absorption rate
- scatter: Scattering rate
- heating: Energy deposition
Basic Example
python
# Create a basic tally
tally = openmc.Tally(name='fuel_tally')
# Add filters (where to tally)
tally.filters = [
openmc.CellFilter([fuel_cell]), # In fuel cell
openmc.EnergyFilter([0.0, 20.0e6]) # Full energy range
]
# Add scores (what to tally)
tally.scores = ['flux', 'fission']
# Add to collection
tallies = openmc.Tallies([tally])
tallies.export_to_xml()Filter Types
Spatial Filters
python
# Cell and material filters
cell_filter = openmc.CellFilter([fuel_cell])
mat_filter = openmc.MaterialFilter([fuel_mat])
# Mesh filter
mesh = openmc.RegularMesh()
mesh.dimension = [10, 10, 10]
mesh.lower_left = [-50, -50, -50]
mesh.upper_right = [50, 50, 50]
mesh_filter = openmc.MeshFilter(mesh)Energy and Time Filters
python
# Energy groups
energies = [0.0, 0.625, 1e6, 20e6] # eV
energy_filter = openmc.EnergyFilter(energies)
# Time bins
times = [0.0, 1e-6, 1e-5] # seconds
time_filter = openmc.TimeFilter(times)Angular Filters
python
import numpy as np
# Polar angles (5 bins)
polar_bins = np.linspace(0.0, np.pi, 6)
polar = openmc.PolarFilter(polar_bins)
# Azimuthal angles (8 bins)
azimuthal_bins = np.linspace(-np.pi, np.pi, 9)
azimuthal = openmc.AzimuthalFilter(azimuthal_bins)Note: Each filter adds a dimension to the tally results. Use only the filters you need to avoid memory issues and slow convergence.
Advanced Features
Specific Reactions
python
# Common MT numbers
tally.scores = [
'elastic', # MT2
'(n,gamma)', # MT102
'(n,p)', # MT103
'(n,alpha)', # MT107
]Nuclide Tallies
python
# Tally by nuclide
tally.nuclides = ['U235', 'U238']
tally.scores = ['fission', 'absorption']
# All nuclides
tally.nuclides = ['total']Derived Tallies
python
# Reaction rate ratio (conversion ratio)
tally1 = openmc.Tally(name='u238_capture')
tally1.filters = [openmc.CellFilter([fuel_cell])]
tally1.nuclides = ['U238']
tally1.scores = ['(n,gamma)']
tally2 = openmc.Tally(name='u235_fission')
tally2.filters = [openmc.CellFilter([fuel_cell])]
tally2.nuclides = ['U235']
tally2.scores = ['fission']
# After running:
sp = openmc.StatePoint('statepoint.h5')
t1 = sp.get_tally(name='u238_capture')
t2 = sp.get_tally(name='u235_fission')
ratio = t1.mean / t2.meanResults Analysis
After your simulation runs, you can analyze tally results using the same StatePoint interface we learned about in the Results section:
Processing Results
python
# Load results (from previous section)
sp = openmc.StatePoint('statepoint.h5')
tally = sp.get_tally(name='fuel_flux')
# Basic statistics
mean_flux = tally.mean # Average flux
rel_error = tally.std_dev / tally.mean # Relative uncertainty
# Convert to pandas DataFrame for analysis
df = tally.get_pandas_dataframe()
# Example analysis
import matplotlib.pyplot as plt
plt.figure()
plt.errorbar(df.index, df['mean'],
yerr=df['std. dev.'],
fmt='o', capsize=5)
plt.xlabel('Tally bin')
plt.ylabel('Flux (n/cm²/src)')
plt.grid(True)
plt.show()