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

python
# 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 surface
  • transmission: Particles pass through the surface freely (default)
  • vacuum: Particles are terminated when crossing the surface
  • periodic: Particles reappear at a corresponding location on another periodic surface
  • white: Particles are reflected in a random direction when hitting the surface
python
# 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:

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

Tutorial snippet — no separate file in examples repo

General Planes

For planes with arbitrary orientation, you can use the general Plane class:

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

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

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

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

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

python
# 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² = 1

Tutorial snippet — no separate file in examples repo

Quadric and Other Advanced Surfaces

General Quadric Surface

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

Tutorial snippet — no separate file in examples repo

Creating Half-Spaces

python
# 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 = +sphere

Tutorial 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.

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

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

Tutorial snippet — no separate file in examples repo

Creating a Reactor Core Boundary

Defining a cylindrical reactor core with a hemispherical bottom:

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

Tutorial 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.

Related Resources

Further reading: