Start here01 / 84

Physics-Informed Neural Networks

Learn the ideas from the beginning, then train a small PyTorch model that predicts how a warm rod cools.

No calculus background assumedWorked numbersCode + data included
coordinates (x, t)
↓ neural network
predicted temperature û
↓ checked against physics
Take this as a self-paced course. Pause at the examples; use the chapter selector to return to any topic.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
Start here02 / 84

Four parts, in a useful order

1 · Learn what a network does

Functions, neurons, predictions, loss, and training.

2 · Read the physics

Change, slopes, curvature, the heat equation, and conditions.

3 · Build a PINN

Residuals, sampling, loss terms, and automatic differentiation.

4 · Run and check it

Tensors, the PyTorch code, training results, and experiments.

You only need basic arithmetic to start. Python installation instructions are included near the end.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero03 / 84

What are we trying to predict?

A physical system

cool endwarm middlecool end

A thin rod conducts heat along its length.

A question

How warm is the rod at a particular position and time?

input: position + time
output: temperature
Treat the rod as one-dimensional: we describe changes along its length and ignore its thickness.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero04 / 84

One prediction needs two coordinates

x = 0.25 → ¼ of the rod
t = 0.50 → halfway through time
u(0.25, 0.50) = temperature

Read the notation

x tells us where we are. t tells us when.

u is the name we give the temperature field: a value for every (x,t).

We use normalized position, time, and temperature in this example. A value of 0.6 is a normalized temperature, not 0.6°C.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero05 / 84

A function turns an input into an output

f(x) = 2x + 1

f(0) = 1
f(2) = 5
f(3) = 7

Evaluate a function

Choose an input. Substitute it into the rule. Calculate the output.

Our final rule needs two inputs: u(x,t).

A model is a rule we use to describe or predict a system. A neural network is one way to represent that rule.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero06 / 84

A data point is one observed example

xtu
0.500.500.610498

What the row says

At the middle of the rod, halfway through our time interval, the temperature is about 0.61.

We can compare a prediction at (0.50,0.50) with this number.

In a real experiment, u could come from a sensor. In this tutorial, it comes from a known exact solution so we can check our work.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero07 / 84

Learning means adjusting a rule

prediction: ŷ = wx + b

w = 1, b = 0, x = 2
ŷ = 2

observed answer: y = 5

Parameters

w is a weight: it scales the input.

b is a bias: it adds an offset.

Training changes w and b to bring predictions closer to the examples.

The hat in ŷ or û means “predicted value.” The symbol θ collects all the trainable weights and biases of a network.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero08 / 84

A neuron combines inputs, then transforms them

z = w₁x + w₂t + b
a = tanh(z)

x=.5, t=.2, w₁=2, w₂=−1, b=0
z = 1 − .2 = .8
a ≈ .664

Two operations

1. Compute a weighted sum z.

2. Apply an activation function to get a.

The activation lets a network represent curved, more complex functions.

The numbers in this example are illustrative weights; training will find different values.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero09 / 84

Try changing a neuron's weight

Hold x = 0.5, t = 0.2, w₂ = −1, b = 0

z = 0.800
tanh(z) = 0.664

Watch the effect

Moving the weight changes the weighted sum and the neuron's output.

Training does this automatically for every weight in the network.

This is a forward calculation only. The slider changes a parameter; it does not run an optimizer.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero10 / 84

Why do we use tanh?

tanh(−2) ≈ −0.964
tanh(0) = 0
tanh(2) ≈ 0.964

A smooth activation

tanh bends smoothly between −1 and +1.

Without activations, a stack of linear layers is still just a linear function.

Smoothness will matter when we take second derivatives.

tanh limits the hidden neuron outputs. Our last layer is linear, so the final predicted temperature is not forced into [−1,1].
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero11 / 84

A layer applies many neurons at once

2 inputs
x, t
→
32 neurons
tanh
→
32 neurons
tanh
→
32 neurons
tanh
→
1 output
û

Each layer uses the previous layer's outputs as its inputs. This is a multilayer perceptron, or MLP.

Our network has 2,241 parameters: 96 in the first layer, 1,056 in each of the next two, and 33 in the output layer.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero12 / 84

