Julia interface

The PVFMM Julia package (in julia/) wraps the C interface using Libdl; its API mirrors the Python bindings.

Installation and setup

Build the PVFMM library first. The package locates libpvfmm from:

  1. ENV["PVFMM"] — either the direct library path or a directory containing libpvfmm.{so,dylib,dll};

  2. the system library search path (Libdl.find_library).

ENV["PVFMM"] = "/path/to/dir-containing-libpvfmm"
using PVFMM

Precision is selected with the type parameter/keyword (Float64 default, Float32). Array arguments are Vector{T} in [x1 y1 z1 x2 y2 z2 ...] (array-of-structures) layout. Communicators may be passed as an Integer (Fortran-style handle), a Ptr{Cvoid}, or any object with a val field of one of those types (which covers MPI.Comm from MPI.jl). Contexts and trees are freed by GC finalizers.

Exported names: FMMKernel, FMMBoundaryType, FMMVolumeContext, FMMParticleContext, FMMVolumeTree, nodes_to_coeff, from_function, from_coefficients, evaluate, leaf_count, get_leaf_coordinates, get_coefficients, get_values.

FMMKernel

@enum FMMKernel begin
    LaplacePotential    = 0
    LaplaceGradient     = 1
    StokesPressure      = 2
    StokesVelocity      = 3
    StokesVelocityGrad  = 4
    BiotSavartPotential = 5
end

Source/target dimensions per kernel are listed in Kernel functions.

FMMBoundaryType

@enum FMMBoundaryType begin
    FreeSpace = 0
    PXYZ = 1
    PX = 2
    PXY = 3
end
const Periodic = PXYZ  # alias

Mirrors the C PVFMMBoundaryType enum (Boundary conditions); periodic arguments also still accept a plain Bool.

Particle FMM

FMMParticleContext(box_size, max_points, multipole_order, kernel, comm=nothing;
                   T=Float64, boundary=nothing)

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); multipole_order must be positive and even. comm may be an MPI communicator (e.g. MPI.COMM_WORLD from MPI.jl); if omitted, the context runs on the world communicator obtained from the library itself (via PVFMMGetCommWorld), so MPI.jl is not required for single- or multi-rank runs launched with mpirun. Passing boundary=PVFMM.PX (etc.) selects the boundary conditions explicitly; with boundary === nothing the sign of box_size decides (> 0 fully periodic, otherwise free space).

evaluate(ctx::FMMParticleContext{T}, src_pos, sl_den, dl_den, trg_pos; setup=true)

Evaluates the potential at the target points. 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 vector has trg_dim values per target; either density may be nothing. Pass setup=true whenever source or target positions changed.

Volume FMM

FMMVolumeContext(multipole_order, chebyshev_degree, kernel, comm; T=Float64)

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

from_function(FMMVolumeTree{T}, cheb_deg, data_dim, fn_ptr::Ptr{Cvoid},
              fn_ctx::Ptr{Cvoid}, trg_coord, comm, tol, max_pts,
              periodic::Bool, init_depth)

Builds an adaptively refined Chebyshev tree from a source-density callback. fn_ptr is a C function pointer with signature void fn(const T* coord, long n, T* out, const void* ctx) (e.g. from @cfunction); fn_ctx is passed through as ctx.

from_coefficients(FMMVolumeTree{T}, cheb_deg, data_dim, leaf_coord, fn_coeff,
                  trg_coord, comm, periodic::Bool)

Builds the tree from leaf-node coordinates and Chebyshev coefficients; trg_coord may be nothing.

evaluate(tree::FMMVolumeTree{T}, fmm::FMMVolumeContext{T}, loc_size)

Runs the volume FMM; returns the potential at the target points (n_trg * trg_dim values).

leaf_count(tree)             # number of leaf nodes
get_leaf_coordinates(tree)   # leaf corners, 3 per leaf
get_coefficients(tree)       # Chebyshev coefficients of the potential
get_values(tree)             # potential on tensor-product Chebyshev nodes
nodes_to_coeff(N_leaf, cheb_deg, dof, node_val)  # node values -> coefficients

get_coefficients/get_values require a prior evaluate call.

Tests as examples

julia/test/reference_comparison.jl validates the particle FMM against direct O(N²) sums for the Laplace potential/gradient and Stokes velocity/pressure kernels — a good starting point for usage patterns.