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

ladderAIPlasma physics

The Hasegawa-Wakatani drift-wave model

The Hasegawa-Wakatani equations are the simplest model of drift-wave turbulence at the edge of a tokamak that contains the instability driving it. Five rungs build their linear theory: the drift-wave frequency, the growth rate as the eigenvalue of a 2×2 matrix (0.098684 at , as numpy's eigensolver gives), the return to the drift wave as at the predicted rates and , a zonal flow that keeps of its start as it relaxes, and the one-line change in the modified model that leaves it untouched.

Look inside this program

  • Atlas

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

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

The edge of a magnetically confined plasma has a steep density gradient, and the gradient drives drift waves: ripples in density and electric potential that travel across the magnetic field, along the surfaces of constant density. The Hasegawa-Wakatani equations (1983) describe them with two fields in the plane perpendicular to : the density fluctuation and the electric potential , whose Laplacian is the vorticity of the flow.

is the density gradient, the drive. is the adiabaticity: how fast electrons stream along the field line to keep the density in step with the potential. Everything is dimensionless, with lengths in units of the ion sound gyroradius , and here . The brackets are the nonlinear advection; every rung here is linear, so they drop out.

posts/refs/hasegawa_wakatani.py computes the reference values with numpy.linalg.eigvals and scipy.linalg.expm.

The drift wave

In the limit the electrons follow the potential at once and . Subtracting the two equations then leaves one, the Hasegawa-Mima equation (linear part). A wave solves it when

The wave moves only in , along the surfaces of constant density. The 1 in the denominator comes from ; the comes from the ion polarization drift, which is stronger for small eddies. So the frequency first rises with , peaks at (for ), and then falls.

new: omega_hm

Rung 1 tests 3 of 3 pass

  • the drift wave at k = (0, 1) has frequency 1/2 (passes)
  • at k = (0.3, 0.7) it is 0.7 / 1.58 = 0.44303797468354 (passes)
  • past k_y = 1 the frequency falls: 0.4 at k_y = 2 (passes)

The growth rate is an eigenvalue

At finite the density lags the potential, and the lag lets the wave draw energy from the gradient. For one Fourier mode, and , and the linear equations become with the matrix under the title. Its eigenvalues are : the real part is the growth rate, and minus the imaginary part is the frequency.

The trace of is real and its determinant, , is imaginary, so the quadratic formula needs the square root of a complex number. Viv has complex arithmetic, and sqrt of a complex value is the principal root, whose real part is not negative; that picks the eigenvalue that grows faster.

At and : and , below the drift-wave 0.5. Scanning , the fastest growth at is near .

new: hw_lambda, growth, freq

Rung 2 tests 3 of 3 pass

  • at C = 1, k = (0, 1): gamma = 0.09868411347 and omega = 0.45508986056 (numpy eigvals) (passes)
  • at C = 0.5, k = (0.3, 0.7): gamma = 0.10155874337 and omega = 0.38554401937 (numpy eigvals) (passes)
  • the fastest growth at C = 1 is 0.106870 near k_y = 1.30 (numpy scan with step 0.0005) (passes)

Stiff coupling gives back the drift wave

Rung 1 took by hand. The eigenvalue should agree, and expanding the small root of in powers of says how fast. With , the first term is , the drift wave. The next two terms are

The growth rate vanishes like and the frequency error like . At both coefficients are , and the cell checks and at . The growth needs the lag: electrons that keep up exactly give a wave that neither grows nor decays.

Rung 3 tests 2 of 2 pass

  • C gamma approaches omega_HM^2 k^2 / (1 + k^2) = 1/8 (0.12499996 at C = 1000) (passes)
  • C^2 (1 - omega / omega_HM) approaches 2 omega_HM^2 k^4 / (1 + k^2)^2 = 1/8 (passes)

A zonal flow relaxes to k^2 / (1 + k^2) of its start

A zonal flow is a mode with : a band of flow in the direction, constant along . For it the drive is zero and only the coupling acts, . Here is singular. One eigenvalue is ; the other is 0, because never changes. So a band started with , does not decay away: it relaxes to

which is at . Wide bands (small ) keep little, narrow ones keep most. The cell integrates the two equations with fourth-order Runge-Kutta to , where the exact ratio is .

new: zonal_history

Rung 4 tests 2 of 2 pass

  • Runge-Kutta gives the exact k^2/(1+k^2) + e^(-C(1+1/k^2)t)/(1+k^2) at t = 2 to 1e-12 (passes)
  • and scipy's matrix exponential gives 0.20003631994381 for the same band (passes)

The modified model leaves the band alone

In a tokamak the coupling term comes from electrons moving along field lines, and a zonal flow is constant on a whole flux surface, so there is nothing along the field line for the electrons to smooth out. The modified Hasegawa-Wakatani model (Numata, Ball and Dewar, 2007) writes this in: the coupling acts only on the non-zonal parts, , where the tilde removes the average over . For a mode that makes the coupling exactly zero, and every non-zonal mode is unchanged.

With the same Runge-Kutta loop the zonal band now stays at its starting value, where rung 4's fell to . The band has no linear sink left; in the full equations it changes through the nonlinear bracket: the Reynolds stress of the drift waves around it.

new: modified_coupling

Rung 5 tests 2 of 2 pass

  • in the modified model the zonal band keeps its full amplitude (passes)
  • a non-zonal mode is unchanged: at k = (0, 1) the growth rate is still 0.09868411347 (passes)

Printed

w1: 0.5
0.443038
0.0986841
0.45509
g_best: 0.106869
ky_best: 1.3
c_gamma: 0.125
c2_dw: 0.125
zr: 0.200036
zr_exact: 0.200036
zr_mod: 1
One mode of Hasegawa-Wakatani, kx=0, C=1
growth rate γfrequency ωdrift wave, κky/(1+k2)
00.20.40.51.01.52.02.53.0kyrate
A zonal band, kx=0.5, C=1
classical Hasegawa-Wakataniresidual k2/(1+k2)
00.51.000.51.01.52.0tzeta(t) / zeta(0)
The same band in the two models
classicalmodifiedresidual k2/(1+k2)
00.51.000.51.01.52.0tzeta(t) / zeta(0)

Checked when the site was built: 12 of 12 tests passed, in under 0.1 s. Download 2026-09-25-hasegawa-wakatani-one-rung-at-a-time.viv