A forward pass produces a prediction

(x,t) = (.5,.5)
↓ hidden layers
û = 0.48

Before training

We initialize weights to small random values.

The first prediction will generally be inaccurate.

A forward pass evaluates the current network; it does not change any weights.

The prediction 0.48 is illustrative. For this coordinate, our reference answer is approximately 0.610498.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero13 / 84

A loss measures how wrong a prediction is

error = prediction − target
0.48 − 0.61 = −0.13

squared error = (−0.13)²
= 0.0169

Why square the error?

Positive and negative mistakes cannot cancel.

Larger mistakes receive a larger penalty.

A perfect prediction has squared error zero.

A loss is one scalar number to minimize. It tells the optimizer how the current model performs.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero14 / 84

Mean squared error averages many mistakes

errorerror²
−0.10.01
+0.20.04
0.00.00
MSE = (0.01 + 0.04 + 0)/3
= 0.016667
The mean divides by the number of points. This makes loss size less dependent on the size of the batch.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero15 / 84

One weight update, calculated by hand

ŷ = wx; x=2, y=5, w=1
L = (2w − 5)² = 9
dL/dw = 4(2w − 5) = −12

w_new = 1 − 0.1(−12) = 2.2
new L = (4.4 − 5)² = 0.36

Gradient descent

A gradient tells us how loss changes when a weight changes.

Move the weight opposite the gradient.

The learning rate, here 0.1, sets the step size.

We will explain derivatives next. For now, see that an update based on the loss can improve the prediction.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero16 / 84

Training repeats the same four operations

  1. Predict outputs with the current weights.
  2. Calculate the loss from those predictions.
  3. Backpropagate: compute the loss gradient for every weight.
  4. Use an optimizer to update the weights.
An optimizer is the update algorithm. We use Adam, which adapts step sizes using recent gradients. In this script, one “epoch” means one full optimizer step.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
1 · Networks from zero17 / 84

What do measurements leave unknown?

Sparse observations

A few sensors tell us the temperature at a few coordinates.

Many functions can match those observed values.

Known physical law

The heat equation constrains how temperature can change throughout the rod.

PINNs use that law to supply extra training information.

We now build the mathematical ingredients needed to turn the heat equation into a loss.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics18 / 84

A rate is change divided by an interval

temperature: 0.80 → 0.70
time: 0.20 → 0.30

average rate = −0.10 / 0.10
= −1.0

Read the sign

A negative rate means the temperature is decreasing.

The rate is an average over that time interval.

A derivative measures the local rate at a specific point. We estimate it by using progressively smaller intervals.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics19 / 84

A derivative is the slope at one point

f(x) = x²
near x=2:
(2.1² − 2²) / 0.1 = 4.1
(2.01² − 2²) / 0.01 = 4.01

f′(2) = 4

Shrink the step

The closer the two x values are, the closer this estimate gets to the local slope.

For x², the exact derivative is f′(x)=2x.

These calculations explain finite differences. PyTorch autograd calculates derivatives of its operations directly through the chain rule.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics20 / 84

With two inputs, change one at a time

u(x,t) = x² + 3t

∂u/∂x = 2x (hold t fixed)
∂u/∂t = 3 (hold x fixed)

Partial derivative

The symbol ∂ tells us the function has several inputs.

A partial derivative changes one input while holding the others fixed.

u_x is shorthand for ∂u/∂x. u_t is shorthand for ∂u/∂t. Both refer to derivatives of the same temperature field.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics21 / 84

A second derivative measures changing slope

f(x) = x²
f′(x) = 2x
f″(x) = 2

g(x) = 1 − x²
g″(x) = −2

Curvature

Positive second derivative: the curve bends upward.

Negative second derivative: the curve bends downward.

Zero second derivative: a locally straight profile.

For temperature, u_xx means take a derivative with respect to x, then take another derivative with respect to x.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics22 / 84

Heat exchange explains curvature

0.6left
1.0center
0.6right
neighbor sum − 2 × center
0.6 + 0.6 − 2(1.0) = −0.8

The center cools

The center is hotter than both neighbors, so heat flows outward.

