Python API Basics

Getting Started with the API

OpenMC's Python API makes nuclear simulations much more accessible than traditional input-file approaches. Instead of learning complex syntax rules, you use familiar Python to build models, run simulations, and analyze results.

The API follows object-oriented principles. You create materials, surfaces, and cells as Python objects, then combine them into a complete model. This approach makes it easy to modify designs, run parameter studies, and integrate with other Python tools.

python
import openmc
import numpy as np
import matplotlib.pyplot as plt

# Basic workflow: create objects, combine them, run simulation
fuel = openmc.Material(name='UO2')
fuel.set_density('g/cm3', 10.4)
fuel.add_nuclide('U235', 0.04)
fuel.add_nuclide('U238', 0.96)
fuel.add_element('O', 2.0)

# OpenMC objects are Pythonic - they have useful methods
print(f"Fuel density: {fuel.density} g/cm³")
print(f"Fuel contains {len(fuel.nuclides)} nuclides")

Essential Patterns

Here are the most important patterns you'll use repeatedly in OpenMC. Master these and you'll be able to build complex models efficiently.

1. Creating and Organizing Objects

python
# Use descriptive names for clarity
fuel = openmc.Material(name='UO2 Fuel 4.5%')
clad = openmc.Material(name='Zircaloy-4')
water = openmc.Material(name='Light Water')

# Group related objects into collections
materials = openmc.Materials([fuel, clad, water])

2. Working with Geometry

python
# Surfaces define boundaries
fuel_outer = openmc.ZCylinder(r=0.4096, name='fuel outer')
clad_outer = openmc.ZCylinder(r=0.4750, name='clad outer')

# Regions use boolean operations (& = and, | = or, ~ = not)
fuel_region = -fuel_outer
clad_region = +fuel_outer & -clad_outer
water_region = +clad_outer

# Cells fill regions with materials
fuel_cell = openmc.Cell(fill=fuel, region=fuel_region)
clad_cell = openmc.Cell(fill=clad, region=clad_region)
water_cell = openmc.Cell(fill=water, region=water_region)

3. Building Complete Models

python
# Combine everything into a model
universe = openmc.Universe(cells=[fuel_cell, clad_cell, water_cell])
geometry = openmc.Geometry(universe)
settings = openmc.Settings()
settings.particles = 10000
settings.batches = 100

# The Model class ties everything together
model = openmc.Model(geometry, materials, settings)

# Run and get results (model.run() returns statepoint path)
sp = openmc.StatePoint(model.run())
keff = sp.keff
print(f"k-effective: {keff.nominal_value:.5f} ± {keff.std_dev:.5f}")

Common Mistakes to Avoid

These are the most frequent errors we see from new OpenMC users. Avoiding them will save you debugging time and frustration.

Missing Material Properties

python
# Wrong - OpenMC will throw an error
fuel = openmc.Material()
fuel.add_nuclide('U235', 0.04)  # No density set!

# Correct - always set density first
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.4)  # Density must be set
fuel.add_nuclide('U235', 0.04)   # Now this works

Ambiguous Geometry

python
# Wrong - unclear what this region means
cell_region = +surf1 +surf2  # Addition, not boolean logic

# Correct - use explicit boolean operators
cell_region = +surf1 & +surf2  # Intersection (inside both)
# or
cell_region = +surf1 | +surf2  # Union (inside either)

Forgetting Collections

python
# Wrong - individual exports are error-prone
materials.export_to_xml()
geometry.export_to_xml()
settings.export_to_xml()
tallies.export_to_xml()

# Better - use Model to handle everything
model = openmc.Model(geometry, materials, settings, tallies)
model.export_to_xml()

Practical Example: Parameter Study

Here's how the Python API makes complex tasks simple. This example shows how to study the effect of fuel enrichment on reactivity - something that would be tedious with traditional input files.

python
import openmc
import numpy as np
import matplotlib.pyplot as plt

def create_pin_model(enrichment):
    """Create a pin cell model with specified enrichment."""
    # Materials
    fuel = openmc.Material()
    fuel.set_density('g/cm3', 10.4)
    fuel.add_nuclide('U235', enrichment)
    fuel.add_nuclide('U238', 1.0 - enrichment)
    fuel.add_element('O', 2.0)
    
    water = openmc.Material()
    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')
    
    # Simple infinite lattice geometry
    fuel_boundary = openmc.ZCylinder(r=0.4)
    pin_cell = openmc.Cell(fill=fuel, region=-fuel_boundary)
    water_cell = openmc.Cell(fill=water, region=+fuel_boundary)
    
    # Settings for k-eigenvalue calculation
    settings = openmc.Settings()
    settings.particles = 5000
    settings.batches = 50
    settings.inactive = 10
    
    universe = openmc.Universe(cells=[pin_cell, water_cell])
    return openmc.Model(
        geometry=openmc.Geometry(universe),
        materials=openmc.Materials([fuel, water]),
        settings=settings
    )

# Run parameter study
enrichments = np.linspace(0.02, 0.06, 5)
k_values = []

for enr in enrichments:
    model = create_pin_model(enr)
    sp = openmc.StatePoint(model.run())
    keff = sp.keff
    k_values.append(keff.nominal_value)
    print(f"Enrichment {enr:.1%}: k = {k_values[-1]:.4f}")

# Plot results
plt.figure(figsize=(8, 6))
plt.plot(enrichments * 100, k_values, 'o-', linewidth=2, markersize=8)
plt.xlabel('Enrichment (%)')
plt.ylabel('k-effective')
plt.title('Reactivity vs. Fuel Enrichment')
plt.grid(True, alpha=0.3)
plt.show()

Why this works: The Python API makes it easy to parameterize models, run multiple cases, and analyze results. Try doing this with traditional input files - you'd need dozens of separate files and manual result extraction.

Integration with Scientific Python

OpenMC works seamlessly with the scientific Python ecosystem. NumPy handles arrays and mathematical operations, Matplotlib creates plots, and Pandas manages data analysis. This integration is one of OpenMC's biggest advantages over traditional codes.

As you become more advanced, you can integrate OpenMC with optimization libraries (SciPy), machine learning tools (scikit-learn), and uncertainty quantification frameworks. The Python ecosystem makes sophisticated analysis workflows much more accessible.