Prerequisites
Physics-informed neural networks build on neural network training from Chapter 26: Representation Learning, particularly the concepts of loss functions, backpropagation, and automatic differentiation. Familiarity with partial differential equations at the level of the heat equation and wave equation (what they express physically, if not how to solve them analytically) is helpful. Appendix A reviews the necessary multivariable calculus. We build on the simulation concepts from Chapter 5.
Traditional partial differential equation (PDE) solvers discretize space and time into grids, then march forward step by step. Physics-informed neural networks (PINNs) take a fundamentally different approach: they train a neural network to approximate the solution function directly, using the PDE itself as a training signal. Instead of "solve this equation on this grid," the instruction becomes "find a function whose derivatives satisfy this equation everywhere." This reformulation converts PDE solving into an optimization problem, the one thing neural networks do well. The payoff is a mesh-free solver that handles complex geometries, incorporates sparse experimental data, and solves inverse problems (identifying unknown parameters) with the same machinery used for forward problems.
1. The Core PINN Idea
In 2017, engineers modeling heat dissipation in a novel battery geometry spent weeks generating a computational mesh before a single simulation could run. Physics-informed neural networks eliminate that bottleneck entirely, replacing grid generation with gradient descent.
Imagine handing a neural network not a labeled dataset but a differential equation, then asking it to find a function whose derivatives satisfy that equation at every point in the domain: no grid, no mesh, no time-stepping loop, just an optimization problem. To see how this works, consider a general PDE defined on a domain \(\Omega \subset \mathbb{R}^d\) with boundary \(\partial\Omega\):
$$\mathcal{N}[u](x) = f(x), \quad x \in \Omega$$ $$\mathcal{B}[u](x) = g(x), \quad x \in \partial\Omega$$Here \(u(x)\) is the unknown solution, \(\mathcal{N}\) is a (possibly nonlinear) differential operator, \(\mathcal{B}\) is a boundary operator, and \(f, g\) are known source and boundary data. A PINN approximates \(u\) with a neural network \(u_\theta(x)\) parameterized by weights \(\theta\), and trains by minimizing a composite loss:
$$\mathcal{L}(\theta) = \lambda_r \mathcal{L}_r + \lambda_b \mathcal{L}_b + \lambda_d \mathcal{L}_d$$The three terms serve distinct purposes. The residual loss \(\mathcal{L}_r\) penalizes violations of the PDE at a set of collocation points \(\{x_r^{(i)}\}\) sampled inside the domain:
$$\mathcal{L}_r = \frac{1}{N_r} \sum_{i=1}^{N_r} \left| \mathcal{N}[u_\theta](x_r^{(i)}) - f(x_r^{(i)}) \right|^2$$Collocation points are specific locations in the domain where the PINN evaluates whether the PDE holds. The network cannot check the equation at every point in a continuous domain. Instead, it samples a finite set of locations, penalizes PDE violations there, and relies on its own smoothness to interpolate correct behavior between samples. Unlike grid points in finite-difference methods, you place collocation points randomly, quasi-randomly, or adaptively in regions of large residual. Use random or quasi-random collocation when the solution is smooth across the domain. Switch to adaptive residual-based refinement (adding points where the PDE error is highest) when the solution has localized features such as boundary layers or sharp gradients.
The diagram in Figure 33.1 shows the full PINN training loop: spatial and temporal coordinates enter the network, automatic differentiation computes the required derivatives, and the three loss terms (residual, boundary, data) jointly drive gradient descent.
Boundary and Data Terms
The boundary loss \(\mathcal{L}_b\) enforces boundary conditions at points \(\{x_b^{(i)}\}\) on \(\partial\Omega\):
$$\mathcal{L}_b = \frac{1}{N_b} \sum_{i=1}^{N_b} \left| \mathcal{B}[u_\theta](x_b^{(i)}) - g(x_b^{(i)}) \right|^2$$The data loss \(\mathcal{L}_d\) fits any available measurement data \(\{(x_d^{(i)}, u_d^{(i)})\}\):
$$\mathcal{L}_d = \frac{1}{N_d} \sum_{i=1}^{N_d} \left| u_\theta(x_d^{(i)}) - u_d^{(i)} \right|^2$$The weights \(\lambda_r, \lambda_b, \lambda_d\) balance these objectives. Getting these weights right is one of the practical challenges of PINNs, as we will see. In short: a PINN turns the laws of physics into a loss function and lets gradient descent find the solution. Figure 33.1.1 illustrates PINN architecture and composite loss.
Mental Model
Think of a PINN like tuning a guitar by ear without a tuner. A classical solver is like placing your finger on exact fret positions (grid points) and computing the note mechanically. A PINN instead asks: "Does this string vibrate according to the laws of acoustics?" You pluck the string (evaluate the PDE residual at sampled points), listen for dissonance (measure the residual error), and tighten or loosen the tuning peg (adjust network weights via gradient descent) until the string's vibration pattern satisfies the physics everywhere you check. The boundary conditions are like requiring the string to be pinned at the nut and bridge: those endpoints must remain fixed no matter how the rest of the string moves. Just as a guitarist iteratively adjusts tension until the harmonics sound right across the whole string, the optimizer iteratively adjusts weights until the PDE residual is small across the whole domain.
The critical enabler is automatic differentiation (AD), where the framework traces each arithmetic operation in the network's forward pass and applies the chain rule to compute exact gradients without finite-difference approximations. Computing \(\mathcal{N}[u_\theta]\) requires exact derivatives of the network output with respect to its inputs (spatial coordinates, time). AD provides these derivatives exactly (not numerically), to machine precision, at a cost proportional to a single forward pass. Without AD, PINNs would require finite-difference approximations of derivatives, introducing discretization error and defeating the purpose. This is why frameworks like JAX, PyTorch, and TensorFlow, all built around AD, are the natural substrate for PINNs. The connection to Chapter 42: Differentiable Programming is direct: PINNs are a specific application of the broader principle that making computation differentiable unlocks gradient-based optimization for scientific problems.
2. Solving the Heat Equation with a PINN
Let us build a concrete PINN from scratch. The 1D heat equation describes how temperature \(u(x, t)\) evolves over time in a rod of length \(L\):
$$\frac{\partial u}{\partial t} = \alpha \frac{\partial^2 u}{\partial x^2}$$with initial condition \(u(x, 0) = \sin(\pi x)\) and boundary conditions \(u(0, t) = u(1, t) = 0\). The exact solution is \(u(x, t) = e^{-\alpha \pi^2 t} \sin(\pi x)\), which lets us verify our PINN. We set \(\alpha = 0.01\).
import jax
import jax.numpy as jnp
from jax import grad, vmap, jit
import optax
from functools import partial
# Network architecture: simple MLP with tanh activations
def init_params(layer_sizes, key):
"""Initialize network parameters with Xavier initialization
(scaling weights by the layer widths to keep variance stable across layers)."""
params = []
for i in range(len(layer_sizes) - 1):
key, subkey = jax.random.split(key)
scale = jnp.sqrt(2.0 / (layer_sizes[i] + layer_sizes[i + 1]))
W = scale * jax.random.normal(subkey, (layer_sizes[i], layer_sizes[i + 1]))
b = jnp.zeros(layer_sizes[i + 1])
params.append((W, b))
return params
def network(params, x, t):
"""Forward pass: inputs (x, t) -> predicted u(x, t)."""
inputs = jnp.array([x, t])
for W, b in params[:-1]:
inputs = jnp.tanh(inputs @ W + b)
W, b = params[-1]
return (inputs @ W + b).squeeze()
# Compute PDE residual using automatic differentiation
def pde_residual(params, x, t, alpha=0.01):
"""Residual of heat equation: du/dt - alpha * d2u/dx2."""
u_t = grad(network, argnums=2)(params, x, t) # du/dt
u_x = grad(network, argnums=1)(params, x, t) # du/dx
u_xx = grad(grad(network, argnums=1), argnums=1)(params, x, t) # d2u/dx2
return u_t - alpha * u_xx
# Vectorize over collocation points
pde_residual_batch = vmap(pde_residual, in_axes=(None, 0, 0))
network_batch = vmap(network, in_axes=(None, 0, 0))
def loss_fn(params, x_r, t_r, x_b, t_b, u_b, x_i, t_i, u_i):
"""Composite PINN loss: residual + boundary + initial condition."""
# PDE residual loss at interior collocation points
residuals = pde_residual_batch(params, x_r, t_r)
loss_r = jnp.mean(residuals ** 2)
# Boundary condition loss
u_pred_b = network_batch(params, x_b, t_b)
loss_b = jnp.mean((u_pred_b - u_b) ** 2)
# Initial condition loss
u_pred_i = network_batch(params, x_i, t_i)
loss_i = jnp.mean((u_pred_i - u_i) ** 2)
return loss_r + 10.0 * loss_b + 10.0 * loss_i
# Generate training points
key = jax.random.PRNGKey(42)
N_r = 5000 # interior collocation points
N_b = 200 # boundary points
N_i = 200 # initial condition points
key, *subkeys = jax.random.split(key, 4)
x_r = jax.random.uniform(subkeys[0], (N_r,), minval=0.0, maxval=1.0)
t_r = jax.random.uniform(subkeys[1], (N_r,), minval=0.0, maxval=1.0)
# Boundary: u(0,t) = u(1,t) = 0
t_b = jax.random.uniform(subkeys[2], (N_b,))
x_b = jnp.concatenate([jnp.zeros(N_b // 2), jnp.ones(N_b // 2)])
t_b = jnp.concatenate([t_b[:N_b // 2], t_b[N_b // 2:]])
u_b = jnp.zeros(N_b)
# Initial condition: u(x,0) = sin(pi*x)
x_i = jnp.linspace(0, 1, N_i)
t_i = jnp.zeros(N_i)
u_i = jnp.sin(jnp.pi * x_i)
# Initialize and train
layer_sizes = [2, 64, 64, 64, 1]
params = init_params(layer_sizes, jax.random.PRNGKey(0))
optimizer = optax.adam(1e-3)
opt_state = optimizer.init(params)
@jit
def train_step(params, opt_state):
loss, grads = jax.value_and_grad(loss_fn)(
params, x_r, t_r, x_b, t_b, u_b, x_i, t_i, u_i
)
updates, opt_state = optimizer.update(grads, opt_state)
params = optax.apply_updates(params, updates)
return params, opt_state, loss
for epoch in range(10000):
params, opt_state, loss = train_step(params, opt_state)
if epoch % 2000 == 0:
print(f"Epoch {epoch:5d}, Loss: {loss:.6f}")
# Epoch 0, Loss: 0.482103
# Epoch 2000, Loss: 0.000847
# Epoch 4000, Loss: 0.000031
# Epoch 6000, Loss: 0.000004
# Epoch 8000, Loss: 0.000001
grad calls for exact second derivatives. The composite loss balances PDE residual, boundary, and initial condition terms with boundary and initial weights set 10x higher to prioritize constraint satisfaction.Notice the structure: we never discretize space or time onto a grid. The collocation points \(\{(x_r^{(i)}, t_r^{(i)})\}\) are random samples from the domain. The network learns a continuous function \(u_\theta(x, t)\) that can be evaluated at any resolution after training. This is the mesh-free property that makes PINNs attractive for complex geometries.
Common Misconception
A frequent misconception is that PINNs are more accurate than classical numerical solvers (finite element, finite difference, spectral methods) for standard forward PDE problems. They are not. For a well-posed PDE on a simple geometry with known boundary conditions and no experimental data to assimilate, classical solvers converge faster, provide rigorous error bounds, and produce more accurate solutions. PINNs trade raw accuracy for flexibility: their advantage lies in handling inverse problems, irregular geometries, sparse data integration, and situations where meshing is impractical, not in outperforming established solvers on their home turf.
3. Boundary Condition Strategies
The soft penalty approach above (adding boundary violations to the loss) is the most common but not the only option. It has a known weakness: the optimizer must balance satisfying the PDE against satisfying the boundary, and these objectives can conflict during training. Three alternative strategies address this.
Hard constraint encoding reformulates the network output so boundary conditions are satisfied exactly by construction. For Dirichlet conditions, where the solution value itself is prescribed on the boundary (\(u(0, t) = u(1, t) = 0\)), we can write:
$$u_\theta(x, t) = x(1 - x) \cdot \hat{u}_\theta(x, t)$$where \(\hat{u}_\theta\) is the raw network output. The factor \(x(1 - x)\) vanishes at both boundaries regardless of what \(\hat{u}_\theta\) produces. This eliminates the boundary loss entirely, reducing the optimization to a single objective.
Exact initial condition encoding extends this idea to time:
$$u_\theta(x, t) = (1 - e^{-t}) \cdot \hat{u}_\theta(x, t) + \sin(\pi x) \cdot e^{-t}$$At \(t = 0\), the first term vanishes and the second reduces to the initial condition \(\sin(\pi x)\). As \(t\) grows, the network takes over. This technique, sometimes called the "trial function" approach, is borrowed from classical variational methods.
Checkpoint
So far: three boundary-condition strategies exist for PINNs, progressing from soft penalties (easy but imprecise) through hard constraint encoding (exact by construction) to exact initial-condition encoding (extending the idea to time), each trading implementation complexity for tighter constraint satisfaction.
Augmented Lagrangian methods treat boundary conditions as constraints and use Lagrange multipliers, where each multiplier is a learned scalar that increases the penalty for a specific constraint whenever that constraint remains violated, that are updated during training:
$$\mathcal{L}(\theta, \mu) = \mathcal{L}_r + \mu \cdot \mathcal{L}_b + \frac{\rho}{2} \mathcal{L}_b^2$$The multiplier \(\mu\) is increased when boundary violations persist, automatically adjusting the balance. This is more robust than fixed weighting but adds hyperparameters \(\rho\) and the multiplier update schedule.
In structural engineering, beam deflection problems have both Dirichlet conditions (fixed endpoints) and Neumann conditions, where the derivative of the solution (such as slope or flux) is prescribed on the boundary rather than the solution value itself. A cantilevered beam has \(u(0) = 0\) (no displacement at the wall) and \(u'(0) = 0\) (no rotation at the wall). The hard constraint encoding becomes \(u_\theta(x) = x^2 \cdot \hat{u}_\theta(x)\), which satisfies both \(u(0) = 0\) and \(u'(0) = 0\) automatically. In practice, hard constraints typically reduce training time by 5x to 10x for well-posed problems because the optimizer no longer wastes gradient steps trying to learn the boundary behavior.
4. The DeepXDE Library
Building PINNs from scratch with raw JAX (as above) gives full control but requires implementing collocation point sampling, loss balancing, adaptive resampling, and many other details. The DeepXDE library (Lu et al., 2021) wraps all of this into a high-level API that supports multiple backends (TensorFlow, PyTorch, JAX, PaddlePaddle). Let us solve the same heat equation problem in far fewer lines.
import deepxde as dde
import numpy as np
# Define the computational domain: x in [0,1], t in [0,1]
geom = dde.geometry.Interval(0, 1)
timedomain = dde.geometry.TimeDomain(0, 1)
geomtime = dde.geometry.GeometryXTime(geom, timedomain)
# Define the PDE: du/dt - alpha * d2u/dx2 = 0
alpha = 0.01
def heat_equation(x, u):
du_t = dde.grad.jacobian(u, x, i=0, j=1) # du/dt
du_xx = dde.grad.hessian(u, x, i=0, j=0) # d2u/dx2
return du_t - alpha * du_xx
# Boundary conditions: u(0,t) = u(1,t) = 0
bc = dde.icbc.DirichletBC(
geomtime,
lambda x: 0,
lambda _, on_boundary: on_boundary
)
# Initial condition: u(x,0) = sin(pi*x)
ic = dde.icbc.IC(
geomtime,
lambda x: np.sin(np.pi * x[:, 0:1]),
lambda _, on_initial: on_initial
)
# Assemble the problem
data = dde.data.TimePDE(
geomtime,
heat_equation,
[bc, ic],
num_domain=5000, # interior collocation points
num_boundary=200,
num_initial=200,
num_test=1000
)
# Build and train the network
net = dde.nn.FNN([2] + [64] * 3 + [1], "tanh", "Glorot normal")
model = dde.Model(data, net)
model.compile("adam", lr=1e-3)
losshistory, train_state = model.train(epochs=10000, display_every=2000)
# Evaluate on a test grid
x_test = np.linspace(0, 1, 100)
t_test = np.full_like(x_test, 0.5)
xt_test = np.column_stack([x_test, t_test])
u_pred = model.predict(xt_test)
u_exact = np.exp(-alpha * np.pi**2 * 0.5) * np.sin(np.pi * x_test)
print(f"L2 relative error at t=0.5: {np.linalg.norm(u_pred.flatten() - u_exact) / np.linalg.norm(u_exact):.4e}")
# L2 relative error at t=0.5: 1.82e-03
The raw JAX PINN required ~80 lines of code for point sampling, loss construction, gradient computation, and training. DeepXDE reduces this to ~30 lines by providing domain geometry objects, automatic collocation point sampling, a declarative boundary/initial condition API, and built-in training with adaptive learning rates. DeepXDE also includes residual-based adaptive refinement (RAR), which automatically adds collocation points where the PDE residual is large, and supports inverse problems (learning unknown PDE parameters) with minimal code changes. For production PINN work, start with DeepXDE and drop to raw JAX only when you need custom architectures or loss functions that the library does not support. As of 2024, NVIDIA Modulus has emerged as another major framework for physics-informed models, offering GPU-optimized training pipelines, built-in support for large-scale multi-GPU runs, and a library of reference PINN architectures; it is worth evaluating alongside DeepXDE for performance-critical workloads.
With high-level libraries handling collocation, loss balancing, and training loops, the practical question shifts from "how do I build a PINN?" to "where will it break down?", because knowing the boundaries of a method matters as much as knowing how to use it.
5. Failure Modes and Mitigations
PINNs are not a universal solver. Understanding when and why they fail is essential for using them effectively in scientific work.
Spectral bias. Neural networks with smooth activations (tanh, sigmoid) learn low-frequency components of the solution first and struggle with high-frequency features. This is called spectral bias or the F-principle (Xu et al., 2019). For PDEs with sharp gradients, shocks, or turbulent behavior, standard PINNs converge slowly or fail entirely. Mitigations include Fourier feature encodings (mapping inputs through \(\sin\) and \(\cos\) at multiple frequencies before feeding them to the network), multi-scale architectures, and adaptive activation functions.
def fourier_features(x, t, num_features=64, sigma=1.0, key=None):
"""Map (x,t) through random Fourier features to combat spectral bias."""
if key is None:
key = jax.random.PRNGKey(0)
# Random frequency matrix
B = sigma * jax.random.normal(key, (2, num_features))
inputs = jnp.stack([x, t])
projection = inputs @ B # shape: (num_features,)
# Concatenate sin and cos for 2*num_features total
return jnp.concatenate([jnp.sin(2 * jnp.pi * projection),
jnp.cos(2 * jnp.pi * projection)])
def network_with_ff(params, x, t, ff_key):
"""Network with Fourier feature input encoding."""
inputs = fourier_features(x, t, num_features=64, sigma=10.0, key=ff_key)
for W, b in params[:-1]:
inputs = jnp.tanh(inputs @ W + b)
W, b = params[-1]
return (inputs @ W + b).squeeze()
Causal training. For time-dependent PDEs, the solution at time \(t\) depends on the solution at earlier times. Standard PINNs sample collocation points uniformly across the entire space-time domain and try to learn everything at once. This ignores the causal structure and can lead to incorrect solutions. Wang, Sankaran, and Perdikaris (2024) proposed causal PINNs that weight the residual loss temporally, enforcing that the network learns earlier times before later times:
$$\mathcal{L}_r = \sum_{k=1}^{N_t} w_k \cdot \frac{1}{N_x} \sum_{i=1}^{N_x} \left| \mathcal{N}[u_\theta](x_i, t_k) \right|^2, \quad w_k = \exp\left(-\epsilon \sum_{j=1}^{k-1} \ell_j\right)$$where \(\ell_j\) is the residual at time step \(j\). The exponential weighting ensures that later time steps receive low weight until the residual at earlier times is small.
Stiff multi-physics problems. A system is called "stiff" when it contains processes evolving on vastly different timescales, forcing solvers to take tiny steps to track the fastest component even when the slower components dominate the behavior of interest. When the PDE couples fast and slow dynamics (for example, chemical reactions with timescales spanning orders of magnitude), the loss components develop vastly different magnitudes. Gradient-based optimizers struggle because gradients from stiff components dominate. Learning rate annealing and self-adaptive loss weighting (letting the network learn \(\lambda\) weights as additional parameters) reduce the imbalance but do not eliminate it. For extremely stiff systems, domain decomposition, where the spatial or temporal domain is split into smaller subregions with a separate PINN trained on each and interface conditions linking them, proves more robust.
Perhaps the most scientifically exciting application of PINNs is solving inverse problems: given partial observations of a system's behavior, infer the unknown parameters of the governing PDE. Raissi, Perdikaris, and Karniadakis (2019) demonstrated identifying the unknown coefficients in the Navier-Stokes equations, the fundamental PDEs governing fluid motion by relating velocity, pressure, and viscous forces, from sparse velocity measurements. In practice, setting up an inverse PINN requires only a small change to the forward formulation: promote the unknown parameter (say, the thermal diffusivity \(\alpha\) in the heat equation) from a fixed constant to a trainable variable, add a data loss term matching sensor observations, and let gradient descent optimize both \(\theta\) and \(\alpha\) simultaneously. The composite loss remains the same; the optimizer simply has one more degree of freedom. This connects directly to the symbolic regression ideas in Chapter 35, where the goal is to discover the equation itself rather than its parameters. Recent work combines PINNs with neural ODEs and sparse regression to discover governing equations from data, bridging the gap between parameter estimation and equation discovery. Wang, Wang, and Perdikaris (2021) introduced PI-DeepONet, which merges physics-informed training with the DeepONet operator learning architecture, enabling a single trained model to solve families of parametric PDEs while still enforcing PDE constraints through the residual loss. Their approach reported order-of-magnitude speedups over retraining a standard PINN for each new parameter configuration, pointing toward a future where physics-informed models generalize across problem instances rather than solving one at a time.
These research advances expand the frontier of what PINNs can achieve, but translating that potential into practice requires knowing which problems are a natural fit and which are better served by other methods.
6. When to Use PINNs (and When Not To)
PINNs excel in specific niches. They fit inverse problems, where the goal is inferring unknown parameters from partial observations. They suit data assimilation, fusing a known PDE with sparse, noisy measurements. Their mesh-free nature handles complex geometries where generating a grid is impractical. And they accommodate multi-physics coupling, where different PDEs govern different subdomains and the interfaces between them are irregular.
PINNs are a poor choice for well-posed forward problems on simple geometries, where classical solvers (finite element, spectral methods) are faster and more accurate. They struggle with turbulence and chaotic systems where the solution has fine-scale structure across the entire domain. And they are not yet competitive for time-stepping over long horizons, where errors accumulate and the causal structure of the problem fights against the global optimization formulation. For these cases, the neural operators in Section 33.2 offer a better alternative.
The name "physics-informed neural network" was coined in 2019, but the idea of using neural networks to solve PDEs dates back to Lagaris, Likas, and Fotiadis (1998), who used single-hidden-layer networks with hard constraint encoding. The 20-year gap between the original idea and its modern revival was bridged primarily by two developments: automatic differentiation frameworks that made computing PDE residuals trivial, and GPU hardware that made training deep networks practical. In this case, the enabling technology mattered as much as the idea.
Try It: Solve a 1D Poisson Equation with a PINN
Build a minimal PINN for the Poisson equation \(-u''(x) = \sin(\pi x)\) on \([0, 1]\) with \(u(0) = u(1) = 0\) (exact solution: \(u(x) = \sin(\pi x) / \pi^2\)). This requires only NumPy, PyTorch or JAX, and matplotlib.
Step 1. Define a two-hidden-layer multi-layer perceptron (MLP) (e.g., [1, 32, 32, 1] with tanh activations) that takes a scalar \(x\) and outputs a scalar \(u_\theta(x)\).
Step 2. Write the residual function: use automatic differentiation to compute \(u''_\theta(x)\), then evaluate \(u''_\theta(x) + \sin(\pi x)\). This should be zero if the PDE is satisfied.
Step 3. Sample 100 random interior points in \((0, 1)\) for the residual loss and 2 boundary points at \(x = 0\) and \(x = 1\). Compute the composite loss: \(\mathcal{L} = \text{mean}(r^2) + 100 \cdot (u_\theta(0)^2 + u_\theta(1)^2)\).
Step 4. Train with Adam (lr = 1e-3) for 5,000 epochs. Print the loss every 1,000 epochs; it should drop below \(10^{-5}\).
Step 5. Plot \(u_\theta(x)\) against the exact solution \(\sin(\pi x)/\pi^2\) on a grid of 200 points. Compute the maximum absolute error; it should be below \(10^{-3}\). Then experiment: replace the soft boundary penalty with hard constraints by outputting \(x(1 - x) \hat{u}_\theta(x)\) and observe how training speed changes.
Exercise 33.1.1
Suppose you train a PINN on the heat equation with \(\lambda_b = 0\) (no boundary loss weight). The PDE residual loss drops to \(10^{-6}\), yet the predicted solution is wildly wrong near \(x = 0\) and \(x = 1\). Why does minimizing the PDE residual alone not guarantee a correct solution, even when the residual is extremely small?
Hint
A PDE by itself (without boundary conditions) does not have a unique solution. Any function from the family \(u(x,t) = C \cdot e^{-\alpha \pi^2 t}\sin(\pi x)\) satisfies the heat equation for any constant \(C\). The boundary and initial conditions select one specific member of this family. Without enforcing them, the network can find a function that satisfies the differential equation perfectly but corresponds to the wrong physical scenario.
Step-Through: PINN Training on a 3-Point Domain
Trace through one training step of a toy PINN for \(-u''(x) = 1\) on \([0,1]\) with \(u(0)=u(1)=0\) (exact solution: \(u(x) = x(1-x)/2\)). Suppose the network currently predicts \(u_\theta(x) = 0.3x\) for all \(x\).
Collocation point: \(x_r = 0.5\). We need \(u''_\theta(0.5)\). Since \(u_\theta\) is linear, \(u''_\theta = 0\) everywhere. Residual: \(-0 - 1 = -1\). Squared residual: \(1.0\).
Boundary points: At \(x=0\): \(u_\theta(0) = 0\), error \(= 0\). At \(x=1\): \(u_\theta(1) = 0.3\), error \(= 0.3^2 = 0.09\).
Total loss (with \(\lambda_b = 10\)): \(1.0 + 10 \times \frac{0 + 0.09}{2} = 1.45\). The gradient will push the network toward a function with nonzero curvature (to reduce the residual from 1.0) and toward \(u_\theta(1) = 0\) (to reduce the boundary error). After many such steps, the network converges to the parabola \(x(1-x)/2\).
Real-World Application: Cardiovascular Flow Modeling
Researchers at Brown University used PINNs to reconstruct blood velocity and pressure fields in patient-specific aortic geometries from sparse 4D-flow MRI measurements (Kissas et al., 2020, Computer Methods in Applied Mechanics and Engineering). The PINN enforced the incompressible Navier-Stokes equations as a physics constraint while assimilating noisy, spatially incomplete clinical scans. This produced full-field hemodynamic maps (including wall shear stress, a predictor of aneurysm rupture risk) that neither the MRI data alone nor a forward simulation without patient data could provide.
Lab: Spectral Bias Under the Microscope
Goal: Observe and quantify spectral bias in a PINN, then verify that Fourier feature encoding fixes it.
Tools: Python 3.9+, JAX (or PyTorch), matplotlib, numpy. About 20 minutes.
Setup: Solve \(-u''(x) = f(x)\) on \([0,1]\) with \(u(0)=u(1)=0\), where \(f(x) = \sin(2\pi x) + \sin(16\pi x)\). The exact solution is a sum of a low-frequency and a high-frequency sinusoid. Train a 3-layer tanh MLP (width 64) for 10,000 epochs.
What to vary: (1) Run with the standard MLP and plot the learned solution at epochs 500, 2000, 5000, 10000. (2) Add a Fourier feature layer (\(\sigma=10\), 64 features) and repeat. (3) Try \(\sigma \in \{1, 5, 10, 50\}\) and record the L2 error at epoch 5000.
What to observe: The standard MLP learns the low-frequency component first and the high-frequency component much later (or never). With Fourier features, both components appear early. Too-large \(\sigma\) introduces optimization instability. Plot the Fourier spectrum of the error at each checkpoint to see spectral bias directly.
Exercises
- (Conceptual) A colleague proposes using a PINN to simulate turbulent flow around an aircraft wing, a problem where commercial computational fluid dynamics (CFD) software takes 48 hours on a cluster. Explain two specific reasons why a standard PINN would struggle with this problem, and suggest one mitigation for each.
- (Coding) Modify the JAX PINN above to solve Burgers' equation, \(\frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} = \nu \frac{\partial^2 u}{\partial x^2}\), with \(\nu = 0.01/\pi\), initial condition \(u(x, 0) = -\sin(\pi x)\), and boundary conditions \(u(-1, t) = u(1, t) = 0\). Use Fourier features to handle the developing shock. Compare your solution against the reference solution at \(t = 1\).
- (Analysis) Run the DeepXDE heat equation example with different loss weights for the boundary term (\(\lambda_b \in \{1, 10, 100, 1000\}\)). Plot the L2 relative error as a function of \(\lambda_b\). At what value does the boundary loss start to dominate the optimization and degrade the interior solution? What does this tell you about the soft penalty approach?
What's Next
PINNs learn a single solution function for a single set of initial/boundary conditions. If the conditions change, you must retrain from scratch. Section 33.2: Neural Operators addresses this limitation by learning operators that map entire function spaces to function spaces. Once trained, a neural operator can produce solutions for any new initial condition or forcing in a single forward pass, with no retraining. This is the difference between memorizing one answer and learning the solution method.
Bibliography
The seminal PINN paper establishing PDE residual losses as the core training signal.
The production PINN library used in this section for the high-level heat equation implementation.
The F-principle paper explaining spectral bias in neural networks, the key PINN failure mode.
Causal PINNs: temporal weighting that enforces learning earlier times before later times.
The original 1998 paper proposing neural networks as PDE solvers, two decades before the modern PINN revival.
Introduced PI-DeepONet, merging physics-informed residual losses with the DeepONet operator learning architecture for parametric PDE families.