The negative difference corresponds to negative spatial curvature.

For equal spacing h, u_xx is approximated by [u(x−h)−2u(x)+u(x+h)]/h². A colder center gives the opposite sign.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics23 / 84

The heat equation connects time and curvature

∂u/∂t = α ∂²u/∂x²

u_t = αu_xx

Read the law

The rate of temperature change equals diffusivity times spatial curvature.

If curvature is negative, temperature decreases; if positive, it increases.

We assume uniform material properties, constant positive diffusivity, and no internal heat source.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics24 / 84

Diffusivity α controls how quickly heat spreads

if u_xx = −4:

α = 0.1 → u_t = −0.4
α = 0.01 → u_t = −0.04

A physical coefficient

Larger α means faster smoothing.

In our example α=0.1 is known and fixed.

The neural-network weights θ are different: they represent the solution.

In dimensional units, thermal diffusivity has units of length²/time. This example uses normalized variables.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics25 / 84

What makes this a differential equation?

Differential equation

It relates an unknown function to its derivatives.

Solving it means finding a function that satisfies the relation.

u_t = αu_xx

PDE = partial differential equation
inputs: x and t
An ordinary differential equation (ODE) has derivatives with respect to one independent variable. A PDE involves partial derivatives across several.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics26 / 84

The domain says where the equation applies

0 ≤ x ≤ 1
0 ≤ t ≤ 1

(0.3,0.8) is inside
(1.4,0.5) is outside

Position × time

Every pair in this rectangle is a place where we want temperature predictions.

We train and evaluate on this domain.

A PINN does not automatically generalize to coordinates outside its training domain.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics27 / 84

The PDE allows many possible solutions

u(x,t) = 0
u(x,t) = 1

for both: u_t = 0, u_xx = 0
both satisfy the heat equation

What is missing?

We must specify the starting temperature and what happens at the ends.

Those conditions identify the physical problem we intend to solve.

The constant-one solution will violate our zero-temperature boundaries. The zero solution will violate our warm initial profile.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics28 / 84

The initial condition gives the starting profile

u(x,0) = sin(πx)

u(0,0) = 0
u(0.5,0) = 1
u(1,0) = 0

At time zero

The ends start cool and the middle starts warm.

We prescribe temperature at every position along the rod.

π is approximately 3.14159. sin(πx) creates one smooth positive hump between x=0 and x=1.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics29 / 84

Boundary conditions describe the ends

u(0,t) = 0
u(1,t) = 0

for every time t in [0,1]

Fixed temperatures

Imagine both ends are attached to reservoirs held at the reference temperature.

Heat can leave through those ends.

These are Dirichlet boundary conditions: they specify a function's value. Other problems may specify heat flux or an insulated end.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics30 / 84

We use a problem with a known solution

u(x,t) = e−απ²t sin(πx)

Separate the factors

sin(πx) sets the shape along the rod.

e−απ²t reduces the amplitude over time.

This exact formula lets us generate demonstration data and judge the trained model. Real PDEs often lack such a convenient solution.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics31 / 84

Check that the formula obeys the PDE

u = e−απ²tsin(πx)

u_t = −απ²u
u_xx = −π²u

αu_xx = −απ²u = u_t

Also check conditions

At t=0, the exponential is 1, giving sin(πx).

At x=0 or x=1, the sine is zero.

This is a direct substitution check. The factors were chosen so the PDE and conditions all agree.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics32 / 84

Calculate one reference temperature

x=.5, t=.5, α=.1

sin(π × .5) = 1
e−.1 × π² × .5 ≈ .610498

u(.5,.5) ≈ .610498

A benchmark

After training, we can query the same coordinate.

The prediction should be close to this value when the model has learned the solution.

The exact mid-rod values are 1.0 at t=0, about 0.6105 at t=0.5, and about 0.3727 at t=1.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
2 · Calculus and physics33 / 84

Move through time and observe the solution

Both ends stay at zero. The center cools as the curve's amplitude decreases.

α = 0.1
This interactive curve evaluates the exact formula in your browser. It is a reference visualization, not a trained model.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN34 / 84

What makes a neural network physics-informed?

