What is ParkiPy?¶
The (Par)ticle (K)ernel (I)nteractions library for (Py)thon provides performance-portable, parallel APIs on both CPUs and GPUs. ParkiPy leverages Kokkos [1] through its Python framework PyKokkos [2] to expose high-performance kernels behind a clean, NumPy-style interface.
ParkiPy is designed for simulations that require fast evaluation of pairwise particle interactions—particularly problems in computational fluid dynamics and potential theory that involve large numbers of particles under periodic boundary conditions.
Key Features¶
Ewald summation for the Stokes and Laplace kernels in 1- and 3-periodic domains via the
parkipy.ewaldmodule.Distributed Ewald summation in slab geometries across multiple GPUs via the
parkipy.distributed.ewaldmodule.Cell list construction for efficient local particle-interaction lookups via the
parkipy.CellListclass.Seamless NumPy/CuPy support: pass
numpyarrays for CPU execution orcupyarrays for GPU execution — the API is identical.Just-in-time compiled kernels: PyKokkos kernels are compiled on first use and cached automatically, so subsequent calls incur no recompilation overhead.
Supported Kernels¶
The table below summarises which kernel and periodicity combinations are currently available.
Periodicity |
Stokes single layer |
Stokes single + double layer |
Laplace |
|---|---|---|---|
0-periodic |
✗ |
✗ |
✗ |
1-periodic |
✓ |
✓ |
✗ |
2-periodic |
✗ |
✗ |
✗ |
3-periodic |
✓ |
✓ |
✓ |
How It Works¶
ParkiPy splits the evaluation of a kernel sum into two parts following the classical Ewald decomposition:
Near-field (P2P): direct particle-to-particle interactions within a cutoff radius, evaluated using a cell list for O(N) neighbour finding.
Far-field (G2P/P2G): long-range interactions handled in Fourier space via non-uniform FFTs on a regular grid.
This decomposition enables both accuracy control (via the tolerance
parameter) and performance scaling to large particle counts on modern GPU
hardware.
Array Framework Compatibility¶
ParkiPy works with both CPU and GPU array frameworks through the same API:
import numpy as np # CPU
import cupy as cp # GPU
import parkipy
# The ewald.stokes_sl call accepts arrays from either framework.
u_cpu = parkipy.ewald.stokes_sl(x_np, y_np, f_np, options)
u_gpu = parkipy.ewald.stokes_sl(x_cp, y_cp, f_cp, options)
The execution space ("OpenMP" or "CUDA") is specified once in the
EwaldOptions object and controls which Kokkos backend
is used.