Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Step 3 — 1D Diffusion

Authors
Affiliations
University of Valencia

13 Steps to Navier-Stokes with somax (inspired by Lorena Barba’s CFD Python)

After linear advection (Step 1) and nonlinear advection (Step 2), we now study the other fundamental process in fluid dynamics: diffusion. Diffusion smooths gradients and dissipates energy. It models heat conduction, molecular mixing, and viscous momentum transfer.

What you’ll learn:

  1. The physics of diffusion — smoothing, dissipation, and the analytical Gaussian solution

  2. How to create and run a Diffusion1D model in somax

  3. How to compare numerical results against the exact solution

  4. How to compute ∂L/∂ν\partial \mathcal{L} / \partial \nu via eqx.filter_grad

The PDE

∂u∂t=ν∂2u∂x2\frac{\partial u}{\partial t} = \nu \frac{\partial^2 u}{\partial x^2}

where ν>0\nu > 0 is the diffusion coefficient (kinematic viscosity for momentum, thermal diffusivity for heat).

Analytical solution

If the initial condition is a Gaussian with standard deviation σ0\sigma_0 centered at μ\mu:

u(x,0)=Aexp⁡ ⁣(−(x−μ)22σ02)u(x, 0) = A \exp\!\left( -\frac{(x - \mu)^2}{2\sigma_0^2} \right)

then the exact solution at time tt is:

u(x,t)=A σ0σ(t)exp⁡ ⁣(−(x−μ)22σ(t)2),σ(t)=σ02+2νtu(x, t) = \frac{A \, \sigma_0}{\sigma(t)} \exp\!\left( -\frac{(x - \mu)^2}{2\sigma(t)^2} \right), \qquad \sigma(t) = \sqrt{\sigma_0^2 + 2\nu t}

The Gaussian spreads (wider σ\sigma) and its peak decreases, but the total integral ∫u dx\int u \, dx is conserved. Energy 12∫u2 dx\frac{1}{2} \int u^2 \, dx, however, decays monotonically.

Grid layout and boundary conditions

somax uses the Arakawa C-grid from finitevolX. In 1D, scalar fields (like uu) live at T-points (cell centres) and fluxes are computed at U-points (cell edges):

 ghost                    interior                     ghost
 ┌─────┬──────┬──────┬──────┬──────┬──────┬──────┬─────┐
 │  G  │  T₁  │  T₂  │  T₃  │ ···  │ Tₙ₋₁│  Tₙ  │  G  │
 └──┬──┴──┬───┴──┬───┴──┬───┴──┬───┴──┬───┴──┬───┴──┬──┘
    U₀    U₁     U₂     U₃           Uₙ₋₁    Uₙ    Uₙ₊₁
         ←── dx ──→
  • T-points (indices 1:-1): where u is stored and updated

  • U-points: where Difference1D computes derivatives

  • Ghost cells (indices 0 and -1): filled by BCs before each RHS evaluation

The diffusion operator computes the Laplacian via the standard second-order centered stencil:

∂2u∂x2∣i≈ui+1−2ui+ui−1Δx2\frac{\partial^2 u}{\partial x^2}\bigg|_i \approx \frac{u_{i+1} - 2u_i + u_{i-1}}{\Delta x^2}

This stencil reaches both left and right neighbours, so the ghost cells are essential -- without them, the boundary T-points would have no neighbour on one side.

Periodic BCs copy the last interior value into the opposite ghost cell:

 u[0] = u[-2]      (left ghost ← rightmost interior)
 u[-1] = u[1]      (right ghost ← leftmost interior)

This makes the domain wrap around so that diffusion operates seamlessly across the boundary.

1. Create the model

The diffusion coefficient ν\nu is a differentiable parameter.

Grid: Nx=202, dx=0.0200
Diffusion coefficient nu = 0.05000000074505806

2. Initial condition

A Gaussian centered at the domain midpoint x=2.0x = 2.0 with σ0=0.2\sigma_0 = 0.2.

<Figure size 800x300 with 1 Axes>

3. Forward simulation

We integrate to t=0.5t = 0.5 and save several snapshots to visualize how the profile spreads.

Trajectory shape: u=(6, 202)
Stability limit: dt_max = dx^2 / (2*nu) = 0.004000
Actual dt = 0.001, ratio = 0.250

4. Visualize the spreading

The Gaussian broadens and its peak decreases — energy is being dissipated.

<Figure size 1000x400 with 1 Axes>

5. Comparison with the analytical solution

We overlay the numerical result with the exact spreading Gaussian at each saved time.

<Figure size 1400x700 with 6 Axes>

6. Error analysis

<Figure size 800x300 with 1 Axes>
Max error: 0.000206
L2 error:  0.000128

7. Energy decay

Diffusion dissipates energy. Analytically, the energy of the Gaussian solution decays as:

E(t)=A2σ02π22 σ(t)E(t) = \frac{A^2 \sigma_0^2 \sqrt{\pi}}{2 \sqrt{2} \, \sigma(t)}

We compare the numerical energy trajectory with this prediction.

<Figure size 800x350 with 1 Axes>
Energy: initial = 0.177245, final = 0.118182
Relative decay: 33.32%

8. Differentiability demo — gradient w.r.t. viscosity

A key question in inverse problems: given observations of a diffusing field, what is the diffusion coefficient? We compute ∂L/∂ν\partial \mathcal{L} / \partial \nu to see how the loss responds to changes in viscosity.

--- Gradient w.r.t. model parameters ---
  dL/d(nu) = -0.072464

A negative gradient means increasing nu would decrease the loss,
i.e., the current nu produces a profile that is too narrow
compared to the target width.

Summary

Conceptsomax API
Create modelDiffusion1D.create(nx=200, Lx=4.0, nu=0.05)
Initial stateDiffusion1DState(u=...)
Forward simmodel.integrate(state0, t0, t1, dt, saveat=...)
Analytical checkGaussian spreads: σ(t)=σ02+2νt\sigma(t) = \sqrt{\sigma_0^2 + 2\nu t}
Energy decaymodel.diagnose(state).energy decreases monotonically
Grad w.r.t. nueqx.filter_grad(loss)(model)

Key takeaway: Diffusion smooths gradients and dissipates energy. The analytical Gaussian solution provides an exact benchmark.

Next: Step 4 — Burgers’ Equation combines nonlinear convection and diffusion, creating the competition between steepening and smoothing.