Geometry Basics

The Building Block Approach

OpenMC uses constructive solid geometry (CSG) where you build complex shapes by combining simple surfaces with boolean operations. Think of it like building with digital blocks - surfaces divide space into regions, and you select which regions to fill with materials.

Every surface splits 3D space into two regions: positive (outside) and negative (inside). The key insight is learning to combine these regions logically to create the shapes you need.

python
import openmc

# Surface divides space into two regions
cylinder = openmc.ZCylinder(r=0.5)

# Boolean operators combine regions
inside_cylinder = -cylinder      # Negative side (inside)
outside_cylinder = +cylinder     # Positive side (outside)
# Note: + is often omitted, so 'cylinder' means +cylinder

Essential Surface Types

Start with these fundamental surfaces that cover most nuclear engineering applications:

python
# Cylinders (for pins, rods, pipes)
fuel_surface = openmc.ZCylinder(r=0.4096)  # Cylinder along z-axis
pipe = openmc.XCylinder(r=2.5)             # Cylinder along x-axis

# Planes (for boundaries, flat surfaces)
centerline = openmc.XPlane(0.0)            # Plane at x=0
top = openmc.ZPlane(365.76)                # Plane at z=365.76 cm

# Spheres (for particles, pellets)
pellet = openmc.Sphere(r=0.1)              # Sphere at origin

# Rectangular regions (for assemblies, lattices)
box = openmc.rectangular_prism(2.0, 2.0)  # 2×2 cm square (helper function)

Creating Cells with Boolean Logic

Cells are regions of space filled with material or left void. You define them by combining surface regions with logical operators.

python
# Example: Fuel pin with cladding
fuel_outer = openmc.ZCylinder(r=0.4096)
clad_outer = openmc.ZCylinder(r=0.4750)

# Define regions using boolean operations
fuel_region = -fuel_outer                    # Inside fuel cylinder
clad_region = +fuel_outer & -clad_outer     # Between fuel and clad
water_region = +clad_outer                  # Outside clad

# Create cells by filling regions
fuel_cell = openmc.Cell(fill=fuel_material, region=fuel_region)
clad_cell = openmc.Cell(fill=clad_material, region=clad_region)
water_cell = openmc.Cell(fill=water_material, region=water_region)

The logical operators work intuitively: & means "and" (intersection), | means "or" (union), and ~ means "not" (complement).

Boundary Conditions

Surface boundary conditions control what happens when particles reach model edges:

python
# Common boundary types
vacuum_boundary = openmc.ZPlane(100, boundary_type='vacuum')      # Particles escape
reflect_boundary = openmc.ZPlane(-100, boundary_type='reflective') # Particles reflect
periodic_left = openmc.XPlane(-10, boundary_type='periodic')      # Particles wrap around
periodic_right = openmc.XPlane(10, boundary_type='periodic')

# For infinite lattice problems, use reflective boundaries
# For shielding problems, use vacuum boundaries  
# For reactor cores, mix reflective (sides) and vacuum (top/bottom)

Working Example: Pin Cell

Here's a complete pin cell geometry that demonstrates these concepts:

python
import openmc

# Define surfaces
fuel_radius = 0.4096
clad_radius = 0.4750
pitch = 1.26

fuel_outer = openmc.ZCylinder(r=fuel_radius)
clad_outer = openmc.ZCylinder(r=clad_radius) 

# Square boundary with reflective conditions
left = openmc.XPlane(-pitch/2, boundary_type='reflective')
right = openmc.XPlane(pitch/2, boundary_type='reflective')
bottom = openmc.YPlane(-pitch/2, boundary_type='reflective')
top = openmc.YPlane(pitch/2, boundary_type='reflective')

# Define regions
fuel_region = -fuel_outer
clad_region = +fuel_outer & -clad_outer
water_region = +clad_outer & +left & -right & +bottom & -top

# Create cells (materials defined elsewhere)
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)

# Combine into universe and geometry
universe = openmc.Universe(cells=[fuel_cell, clad_cell, water_cell])
geometry = openmc.Geometry(universe)

Common Mistakes

Avoid these frequent geometry errors:

python
# Wrong: Missing boolean operators
region = surf1 surf2  # This doesn't work

# Correct: Explicit operators
region = +surf1 & +surf2  # Intersection
region = +surf1 | +surf2  # Union

# Wrong: Forgetting boundary conditions for finite geometry
boundary = openmc.ZPlane(100)  # Particles will be lost

# Correct: Specify boundary behavior
boundary = openmc.ZPlane(100, boundary_type='vacuum')

# Wrong: Overlapping regions (OpenMC will detect this)
cell1_region = -cylinder
cell2_region = -cylinder  # Same region used twice!

# Correct: Non-overlapping regions
cell1_region = -inner_cylinder
cell2_region = +inner_cylinder & -outer_cylinder

Next Steps

With these geometry fundamentals, you can model most nuclear systems. For repeated structures like fuel assemblies, you'll want to learn about lattices and universes. For complex shapes, explore additional surface types and advanced boolean operations.

The key is starting simple and building complexity gradually. Master these basics first, then tackle more sophisticated geometries as your needs require.