OpenMC Guide
Tallies in OpenMC
Understanding Tallies
Tallies are OpenMC's mechanism for scoring quantities of interest during a 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
A simple example using previously defined geometry and materials:
Example: Fuel Pin Flux
# 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)Tutorial snippet — no separate file in examples repo
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
# 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()Tutorial snippet — no separate file in examples repo
Filter Types
Spatial Filters
# 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)Tutorial snippet — no separate file in examples repo
Energy and Time Filters
# 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)Tutorial snippet — no separate file in examples repo
Angular Filters
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)Tutorial snippet — no separate file in examples repo
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
# Common MT numbers
tally.scores = [
'elastic', # MT2
'(n,gamma)', # MT102
'(n,p)', # MT103
'(n,alpha)', # MT107
]Tutorial snippet — no separate file in examples repo
Nuclide Tallies
# Tally by nuclide
tally.nuclides = ['U235', 'U238']
tally.scores = ['fission', 'absorption']
# All nuclides
tally.nuclides = ['total']Tutorial snippet — no separate file in examples repo
Derived Tallies
# 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.50.h5')
t1 = sp.get_tally(name='u238_capture')
t2 = sp.get_tally(name='u235_fission')
ratio = t1.mean / t2.meanTutorial snippet — no separate file in examples repo
Results Analysis
Tally results are accessed through the StatePoint interface:
Processing Results
# Load results — filename includes the batch number
sp = openmc.StatePoint('statepoint.50.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()Tutorial snippet — no separate file in examples repo