# Using the Python and Julia bindings Both bindings wrap the {doc}`C interface <../api/c>` and require the shared library `libpvfmm.so` — build it first and point the `PVFMM` environment variable at the directory containing it (see {doc}`../api/python` and {doc}`../api/julia` for installation details). ## Python: particle FMM Based on `python/examples/example1.py`. For a single process just run `python example1.py`; to use several ranks, launch with `mpirun -n 2 python -m mpi4py example1.py` and pass an `mpi4py` communicator. ```python import numpy as np import pvfmm N = 20000 src_pos = np.random.rand(3 * N) # coordinates in [0,1]^3, AoS layout src_den = np.random.rand(3 * N) - 0.5 # Biot-Savart: 3 values per source trg_pos = np.random.rand(3 * N) fmm = pvfmm.FMMParticleContext( box_size=-1, # <= 0: free space max_points=1000, # max points per leaf multipole_order=10, # accuracy (even) kernel=pvfmm.FMMKernel.BiotSavartPotential, # comm omitted: uses the world communicator from the library, so mpi4py is # not needed. Pass comm=MPI.COMM_WORLD (from mpi4py) to run across ranks. ) trg_val = fmm.evaluate(src_pos, src_den, None, trg_pos) # with setup trg_val = fmm.evaluate(src_pos, src_den, None, trg_pos, setup=False) # densities only ``` The example verifies the result against a direct sum compiled with numba. ## Python: volume FMM Based on `python/examples/example2.py` (Stokes velocity). The source density callback must be a C function pointer; `numba.cfunc` produces one without writing C: ```python import numba import pvfmm @numba.cfunc(numba.types.void( numba.types.CPointer(numba.types.double), # coord (3n) numba.types.int64, # n numba.types.CPointer(numba.types.double), # out (n * data_dim) numba.types.voidptr), nopython=True) # ctx def fn_input_C(coord_, n, out_, ctx): coord = numba.carray(coord_, n * 3) out = numba.carray(out_, n * 3) # ... evaluate the density ... fmm = pvfmm.FMMVolumeContext(multipole_order, cheb_deg, pvfmm.FMMKernel.StokesVelocity, comm) tree = pvfmm.FMMVolumeTree.from_function( cheb_deg, 3, fn_input_C.ctypes, None, trg_coord, comm, tol=1e-6, max_pts=100, periodic=False, init_depth=0) trg_val = tree.evaluate(fmm, loc_size=len(trg_coord) // 3) ``` The coefficient path mirrors the C example: prepare density values on the tensor-product Chebyshev nodes of chosen leaves, convert with `pvfmm.nodes_to_coeff`, build with `FMMVolumeTree.from_coefficients`, and read the result back with `tree.get_coefficients()` / `tree.get_values()`. ## Julia: particle FMM Based on `julia/test/reference_comparison.jl`: ```julia ENV["PVFMM"] = "/path/to/dir-containing-libpvfmm" using PVFMM N = 10000 src_pos = rand(3N); src_den = rand(3N) .- 0.5; trg_pos = rand(3N) # comm omitted: the world communicator is obtained from the library, so no # MPI.jl dependency is needed. Pass MPI.COMM_WORLD explicitly if you use MPI.jl. ctx = FMMParticleContext(-1.0, 1000, 10, PVFMM.StokesVelocity) trg_val = evaluate(ctx, src_pos, src_den, nothing, trg_pos) trg_val = evaluate(ctx, src_pos, src_den, nothing, trg_pos; setup=false) ``` Per-axis periodicity is selected with the `boundary` keyword (e.g. `boundary=PVFMM.PX` with `box_size > 0`). The volume-FMM path (`FMMVolumeContext`, `from_function` / `from_coefficients`, `evaluate`, `get_values`) follows the Python API one-to-one — see {doc}`../api/julia`.