Skip to main content

TorchCor logo

GPU-accelerated cardiac electrophysiology simulation in PyTorch

Documentation

TorchCor is a high-performance simulator for cardiac electrophysiology (CEP) using the finite element method (FEM) on general-purpose GPUs. Built on top of PyTorch, TorchCor delivers substantial computational acceleration for large-scale CEP simulations, with seamless integration into modern deep learning workflows and efficient handling of complex mesh geometries.

TorchCor offers:

  • 🚀 Fast, scalable CEP simulations on large and complex heart meshes
  • 🔗 Seamless integration with PyTorch and scientific machine learning workflows
  • ⚙️ Support for a wide range of ionic models and conductivity heterogeneity
  • 📈 Generation of precise local activation and repolarization time maps with monodomain or reaction-eikonal
  • 🩺 Simulation of clinically relevant 12-lead ECG signals via the lead-field method

🫀 Simulation Previews

Below are simulation results showcasing the electrical activation patterns over time in the left atrium and bi-ventricle.

Left Atrium simulation
3D left atrium surface mesh
Bi-ventricle simulation
3D bi-ventricle volume mesh

📦 Installation

pip install torchcor

Note: Requires PyTorch with CUDA support for GPU acceleration.

🚀 Quickstart Example

Here’s a concise example to run a simulation using the TenTusscher-Panfilov ionic model on a bi-ventricle mesh.

🧩 Mesh file:
You can download the bi-ventricle mesh from the following link:
Google Drive – Bi-ventricle Mesh

The inputs are:

  • .pts file: coordinates of the vertices
  • .elem file: connectivities of the mesh
  • .lon file: fibre orientations
  • One or more .vtx files: pacing locations

Running the following code will produce:

  • a list of membrane potentials, each saved after every 1 ms of the simulation
  • a local activation time map and a repolarisation time map

all saved in .pt file format readable by torch.load. This execution takes 47.6 seconds on RTX 5090.

import torchcor as tc
from torchcor.simulator import Monodomain
from torchcor.ionic import TenTusscherPanfilov
from pathlib import Path

# Specify the GPU device for running the simulation
tc.set_device("cuda:0")
dtype = tc.float32
# The total simulation duration (ms)
simulation_time = 500
dt = 0.01

home_dir = Path.home()
mesh_dir = home_dir / "Data/ventricle/Case_1"
# Load in the ionic model. Here we use TenTusscherPanfilov for the simulation on bi-ventricle
im = TenTusscherPanfilov(cell_type="ENDO", dt=dt, dtype=dtype)
# 1. Initialise the Monodomain model
simulator = Monodomain(ionic_models=[im], T=simulation_time, dt=dt, dtype=dtype)
# 2. Load in the mesh files (.pts .elem .lon)
simulator.load_mesh(path=mesh_dir)
# 3. Specify the conductivity for each region
simulator.add_conductivity([34, 35], il=0.5272, it=0.2076, el=1.0732, et=0.4227)
simulator.add_conductivity([44, 45, 46], il=0.9074, it=0.3332, el=0.9074, et=0.3332)
# 4. Specify the locations where stimulation is applied
simulator.add_stimulus(mesh_dir / "LV_sf.vtx", start=0.0, duration=1.0, intensity=100)
simulator.add_stimulus(mesh_dir / "LV_pf.vtx", start=0.0, duration=1.0, intensity=100)
simulator.add_stimulus(mesh_dir / "LV_af.vtx", start=0.0, duration=1.0, intensity=100)
simulator.add_stimulus(mesh_dir / "RV_sf.vtx", start=5.0, duration=1.0, intensity=100)
simulator.add_stimulus(mesh_dir / "RV_mod.vtx", start=5.0, duration=1.0, intensity=100)

# 5. Start the simulation
snapshot_interval = 1
Vm = simulator.solve(a_tol=1e-5,              # absolute tolerance
                     r_tol=1e-5,              # relative tolerance
                     max_iter=100,            # maximum number of iterations for each CG calculation
                     snapshot_interval=snapshot_interval,     # save the solution after every 1 ms
                     verbose=True,
                     result_path="./biventricle")  # the folder in which the results are saved

# POSTPROCESSING: 
ATs = simulator.compute_activation_map(Vm=Vm, 
                                       snapshot_interval=snapshot_interval, 
                                       threshold=0)
