Packaged Fuel Array (Universe and Lattice)¶
Problem Description¶
A three-dimensional fixed-source problem featuring two identical fuel assemblies placed side-by-side inside a water-filled box. Each assembly uses a composite “shooting-star” fuel geometry built from the union of two orthogonal cylinders enclosed by a cladding sphere.
This example demonstrates MC/DC’s universe, translation, and rotation capabilities for constructive solid geometry (CSG) packaging.
Geometry and Materials¶
The global domain is a rectangular box: \(x \in [-10,10]\), \(y \in [-5,5]\), \(z \in [-5,5]\) cm, with vacuum boundary conditions.
Each assembly is defined as a universe containing three cells:
Fuel — union of a z-aligned and an x-aligned cylinder (radius 1 cm, half-length 5 cm).
Cladding — spherical shell (radius 3 cm) surrounding the fuel.
Water — region outside the cladding sphere.
The left assembly is translated to \((-5,0,0)\) cm; the right assembly is translated to \((+5,0,0)\) cm and rotated \(10°\) about the \(y\)-axis.
Region |
\(\Sigma_c\) |
\(\Sigma_s\) |
\(\Sigma_f\) |
\(\nu\) |
Fuel |
0.45 |
— |
0.55 |
2.5 |
Cladding |
0.05 |
0.95 |
— |
— |
Water |
0.02 |
0.08 |
— |
— |
Physical Assumptions¶
Mono-energetic (one-speed) neutron transport.
Isotropic scattering.
Steady-state fixed-source calculation.
No delayed neutrons.
Numerical Setup¶
Spatial mesh (tally) |
\(201 \times 101\) in the \((x,z)\)-plane |
Tally score |
Fission rate |
Source particles |
\(10^{3}\) (demonstration) |
Batches |
2 |
Quantities of Interest¶
Two-dimensional fission rate distribution in the \((x,z)\)-plane.
Relative standard deviation map for convergence assessment.
Reference Solution¶
No analytical reference. The geometry can be verified using MC/DC’s
built-in mcdc.visualize() function to render the CSG model.
Step-by-Step Walkthrough¶
1. Materials (lines 1–27)
1import numpy as np
2import mcdc
3
4# ======================================================================================
5# Materials
6# ======================================================================================
7
8fuel = mcdc.MaterialMG(
9 capture=np.array([0.45]),
10 fission=np.array([0.55]),
11 nu_p=np.array([2.5]),
12)
13
14cover = mcdc.MaterialMG(
15 capture=np.array([0.05]),
16 scatter=np.array([[0.95]]),
17)
18
19water = mcdc.MaterialMG(
20 capture=np.array([0.02]),
21 scatter=np.array([[0.08]]),
22)
23
24# ======================================================================================
25# The assembly
26# ======================================================================================
27
Three mono-energetic materials: fissile fuel, a scattering cladding, and water moderator.
2. Assembly Geometry — Shooting-Star CSG (lines 29–54)
29cylinder_z = mcdc.Surface.CylinderZ(center=[0.0, 0.0], radius=1.0)
30cylinder_x = mcdc.Surface.CylinderX(center=[0.0, 0.0], radius=1.0)
31
32top_z = mcdc.Surface.PlaneZ(z=2.5)
33bot_z = mcdc.Surface.PlaneZ(z=-2.5)
34top_x = mcdc.Surface.PlaneX(x=2.5)
35bot_x = mcdc.Surface.PlaneX(x=-2.5)
36
37sphere = mcdc.Surface.Sphere(center=[0.0, 0.0, 0.0], radius=3.0)
38
39# Cells
40pellet_z = -cylinder_z & +bot_z & -top_z
41pellet_x = -cylinder_x & +bot_x & -top_x
42shooting_star = pellet_z | pellet_x
43fuel_shooting_star = mcdc.Cell(region=shooting_star, fill=fuel)
44cover_sphere = mcdc.Cell(region=-sphere & ~shooting_star, fill=cover)
45water_tank = mcdc.Cell(region=+sphere, fill=water)
46
47# ======================================================================================
48# Copy the assembly via universe cells
49# ======================================================================================
50
51# Set the universe
52assembly = mcdc.Universe(cells=[fuel_shooting_star, cover_sphere, water_tank])
53
54# Set container cell surfaces
The fuel region is the union of a z-cylinder and an x-cylinder (the “shooting star”). The cladding fills the sphere minus the fuel. Water fills outside the sphere. These three cells form a reusable universe.
3. Packaging with Universe, Translation, and Rotation (lines 56–80)
56mid_x = mcdc.Surface.PlaneX(x=0.0)
57max_x = mcdc.Surface.PlaneX(x=10.0, boundary_condition="vacuum")
58min_y = mcdc.Surface.PlaneY(y=-5.0, boundary_condition="vacuum")
59max_y = mcdc.Surface.PlaneY(y=5.0, boundary_condition="vacuum")
60min_z = mcdc.Surface.PlaneZ(z=-5.0, boundary_condition="vacuum")
61max_z = mcdc.Surface.PlaneZ(z=5.0, boundary_condition="vacuum")
62
63# Make copies via universe cells
64container_left = +min_y & -max_y & +min_z & -max_z & +min_x & -mid_x
65container_right = +min_y & -max_y & +min_z & -max_z & +mid_x & -max_x
66assembly_left = mcdc.Cell(region=container_left, fill=assembly, translation=[-5, 0, 0])
67assembly_right = mcdc.Cell(
68 region=container_right, fill=assembly, translation=[+5, 0, 0], rotation=[0, 10, 0]
69)
70
71# Root universe
72mcdc.simulation.set_root_universe(cells=[assembly_left, assembly_right])
73
74# ======================================================================================
75# Set source
76# ======================================================================================
77
78mcdc.Source(x=[-0.1, 0.1], isotropic=True, energy_group=0)
79
80# ======================================================================================
The assembly universe is placed twice using mcdc.Cell(..., fill=assembly):
Left — translated to \((-5, 0, 0)\).
Right — translated to \((+5, 0, 0)\) and rotated 10° about \(y\).
set_root_universe() tells MC/DC these are the top-level cells.
4. Source, Tallies, Settings, and Run (lines 82–105)
82# ======================================================================================
83
84# Tallies
85mesh = mcdc.MeshStructured(
86 x=np.linspace(-10, 10, 201),
87 z=np.linspace(-5, 5, 101),
88)
89mcdc.Tally(mesh=mesh, scores=["fission"])
90
91# Settings
92mcdc.settings.N_particle = 1000
93mcdc.settings.N_batch = 2
94mcdc.settings.active_bank_buffer = 1000
95
96# Run (or visualize)
97visualize = False
98if not visualize:
99 mcdc.run()
100else:
101 colors = {
102 fuel: "red",
103 cover: "gray",
104 water: "blue",
105 }
A point-like source near the centre, a structured mesh tally for the
\((x,z)\)-plane fission rate, and 1 000 particles in 2 batches.
The active_bank_buffer accommodates fission-born particles.
5. Optional Visualization (lines 107–end)
107 "xz", y=0.0, x=[-11.0, 11.0], z=[-6, 6], pixels=(400, 400), colors=colors
108 )
Set visualize = True to render the CSG geometry with
mcdc.visualize() instead of running the transport.
What to try:
Change the rotation angle and observe the effect on the fission map.
Add a third assembly copy with a different translation.
Use
mcdc.Latticeinstead of manual universe placement.
Full Input¶
Click here to view the input file: examples/fuel_array_packaged/input.py.
The complete input used for this example is embedded below:
1import numpy as np
2import mcdc
3
4# ======================================================================================
5# Materials
6# ======================================================================================
7
8fuel = mcdc.MaterialMG(
9 capture=np.array([0.45]),
10 fission=np.array([0.55]),
11 nu_p=np.array([2.5]),
12)
13
14cover = mcdc.MaterialMG(
15 capture=np.array([0.05]),
16 scatter=np.array([[0.95]]),
17)
18
19water = mcdc.MaterialMG(
20 capture=np.array([0.02]),
21 scatter=np.array([[0.08]]),
22)
23
24# ======================================================================================
25# The assembly
26# ======================================================================================
27
28# Surfaces
29cylinder_z = mcdc.Surface.CylinderZ(center=[0.0, 0.0], radius=1.0)
30cylinder_x = mcdc.Surface.CylinderX(center=[0.0, 0.0], radius=1.0)
31
32top_z = mcdc.Surface.PlaneZ(z=2.5)
33bot_z = mcdc.Surface.PlaneZ(z=-2.5)
34top_x = mcdc.Surface.PlaneX(x=2.5)
35bot_x = mcdc.Surface.PlaneX(x=-2.5)
36
37sphere = mcdc.Surface.Sphere(center=[0.0, 0.0, 0.0], radius=3.0)
38
39# Cells
40pellet_z = -cylinder_z & +bot_z & -top_z
41pellet_x = -cylinder_x & +bot_x & -top_x
42shooting_star = pellet_z | pellet_x
43fuel_shooting_star = mcdc.Cell(region=shooting_star, fill=fuel)
44cover_sphere = mcdc.Cell(region=-sphere & ~shooting_star, fill=cover)
45water_tank = mcdc.Cell(region=+sphere, fill=water)
46
47# ======================================================================================
48# Copy the assembly via universe cells
49# ======================================================================================
50
51# Set the universe
52assembly = mcdc.Universe(cells=[fuel_shooting_star, cover_sphere, water_tank])
53
54# Set container cell surfaces
55min_x = mcdc.Surface.PlaneX(x=-10.0, boundary_condition="vacuum")
56mid_x = mcdc.Surface.PlaneX(x=0.0)
57max_x = mcdc.Surface.PlaneX(x=10.0, boundary_condition="vacuum")
58min_y = mcdc.Surface.PlaneY(y=-5.0, boundary_condition="vacuum")
59max_y = mcdc.Surface.PlaneY(y=5.0, boundary_condition="vacuum")
60min_z = mcdc.Surface.PlaneZ(z=-5.0, boundary_condition="vacuum")
61max_z = mcdc.Surface.PlaneZ(z=5.0, boundary_condition="vacuum")
62
63# Make copies via universe cells
64container_left = +min_y & -max_y & +min_z & -max_z & +min_x & -mid_x
65container_right = +min_y & -max_y & +min_z & -max_z & +mid_x & -max_x
66assembly_left = mcdc.Cell(region=container_left, fill=assembly, translation=[-5, 0, 0])
67assembly_right = mcdc.Cell(
68 region=container_right, fill=assembly, translation=[+5, 0, 0], rotation=[0, 10, 0]
69)
70
71# Root universe
72mcdc.simulation.set_root_universe(cells=[assembly_left, assembly_right])
73
74# ======================================================================================
75# Set source
76# ======================================================================================
77
78mcdc.Source(x=[-0.1, 0.1], isotropic=True, energy_group=0)
79
80# ======================================================================================
81# Set tallies, settings, and run MC/DC
82# ======================================================================================
83
84# Tallies
85mesh = mcdc.MeshStructured(
86 x=np.linspace(-10, 10, 201),
87 z=np.linspace(-5, 5, 101),
88)
89mcdc.Tally(mesh=mesh, scores=["fission"])
90
91# Settings
92mcdc.settings.N_particle = 1000
93mcdc.settings.N_batch = 2
94mcdc.settings.active_bank_buffer = 1000
95
96# Run (or visualize)
97visualize = False
98if not visualize:
99 mcdc.run()
100else:
101 colors = {
102 fuel: "red",
103 cover: "gray",
104 water: "blue",
105 }
106 mcdc.visualize(
107 "xz", y=0.0, x=[-11.0, 11.0], z=[-6, 6], pixels=(400, 400), colors=colors
108 )
How to Run¶
From the repository root run:
python examples/fuel_array_packaged/input.py
Expected Output¶
An HDF5 mesh tally and optional visualization images produced by the
mcdc.visualize() helper when run with visualization enabled.