This project demonstrates CPU-based parallelization techniques using a toy reservoir simulation. We simulate oil particles flowing through a porous 3D medium, visualized over time with a side and top view. The simulation is intentionally simple and visual to help illustrate the effects of parallel strategies like serial, multithreading, and multiprocessing.
The simulation does not aim for high physical realism, rather it is a tool for comparing performance impacts of parallel execution.
- The reservoir grid is a 3D structure with per-cell porosity values.
- Flow is constrained to 6 neighbors (±x, ±y, -z). No upward flow (+z).
- Flow is biased by:
- Porosity: Higher porosity = higher flow chance.
- Gravity: Stronger bias to flow downward (-z).
- A barrier layer exists at a fixed z=7 with small perforated holes to mimic restricted vertical flow.
- Oil particles start as a sheet at the top layer and migrate over time.
- Oil movement is stochastic and not pressure-driven.
- Porosity values are fixed and static.
- Time steps are uniform and abstract (not tied to physical units).
- No fluid saturation dynamics or mass conservation modeled.
- Each particle independently selects its next position based on its neighbors.
- Neighbor selection uses weighted probabilities (based on porosity and gravity).
- The simulation is step-based, updating all particles per frame.
We implemented three strategies using the Strategy Pattern:
| Strategy | Method | Notes |
|---|---|---|
| Serial | Standard for-loop | Baseline approach, no parallelism |
| Multithreading | ThreadPoolExecutor | Thread-safe, but limited by Python GIL |
| Multiprocessing | multiprocessing.Pool | True parallelism via process-based concurrency |
To further optimize multiprocessing and threading, we added batch processing, where particles are grouped and each batch is processed concurrently.
Tested on a simulated grid with 2440 oil particles.
| Strategy | Time (s) |
|---|---|
| Serial | 9.62 |
| Multithreading | 33.66 |
| Multiprocessing | 12.53 |
- Multithreading performs worse due to Python's Global Interpreter Lock (GIL), which limits CPU-bound threads from executing in parallel.
- Multiprocessing outperforms multithreading because it bypasses the GIL using multiple processes.
- Batching reduces inter-process overhead and memory copying, improving multiprocessing speed.
The final animation shows a top-down and side view of the oil particles as they flow through the porous medium.
The animation is saved as Artifacts/oil_top_and_side_with_perforations.mp4.
In a linux environment
# Set up the required environment
pip install -r requirements.txt
# Run the main animated simulation with Serial strategy
python run_particle_simulation.py
# Run all strategies and compare performance
python run_all_strategies.py