û(x,t) = NNθ(x,t)

ordinary training: fit examples
PINN training: also obey the PDE

The same network

The architecture is an ordinary smooth MLP.

The physics enters through the training loss.

We change θ until predictions satisfy the rules well.

A PINN is not a simulation of the rod inside each neuron. It is a function trained with physical constraints.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN35 / 84

A residual measures violation of the PDE

r(x,t) = û_t − αû_xx

if û_t = −0.30, û_xx = −2
r = −0.30 − .1(−2) = −0.10

Zero is the target

A residual of zero means the prediction satisfies the equation at this coordinate.

Our example residual of −0.10 means it does not.

A residual checks local physics. It does not directly measure the temperature's error relative to the correct solution.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN36 / 84

Turn residuals into a physics loss

residuals: −0.1, +0.2, 0

Lphysics = mean(r²)
= (0.01 + 0.04 + 0)/3
= 0.016667

Many checks

Evaluate the residual at many position-time pairs.

Square each result and average.

Training pushes that average toward zero.

A finite set of residual checks cannot guarantee that the PDE holds everywhere. We will also evaluate at new points.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN37 / 84

Physics points need coordinates but no labels

sample (x,t) = (.37,.64)
↓ predict û
↓ compute û_t and û_xx
↓ compare residual with zero

Collocation points

This is the name for coordinates used to enforce the differential equation.

We do not need a measured u value at these locations.

The script samples 1,000 new uniformly distributed physics points every step. Sampling alone does not encode physics; the residual calculation does.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN38 / 84

Initial-condition loss checks the starting state

Linitial = mean[(û(x,0) − sin(πx))²]

at x=.5: target = 1
prediction = .8
squared error = .04

Known targets

Choose positions x and set time to zero.

The prescribed sine profile supplies the correct answer at each position.

Without the initial condition, the all-zero temperature field satisfies the PDE and our end conditions.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN39 / 84

Boundary loss keeps both ends at zero

left-end prediction = .10
right-end prediction = −.20

Lboundary = (.10² + .20²)/2
= .025

Same rule at many times

Sample times and evaluate both x=0 and x=1.

The target at every one of these points is zero.

The script averages over the combined set of left and right boundary points. It does not add two unnormalized sums.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN40 / 84

Observation loss adds temperature measurements

target = .610498
prediction = .580498

error = −.03
squared error = .0009

Optional evidence

The PDE and conditions already define this forward problem.

Interior observations can help training and are needed in many inverse problems.

The tutorial uses 16 observations from the included CSV by default; these are synthetic reference values.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN41 / 84

Combine all four losses

L = Lphysics
+ 10 Linitial
+ 10 Lboundary
+ Ldata

Loss weights

The factors 10 give the condition errors more influence at the start.

These are training choices, not constants from the heat equation.

All coefficients are nonnegative. One small total loss can conceal an under-enforced term, so we report each component separately.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN42 / 84

A numerical example of loss weighting

termraw lossweightcontribution
physics.0201.020
initial.01010.100
boundary.00310.030
data.0051.005

Total = 0.155

The initial-condition error contributes the most after weighting.

Weighting changes which violations the optimizer prioritizes.

Comparing raw and weighted losses helps diagnose training. Losses with different physical units require careful scaling in dimensional problems.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN43 / 84

Autograd tracks how outputs depend on inputs

x = torch.tensor([[2.0]],
                 requires_grad=True)
y = x ** 2

dy_dx = torch.autograd.grad(
    y, x, create_graph=True
)[0]
# dy_dx = tensor([[4.]])

Automatic differentiation

PyTorch records differentiable operations in a computation graph.

It applies the chain rule backward through those operations to calculate a derivative.

Autograd differentiates the network's mathematical operations. Numerical rounding still exists; a derivative being correct does not make the network's prediction correct.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN44 / 84

The chain rule handles stacked operations

z = 2x
y = z²

dy/dz = 2z; dz/dx = 2
dy/dx = (2z)(2) = 4z = 8x

at x=1: dy/dx = 8

Why this matters

A neural network stacks many operations.

The derivative of the final output combines the derivatives along its computation paths.

