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:
ENV["PVFMM"]— either the direct library path or a directory containinglibpvfmm.{so,dylib,dll};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.