Minimal Python Simulation Script¶
The smallest complete Python script that runs a particle tracking simulation with mod-PATH3DU.
Script¶
import json
import numpy as np
import mp3du
# --- 1. Build the grid from vertex and center data ---
# vertices: list of polygons, each polygon is a list of (x, y) tuples
# centers: list of (x, y, z) tuples for cell centroids
vertices = [
[(0.0, 0.0), (100.0, 0.0), (100.0, 100.0), (0.0, 100.0)],
]
centers = [(50.0, 50.0, 25.0)]
grid = mp3du.build_grid(vertices, centers)
# --- 2. Hydrate cell properties (one cell) ---
cell_properties = mp3du.hydrate_cell_properties(
top=np.array([50.0]),
bot=np.array([0.0]),
porosity=np.array([0.3]),
retardation=np.array([1.0]),
hhk=np.array([1e-4]),
vhk=np.array([1e-5]),
disp_long=np.array([0.0]),
disp_trans_h=np.array([0.0]),
disp_trans_v=np.array([0.0]),
)
# --- 3. Hydrate cell flows ---
cell_flows = mp3du.hydrate_cell_flows(
head=np.array([45.0]),
water_table=np.array([45.0]),
q_top=np.array([0.0]),
q_bot=np.array([0.0]),
q_vert=np.array([0.0]),
q_well=np.array([0.0]),
q_other=np.array([0.0]),
q_storage=np.array([0.0]),
has_well=np.array([False]),
face_offset=np.array([0], dtype=np.uint64),
face_flow=np.array([], dtype=np.float64),
face_neighbor=np.array([], dtype=np.int64),
)
# --- 4. Hydrate Waterloo velocity inputs ---
fit_inputs = mp3du.hydrate_waterloo_inputs(
centers_xy=np.array([[50.0, 50.0]]),
radii=np.array([56.42]),
perimeters=np.array([400.0]),
areas=np.array([10000.0]),
q_vert=np.array([0.0]),
q_well=np.array([0.0]),
q_other=np.array([0.0]),
face_offset=np.array([0], dtype=np.uint64),
face_vx1=np.array([], dtype=np.float64),
face_vy1=np.array([], dtype=np.float64),
face_vx2=np.array([], dtype=np.float64),
face_vy2=np.array([], dtype=np.float64),
face_length=np.array([], dtype=np.float64),
face_flow=np.array([], dtype=np.float64),
noflow_mask=np.array([], dtype=np.bool_),
)
# --- 5. Fit the Waterloo velocity field ---
waterloo_config = mp3du.WaterlooConfig(order_of_approx=35, n_control_points=122)
field = mp3du.fit_waterloo(waterloo_config, grid, fit_inputs, cell_properties, cell_flows)
# --- 6. Load simulation configuration ---
config = mp3du.SimulationConfig.from_json(json.dumps({
"velocity_method": "Waterloo",
"solver": "DormandPrince",
"adaptive": {
"tolerance": 1e-6,
"safety": 0.9,
"alpha": 0.2,
"min_scale": 0.2,
"max_scale": 5.0,
"max_rejects": 10,
"min_dt": 1e-10,
"euler_dt": 1.0
},
"dispersion": {"method": "None"},
"retardation_enabled": False,
"capture": {
"max_time": 365250.0,
"max_steps": 1000000,
"stagnation_velocity": 1e-12,
"stagnation_limit": 100
},
"initial_dt": 1.0,
"max_dt": 100.0,
"direction": 1.0
}))
# --- 7. Define particle starting positions ---
particles = [
mp3du.ParticleStart(id=0, x=50.0, y=50.0, z=25.0, cell_id=0, initial_dt=1.0),
]
# --- 8. Run the simulation ---
results = mp3du.run_simulation(config, field, particles)
# --- 9. Print results ---
for r in results:
print(f"Particle {r.particle_id}: status={r.final_status}, steps={len(r)}")
What This Script Does¶
- Builds a grid from vertex polygons and cell centroids.
- Hydrates cell properties — top/bottom elevations, porosity, hydraulic conductivity.
- Hydrates cell flows — heads, water table, face flows and budgets.
- Hydrates Waterloo inputs — geometric data for the Waterloo velocity interpolation.
- Fits the velocity field using the Waterloo method.
- Creates a simulation config from JSON (DormandPrince solver, forward tracking, no dispersion).
- Defines one particle starting position.
- Runs the simulation and prints the result status.
Prerequisites¶
- mod-PATH3DU installed (Installation Guide)
- NumPy available (
pip install numpy) - Grid geometry and MODFLOW-USG output data available
See Also¶
- Quickstart — More detailed tutorial
- Batch Simulation — Multiple particles
- Running Simulations — Full workflow guide