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

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)

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

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()

Tutorial snippet — no separate file in examples repo

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)

Tutorial snippet — no separate file in examples repo

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)

Tutorial snippet — no separate file in examples repo

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)

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

python
# 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

python
# 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

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.50.h5')
t1 = sp.get_tally(name='u238_capture')
t2 = sp.get_tally(name='u235_fission')
ratio = t1.mean / t2.mean

Tutorial snippet — no separate file in examples repo

Results Analysis

Tally results are accessed through the StatePoint interface:

Processing Results

python
# 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

Additional Resources