Backpropagation is an efficient implementation of this chain-rule calculation for many parameters.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN45 / 84

PINNs use two kinds of differentiation

Coordinate derivatives

∂û/∂t, ∂û/∂x, ∂²û/∂x²

These build the physics residual.

Parameter gradients

∂L/∂θ

These tell the optimizer how to update the network.

Both are needed in a PINN training step. The optimizer updates θ; it does not optimize the randomly sampled x and t.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN46 / 84

Keep the graph to differentiate twice

u_x = torch.autograd.grad(
    u, x, torch.ones_like(u),
    create_graph=True
)[0]
u_xx = torch.autograd.grad(
    u_x, x, torch.ones_like(u_x),
    create_graph=True
)[0]

create_graph=True

It keeps first derivatives differentiable, allowing a second derivative.

It also allows the final physics loss to backpropagate to the weights.

Do not use torch.no_grad() around the physics residual, including residual evaluation after training.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
3 · Building the PINN47 / 84

Second derivatives favor smooth activations

tanh

smooth first derivative
smooth second derivative

A practical choice for this heat equation.

ReLU

ReLU(z) = max(0,z)

Its second derivative is zero almost everywhere, and the slope has a kink at zero.

With raw x,t inputs and a plain ReLU MLP, spatial second derivatives provide little useful curvature information. Other PINN formulations may use different representations.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough48 / 84

A tensor is an array of numbers

x = torch.tensor([[0.2], [0.5], [0.8]])
t = torch.tensor([[0.1], [0.1], [0.1]])

print(x.shape)  # torch.Size([3, 1])

Shape (N,1)

N is the number of examples.

Each row holds one coordinate.

Here we query three positions at the same time.

Keep coordinate arrays as columns. Mixing shapes (N,) and (N,1) can accidentally create an (N,N) error matrix through broadcasting.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough49 / 84

Combine position and time into each row

coordinates = torch.cat((x, t), dim=1)
# [[0.2, 0.1],
#  [0.5, 0.1],
#  [0.8, 0.1]]

# shape: (3, 2)

dim=1

Concatenate along the column direction.

Each example now has the two inputs the network needs.

dim=0 would stack rows and produce the wrong layout. We want to preserve the N examples while adding input columns.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough50 / 84

Map inputs to a range suitable for tanh

normalized = 2 × coordinate − 1

0 → −1
.5 → 0
1 → 1

Input scaling

The domain is [0,1] for both x and t.

This transformation centers inputs near zero, where tanh is sensitive to changes.

Because normalization happens inside forward(), autograd includes its factor of 2 when differentiating with respect to the original coordinates.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough51 / 84

nn.Module holds the trainable layers

class PINN(nn.Module):
    def __init__(self, width=32):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(2, width), nn.Tanh(),
            nn.Linear(width, width), nn.Tanh(),
            nn.Linear(width, width), nn.Tanh(),
            nn.Linear(width, 1),
        )

Read the architecture

Linear(2,32): two inputs become 32 features.

Two more hidden layers refine those features.

Linear(32,1): predict one temperature.

The supplied script initializes every Linear layer using Xavier weights and zero biases.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough52 / 84

forward() defines a prediction

def forward(self, x, t):
    coordinates = torch.cat((x, t), dim=1)
    return self.net(2.0 * coordinates - 1.0)

u = model(x, t)
# shape: (N, 1)

A pointwise model

Each row is processed independently.

The output row corresponds to the input (x,t) row.

This independence matters for the derivative helper. Batch normalization or other operations that mix samples would change its assumptions.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough53 / 84

The CSV provides repeatable observations

x,t,u
0.0,0.0,0.000000000000
0.1,0.0,0.309016994375
0.2,0.0,0.587785252292
...
0.5,0.5,0.610498025266

121 rows

11 positions × 11 times, including the edges and time zero.

Training selects 16 interior, positive-time rows from this data.

The dots above abbreviate the file for display. The downloadable CSV contains every numeric row and no ellipses.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough54 / 84

Load and choose observations

x, t, u = load_data(path, device)
interior = (x > 0) & (x < 1) & (t > 0)
mask = interior.reshape(-1)
x, t, u = x[mask], t[mask], u[mask]
indices = torch.randperm(len(x))[:16]
x_d, t_d, u_d = x[indices], t[indices], u[indices]

