Born from solving PDEs: fastlsq fits a random-Fourier surrogate of your field in one least-squares call. You get the field and every derivative, ∂t, ∇, Δ, analytically, at any query point. A real digital twin you can drop into an optimiser, a Kalman filter, an inverse problem, or a control loop.
The unknown solution is expanded in a fixed basis of random sinusoids: φⱼ(x) = sin(Wⱼ·x + bⱼ), with Wⱼ and bⱼ sampled once and never updated.
Averaging enough random Fourier features recovers the Gaussian RBF kernel (Bochner). Smooth solutions live in that RKHS, so a few hundred sinusoids cover the space.
Find β by a single least-squares call. Scalar or vector-valued targets: components stack into the same block-LSQ, one solve.
We fit β once against the target below. After that the twin is a closed-form function: differentiating it just multiplies each coefficient by Wⱼᵏ and shifts the phase by k·π⁄2. No re-solve, no finite differences, no autodiff graph. Step through the orders, the analytic curve (solid) lands exactly on the true derivative (dashed) every time.
import numpy as np import fastlsq as fl from fastlsq.basis import SinusoidalBasis, Op # Helmholtz 2D: Δu + k² u = f on [0, 1]² basis = SinusoidalBasis(d=2, N=1500, sigma=10.0) L = Op.laplacian(d=2) + (10.0**2) * Op.identity(d=2) u, info = fl.solve( L = L, f = lambda x: 0.0, bc = lambda x: np.sin(np.pi * x[..., 0]), domain = fl.Box(d=2), basis = basis, ) print(info.l2_error) # 1.9e-6 print(info.wall_clock) # 0.08 s
Four hidden heaters warm a square plate. Four sensors, one per quadrant, record a temperature time-series as the heat diffuses outward. From only those 4 × 60 = 240 numbers, recover where the heaters are — and their shape and strength: 24 unknown source parameters.
The forward model is the full space–time heat equation. Every step of the search needs a complete PDE solve, normally far too expensive to drop inside an optimiser that runs it a thousand times.
fastlsq fits the field in a sinusoidal random-Fourier basis whose ∂t and ∇² are closed-form. The (PDE + BC + IC) least-squares operator is assembled and Cholesky-factored once; each forward solve is then a single back-substitution, and the loss gradient over all 24 parameters rides back through the same factor in one adjoint solve.
A drone must cross a radar interference field corner to corner without the intensity it senses ever tripping a detector. It has no map — only a tiny five-point cross of field samples around its current position, streaming in as it moves.
From that trickle it refits a FastLSQ surrogate of the field every few steps — one Tikhonov least-squares solve, about 8 ms — then reads the surrogate's analytic gradient to surf the low-intensity corridors between the bright fringes toward the goal.
This is FastLSQ as a differentiable digital twin inside a control loop: cheap enough to re-solve hundreds of times per episode, exact-gradient enough to steer on. The twin is trustworthy only where the drone has sensed — so the right panel paints in along the path and fades elsewhere.
Full method, proofs, ablations, and 17-PDE benchmark are described in Sulc, A. FastLSQ: Solving PDEs in One Shot via Fourier Features with Exact Analytical Derivatives, arXiv:2602.10541.
Code, examples, and the inverse-problem demos are available in the reference implementation on GitHub.
@misc{sulc2026solvingpdesshotfourier,
title = {FastLSQ: Solving PDEs in One Shot
via Fourier Features with
Exact Analytical Derivatives},
author = {Antonin Sulc},
year = {2026},
eprint = {2602.10541},
archivePrefix = {arXiv},
primaryClass = {math.NA},
url = {https://github.com/sulcantonin/FastLSQ},
}