OpenMC Guide
Materials in OpenMC
Understanding Materials
Materials in OpenMC represent the physical substances in your reactor model. Each material needs a composition (what nuclides it contains) and a density. OpenMC uses this information to calculate how neutrons interact with the material.
The basic workflow is simple: create a material object, set its density, add nuclides or elements, and optionally add thermal scattering data. Temperature is set on cells, not on materials.
import openmc
# Basic UO2 fuel - the essential components
fuel = openmc.Material(name='UO2 Fuel')
fuel.set_density('g/cm3', 10.4)
fuel.add_nuclide('U235', 0.045) # 4.5% enriched uranium
fuel.add_nuclide('U238', 0.955) # Depleted uranium
fuel.add_element('O', 2.0) # Stoichiometric oxygen
# Light water with thermal scattering
water = openmc.Material(name='Light Water')
water.set_density('g/cm3', 1.0)
water.add_nuclide('H1', 2.0)
water.add_element('O', 1.0)
water.add_s_alpha_beta('c_H_in_H2O') # Critical for neutron thermalization
# Structural material
zirc = openmc.Material(name='Zircaloy-4')
zirc.set_density('g/cm3', 6.55)
zirc.add_element('Zr', 0.982)
zirc.add_element('Sn', 0.015)
zirc.add_element('Fe', 0.002)
zirc.add_element('Cr', 0.001)
print(f"Fuel density: {fuel.density} g/cm³")
print(f"Water contains {len(water.nuclides)} nuclides")Tutorial snippet — no separate file in examples repo
Practical Material Examples
PWR Materials
# Standard PWR UO2 fuel pellet
fuel = openmc.Material(name='PWR UO2 Fuel')
fuel.set_density('g/cm3', 10.4)
fuel.add_nuclide('U235', 0.04) # 4% enrichment
fuel.add_nuclide('U238', 0.96)
fuel.add_element('O', 2.0)
# Temperature is set via cell.temperature, not on materials
# Zircaloy-4 cladding with realistic composition
clad = openmc.Material(name='Zircaloy-4 Cladding')
clad.set_density('g/cm3', 6.55)
clad.add_element('Zr', 0.982)
clad.add_element('Sn', 0.015)
clad.add_element('Fe', 0.002)
clad.add_element('Cr', 0.001)
# Borated water moderator (typical PWR conditions)
moderator = openmc.Material(name='Borated Water')
moderator.set_density('g/cm3', 0.7) # Hot, pressurized water
moderator.add_nuclide('H1', 2.0)
moderator.add_element('O', 1.0)
moderator.add_nuclide('B10', 0.00002) # 1000 ppm boron
moderator.add_nuclide('B11', 0.00008)
moderator.add_s_alpha_beta('c_H_in_H2O')
# Temperature is set via cell.temperature, not on materials
# Structural steel (for reactor internals)
steel = openmc.Material(name='Stainless Steel 316')
steel.set_density('g/cm3', 8.0)
steel.add_element('Fe', 0.68, 'wo') # Weight fractions
steel.add_element('Ni', 0.12, 'wo')
steel.add_element('Cr', 0.17, 'wo')
steel.add_element('Mo', 0.025, 'wo')
steel.add_element('Mn', 0.02, 'wo')Tutorial snippet — no separate file in examples repo
Advanced Fuel Types
# MOX fuel (mixed oxide with plutonium)
mox_fuel = openmc.Material(name='MOX Fuel')
mox_fuel.set_density('g/cm3', 10.8)
mox_fuel.add_nuclide('U235', 0.002) # Depleted uranium
mox_fuel.add_nuclide('U238', 0.948)
mox_fuel.add_nuclide('Pu239', 0.04) # 4% fissile Pu-239
mox_fuel.add_nuclide('Pu240', 0.01)
mox_fuel.add_element('O', 2.0)
# TRISO fuel particles (for advanced reactors)
triso_fuel = openmc.Material(name='TRISO Fuel Kernel')
triso_fuel.set_density('g/cm3', 10.5)
triso_fuel.add_nuclide('U235', 0.15) # Highly enriched
triso_fuel.add_nuclide('U238', 0.85)
triso_fuel.add_element('C', 1.0) # UC kernel
# Temperature is set via cell.temperature, not on materials
# Graphite moderator (for HTGR)
graphite = openmc.Material(name='Nuclear Graphite')
graphite.set_density('g/cm3', 1.7)
graphite.add_element('C', 1.0)
graphite.add_s_alpha_beta('c_Graphite')
# Temperature is set via cell.temperature, not on materialsTutorial snippet — no separate file in examples repo
Working with Material Collections
OpenMC requires all materials to be collected into a Materials object before running a simulation. This collection also provides useful methods for validation and manipulation.
# Create a complete materials collection
materials = openmc.Materials([fuel, clad, moderator, steel])
# Useful material collection methods
print(f"Total materials: {len(materials)}")
print(f"Material names: {[mat.name for mat in materials]}")
# Find materials by name
fuel_mat = next(m for m in materials if m.name == 'PWR UO2 Fuel')
print(f"Found material: {fuel_mat.name}")
# Export for use in OpenMC (performs validation)
materials.export_to_xml()
# You can also modify materials after creation
fuel.add_nuclide('Gd155', 0.001) # Add burnable absorber
print("Added gadolinium to fuel")Tutorial snippet — no separate file in examples repo
Advanced Material Features
Material Mixtures
# Control rod material (B4C with steel cladding)
b4c = openmc.Material(name='Boron Carbide')
b4c.set_density('g/cm3', 2.5)
b4c.add_nuclide('B10', 0.8)
b4c.add_nuclide('B11', 0.2)
b4c.add_element('C', 1.0)
# Create control rod mixture
control_rod = openmc.Material.mix_materials(
materials=[b4c, steel],
fracs=[0.8, 0.2],
percent_type='vo' # 'vo' = volume, 'wo' = weight
)
control_rod.name = 'Control Rod'
# Note: mix_materials does not support materials that
# contain S(alpha,beta) thermal scattering data.
# To mix a moderator with fuel, omit add_s_alpha_beta
# from the moderator before mixing, or model the
# regions with separate cells instead.Tutorial snippet — no separate file in examples repo
Depletion Setup
# Temperature is a cell property, not a material property.
# Set it when creating cells:
# fuel_cell = openmc.Cell(fill=fuel, region=region)
# fuel_cell.temperature = 900 # Kelvin
# Material set up for depletion calculations
depleting_fuel = openmc.Material(name='Depleting Fuel')
depleting_fuel.set_density('g/cm3', 10.4)
depleting_fuel.add_nuclide('U235', 0.045)
depleting_fuel.add_nuclide('U238', 0.955)
depleting_fuel.add_element('O', 2.0)
depleting_fuel.depletable = True # Enable depletion tracking
depleting_fuel.volume = 100.0 # cm³ (required for depletion)
print(f"Material can be depleted: {depleting_fuel.depletable}")
print(f"Material volume: {depleting_fuel.volume} cm³")Tutorial snippet — no separate file in examples repo
Common Mistakes and Tips
Here are the most common material definition errors and how to avoid them:
Don't Forget to Set Density
# Wrong - missing density entirely
material = openmc.Material()
material.add_nuclide('U235', 0.05)
# No density set — OpenMC will raise an error at export/runtime
# Correct - always set density (order doesn't matter at the Python level)
material = openmc.Material()
material.add_nuclide('U235', 0.05)
material.set_density('g/cm3', 10.4)Tutorial snippet — no separate file in examples repo
Use Realistic Values
# Check your material densities against references
# UO2 fuel: 10.4 g/cm³ (theoretical density)
# Zircaloy: 6.55 g/cm³
# Water (20°C): 1.0 g/cm³, (300°C): ~0.7 g/cm³
# Steel: 7.8-8.0 g/cm³
# Always add thermal scattering for light materials
water.add_s_alpha_beta('c_H_in_H2O') # Essential for water
# Available S(α,β) tables: c_H_in_H2O, c_Graphite, c_Be, etc.
# Set temperatures on cells, not materials (in Kelvin)
# cell.temperature = 600 # 327°C
# Room temperature = 293 K, PWR operating = 580 KTutorial snippet — no separate file in examples repo
Use well-established reference values and validate your materials collection before running calculations.