Separate kinds of evidence

Initial and boundary values are already enforced by their own loss terms.

The data term uses selected interior observations.

The complete script puts indices on the same device as the tensors and fixes a seed to make the selection reproducible.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough55 / 84

Create physics points with gradient tracking

x_f = torch.rand(1000, 1, device=device,
                 requires_grad=True)
t_f = torch.rand(1000, 1, device=device,
                 requires_grad=True)

What the flags mean

rand samples uniform coordinates in [0,1).

requires_grad=True lets autograd differentiate outputs with respect to x_f and t_f.

We sample fresh physics points every epoch. Their coordinates are inputs, not trainable parameters.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough56 / 84

Create initial and boundary points

x_i = torch.linspace(0, 1, 64).reshape(-1, 1)
t_i = torch.zeros_like(x_i)
u_i = torch.sin(math.pi * x_i)

times = torch.linspace(0, 1, 64).reshape(-1, 1)
x_b = torch.cat((0 * times, 0 * times + 1))
t_b = torch.cat((times, times))

Fixed conditions

64 positions at t=0 check the initial shape.

64 times on each end give 128 boundary checks.

The complete script creates these tensors on the selected device. All boundary targets are zero.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough57 / 84

A small helper calculates derivatives

def derivative(y, x):
    return torch.autograd.grad(
        y, x,
        grad_outputs=torch.ones_like(y),
        create_graph=True,
    )[0]

Read the arguments

y: the outputs to differentiate.

x: the inputs to differentiate against.

ones_like(y): an all-one seed with matching shape.

Technically this is a vector-Jacobian product, the gradient of the summed outputs. Because rows are independent, each returned row is that sample's derivative.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough58 / 84

Implement the differential equation directly

def pde_residual(model, x, t, alpha):
    u = model(x, t)
    u_t = derivative(u, t)
    u_x = derivative(u, x)
    u_xx = derivative(u_x, x)
    return u_t - alpha * u_xx

One line per mathematical step

Predict temperature.

Compute its time derivative and spatial curvature.

Subtract the two sides of the heat equation.

The helper returns one residual per physics point, with shape (N,1). The loss will reduce this column to a scalar.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough59 / 84

Implement the four losses

r = pde_residual(model, x_f, t_f, alpha)
loss_f = r.square().mean()
loss_i = (model(x_i, t_i) - u_i).square().mean()
loss_b = model(x_b, t_b).square().mean()
loss_d = (model(x_d, t_d) - u_d).square().mean()

loss = loss_f + 10*loss_i + 10*loss_b + loss_d

Same pattern

For each rule: calculate a mismatch, square it, average it.

Then combine the scalar terms with weights.

The script's loss_terms() helper returns the raw terms so logs can show them separately from the weighted total.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough60 / 84

One epoch makes one optimizer update

optimizer.zero_grad(set_to_none=True)
terms = loss_terms(model, physics_points(...),
                   conditions, data, alpha)
loss = (terms['physics'] + 10*terms['initial']
        + 10*terms['boundary'] + terms['data'])
loss.backward()
optimizer.step()

The optimizer

Adam receives model.parameters() and learning rate 0.001.

backward computes weight gradients.

step changes weights; zero_grad clears previous gradients.

The displayed physics_points(...) call is explanatory shorthand. The downloadable script contains complete, runnable calls.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough61 / 84

Prediction after training is simpler

model.eval()
with torch.no_grad():
    x = torch.tensor([[0.5]])
    t = torch.tensor([[0.5]])
    predicted_u = model(x, t).item()

Two different purposes

eval() sets evaluation behavior for certain layers.

no_grad() disables gradient tracking for ordinary predictions.

Residual evaluation still needs gradients.

An MLP containing only Linear and tanh has the same forward behavior in train and eval modes, but calling eval is a good inference habit.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
4 · PyTorch walkthrough62 / 84

Save the model so you can use it again

torch.save({
    'state_dict': model.state_dict(),
    'width': args.width,
    'alpha': args.alpha,
}, output / 'pinn_heat_equation.pt')

