This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

PDE solvers

Partial differential equations, solved and checked

15 equations. Each is one Viv program that solves it, draws the solution, and ends in tests against something exact: a closed-form solution, a conserved quantity, a measured order of accuracy. 57 tests in all.

The programs are short enough to read whole, and every page has the source in an editable cell: change the scheme, the time step or the initial condition and run it again.

Diffusion (parabolic)

Smoothing, irreversible, and stiff: an explicit step is limited by , so the working methods are implicit and the work is a tridiagonal solve.

Waves and transport (hyperbolic)

Information moves at a finite speed along characteristics. Nothing smooths the solution, so the scheme's own dissipation and dispersion are what you see, and shocks need conservation.

Steady states and modes (elliptic)

No time to march through: every unknown depends on every other, and the work is a large sparse linear system or its eigenvalues.

Waves whose speed depends on wavelength (dispersive)

The linear part is exact in Fourier space for any time step, so these are split-step spectral codes built on fft.

A nonlinearity against diffusion (nonlinear parabolic)

Steepening or growth on one side, diffusion on the other, and a front whose width and speed are set by the balance.

The builtins they use

A finite-difference stencil is array arithmetic on shifted copies; an implicit step is a tridiagonal solve; a spectral step is an FFT. These are the builtins the solvers use, with the descriptions from the reference.

roll(a, k) · roll(A, k, axis)
circular shift: element i moves to i + k, wrapping. A periodic stencil in one line: roll(u, 1) - 2.0 * u + roll(u, -1)
tridiag_solve(sub, diag, super, rhs)
the Thomas algorithm: solves a tridiagonal system in O(n), for the diagonally dominant systems that implicit PDE schemes produce. sub[0] and super[n-1] are unused
fft(a)
forward transform, in place, any length
ifft(a)
inverse transform, in place; ifft(fft(x)) returns x to rounding error
slab(A, k)
a COPY of the k-th slab along the leading axis: row k of a matrix, plane k of a rank-3 array. Real or complex
setslab(A, k, S)
overwrite that slab with S, in place
transpose(A)
max(a) · min(a)
with ONE array: its largest / smallest entry. max(abs(u - exact)) is the max-norm error of a solve
pow(a, s)
every entry of a real array to the same scalar power: pow(rho, 1.0 / 3.0)
sum(a)
the sum of every element of a real array, in NumPy's order in every exact engine: the entries in row-major order, from 0.0, in blocks of 8192, each block by NumPy's pairwise sum (below 8 entries left to right; to 128, eight running sums combined as a tree; above, two halves, the first a multiple of 8 long). Fast mode is not bound by this order

How they are checked

Against something exact
A closed-form solution where there is one (a decaying mode, a soliton, d'Alembert, Black–Scholes, the Riemann problem); a manufactured solution where there is not.
The order is measured, not quoted
Each solver runs at two or three resolutions and a test asserts the observed convergence rate. That includes the rates below the textbook figure: the first-order shock-capturing scheme for the Euler equations converges at 0.66 in L1, because the contact discontinuity smears, and its test asserts a rate between one half and one.
Conservation to rounding
Where the equation conserves something and the scheme is built to, the test tolerance is 1e-12.
In the interpreter and in C
pde/check.sh runs every program through the interpreter and through Viv → C → native, and requires the two outputs to agree line for line.