Python interface

The pvfmm Python package (in python/) wraps the C interface using ctypes, numpy, and mpi4py.

Installation and setup

Build and install the PVFMM library first, then:

cd python && pip install .

If libpvfmm.so is not on the system library search path, point the PVFMM environment variable at the directory containing it (e.g. the CMake build/ directory or the install prefix’s lib/pvfmm).

mpi4py is optional and imported only when you pass an explicit communicator. For a single process, or to let the library use MPI_COMM_WORLD, omit the communicator (comm=None) and no mpi4py install is required. To drive several ranks, pass an mpi4py communicator and launch through it so that MPI_Init/MPI_Finalize are handled correctly:

export PVFMM=/path/to/dir-containing-libpvfmm
mpirun -n 2 python -m mpi4py your_program.py

The comm-less default is available for FMMParticleContext; the volume constructors require an explicit mpi4py communicator.

Precision is selected per object with the dtype argument (numpy.float64, the default, or numpy.float32); all array arguments must be 1-D contiguous NumPy arrays of that dtype in [x1 y1 z1 x2 y2 z2 ...] (array-of-structures) layout.

Note

The classes below have no docstrings yet; this page is the reference. Signatures correspond to python/src/pvfmm/wrapper.py.

FMMKernel

class FMMKernel(Enum):
    LaplacePotential    = 0
    LaplaceGradient     = 1
    StokesPressure      = 2
    StokesVelocity      = 3
    StokesVelocityGrad  = 4
    BiotSavartPotential = 5

Mirrors the C PVFMMKernel enum. Source/target dimensions per kernel are listed in Kernel functions.

FMMBoundaryType

class FMMBoundaryType(Enum):
    FreeSpace = 0
    PXYZ      = 1
    PX        = 2
    PXY       = 3
    Periodic  = 1   # alias for PXYZ

Mirrors the C PVFMMBoundaryType enum (Boundary conditions); functions taking a periodic argument also still accept a plain bool (False/True = free space / fully periodic).

Particle FMM

class FMMParticleContext(box_size, max_points, multipole_order, kernel,
                         comm=None, dtype=np.float64, boundary=None)

Creates a particle-FMM context (PVFMMCreateContext*). box_size is the domain length and the period along the periodic directions (<= 0 allowed only for free space); max_points is the maximum number of points per leaf node; multipole_order must be positive and even. comm may be an mpi4py communicator; if omitted (None) the context uses the world communicator obtained from the library itself (PVFMMGetCommWorld), so mpi4py is not required for single- or multi-rank runs launched with mpirun. Passing boundary=FMMBoundaryType.PX (etc.) selects the boundary conditions explicitly; with boundary=None the sign of box_size decides (> 0 fully periodic, otherwise free space). The underlying context is freed when the object is garbage-collected.

FMMParticleContext.evaluate(src_pos, sl_den, dl_den, trg_pos, setup=True) -> np.ndarray

Evaluates the potential at the target points (PVFMMEval*). With (src_dim, trg_dim) the kernel dimensions from Kernel functions: sl_den (single-layer density) has src_dim values per source, dl_den (double-layer density + normal) has src_dim + 3 values per source, and the returned array has trg_dim values per target; either density may be None. Pass setup=True whenever source or target positions changed since the last call; setup=False re-uses the tree when only densities changed.

Volume FMM

class FMMVolumeContext(multipole_order, chebyshev_degree, kernel, comm, dtype=np.float64)

Builds (or loads from cache — see Precomputed operator files) the volume-FMM translation operators (PVFMMCreateVolumeFMM*).

FMMVolumeTree.from_function(cheb_deg, data_dim, fn, context, trg_coord, comm,
                            tol, max_pts, periodic, init_depth) -> FMMVolumeTree

Builds an adaptively refined Chebyshev tree from a source-density callback (PVFMMCreateVolumeTree*). fn must be a ctypes function pointer with C signature void fn(const double* coord, long n, double* out, const void* ctx) (use pvfmm.ffi.double_volume_callback / float_volume_callback, e.g. via numba.cfunc as in python/examples/example2.py); context is passed through to the callback as ctx.

FMMVolumeTree.from_coefficients(cheb_deg, data_dim, leaf_coord, fn_coeff,
                                trg_coord, comm, periodic) -> FMMVolumeTree

Builds the tree from given leaf-node coordinates and Chebyshev coefficients (PVFMMCreateVolumeTreeFromCoeff*); fn_coeff must have length N_leaf * data_dim * (cheb_deg+1)(cheb_deg+2)(cheb_deg+3)/6. trg_coord may be None. In both constructors periodic accepts a bool or an FMMBoundaryType.

FMMVolumeTree.evaluate(fmm: FMMVolumeContext, loc_size: int) -> np.ndarray

Runs the volume FMM and returns the potential at the target points, an array of length n_trg * trg_dim for the context’s kernel.

FMMVolumeTree.leaf_count() -> int                 # number of leaf nodes
FMMVolumeTree.get_leaf_coordinates() -> np.ndarray  # leaf corners, 3 per leaf
FMMVolumeTree.get_coefficients() -> np.ndarray    # Chebyshev coeffs of the potential
FMMVolumeTree.get_values() -> np.ndarray          # potential on Chebyshev nodes

get_coefficients/get_values require that evaluate has been called (they raise ValueError otherwise).

pvfmm.nodes_to_coeff(N_leaf, cheb_deg, dof, node_val) -> np.ndarray

Converts function values on tensor-product Chebyshev nodes (first kind) to Chebyshev coefficients (PVFMMNodes2Coeff*) — the usual way to prepare fn_coeff for from_coefficients.

Examples

  • python/examples/example1.py — particle FMM (Biot–Savart), timed against a direct O(N²) sum compiled with numba.

  • python/examples/example2.py — volume FMM (Stokes velocity), building the tree both from a numba.cfunc callback and from Chebyshev coefficients.