Skip to content

Training Techniques

Hard PDEs break naive PINN training in reproducible ways: stiff dynamics get skipped, unstable equilibria attract the optimizer, shocks produce spurious weak solutions. JAXPI packages the counter-measures as config switches that compose freely.

Grad-norm loss balancing

Problem. Multi-term losses (Lic+Lbc+Lres) have wildly different gradient scales; one term dominates and the others stall.

Fix. With loss_weighting.strategy = "dynamic", weights are periodically set to

λiθLθLi,

then smoothed with momentum, so all terms contribute equally-sized gradients.

python
loss_weighting.strategy = "dynamic"
loss_weighting.update_schedule = {"start": 100, "every": 1000}
loss_weighting.momentum = 0.9

Deep dive: Loss Balancing.

Causal training

Problem. For time-dependent PDEs, the residual can be minimized at late times before the early dynamics are resolved — the network "predicts the future" from wrong initial data and converges to garbage (classic on Allen–Cahn and fast advection).

Fix. Sort the collocation batch by time, split it into chunks, and gate each chunk by the cumulative residual of everything earlier:

Lres=1Kk=1KγkLk,γk=exp(τj<kLj).

Late chunks only receive weight once earlier chunks have converged.

python
causal.enabled = True
causal.num_chunks = 32
causal.tol = 1.0

Under multi-GPU sharding, chunk losses are gathered across devices in global time order, so causality is exact for any device count.

Deep dive: Causal Training.

Pseudo-time stepping

Problem. PDEs with unstable equilibria (Gray–Scott, Ginzburg–Landau, high-Re cavity flow) admit spurious steady solutions that are perfect residual minimizers — the optimizer happily finds them.

Fix. Augment the residual with a damping term toward the previous iterate, which mimics an implicit pseudo-time discretization and destabilizes the spurious fixed points:

r~(θ)=r(θ)+w(uθuθprev).

The per-component weights w can be constant (strategy = "constant") or adapted from the ratio of residual change to solution change (strategy = "dynamic"), with an optional cosine shrink as the residual converges:

python
pseudo_time.enabled = True
pseudo_time.strategy = "dynamic"
pseudo_time.pts_weights = {"u": 1.0, "v": 1.0, "p": 1.0}
pseudo_time.shrink.enabled = True

Deep dive: Pseudo-Time Stepping.

Time-window curriculum

Problem. Chaotic trajectories (Kuramoto–Sivashinsky, Kolmogorov flow) cannot be fit globally — small early errors amplify exponentially.

Fix. Train on consecutive windows [kΔT,(k+1)ΔT], propagating the network's own prediction as the next initial condition, with parameter transfer between windows. This is train_time_windows (see The Trainer):

python
training.num_time_windows = 10
training.time_window_size = 0.2   # examples that define dT explicitly
training.transfer_learning = True
training.resume = True            # continue an interrupted cascade

Multi-stage homotopy

Problem. Even a well-trained network plateaus at a finite residual; multi-scale flows (Taylor–Green at Re 1600) need more accuracy than one network can deliver.

Fix. Freeze the trained solution and train a correction network on the linearized equations around it,

u=uprev+εudiff,f(udiff)+r(uprev)ε=0,

with a higher Fourier frequency (corrections live at finer scales) and extra collocation points rejection-sampled where the previous residual is large. Stages compose: each new stage corrects the sum of all previous ones. See examples/taylor_green/train_multi_stage.py.

Composition cheat sheet

Problem symptomReach for
One loss term dominatesgrad-norm balancing
Solution ignores initial conditioncausal training
Converges to a trivial/steady solutionpseudo-time stepping
Chaotic / long-time dynamicstime windows
Residual plateaus above target accuracymulti-stage correction
Slow convergence, zigzagging lossesSOAP optimizer (deep dive)

Released under the Apache 2.0 License.