OpenMC Guide
Surface Types in OpenMC
Introduction to Surfaces
Surfaces are the building blocks of constructive solid geometry (CSG) in OpenMC. They define the boundaries that separate different regions of space, allowing you to construct complex geometric models by combining simple shapes.
Each surface is defined by a mathematical equation that divides space into two regions: positive and negative. When a surface is used in a cell definition, you specify which side of the surface the cell exists on using the + or - operator.
OpenMC provides a wide variety of surface types, each represented by a different Python class that inherits from the base Surface class.
Basic Surface Concepts
Surface Equations and Half-Spaces
A surface in OpenMC is defined by an equation of the form f(x,y,z) = 0. This equation divides the 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
When defining regions using surfaces, the - operator indicates the negative half-space, while the + operator indicates the positive half-space.
Surface ID and Name
Each surface in OpenMC can be assigned an optional ID (integer) and name (string) for easier reference:
# 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"Boundary Conditions
Surfaces can have boundary conditions applied to them to define how particles behave when they reach the surface. Available boundary conditions in OpenMC include:
reflective: Particles are reflected specularly when hitting the surfacevacuum: Particles are terminated when crossing the surface (default)periodic: 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')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 = 0General 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
# Plane defined from three points
point = (0.0, 0.0, 5.0)
point2 = (1.0, 0.0, 5.0)
point3 = (0.0, 1.0, 5.0)
plane2 = openmc.Plane.from_points(point, point2, point3)Cylindrical Surfaces
Cylindrical surfaces are commonly used in nuclear engineering to model fuel pins, control rods, and pressure vessels.
Cylinders Parallel to Axes
OpenMC provides dedicated classes for cylinders parallel to the coordinate 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²General Cylinders
For cylinders with arbitrary orientation, you can use the general Cylinder class:
# Cylinder defined by a point, direction vector, and radius
center = (0.0, 0.0, 0.0)
direction = (1.0, 1.0, 1.0)
radius = 0.5
cyl = openmc.Cylinder(center=center, direction=direction, r=radius)Note: For most typical reactor geometries, the cylinders parallel to coordinate axes (XCylinder, YCylinder, ZCylinder) are more efficient and easier to use than the general Cylinder class.
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)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)²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(r=5.0, a=1.0) # (√((x-x0)² + (y-y0)²) - r)² + (z-z0)² = a²
# where:
# r = distance from the center of the tube to the center of the torus
# a = radius of the tubeQuadric and Other Advanced Surfaces
General Quadric Surface
For more complex geometries, OpenMC provides the 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 = 1Creating Half-Spaces
The + and - operators allow you to create half-spaces from surfaces:
# 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 = +sphereSurface Transformations
OpenMC allows you to apply transformations (translation and rotation) to surfaces:
# Create translation
translation = np.array([1.0, 2.0, 3.0])
# Create rotation (3x3 rotation matrix)
phi, theta, psi = np.radians([30.0, 45.0, 60.0]) # Euler angles
rotation = openmc.rotation_matrix(phi, theta, psi)
# Create a surface and apply the transformation
sphere = openmc.Sphere(r=10.0)
sphere.translation = translation
sphere.rotation = rotation
# You can also define transformations using the `Rotation` class
rot = openmc.Rotation.from_euler('xyz', [30.0, 45.0, 60.0], degrees=True)
sphere.rotation = rotTip: Rather than applying transformations to many surfaces, it's often more efficient to use the universe and lattice features to position and orient repeated structures.
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_planeCreating 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_partBest 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
To learn more about surfaces in OpenMC, check these resources: