1. Kernel methods

Every basis function is a translate of the same radial kernel, centred on one sampled point \(x_j\):

\(\varphi_j(x) = k(x, x_j)\)

and the approximation is the linear combination \(u_h(x) = \sum_j c_j\, \varphi_j(x)\). The linear system is dense (every point sees every other), but for a modest number of points this is often the fastest way to a very accurate answer, with nothing to train beyond the coefficients \(c_j\). A few of the kernels available, with \(r = \lVert x - x_j \rVert\):

\(k_{\text{Gaussian}}(x, x_j) = \exp\!\left(-\dfrac{r^2}{2\sigma^2}\right)\)

\(k_{\text{Matérn-3/2}}(x, x_j) = \left(1 + \dfrac{\sqrt{3}\,r}{\sigma}\right)\exp\!\left(-\dfrac{\sqrt{3}\,r}{\sigma}\right)\)

\(k_{\text{Matérn-5/2}}(x, x_j) = \left(1 + \dfrac{\sqrt{5}\,r}{\sigma} + \dfrac{5 r^2}{3\sigma^2}\right)\exp\!\left(-\dfrac{\sqrt{5}\,r}{\sigma}\right)\)

The Matérn family trades the Gaussian's infinite smoothness for a fixed, finite one — useful when the solution itself is not perfectly smooth. A fifth option, FundamentalSolutionKernel, is not a shape choice at all: it plugs in the PDE's own Green's function (\(\log r\) in 2D for the Laplacian), so the basis already solves the equation away from its center.

from scimba_jax.linear_approximation.basis.kernel_basis import KernelBasis
from scimba_jax.linear_approximation.basis.kernel_function import GaussianKernel
from scimba_jax.linear_approximation.collocation.collocation_elliptic import (
    EllipticCollocationScheme,
)
from scimba_jax.linear_approximation.variables.collocation_variables import (
    CollocationVariables,
)

# No mesh, no cells: ONE basis function per sampled point -- the centers
# ARE the collocation points, and the PDE is enforced AT those same points.
basis = KernelBasis(
    dim=2,
    output_dim=1,
    kernel_function=GaussianKernel(sigma=0.5),
    centers=interior_points,       # (n_points, 2), drawn by a DomainSampler
    learnable_center_bool=False,   # frozen: only the linear weights are fit
    basis_type="scalar",
)
variables = CollocationVariables(basis=basis, nb_variables=1)
scheme = EllipticCollocationScheme(
    pde=pde,
    variables=variables,
    collocation_points=interior_points,
    bc_collocation_points=boundary_points,
)
scheme = EllipticCollocationScheme.solve(scheme)
# 600 interior + 80 boundary points, sigma=0.5: 3.0e-06 relative L2 error
# against sin(pi x) sin(pi y) on the unit square.

# Swapping GaussianKernel for another kernel_function is the whole change --
# same basis, same scheme. At the same pair of points 0.5 apart:
#   GaussianKernel(sigma=0.5)            -> 0.6065
#   Matern32Kernel(sigma=0.5)            -> 0.4834
#   Matern52Kernel(sigma=0.5)            -> 0.5240
#   ExponentialKernel(sigma=0.5)         -> 0.3679  (C0 only, sharp at r=0)
#   FundamentalSolutionKernel(dim=2)     -> -0.1103 (the Laplacian's own
#                                           Green's function, log(r)/2pi)

2. Random features

Same collocation scheme, a nonlinear basis instead of a radial one:

\(\varphi_j(x) = \tanh\!\left(\dfrac{W_j \cdot (x - x_j)}{s} + b_j\right)\)

with \((W_j, b_j)\) drawn from a fixed random distribution once and never touched again — the extreme-learning-machine convention. Only the downstream coefficients \(c_j\) are fit, exactly as for a kernel.

from scimba_jax.linear_approximation.basis.random_network_basis import (
    RandomFeaturesBasis,
)

# Same collocation scheme, a nonlinear basis instead: (W_j, b_j) drawn ONCE
# and frozen -- the extreme-learning-machine convention.
basis = RandomFeaturesBasis(
    dim=2,
    output_dim=1,
    centers=interior_points,
    scale=0.5,
    activation="tanh",
    learnable_center_bool=False,    # the defaults -- frozen is the point
    learnable_features_bool=False,  # of a RANDOM feature
)
variables = CollocationVariables(basis=basis, nb_variables=1)
scheme = EllipticCollocationScheme(
    pde=pde, variables=variables,
    collocation_points=interior_points, bc_collocation_points=boundary_points,
)
scheme = EllipticCollocationScheme.solve(scheme)
# Same problem as above: 1.4e-08 relative L2 error -- a random nonlinear
# feature can outperform a fixed kernel shape, at the cost of a PRNG key to
# keep track of.

3. Localized random features (RFM)

The Random Feature Method wraps each patch's random features in a smooth window that vanishes outside it, so the assembled system is sparse the way a mesh-based one is — without a mesh. It is the bridge between a purely meshless method and the locality a finite element or finite volume scheme gets for free.

from scimba_jax.linear_approximation.basis.random_network_basis import (
    RandomFeaturePOUBasis,
)

# Random Feature Method (Chen, Chi, E & Yang, 2022): features LOCALISED to
# a patch by a partition-of-unity window instead of the whole domain --
# sparse the way a mesh-based basis is, without building a mesh.
basis = RandomFeaturePOUBasis(
    dim=2,
    output_dim=1,
    centers=patch_centers,       # (n_patches, 2)
    radii=0.6,                   # shared, or (n_patches, 2) for anisotropic patches
    n_features_per_patch=8,
    activation="tanh",
)

Every basis on this page is frozen by construction — centers and shapes are drawn once, not learned. Letting them move under gradient descent instead turns the same basis into a small neural network, which is the territory of PINNs rather than this page.