lpFun


Python package for fast multivariate polynomial interpolation in $\ell^p$-type polynomial spaces.

GitHub Repository Cite this repo arXiv Code style: black License

Contents

Installation

Install the package directly from GitHub using pip:

pip install git+https://github.com/phil-hofmann/lpfun.git

If you do not have pip installed, follow the official installation instructions: https://pip.pypa.io/en/stable/installation/.

Optional environment setup references:

Quick start

import numpy as np
from lpfun import Function

def f(x, y):
    return np.sin(x) * np.cos(y)

# Initialize the function space
fun = Function(
    spatial_dimension=2,
    polynomial_degree=10,
)

# Sample the function on the interpolation grid
values = f(fun.grid[:, 0], fun.grid[:, 1])

# Compute polynomial coefficients
coeffs = fun.interp(values)

# Reconstruct values on the interpolation grid
values_rec = fun.eval(coeffs)

# Differentiate with respect to the first coordinate
coeffs_dx = fun.diff(coeffs, dim=0, order=1)

# Evaluate the derivative on the interpolation grid
values_dx = fun.eval(coeffs_dx)

Detailed example

The Function class provides fast interpolation, evaluation, differentiation, and embedding between polynomial spaces.

import time
import numpy as np

from lpfun import Function
from lpfun.basis.nodes import leja_nodes

# Initialize function space
fun = Function(
    spatial_dimension=3,
    polynomial_degree=20,
    nodes=leja_nodes,  # default nodes are cheb2nd_nodes
)

print(f"Dimension of the polynomial space = {len(fun)}")

def f(x, y, z):
    return np.sin(x) + np.cos(y) + np.exp(z)

# Sample function on the interpolation grid
values = f(fun.grid[:, 0], fun.grid[:, 1], fun.grid[:, 2])

# Interpolate
start = time.time()
coeffs = fun.interp(values)
print("fun.interp:", "{:.2f}".format((time.time() - start) * 1000), "ms")

# Reconstruct values on the interpolation grid
start = time.time()
values_rec = fun.eval(coeffs)
print("fun.eval:", "{:.2f}".format((time.time() - start) * 1000), "ms")

print(
    "max |values_rec - values| =",
    "{:.2e}".format(np.max(np.abs(values_rec - values))),
)

# Compute exact derivative with respect to z
def df_dz(x, y, z):
    return np.exp(z)

values_dz = df_dz(fun.grid[:, 0], fun.grid[:, 1], fun.grid[:, 2])

# Differentiate polynomial coefficients
start = time.time()
coeffs_dz = fun.diff(coeffs, dim=2, order=1)
print("fun.diff:", "{:.2f}".format((time.time() - start) * 1000), "ms")

# Reconstruct derivative values on the interpolation grid
values_dz_rec = fun.eval(coeffs_dz)

print(
    "max |values_dz_rec - values_dz| =",
    "{:.2e}".format(np.max(np.abs(values_dz_rec - values_dz))),
)

# Embed coefficients into a larger polynomial space
fun_larger = Function(
    spatial_dimension=3,
    polynomial_degree=30,
    nodes=leja_nodes,
    report=False,
)

embed_idx = fun.embed(fun_larger)

coeffs_larger = np.zeros(len(fun_larger))
coeffs_larger[embed_idx] = coeffs

When you run this code, you should see output similar to:

---------------------+---------------------
                   Report
---------------------+---------------------
Spatial Dimension    | 3
Polynomial Degree    | 20
lp Degree            | 2.0
Condition V          | 1.44e+06
Amount of Coeffs     | 4_662
Construction         | 300.25 ms
Precompilation       | 19.80 ms
---------------------+---------------------

Dimension of the polynomial space = 4662
fun.interp: 0.55 ms
fun.eval: 0.53 ms
max |values_rec - values| = 8.88e-15
fun.diff: 0.19 ms
max |values_dz_rec - values_dz| = 5.80e-13

API overview

The central object in lpFun is the Function class. It represents a multivariate polynomial function space on a quasi-tensorial interpolation grid and provides methods for interpolation, evaluation, differentiation, and embedding.

Construction

from lpfun import Function

fun = Function(
    spatial_dimension=2,
    polynomial_degree=10,
    lp_degree=2.0,
)

Main methods

Task Method Description
Interpolate grid values fun.interp(function_values) Computes polynomial coefficients from values sampled on fun.grid.
Evaluate on the interpolation grid fun.eval(coefficients) Reconstructs function values on the interpolation grid from coefficients.
Evaluate at arbitrary points fun(coefficients, points) Evaluates the polynomial interpolant at user-specified points.
Differentiate fun.diff(coefficients, dim, order) Computes coefficients of a partial derivative.
Apply transposed derivative fun.diffT(coefficients, dim, order) Applies the transpose of a partial differentiation operator.
Embed into a larger space fun.embed(larger_fun) Returns indices for embedding coefficients into a larger compatible function space.

Attributes

Attribute Type Description
fun.spatial_dimension int Spatial dimension m, i.e. the number of input variables.
fun.polynomial_degree int Maximum polynomial $\ell^p$ degree n.
fun.lp_degree float Degree p of the l^p polynomial index set.
fun.tube numpy.ndarray Directional polynomial degree constraints.
fun.index_set numpy.ndarray Index set defining the polynomial exponents.
fun.nodes numpy.ndarray One-dimensional interpolation nodes.
fun.grid numpy.ndarray Interpolation grid with shape (fun.size, fun.spatial_dimension).
fun.leja_order numpy.ndarray Leja ordering used to order the interpolation nodes.

Special methods

Expression Description
len(fun) Returns the dimension of the polynomial space, i.e. the number of coefficients.
fun == other Checks whether two Function objects describe the same polynomial space.
repr(fun) Returns a formatted setup report with dimension, polynomial degree, condition number, number of coefficients, and setup times.

Citation

Download BibTeX

If you use lpFun in any public context, including publications, presentations, or derivative software, please cite both the accompanying paper and the software.

Accompanying paper

Phil-Alexander Hofmann, Michael Hecht, Accelerating Multivariate Newton Interpolation in Downward Closed Polynomial Spaces, arXiv:2505.14909 [math.NA], 2026. https://doi.org/10.48550/arXiv.2505.14909

Software

Phil Hofmann. (2026). lpFun. GitHub. https://github.com/phil-hofmann/lpFun

Troubleshooting

If you encounter segmentation faults, they are most likely caused by stale numba cache files. This can happen when source code changes invalidate previously compiled cache files.

Option 1: Clear numba cache files

find src -name "*.nbi" -o -name "*.nbc" | xargs rm -f

Option 2: Disable caching during development

import lpfun

lpfun.CACHE = False

Set this before importing any other lpfun modules.

Team and Support

License

The project is licensed under the MIT License.

Acknowledgments

We deeply acknowledge:

and the support and resources provided by the Center for Advanced Systems Understanding (Helmholtz-Zentrum Dresden-Rossendorf), where the development of this project took place.