OpenMC Guide
Surface Types in OpenMC
Introduction to Surfaces
Each surface is defined by a mathematical equation f(x,y,z) = 0 that divides space into positive and negative half-spaces. In cell definitions, the + and - operators select which side of a surface the cell occupies.
Basic Surface Concepts
Surface Equations and Half-Spaces
A surface equation f(x,y,z) = 0 divides 3D space into two regions:
- Negative half-space: Points where f(x,y,z) < 0
- Positive half-space: Points where f(x,y,z) > 0
Surface ID and Name
Each surface can have an optional ID (integer) and name (string):
# Creating a surface with ID and name
sphere = openmc.Sphere(r=10.0, surface_id=1, name="fuel_outer_boundary")
# IDs and names can be accessed or modified
print(sphere.id)
sphere.name = "new_name"Tutorial snippet — no separate file in examples repo
Boundary Conditions
Available boundary conditions:
reflective: Particles are reflected specularly when hitting the surfacetransmission: Particles pass through the surface freely (default)vacuum: Particles are terminated when crossing the surfaceperiodic: Particles reappear at a corresponding location on another periodic surfacewhite: Particles are reflected in a random direction when hitting the surface
# Setting boundary conditions
outer_surface = openmc.Sphere(r=50.0, boundary_type='vacuum')
reflective_surface = openmc.XPlane(x0=0.0, boundary_type='reflective')
white_surface = openmc.YPlane(y0=0.0, boundary_type='white')Tutorial snippet — no separate file in examples repo
Planar Surfaces
Planar surfaces are defined by equations of the form Ax + By + Cz = D, where (A,B,C) is the normal vector to the plane.
Planes Perpendicular to Axes
OpenMC provides dedicated classes for planes perpendicular to the coordinate axes:
# X-plane: x = x0
xplane = openmc.XPlane(x0=5.0) # Equation: x - 5.0 = 0
# Y-plane: y = y0
yplane = openmc.YPlane(y0=-2.0) # Equation: y + 2.0 = 0
# Z-plane: z = z0
zplane = openmc.ZPlane(z0=10.0) # Equation: z - 10.0 = 0Tutorial snippet — no separate file in examples repo
General Planes
For planes with arbitrary orientation, you can use the general Plane class:
# Plane defined by coefficients A, B, C, D in equation Ax + By + Cz = D
plane1 = openmc.Plane(a=1.0, b=1.0, c=1.0, d=5.0) # x + y + z = 5
# To define a plane from three points, compute the coefficients manually
import numpy as np
p1 = np.array([0.0, 0.0, 5.0])
p2 = np.array([1.0, 0.0, 5.0])
p3 = np.array([0.0, 1.0, 5.0])
normal = np.cross(p2 - p1, p3 - p1) # normal vector (A, B, C)
A, B, C = normal
D = np.dot(normal, p1)
plane2 = openmc.Plane(a=A, b=B, c=C, d=D)Tutorial snippet — no separate file in examples repo
Cylindrical Surfaces
Cylinders Parallel to Axes
# Cylinder parallel to the z-axis
zcyl = openmc.ZCylinder(r=0.5, x0=0.0, y0=0.0) # (x-x0)² + (y-y0)² = r²
# Cylinder parallel to the y-axis
ycyl = openmc.YCylinder(r=1.0, x0=0.0, z0=0.0) # (x-x0)² + (z-z0)² = r²
# Cylinder parallel to the x-axis
xcyl = openmc.XCylinder(r=0.8, y0=0.0, z0=0.0) # (y-y0)² + (z-z0)² = r²Tutorial snippet — no separate file in examples repo
General Cylinders
For cylinders with arbitrary orientation, you can use the general Cylinder class:
# General cylinder defined by a point on the axis, direction vector, and radius
cyl = openmc.Cylinder(x0=0.0, y0=0.0, z0=0.0,
dx=1.0, dy=1.0, dz=1.0, r=0.5)Tutorial snippet — no separate file in examples repo
Note: The general Cylinder class may only be available in newer versions of OpenMC. For most typical reactor geometries, the axis-aligned cylinders (XCylinder, YCylinder, ZCylinder) are more efficient and easier to use.
Spherical and Other Curved Surfaces
Spheres
Spherical surfaces are defined by the equation (x-x0)² + (y-y0)² + (z-z0)² = r², where (x0,y0,z0) is the center and r is the radius:
# Sphere centered at the origin with radius 10.0
sphere1 = openmc.Sphere(r=10.0)
# Sphere with custom center
sphere2 = openmc.Sphere(r=5.0, x0=1.0, y0=2.0, z0=3.0)Tutorial snippet — no separate file in examples repo
Cones
Conical surfaces are available for coordinate-aligned cones:
# Cone parallel to the z-axis
zcone = openmc.ZCone(r2=1.0, x0=0.0, y0=0.0, z0=0.0) # (x-x0)² + (y-y0)² = r2*(z-z0)²
# Cone parallel to the x-axis
xcone = openmc.XCone(r2=2.0, x0=0.0, y0=0.0, z0=0.0) # (y-y0)² + (z-z0)² = r2*(x-x0)²
# Cone parallel to the y-axis
ycone = openmc.YCone(r2=0.5, x0=0.0, y0=0.0, z0=0.0) # (x-x0)² + (z-z0)² = r2*(y-y0)²Tutorial snippet — no separate file in examples repo
The r2 parameter represents the square of the tangent of the cone's half-angle.
Tori (Toruses)
Toroidal surfaces can be used for more complex geometries:
# Torus parallel to the z-axis
ztorus = openmc.ZTorus(a=5.0, b=1.0, c=1.0)
# where:
# a = major radius (distance from center of torus to center of tube)
# b = minor radius of the tube in the x-y plane
# c = minor radius of the tube in the z direction
# (√((x-x0)² + (y-y0)²) - a)²/b² + (z-z0)²/c² = 1Tutorial snippet — no separate file in examples repo
Quadric and Other Advanced Surfaces
General Quadric Surface
# General quadric surface: Ax² + By² + Cz² + Dxy + Eyz + Fxz + Gx + Hy + Jz + K = 0
quadric = openmc.Quadric(a=1.0, b=1.0, c=1.0, k=-1.0) # x² + y² + z² - 1 = 0 (a sphere)
# Ellipsoid with semi-axes 2, 3, and 4
ellipsoid = openmc.Quadric(a=0.25, b=1/9, c=1/16, k=-1.0) # x²/4 + y²/9 + z²/16 = 1Tutorial snippet — no separate file in examples repo
Creating Half-Spaces
# Create a sphere
sphere = openmc.Sphere(r=10.0)
# Create the region inside the sphere (negative half-space)
inside_sphere = -sphere
# Create the region outside the sphere (positive half-space)
outside_sphere = +sphereTutorial snippet — no separate file in examples repo
Geometry Transformations
Geometric transformations (translation and rotation) are applied at the cell level, not the surface level. Define surfaces in a local coordinate system, then translate or rotate the cell.
# Define surfaces in a local coordinate system
sphere = openmc.Sphere(r=10.0)
cell = openmc.Cell(region=-sphere)
# Translate the cell so the sphere is centered at (10, 0, 0)
cell.translation = (10.0, 0.0, 0.0)
# Rotate the cell using Euler angles (phi, theta, psi) in degrees
cell.rotation = (0.0, 0.0, 45.0)Tutorial snippet — no separate file in examples repo
Tip: For repeated structures such as fuel pin lattices, it is often more convenient to use universes and lattices to position and orient geometry rather than applying individual cell transformations.
Practical Examples
Creating a Simple Fuel Pin
Here's how to create a simple fuel pin model using surfaces:
# Define the surfaces for a fuel pin
fuel_radius = 0.4
clad_inner_radius = 0.41
clad_outer_radius = 0.47
# Create cylindrical surfaces
fuel_surface = openmc.ZCylinder(r=fuel_radius)
clad_inner_surface = openmc.ZCylinder(r=clad_inner_radius)
clad_outer_surface = openmc.ZCylinder(r=clad_outer_radius)
# Create top and bottom planes for finite height
top_plane = openmc.ZPlane(z0=10.0)
bottom_plane = openmc.ZPlane(z0=-10.0)
# Define regions
fuel_region = -fuel_surface & -top_plane & +bottom_plane
gap_region = +fuel_surface & -clad_inner_surface & -top_plane & +bottom_plane
clad_region = +clad_inner_surface & -clad_outer_surface & -top_plane & +bottom_planeTutorial snippet — no separate file in examples repo
Creating a Reactor Core Boundary
Defining a cylindrical reactor core with a hemispherical bottom:
# Define the dimensions
core_radius = 200.0
core_height = 400.0
# Create the cylindrical side
cylinder = openmc.ZCylinder(r=core_radius)
# Create the top plane
top_plane = openmc.ZPlane(z0=core_height)
# Create the hemispherical bottom
sphere = openmc.Sphere(r=core_radius, z0=0.0)
bottom_plane = openmc.ZPlane(z0=0.0)
# Define the core region
cylindrical_part = -cylinder & -top_plane & +bottom_plane
hemispherical_part = -sphere & -bottom_plane
core_region = cylindrical_part | hemispherical_partTutorial snippet — no separate file in examples repo
Best Practices
- Use axis-aligned surfaces when possible, as they are more efficient computationally.
- Use minimal surface definitions to represent your geometry, as each additional surface increases computational overhead.
- Name your surfaces meaningfully to make your model more readable and easier to debug.
- Check surface orientations carefully when using the
+and-operators to ensure regions are defined as intended. - Consider using universes and lattices instead of explicitly defining all surfaces for repeated structures.