Rosetta Stone

Same task, three codes. A side-by-side syntax reference for MCNP, OpenMC, and Serpent.

1. Define Materials

UO₂ fuel — 4.5 % enriched, 10.97 g/cm³. Each code uses ZAID-style nuclide identifiers and atom/weight fractions, but the card syntax differs.

MCNP

text
c --- UO2 fuel 4.5% enriched
c     density set on cell card
m1    92235.80c  4.5   $ U-235
      92238.80c 95.5   $ U-238
      8016.80c  200.0  $ O-16

Serpent

text
% UO2 fuel 4.5% enriched
mat fuel -10.97
 92235.09c  4.5
 92238.09c 95.5
  8016.09c 200.0

OpenMC

python
uo2 = openmc.Material(name='UO2')
uo2.add_nuclide('U235', 4.5)
uo2.add_nuclide('U238', 95.5)
uo2.add_nuclide('O16', 200.0)
uo2.set_density('g/cm3', 10.97)

2. Define Surfaces

A fuel-pin cylinder (radius 0.4096 cm) and a bounding box for the unit cell.

MCNP

text
c --- Surfaces
1  cz  0.4096        $ fuel pin
2  rpp -0.63 0.63
       -0.63 0.63
       -1.0  1.0     $ bounding box

Serpent

text
% --- Surfaces
surf 1 cylz 0.0 0.0 0.4096
surf 2 cuboid -0.63 0.63
              -0.63 0.63
              -1.0  1.0

OpenMC

python
pin = openmc.ZCylinder(r=0.4096)
box = openmc.model.RectangularPrism(
    width=1.26, height=1.26,
    boundary_type='reflective'
)

3. Define Cells

Fuel inside the cylinder, water outside. MCNP uses surface sense signs; Serpent and OpenMC use similar but distinct syntax.

MCNP

text
c --- Cells
c  id mat  dens    surfs
1  1  -10.97  -1       $ fuel
2  2  -1.0     1  -2   $ water
3  0           2       $ outside

Serpent

text
% --- Cells
cell 1 0 fuel   -1      % fuel
cell 2 0 water   1 -2   % water
cell 3 0 outside 2      % outside

OpenMC

python
fuel_cell = openmc.Cell(
    fill=uo2, region=-pin)
water_cell = openmc.Cell(
    fill=water, region=+pin & -box)
root = openmc.Universe(
    cells=[fuel_cell, water_cell])

4. Source Definition (Criticality)

A fission source for k-eigenvalue calculations. All three codes need the number of particles per cycle, the number of inactive/active cycles, and an initial source point.

MCNP

text
c --- Criticality source
KCODE 10000 1.0 50 250
c     nsrck  rkk  ikz  klc
KSRC  0.0 0.0 0.0

Serpent

text
% --- Criticality source
%     neutrons  cycles  inactive
set pop 10000    250      50
src 1 sp 0.0 0.0 0.0

OpenMC

python
settings = openmc.Settings()
settings.batches = 250
settings.inactive = 50
settings.particles = 10000
src = openmc.IndependentSource()
src.space = openmc.stats.Point(
    (0.0, 0.0, 0.0))
settings.source = [src]

5. Tallies

Neutron flux in the fuel cell. MCNP uses an F4 cell tally; Serpent uses a det detector card; OpenMC builds tallies from filters and scores.

MCNP

text
c --- Cell-average flux in fuel
F4:n  1     $ cell 1 flux
E4   0 0.625e-6 20.0
c     thermal / fast bins (MeV)

Serpent

text
% --- Cell-average flux in fuel
det flux dc 1  $ cell 1
de myerg 3 2   $ 2-bin energy grid
  0.0
  0.625E-6
  20.0

OpenMC

python
tally = openmc.Tally(name='flux')
tally.filters = [
    openmc.CellFilter([fuel_cell])
]
tally.scores = ['flux']
tallies = openmc.Tallies([tally])

6. Running

Command-line invocation for each code.

MCNP

bash
mcnp6 i=input o=output r=runtpe

Serpent

bash
sss2 -omp 4 input

OpenMC

python
model = openmc.Model(
    geometry, materials, settings, tallies)
model.run(threads=4)

7. Boundary Conditions

Reflective boundaries — particles hitting the surface are mirror-reflected back. Useful for infinite-lattice or symmetry models.

MCNP

text
c --- Reflective BC: * prefix on SURFACE card
*2  rpp -0.63 0.63 -0.63 0.63 -1 1
c
c --- Cell cards reference surface normally
1  1  -10.97  -1       $ fuel
2  2  -1.0     1  -2   $ water
3  0           2        $ void outside

Serpent

text
% --- Reflective BC (all surfaces)
% 1 = vacuum (default)
% 2 = reflective
% 3 = periodic
set bc 2

OpenMC

python
pin.boundary_type = 'reflective'
# or set at construction:
box = openmc.model.RectangularPrism(
    width=1.26, height=1.26,
    boundary_type='reflective')

8. Temperature Assignment

Setting temperature for Doppler broadening. MCNP specifies kT in MeV on the cell card; Serpent and OpenMC use Kelvin directly.

MCNP

text
c --- Temperature on cell
c     TMP = kT in MeV
c     900 K → 8.617e-11 × 900
c          = 7.756e-8 MeV
1  1  -10.97  -1  TMP=7.756e-8

Serpent

text
% --- Temperature on material (K)
mat fuel -10.97 tmp 900
 92235.09c  4.5
 92238.09c 95.5
  8016.09c 200.0

OpenMC

python
# Temperature is set on the cell (K)
fuel_cell.temperature = 900

Conversion: MCNP's TMP card takes energy in MeV (kT = K × 8.617 × 10⁻¹¹ MeV/K). Serpent and OpenMC accept temperature directly in Kelvin. In OpenMC, temperature is set on the cell, not the material.

9. Thermal Scattering — S(α,β)

Adding thermal scattering treatment for hydrogen in light water. Required for accurate thermal-spectrum calculations.

MCNP

text
c --- Water with S(a,b)
m2    1001.80c  2.0
      8016.80c  1.0
mt2   lwtr.20t

Serpent

text
% --- Water with S(a,b)
therm lwtr lwj3.22t
mat water -1.0 moder lwtr 1001
 1001.06c 2.0
 8016.06c 1.0

OpenMC

python
water = openmc.Material(name='water')
water.add_nuclide('H1', 2.0)
water.add_nuclide('O16', 1.0)
water.set_density('g/cm3', 1.0)
water.add_s_alpha_beta('c_H_in_H2O')

10. Density & Fraction Sign Conventions

All three codes use sign conventions for density and material fractions, but the details vary.

ConventionMCNPSerpentOpenMC
Density (g/cm³)Negative on cell cardNegative on mat cardset_density('g/cm3', val)
Density (atoms/b-cm)Positive on cell cardPositive on mat cardset_density('atom/b-cm', val)
Weight fractionsNegative fractions on m cardNegative fractions on mat cardadd_nuclide(..., percent_type='wo')
Atom fractionsPositive fractions on m cardPositive fractions on mat cardadd_nuclide(..., percent_type='ao')

Key difference: MCNP and Serpent share the same sign convention (negative = mass density / weight fraction, positive = atom density / atom fraction). OpenMC avoids sign tricks entirely — units and fraction types are explicit string parameters.