This project implements a parallel numerical solver for cardiac electrophysiology simulation using the deal.II C++ finite element library. It solves the monodomain equation coupled with ionic cell models, utilizing MPI for distributed parallel execution.
The theoretical derivations, physical modeling formulations, finite element discretization (space and time discretization), detailed mathematical analysis, and all experimental results and visualizations generated by the sweep scripts are documented in the LaTeX report source file:
- MOX Cluster Execution: This project and its sweep/testing scripts are configured to be run on the HPC cluster of the MOX department of Politecnico di Milano. The scripts automate task submissions to the compute nodes using PBS job chaining and resource parameters.
- Apptainer Container: Compilation and execution are performed inside the
dealii_paraview.sifcontainer. This environment packages:- deal.II finite element library (built on
dealii/dealii:master-jammy) - gmsh for mesh compilation
- ParaView (and
pvpythonbindings) for offscreen image generation and plot automations
- deal.II finite element library (built on
To compile the project manually using CMake and make:
- Create and navigate to the
builddirectory:mkdir -p build && cd build
- Run CMake and compile using the container environment:
Alternatively, if running directly on a cluster compute node or inside an interactive container shell:
apptainer exec ../dealii_paraview.sif cmake .. apptainer exec ../dealii_paraview.sif make
cmake .. make
The compiled simulation binary is located at build/exercise-01. You can execute it with MPI inside the container using the following pattern:
mpirun -n <num_procs> apptainer exec dealii_paraview.sif ./build/exercise-01 [options]The executable supports the following parameters:
-
Help Options:
-
-h, --help: Show help message and exit.
-
-
Model Configuration:
-
-m, --model <name>: Set the ionic model name (e.g.EPI,ENDO,M,PB,TNNP). Defaults to the value specified in default settings.
-
-
Output Configuration:
-
-o, --output <file>: Set the output path/filename prefix (e.g., outputs VTU/PVTU files).
-
-
Linear Solver Options:
-
-s, --solver <name>: Set the solver type (cg,gmres,direct). -
-p, --preconditioner <name>: Set the preconditioner type (jacobi,ilu,ssor). -
--max_iter <val>: Set maximum steps for the iterative solver. -
--tol <val>: Set absolute tolerance for the iterative solver. -
--reduce <val>: Set reduction factor for the iterative solver. -
--ilu_fill <val>: Set the fill-in level for the ILU preconditioner. -
--ssor_omega <val>: Set the relaxation parameter$\omega$ for the SSOR preconditioner.
-
-
Discretization & Grid Options:
-
--delta_t <val>: Set the time step size$\Delta t$ in milliseconds. -
--max_time <val>: Set the maximum simulation duration in milliseconds. -
--mesh_size <val>: Set the mesh size$h$ in millimeters.
-
-
Time Discretization Scheme:
-
--theta <val>: Set a custom$\theta$ parameter for the general theta-method. -
--explicit_euler: Set$\theta = 0.0$ (Explicit Euler). -
--implicit_euler: Set$\theta = 1.0$ (Implicit Euler). -
--crank_nicolson: Set$\theta = 0.5$ (Crank-Nicolson).
-
The scripts/ directory contains automated test suites to analyze numerical performance, convergence, scaling, and models comparison.
Note
These automation and plotting scripts were generated using Large Language Models (LLMs) in order to speed up the writing, testing, and graph-rendering pipelines.
- run.sh:
- Default behavior: Builds the Apptainer container (
dealii_paraview.sif) if not present, compiles theexercise-01program, and runs the sweep scripts. - With
--initflag: Builds the Apptainer container (dealii_paraview.sif) and compiles theexercise-01program, but skips launching the sweep scripts. - Usage:
./scripts/run.sh(or./scripts/run.sh --initfor initialization and compilation only).
- Default behavior: Builds the Apptainer container (
- solver_sweep.sh:
- Sweeps across different solver configurations and preconditioners.
- Runs each configuration
10times to compute mean execution times and average solver iterations. - Uses PBS job chaining to schedule plot_performance.py upon completion, rendering horizontal bar charts with standard deviation error bars.
- cpu_sweep.sh:
- Analyzes strong scaling across different MPI core counts (e.g.
1,2,4,8,16,32,58). - Runs each setup
10times and schedules plot_scaling.py as a dependent post-run job. - Outputs line plots with standard deviation error bars showing execution times and average iterations.
- Analyzes strong scaling across different MPI core counts (e.g.
-
model_sweep.sh:
- Sweeps through available cardiac cell models (e.g.
EPI,ENDO,M,PB,TNNP). - Triggers plot_model_activation.py which extracts 1D activation profiles along the line
(0,0,0) -> (20,7,3)(saving full, zoomed$x < 1.0$ , and combined inset plots), renders natively square$1000\times1000$ activation map clips, and outputs a standalone colorbar legend.
- Sweeps through available cardiac cell models (e.g.
-
convergence_sweep.sh:
- Sweeps combinations of mesh size
$h$ and time step size$\Delta t$ . - Executes plot_convergence_3d.py utilizing pure
vtkmodulesXML readers (preventing graphics host-side loading errors) to produce a 3D surface plot of activation times.
- Sweeps combinations of mesh size
-
euler_comparison.sh:
- Compares Explicit Euler, Crank-Nicolson, and Implicit Euler schemes.
- Schedules plot_euler_comparison.py to plot 1D activation profiles along the line
(0,0,0) -> (20,7,3)with a zoomed inset ($x \ge 20.5$ ) in the bottom-right corner.