print("ATs: ", ATs.min().item(), ATs.cpu().max().item(), flush=True)
RTs = simulator.compute_repolarization_map(Vm=Vm, 
                                           snapshot_interval=snapshot_interval, 
                                           threshold=-70)
print("RTs: ", RTs.min().item(), RTs.cpu().max().item(), flush=True)

simulator.vm_to_vtk(Vm=Vm, step=10)

🩺 12-Lead ECG via the Lead-Field Method

TorchCor reconstructs the clinical 12-lead ECG directly from a cardiac simulation using the lead-field (reciprocity) method on a coupled heart–torso mesh. Each electrode's lead field is precomputed with a single elliptic solve; the entire ECG time series then follows from one matrix–vector product with the transmembrane potential Vm, so evaluating the ECG over a whole beat is effectively free.

TorchCor simulated 12-lead ECG
Simulated 12-lead ECG from a full heart–torso model, reconstructed with the lead-field reciprocity method.

import torch
from torchcor.ecg import LeadField

# Coupled heart–torso mesh; precompute one lead field per electrode
lf = LeadField(torso_mesh_dir, heart_mesh_dir,
               device=torch.device("cuda:0"), dtype=torch.float64)

# Passive torso/organ conductivities (S/m) + anisotropic bidomain heart conductivities
lf.add_torso_conductivity([10, 11, 12], g=0.6667)
lf.add_heart_conductivity([24, 25], il=0.5272, it=0.2076, el=1.0732, et=0.4227)
lf.build()

# Electrodes (V1–V6, RA, LA, RL, LL); one elliptic solve per lead
lf.load_electrodes("electrodes/lf_src.vtx")
lf.precompute_all()

# Vm: (T, N_heart) from the EP simulation  ->  dict of the 12 standard leads
ecg = lf.compute_12lead(Vm)

A complete heart → torso → 12-lead pipeline is provided in torchcor/demo/ecg_12lead.py.

🐳 Docker Support

For a GPU-enabled Docker setup to run TorchCor without installing dependencies on your host system, please see the docker/ folder.

📖 Citation

If you use TorchCor in academic work, please consider citing:

@article{zhou2026torchcor,
  title={TorchCor: High-performance cardiac electrophysiology simulations with the finite element method on GPUs},
  author={Zhou, Bei and Balmus, Maximilian and Corrado, Cesare and Cicci, Ludovica and Qian, Shuang and Niederer, Steven A},
  journal={SoftwareX},
  volume={33},
  pages={102521},
  year={2026},
  publisher={Elsevier}
}

👩‍💻 Contributors

TorchCor is developed and maintained by Bei Zhou, Maximilian Balmus, Cesare Corrado, Shuang Qian, and Steven A. Niederer​ in the Cardiac Electro-Mechanics Research Group (CEMRG) at Imperial College London.

We welcome contributions from the community! Feel free to open issues or submit pull requests.

Metadata

Release files for torchcor 1.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for torchcor 1.0.4
File Size Uploaded
torchcor-1.0.4.tar.gz 186.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for torchcor 1.0.4
File Interpreter ABI Platform
torchcor-1.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 394.0 kB

Release files / torchcor-1.0.4.tar.gz

Download URL torchcor-1.0.4.tar.gz
Size 186.5 kB
Tags Source
SHA-256 checksum
How to use checksums
5c10fedf761ebeb0f538df6bcf53a5e3e7f88817acb711e85f14dfc5e51ad35d
BLAKE2b-256 checksum
How to use checksums
826ea0a6f1c7e08fdfe4e28aa47ac3b4d24da0dfbb072662b6336c3bde35ded7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.6

Release files / torchcor-1.0.4-py3-none-any.whl

Download URL torchcor-1.0.4-py3-none-any.whl
Size 207.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6c55b26f9e608bef7d4ad5fa857c73341b67f46c6666512db8fd3fded206e093
BLAKE2b-256 checksum
How to use checksums
5598256e1fae7e0df7e30a18ff83bc140aa75bdaafd1203ad91af0007978fdd4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.6

Release history Release notifications | RSS feed

1.0.6

2 release files

1.0.5

2 release files

This release

1.0.4 This release

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page