What is stored

state_dict holds learned weights and biases.

width reconstructs the architecture.

alpha records which physical problem was solved.

The script's --predict command loads these values, reconstructs the network, and evaluates the requested coordinate.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate63 / 84

Download the complete example

Files to save in one folder

What is included

Runnable code with configurable epochs, network width, sampling, and loss weights.

Data loading, plots, metrics, checkpoints, and prediction from saved weights.

The HTML deck includes the files internally, so the download buttons also work when you open this page locally. The same files are available alongside the deck in the site.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate64 / 84

Set up Python and install dependencies

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

Why these commands?

venv creates an isolated Python environment.

activate selects it for this terminal.

pip installs PyTorch, NumPy, and Matplotlib.

Use Python 3.10 or newer. On Windows PowerShell, activate with .venv\Scripts\Activate.ps1. CPU is sufficient; CUDA is used if available.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate65 / 84

Run a short test, then train the model

# Quick check: 10 optimizer steps
python pinn_heat_equation.py --epochs 10 \
    --n-physics 128 --output-dir output-smoke

# Full tutorial run
python pinn_heat_equation.py --epochs 2500

Default configuration

32 neurons per hidden layer.

1,000 fresh physics points per step.

16 interior observations and Adam learning rate 0.001.

A 10-step run checks that the program works; it is too short to judge final solution quality. Training time depends on your machine.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate66 / 84

Read the training log

epoch 1    | total 7.932e+00
           | physics 2.151e-02
           | initial 5.412e-01
           | boundary 2.189e-01
           | data 3.100e-01

epoch 2500 | total 2.006e-04

Scientific notation

7.932e+00 means 7.932.

2.006e−04 means 0.0002006.

The total is weighted; component losses are reported before weighting.

These numbers are from a real CPU run with seed 7. Because physics points change and Adam updates adaptively, individual losses need not decrease at every step.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate67 / 84

Compare the learned field with the exact field

Actual training result: exact temperature, PINN prediction, and absolute error over position and time.
Actual run: 2,500 Adam steps, seed 7, 16 observations. Exact and prediction use the same 0–1 color scale. The error plot has its own scale.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate68 / 84

Measure accuracy and physics separately

Relative solution error

0.376%

‖û−u‖₂ / ‖u‖₂ on a 101×101 reference grid.

Maximum temperature error

0.00398

Largest absolute difference on that grid.

Physics residual RMSE

0.01198

sqrt(mean(r²)) at 1,000 newly sampled points.

These are measured results from this run, not a guarantee for other hardware or seeds. The reference grid is not used in training, though some coordinates overlap the source CSV.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate69 / 84

Loss curves explain how learning progressed

Actual loss history for total, physics, initial, boundary, and data losses over 2500 training steps.
The y-axis is logarithmic: equal vertical distances represent ratios. Temporary spikes can occur while the overall trend improves.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate70 / 84

Find the saved model, plots, and numerical logs

file under output/purpose
pinn_heat_equation.ptweights + width + α
pinn_results.pngsolution and absolute error
loss_history.pngtraining curves
loss_history.csvlosses from every step
metrics.jsonconfiguration + validation metrics
Give each experiment a different --output-dir to keep previous results.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
5 · Run and evaluate71 / 84

Query a trained model without retraining

python pinn_heat_equation.py --predict 0.5 0.5

# For the verified tutorial run:
# u(x=0.5, t=0.5) = 0.61132526
exact answer = 0.61049803
trained prediction = 0.61132526
absolute error ≈ 0.000827
The command uses output/pinn_heat_equation.pt by default. Use --checkpoint to select a different saved model.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks72 / 84

Train using physics and conditions only

python pinn_heat_equation.py --data-weight 0 \
    --output-dir output-physics-only

What remains?

The PDE residual, initial profile, and fixed end temperatures.

The observation term contributes zero to the total.

Compare the result with the standard run.

This forward problem is fully specified by its PDE and conditions. The script still reads the sample data for consistent logging, but it contributes no training gradient when its weight is zero.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks73 / 84

Compare with fitting conditions and observations

