Skip to content

Pseudo-Time Stepping ​

TL;DR

The empirical residual loss can be small on a spurious solution — sharp transition layers hide between collocation points. Pseudo-time stepping augments the residual with an implicit-Euler damping term toward the previous iterate, which (together with resampling) amplifies these hidden defects so the optimizer must fix them. Based on Wang, Koohy, Lu & Perdikaris, When PINNs Go Wrong, 2026.

The problem: spurious solutions with small losses ​

PINN training sometimes converges to physically wrong solutions despite tiny residual losses. The paper argues this is not an optimization failure but a defect of the empirical loss itself: profiles with a sharp transition layer of width h concentrate their residual in a region a finite collocation set barely samples, so a spurious solution can look nearly perfect to the loss.

The fix: relax in pseudo-time ​

Introduce an artificial relaxation ∂u/∂s+R[u]=0 in pseudo-time s and discretize implicitly with step τ (paper, Eqs. 2.37–2.39). At training step k, the residual loss becomes

Lpts(θ;θk−1)=1N∑i=1N|uθ(xi)−uθk−1(xi)τ+R[uθ](xi)|2,

i.e. the plain residual plus a damping term 1τ(uθ−uθk−1) toward the previous iterate. Systems of PDEs get one step size per component (τu,τv,τp,…).

Why it works (the paper's key insight): one pseudo-time update u†,+=u†−τR[u†] applied to a spurious profile amplifies the expected residual on freshly resampled collocation points from O(h−1) to O(τ2h−3) — the hidden defect becomes glaring, and training is steered away from the spurious attractor. Collocation resampling is essential to the mechanism.

Pseudo-time stepping amplifies hidden residual defects

Adaptive step size ​

The amplification grows with τ, but too large a τ makes the relaxed objective unstable — and the sweet spot cannot be read off the training loss. The paper's adaptive strategy picks the largest locally stable step from a Barzilai–Borwein-style finite-difference surrogate of the residual Jacobian. Per component, JAXPI computes

w=1τ=‖R[uθ]−R[uθprev]‖‖uθ−uθprev‖,

smoothed with momentum and clipped — a local estimate of the residual's Lipschitz constant. An optional cosine shrink schedule decays the weights as the true residual converges, so the damping vanishes near the solution.

In JAXPI ​

python
pseudo_time.enabled = True
pseudo_time.strategy = "dynamic"          # adaptive tau; "constant" for fixed weights
pseudo_time.pts_weights = {"u": 1.0, "v": 1.0, "p": 1.0}   # 1/tau per variable
pseudo_time.update_schedule = {"start": 100, "every": 1000}
pseudo_time.shrink.enabled = True

The residual components and their weights are matched by name — hence the variable-keyed residual convention.

Where it's used ​

Every example ships pseudo_time.py / fixed_pseudo_time.py config variants. The clearest demonstrations are Gray–Scott and Ginzburg–Landau (spurious steady states), inviscid Burgers (spurious weak solutions), and the high-Re lid-driven cavity.

Released under the Apache 2.0 License.