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

← Posts

demoAIPlasma physics

Grad-Shafranov by finite differences, against Solov'ev's closed form

A tokamak equilibrium solved on a grid and graded against an exact one. Solov'ev's solves the Grad-Shafranov equation with constant pressure gradient; the five-point solver, relaxed by SOR until the residual is below , misses it by , and on grids of spacing 0.1, 0.05 and 0.025, an observed order of 1.995 and then 1.994. Those errors are scipy's direct solve of the same equations, to .

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

A tokamak holds its plasma in a magnetic field shaped like nested doughnuts. In equilibrium the magnetic force balances the pressure gradient, . With the machine's rotational symmetry about its vertical axis, that balance reduces to one equation for one function, the poloidal flux , where is the distance from the axis of symmetry and the height. The surfaces are the flux surfaces: the field lines lie in them, and the pressure is constant on each. The equation is the Grad-Shafranov equation above. Its right side holds two free functions of , the pressure and .

When and are constants the equation is linear, and Solov'ev (1968) wrote down exact solutions. This post takes and (lengths in units of the major radius), for which

is exact: its flux surfaces are nested about the magnetic axis at , and near the axis they are ellipses of elongation . posts/refs/grad-shafranov-solovev.py checks the closed form with sympy, then solves the same finite-difference equations directly with scipy's sparse LU, which shares no code or method with the SOR iteration here.

The discrete equation and SOR

On a grid with spacing in and in , the centered differences for , and give at each interior node

with fixed to the closed form on the edge of the box. The term makes the equation unsymmetric in ; that is the only difference from Poisson's equation.

Successive over-relaxation (SOR) sweeps the grid, solves each node's equation for with its neighbors' newest values, and moves times that far. The program takes the that is optimal for Poisson's equation on the same box, , with the Jacobi iteration's spectral radius for and intervals of equal spacing. It sweeps until the largest residual is below , so what is left is the discretization error.

Three grids

The three grids have 8, 16 and 32 intervals across and 14, 28 and 56 across , so = 0.1, 0.05 and 0.025. (The reference script also solves a fourth grid, , where the order is 1.9998; it takes too long in a browser tab.)

The error of the difference equations is second order, and here it can be written down. The closed form's term is a quadratic in each variable, so the centered differences are exact on it. On the second difference is off by and the first difference over by , so the difference operator applied to the exact misses the source by , the same constant at every node. The error therefore solves the difference equation with source and zero boundary values: it is times a fixed function, up to that function's own discretization, and each halving of divides it by 4.

Printed

ints_r: [8, 16, 32]
ints_z: [14, 28, 56]
hs: [0.1, 0.05, 0.025]
halving_1: 3.98745
halving_2: 3.98383
errs: [0.000167718, 4.20615e-05, 1.05581e-05]
sweeps: [53, 108, 223]
resids: [2.65654e-12, 9.14469e-12, 9.86522e-12]
order_1: 1.99547
order_2: 1.99416
Grad-Shafranov error against the Solov'ev solution
five-point difference equations, solved by SORslope 2
10⁻⁵10⁻⁴0.030.040.050.060.070.080.090.1grid spacing hmax|ψ−ψexact|

Tests 5 of 5 pass

  • SOR brought every grid's residual below 1e-11 (passes)
  • the errors are scipy's direct solve of the same equations: 1.6771831e-4, 4.2061527e-5, 1.0558059e-5 (passes)
  • the three grids have 8, 16 and 32 intervals across R and 14, 28 and 56 across Z, so h = 0.1, 0.05 and 0.025 (passes)
  • each halving of h divides the error by 4, to within 0.02 (passes)
  • the observed order is 1.995 and then 1.994 (passes)

The flux surfaces, and the Shafranov shift

The heatmap is the solution on the 33 by 57 grid, with the flux surfaces drawn at five values of . They are nested about the magnetic axis at , taller than wide near the axis (), and pushed toward small farther out.

On the midplane the closed form gives the crossings of a surface directly: puts them at . The surface through crosses again at , so its center is at : the magnetic axis sits outboard of the center of this surface. That offset is the Shafranov shift, and it appears whenever there is pressure: the plasma pushes itself outward, where the field is weaker. The program reads the same crossing off the 33 by 57 grid by linear interpolation along the midplane and gets 0.661489, which is the reference script's interpolation on its own solution of the same grid, and from the closed form.

Printed

r_in: 0.661489
center: 0.955745
Solov'ev equilibrium on a 33 x 57 grid: poloidal flux ψ(R,Z)
Z
R
57 × 33 grid

Tests 2 of 2 pass

  • the surface through R = 1.25 crosses the midplane again at 0.661489, the scipy solution's crossing, and within 1e-4 of the exact 0.661438 (passes)
  • its center is 0.0443 inboard of the magnetic axis at R = 1 (passes)

Checked when the site was built: 7 of 7 tests passed, in 1.31 s. Download 2026-09-25-grad-shafranov-solovev.viv