python pinn_heat_equation.py --physics-weight 0 \
    --output-dir output-without-physics

Check the difference

The network still fits initial values, boundaries, and observations.

The PDE loss no longer influences weight updates.

Compare errors between measurement locations.

The script still computes and reports the PDE term. Its coefficient is zero in the training objective.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks74 / 84

Make heat diffuse more slowly

python pinn_heat_equation.py --alpha 0.01 \
    --data heat_slow.csv --output-dir output-slow

Predict the outcome first

The sine profile should decay more slowly.

At the center and t=1, the exact value becomes about 0.9060.

Use a new CSV path: the script creates matching synthetic data when the file is absent. Reusing α=0.1 observations with α=0.01 would describe inconsistent problems.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks75 / 84

Reduce the number of physics checks

python pinn_heat_equation.py --n-physics 100 \
    --output-dir output-fewer-points

A useful tradeoff

Each step becomes cheaper.

Each step checks fewer coordinates.

Compare residuals on new points, solution error, and runtime.

Fewer points do not always cause worse final results. Sampling, training length, model size, and optimization all interact.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks76 / 84

An inverse problem learns a physical parameter

forward: known α → find u

inverse: measurements of u
→ estimate α and learn u

What must change?

Represent positive α with a trainable parameter.

Include it in the optimizer and residual calculation.

Use observations that contain enough information to identify α.

This is an extension, not implemented in the supplied forward-problem script. Measurements only at t=0 cannot reveal the cooling rate.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks77 / 84

Diagnose a run that does not learn

symptomcheck
outputs all near zeroinitial loss, its weight, and targets
physics loss stays largeautograd graph, tanh, sampling, learning rate
shape mismatch or strange lossall x,t,u arrays are (N,1)
fits data but violates physicsPDE weight and residual on new points
data conflicts with the PDEα and units match the measurements
Inspect individual losses and plots. More epochs help only if the problem formulation and gradients are correct.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks78 / 84

Check your understanding: which points need labels?

Question

You sample (x,t)=(0.37,0.64) to enforce the heat equation.

Do you need to know its true temperature before calculating the physics loss?

Try answering aloud before revealing the explanation.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks79 / 84

Check your understanding: why does the zero model fail?

Question

The network predicts û=0 everywhere.

It obeys the PDE and both boundaries. Which loss rejects it?

This demonstrates why conditions and observations matter even when the residual is zero.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks80 / 84

Keep these terms distinct

termmeaning in this example
θ / parametersnetwork weights and biases
α / diffusivityknown physical coefficient
û / predictionnetwork's temperature estimate
r / residualviolation of the heat equation
loss / objectiveweighted scalar to minimize
gradienthow output or loss changes with an input
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks81 / 84

When are PINNs a useful choice?

Useful applications

Sparse measurements with known physics.

Estimating unknown coefficients.

A smooth function that can be queried and differentiated.

Practical limitations

Training can be difficult for stiff or multiscale equations.

Low sampled loss gives no universal accuracy guarantee.

Traditional numerical solvers are often faster and more reliable.

The tutorial's smooth heat equation is deliberately manageable. It should not be taken as evidence that every PDE will be equally easy.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks82 / 84

Continue with primary references

The first paper develops PINNs for forward and inverse problems. The PyTorch references explain the operations used in our implementation.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks83 / 84

Your next step: train, predict, and explain

  1. Download the three files and run the short check.
  2. Train for 2,500 steps and inspect both saved figures.
  3. Predict u(0.5,0.5) and compare with 0.610498.
  4. Run the physics-only experiment and explain the result.
A PINN approximates the solution with a smooth network, checks physics with derivatives, learns from losses, and must still be validated.
Balbir Singh · October 19, 2026
Generated by the visualize claude skill
6 · Experiments and checks84 / 84

Validate your implementation before training

python pinn_heat_equation.py --self-test

# Expected output:
# 4 checks passed

What is checked

The exact solution's PDE residual, prediction shape, parameter count, and finite gradients through the full loss.

Training also rejects nonfinite gradients and parameters.

All student coding labs
These executed checks support the mathematical reasoning. The complete example contains its own data generator and runs without another presentation.