Moving Fuel Pellet#
Problem Description#
A three-dimensional time-dependent problem in which a cylindrical fuel pellet traverses a box of air-like material along a piecewise-linear trajectory. Both the cylindrical surface and the bounding planes of the pellet move, demonstrating MC/DC’s moving-surface capability for transient geometry.
Geometry and Materials#
The computational domain is a rectangular box: \(x \in [-5,5]\), \(y \in [-5,5]\), \(z \in [-10,10]\) cm, with vacuum boundary conditions on all faces.
A z-aligned cylindrical fuel pellet (radius 1 cm) is initially located at \(z \in [6,9]\) cm. The pellet moves in three consecutive phases:
Phase |
Cylinder velocity |
End-cap velocity |
Duration (s) |
1 |
\((-0.5,\; 0,\; 0)\) |
\((0,\; 0,\; -2)\) |
2 / 5 |
2 |
\((1,\; 0,\; 0)\) |
\((0,\; 0,\; 4)\) |
5 / 2 |
3 |
\((-2,\; 0,\; 0)\) |
\((0,\; 0,\; -10)\) |
1 / 1 |
Two materials are used:
Region |
\(\Sigma_c\) |
\(\Sigma_s\) |
\(\Sigma_f\) |
\(\nu\) |
Fuel pellet |
0.50 |
— |
0.25 |
1.5 |
Air |
0.002 |
0.008 |
— |
— |
Neutron speed: \(v = 2 \times 10^{5}\) cm/s (both regions).
Physical Assumptions#
Mono-energetic (one-speed) neutron transport.
Isotropic scattering.
Time-dependent transport with moving geometry surfaces.
Fission in the pellet region only.
Numerical Setup#
Spatial mesh (tally) |
\(201 \times 201\) in the \((x,z)\)-plane |
Time mesh (tally) |
46 equally spaced bins over \(t \in [0,9]\) s |
Tally score |
Fission rate |
Source particles |
\(10^{5}\) |
Batches |
2 |
Quantities of Interest#
Time-resolved 2-D fission rate distribution in the \((x,z)\)-plane.
Animation of the fission rate tracking the moving pellet geometry.
Reference Solution#
No analytical reference. The solution is validated by verifying that the fission rate follows the pellet trajectory and that particle conservation is maintained.
Step-by-Step Walkthrough#
1. Materials (lines 1–22)
1import numpy as np
2
3import mcdc
4
5simulation = mcdc.Simulation("Moving pellet")
6
7# ======================================================================================
8# Set model
9# ======================================================================================
10
11# Set materials
12fuel = mcdc.Material.multigroup(
13 capture=np.array([0.5]),
14 fission=np.array([0.25]),
15 nu_p=np.array([1.5]),
16 speed=np.array([200000.0]),
17)
18air = mcdc.Material.multigroup(
19 capture=np.array([0.002]),
20 scatter=np.array([[0.008]]),
21 speed=np.array([200000.0]),
22)
A fissile fuel pellet (\(\Sigma_f = 0.25\), \(\nu = 1.5\)) and
an air-like background. Both include speed for time-dependent
transport.
2. Surfaces and Moving Geometry (lines 24–30)
24# Set surfaces
25cylinder_z = mcdc.Surface.CylinderZ(center=[0.0, 0.0], radius=1.0)
26top_z = mcdc.Surface.PlaneZ(z=9.0)
27bot_z = mcdc.Surface.PlaneZ(z=6.0)
28
29# Move surfaces
30cylinder_z.move([[-0.5, 0.0, 0.0], [1.0, 0.0, 0.0], [-2.0, 0.0, 0.0]], [2.0, 5.0, 1.0])
A z-cylinder and two z-planes define the pellet. The key feature:
surface.move(velocities, durations) makes these surfaces time-dependent.
The cylinder moves laterally while the endcaps move axially, simulating
a pellet traversing the domain.
3. Container and Cells (lines 32–50)
32bot_z.move([[0.0, 0.0, -2.0], [0.0, 0.0, 4.0], [0.0, 0.0, -10.0]], [5.0, 2.0, 1.0])
33
34# Set container cell surfaces
35min_x = mcdc.Surface.PlaneX(x=-5.0, boundary_condition="vacuum")
36max_x = mcdc.Surface.PlaneX(x=5.0, boundary_condition="vacuum")
37min_y = mcdc.Surface.PlaneY(y=-5.0, boundary_condition="vacuum")
38max_y = mcdc.Surface.PlaneY(y=5.0, boundary_condition="vacuum")
39min_z = mcdc.Surface.PlaneZ(z=-10.0, boundary_condition="vacuum")
40max_z = mcdc.Surface.PlaneZ(z=10.0, boundary_condition="vacuum")
41
42# Make cells
43fuel_pellet_region = +bot_z & -top_z & -cylinder_z
44fuel_cell = mcdc.Cell(region=fuel_pellet_region, fill=fuel)
45air_cell = mcdc.Cell(
46 region=~fuel_pellet_region & +min_x & -max_x & +min_y & -max_y & +min_z & -max_z,
47 fill=air,
48)
49simulation.set_model([fuel_cell, air_cell])
50
The fuel pellet region is defined by the intersection of the cylinder and the two planes. The air fills the complement inside the bounding box.
4. Source (lines 56–63)
56 x=[2.0, 3.0],
57 y=[-0.5, 0.5],
58 z=[-0.5, 0.5],
59 isotropic=True,
60 energy=0,
61 time=[0.0, 9.0],
62)
63simulation.set_sources([source])
A small box source near the pellet’s initial position, active over the full simulation time \(t \in [0, 9]\) s.
5. Tallies, Settings, and Run (lines 69–83)
69# Tallies
70mesh = mcdc.MeshStructured(
71 x=np.linspace(-5, 5, 201),
72 z=np.linspace(-10, 10, 201),
73)
74tally = mcdc.Tally(mesh=mesh, scores=["fission"], time=np.linspace(0, 9, 46))
75simulation.set_tallies([tally])
76
77# Settings
78simulation.settings.N_particle = 100000
79simulation.settings.N_batch = 2
80simulation.settings.active_bank_buffer = 1000
81
82# Run (or visualize)
83visualize = False
A structured mesh tally in the \((x,z)\)-plane with 46 time bins captures the fission rate as the pellet moves.
What to try:
Change the pellet velocities to create different trajectories.
Set
visualize = Trueto watch the geometry evolve withsimulation.visualize_model(..., time=...).Compare with
moving_sourceto see source motion vs. geometry motion.
Full Input#
Click here to view the input file: examples/moving_pellet/input.py.
The complete input used for this example is embedded below:
1import numpy as np
2
3import mcdc
4
5simulation = mcdc.Simulation("Moving pellet")
6
7# ======================================================================================
8# Set model
9# ======================================================================================
10
11# Set materials
12fuel = mcdc.Material.multigroup(
13 capture=np.array([0.5]),
14 fission=np.array([0.25]),
15 nu_p=np.array([1.5]),
16 speed=np.array([200000.0]),
17)
18air = mcdc.Material.multigroup(
19 capture=np.array([0.002]),
20 scatter=np.array([[0.008]]),
21 speed=np.array([200000.0]),
22)
23
24# Set surfaces
25cylinder_z = mcdc.Surface.CylinderZ(center=[0.0, 0.0], radius=1.0)
26top_z = mcdc.Surface.PlaneZ(z=9.0)
27bot_z = mcdc.Surface.PlaneZ(z=6.0)
28
29# Move surfaces
30cylinder_z.move([[-0.5, 0.0, 0.0], [1.0, 0.0, 0.0], [-2.0, 0.0, 0.0]], [2.0, 5.0, 1.0])
31top_z.move([[0.0, 0.0, -2.0], [0.0, 0.0, 4.0], [0.0, 0.0, -10.0]], [5.0, 2.0, 1.0])
32bot_z.move([[0.0, 0.0, -2.0], [0.0, 0.0, 4.0], [0.0, 0.0, -10.0]], [5.0, 2.0, 1.0])
33
34# Set container cell surfaces
35min_x = mcdc.Surface.PlaneX(x=-5.0, boundary_condition="vacuum")
36max_x = mcdc.Surface.PlaneX(x=5.0, boundary_condition="vacuum")
37min_y = mcdc.Surface.PlaneY(y=-5.0, boundary_condition="vacuum")
38max_y = mcdc.Surface.PlaneY(y=5.0, boundary_condition="vacuum")
39min_z = mcdc.Surface.PlaneZ(z=-10.0, boundary_condition="vacuum")
40max_z = mcdc.Surface.PlaneZ(z=10.0, boundary_condition="vacuum")
41
42# Make cells
43fuel_pellet_region = +bot_z & -top_z & -cylinder_z
44fuel_cell = mcdc.Cell(region=fuel_pellet_region, fill=fuel)
45air_cell = mcdc.Cell(
46 region=~fuel_pellet_region & +min_x & -max_x & +min_y & -max_y & +min_z & -max_z,
47 fill=air,
48)
49simulation.set_model([fuel_cell, air_cell])
50
51# ======================================================================================
52# Set source
53# ======================================================================================
54
55source = mcdc.Source(
56 x=[2.0, 3.0],
57 y=[-0.5, 0.5],
58 z=[-0.5, 0.5],
59 isotropic=True,
60 energy=0,
61 time=[0.0, 9.0],
62)
63simulation.set_sources([source])
64
65# ======================================================================================
66# Set tallies, settings, and run MC/DC
67# ======================================================================================
68
69# Tallies
70mesh = mcdc.MeshStructured(
71 x=np.linspace(-5, 5, 201),
72 z=np.linspace(-10, 10, 201),
73)
74tally = mcdc.Tally(mesh=mesh, scores=["fission"], time=np.linspace(0, 9, 46))
75simulation.set_tallies([tally])
76
77# Settings
78simulation.settings.N_particle = 100000
79simulation.settings.N_batch = 2
80simulation.settings.active_bank_buffer = 1000
81
82# Run (or visualize)
83visualize = False
84if not visualize:
85 simulation.run()
86else:
87 colors = {
88 fuel: "red",
89 air: "blue",
90 }
91 simulation.visualize_model(
92 vis_plane="xz",
93 y=0.0,
94 x=[-5.0, 5.0],
95 z=[-10, 10],
96 pixels=(100, 100),
97 colors=colors,
98 time=np.linspace(0.0, 9.0, 19),
99 save_as="figure",
100 )
How to Run#
From inside examples/moving_pellet run:
python input.py
Expected Output#
An HDF5 tally file with time-resolved fission rates and an optional animation created by the example’s post-processing script.