Chapter 20
20 min read
Section 173 of 353

Direction Fields and Solution Curves

Introduction to Differential Equations

Learning Objectives

By the end of this section you will be able to:

  1. Read a differential equation as a recipe that hands you one slope at every point in the plane.
  2. Sketch a direction field by hand using isoclines.
  3. Trace solution curves through any initial condition without solving the equation symbolically.
  4. Predict long-term behaviour (equilibria, blow-up, oscillation) just from the picture.
  5. Connect the geometric idea of "follow the field" to Euler's method and to differentiable solvers used in modern machine learning.

The Big Picture: A Slope at Every Point

"You don't need to solve an equation to see what it does." — the moral of this section.

A first-order differential equation written as dydx=f(x,y)\dfrac{dy}{dx} = f(x,\, y) is doing something almost mechanical: pick any point (x0,y0)(x_0,\, y_0) in the plane, evaluate ff there, and the equation hands you back one number — the slope of the solution curve that happens to pass through that point. Do this everywhere, sketch each slope as a tiny tangent segment, and you have built a direction field (also called a slope field).

The pay-off is enormous. Before you do any algebra at all you can see what every solution must look like: where curves grow, where they decay, where they curl into closed loops, where two neighbours diverge, and where they all converge. Whole textbooks could be written on solving differential equations and missing this, the first thing you should always do.

The shift in mindset

A differential equation is not a problem to solve — at least, not first. It is a field of slopes, painted across the plane. Solution curves are the threads that, at every point, are tangent to the local slope. Section 20.1 told you what an ODE is. Section 20.2 teaches you how to read one.


One Point at a Time: the Slope Microscope

Before we paint the whole plane, drag a single yellow dot. The equation dy/dx=f(x,y)dy/dx = f(x,\, y) evaluates ff at the dot and draws the resulting slope as a tiny tangent. Toggle Show whole field once you have the idea — the picture you have been building one point at a time fills in at once.

Loading slope microscope…
Notice how at y=0y = 0 the equation dy/dx=ydy/dx = y gives slope 0 — every tick on the x-axis is horizontal. That is the first qualitative fact a direction field hands you: where are the equilibria?

Definition of a Direction Field

Direction field of dy/dx=f(x,y)dy/dx = f(x,\, y). Pick a region RR2R \subset \mathbb{R}^2 and a finite set of points (xi,yj)R(x_i,\, y_j) \in R. At each point draw a short line segment with slope f(xi,yj)f(x_i,\, y_j), centred on (xi,yj)(x_i,\, y_j). The collection of segments is called the direction field, or slope field, of the equation.

Three subtleties make this definition richer than it looks:

  1. The segments are direction-less: a slope of +2+2 draws the same picture as one of 2-2… wait, that is wrong. They have the same magnitude, but different signs. A slope is a rise-over-run, so the segment tilts up to the right when f>0f > 0 and down to the right when f<0f < 0. The arrow tip is conventionally omitted — you should be able to walk the curve in either direction.
  2. If ff is unbounded (say f(x,y)=1/yf(x,\, y) = 1/y near y=0y = 0) we draw vertical hash-marks or simply leave the region blank — the slope is "infinite", meaning solutions cross that horizontal line vertically.
  3. The direction field exists for every first-order ODE in the form dy/dx=f(x,y)dy/dx = f(x,\, y) — even ones with no closed-form solution. That is exactly why it is so useful.

Isoclines: How to Draw the Field by Hand

Painting a slope at every grid point one-by-one is tedious. The trick that working mathematicians have used since the nineteenth century is the isocline:

Isocline of slope c

For the equation dy/dx=f(x,y)dy/dx = f(x,\, y), the curve f(x,y)=cf(x,\, y) = c is called the isocline of slope cc. Every point on this curve has the same slope, namely cc. So a hand sketch reduces to three steps:

  1. Pick a handful of slope values c=2,1,12,0,12,1,2c = -2,\, -1,\, -\tfrac{1}{2},\, 0,\, \tfrac{1}{2},\, 1,\, 2.
  2. Draw each isocline f(x,y)=cf(x,\, y) = c (often just a line or a simple curve).
  3. Along each isocline, draw parallel tick marks at slope cc. That is the field.

Drag the slider below. Notice that for dy/dx=x+ydy/dx = x + y, the isocline x+y=cx + y = c is a 45° line — so the ticks along it are all parallel with the same fixed slope cc. Click Pin this isocline a few times and the entire field crystallises out of the pinned scaffolding.

Loading isocline explorer…
Two special isoclines deserve names. The nullcline is f(x,y)=0f(x,\, y) = 0 — horizontal segments mark where solutions instantaneously stop changing in yy. Whenever the nullcline is itself a solution curve (so that derivatives match identically), it is an equilibrium.

Solution Curves: Following the Arrows

A solution curve of dy/dx=f(x,y)dy/dx = f(x,\, y) through the point (x0,y0)(x_0,\, y_0) is a differentiable function y=φ(x)y = \varphi(x) such that

φ(x0)=y0andφ(x)=f(x,φ(x)) for every x in some interval.\varphi(x_0) = y_0 \qquad \text{and} \qquad \varphi'(x) = f\bigl(x,\, \varphi(x)\bigr)\ \text{for every } x\text{ in some interval.}

Geometrically: at every point on the curve, the tangent line agrees with the direction-field segment at that point. Mathematically you could say the curve is everywhere tangent to the field. Visually, it is the path a tiny ball would follow if you placed it down and let the arrows push it sideways.

Because the equation only fixes the slope at each point — not the height — through every starting point there is a different solution curve. The initial condition y(x0)=y0y(x_0) = y_0 is the choice that pins down which curve.

Two solution curves through the same point can collide only if the slope rule is misbehaving (non-Lipschitz, blowing up). For well-behaved ff, distinct curves never cross — if they did, both would have to share the slope at the crossing point and therefore be identical, contradicting their distinctness. We will sharpen this into the existence-uniqueness theorem in Section 20.5.

Interactive Playground

Click anywhere on the canvas to drop an initial condition. The playground integrates forward and backward and draws the solution curve that exactly follows the local slope field. Cycle through the equation presets and notice how each one organises the plane differently: dy/dx=ydy/dx = y produces a fan of exponentials, dy/dx=y(1y)dy/dx = y(1-y) produces sigmoid curves saturating between two equilibria, and dy/dx=xdy/dx = -x produces parabolas.

Loading direction-field playground…
Try to predict the shape of a solution before you click — sweep the cursor across the field and imagine yourself being pushed along the arrows. The kind of intuition you build here pays off when you study phase planes in Chapter 23.

Worked Example: Sketch dy/dx = x − y by Hand

We will sketch dydx=xy\dfrac{dy}{dx} = x - y over the window 3x,y3-3 \le x,\, y \le 3 and use isoclines to nail it down. Try the steps on paper first; expand the panel below to check.

Show the full hand-worked construction
Step 1. Choose slope values.

Pick c{2,1,0,1,2}c \in \{-2,\, -1,\, 0,\, 1,\, 2\}. Five lines is plenty for a hand sketch.

Step 2. Solve f(x, y) = c for the isocline equation.

xy=c    y=xc.x - y = c \iff y = x - c. Each isocline is a 45° line, shifted up by c-c.

slope cisocline equationy-intercept
−2y = x + 2(0, 2)
−1y = x + 1(0, 1)
0y = x(0, 0)
1y = x − 1(0, −1)
2y = x − 2(0, −2)
Step 3. Along each isocline, draw parallel ticks at slope c.

On the line y=xy = x, draw small horizontal ticks (slope 0). On y=x1y = x - 1, draw ticks at slope 1 (parallel to y=xy = x itself!). On y=x2y = x - 2, draw steeper ticks at slope 2. Mirror across y=xy = x for the negative slopes.

Step 4. Spot the special line.

On y=x1y = x - 1 the slope is x(x1)=1x - (x-1) = 1, which is exactly the slope of the isocline itself. So y=x1y = x - 1 is tangent to its own isocline everywhere — it is a solution. Indeed plug in: if y=x1y = x - 1 then y=1y' = 1 and xy=x(x1)=1. x - y = x - (x-1) = 1.\ \checkmark

Step 5. Read the global picture.
  • Above the line y=x1y = x - 1, slopes are smaller than the line itself, so curves drift down toward it.
  • Below the line, slopes are larger, so curves rise toward it.
  • In both cases, curves approach y=x1y = x - 1 asymptotically as xx \to \infty. That special solution is an attractor.
Step 6. Check against the closed-form solution.

The equation is linear and (we will solve in 21.1) has general solution

y(x)=x1+Cex.y(x) = x - 1 + C\,e^{-x}.

For any CC, the term CexCe^{-x} decays to 0 as xx \to \infty, leaving yx1y \to x - 1. That is exactly the behaviour the sketch predicted — without solving anything!

Now turn back to the Isocline Explorer above, set the equation to dy/dx=xydy/dx = x - y, pin c{2,1,0,1,2}c \in \{-2, -1, 0, 1, 2\}, and verify the sketch you just made matches the rendered field.


From Picture to Number: Euler's Method

"Follow the arrows" is a beautiful instruction for the eye but useless for a computer. To turn the field into actual coordinates we discretise time. Stand at (xn,yn)(x_n,\, y_n), read off the local slope f(xn,yn)f(x_n,\, y_n), and step forward by a small amount hh along that slope:

yn+1=yn+hf(xn,yn),xn+1=xn+h.y_{n+1} = y_n + h\,f(x_n,\, y_n), \qquad x_{n+1} = x_n + h.

This is Euler's method, the simplest possible numerical ODE solver. Geometrically you are walking along the field but pretending the slope is constant between samples — a piecewise linear approximation to the smooth true curve.

Drag the step size hh in the tracer below. With h=0.05h = 0.05 the orange staircase hugs the green "true" curve. Push it up to h=1.0h = 1.0 and the staircase peels away — each step over-shoots a slope it cannot see is curving. This is the single most important picture in numerical analysis.

Loading Euler tracer…
Euler's method is the warm-up. Better methods (midpoint, Runge-Kutta, adaptive schemes) take more slope samples per step to match higher-order Taylor terms. We will meet them in Section 20.4. Section 20.5 will tell you when the green "true" curve we are approximating actually exists and is unique.

Reading a Solution Off the Field Without Solving

Once you have a sketch you can answer most qualitative questions immediately. For dy/dx=y(1y)dy/dx = y(1 - y) (logistic), inspecting the field tells you:

QuestionAnswer from the fieldWhy
Equilibria?y = 0 and y = 1Both make f(x, y) = 0 — horizontal ticks everywhere along these lines.
Long-term y if y(0) = 0.1?y → 1All ticks between 0 and 1 point upward; the curve is funnelled into y = 1.
Long-term y if y(0) = -0.1?y → -∞Below y = 0 the slope y(1 - y) is negative; the curve runs away downward.
Is y = 0 stable?No (repelling)Slightly perturb y and ticks push you AWAY from 0.
Is y = 1 stable?Yes (attracting)Slightly perturb y and ticks push you BACK toward 1.

Not one of these answers required solving the equation. That is the super-power direction fields give you — qualitative analysis comes free with a sketch.


Python Implementation

Here is the code that produces a publication-grade direction field sketch. It uses dy/dx=xydy/dx = x - y so you can cross-check it against the worked example, but the equation is one line — swap it for anything you like.

Build a direction field, then overlay solution curves
🐍direction_field.py
1NumPy

Vectorised arithmetic over arrays. We will evaluate the slope at thousands of points at once, so any non-vectorised loop would be wasteful.

2matplotlib.pyplot

We need quiver() to draw small arrows and plot() to overlay solution curves. plt is the standard alias.

6Define f(x, y)

This single function IS the differential equation. It takes coordinates and returns one number: the slope. Anything you can write here — even a discontinuous Python expression — defines a valid direction field.

7Slope rule: x - y

We chose dy/dx = x - y because it shows isoclines that are straight lines (y = x - c) and a solution curve y = x - 1 sitting in the middle of the picture.

EXAMPLE
f(2, 0.5) returns 1.5
10x sample points

21 evenly spaced x-values from −4 to 4. That gives a column every 0.4 units, dense enough to read the field but sparse enough to keep the arrows distinct.

EXAMPLE
x_vals = [-4, -3.6, …, 3.6, 4]
11y sample points

17 evenly spaced y-values from −3 to 3. Aspect ratios for x and y do not have to match — pick what reads well visually.

EXAMPLE
y_vals = [-3, -2.625, …, 2.625, 3]
12Build the grid

np.meshgrid pairs every x with every y. X and Y are 17×21 arrays so the (i, j) cell holds (x_vals[j], y_vals[i]).

EXAMPLE
X.shape == (17, 21), Y.shape == (17, 21)
15Evaluate slopes

Because f only uses + and −, NumPy broadcasts it across the whole grid. slopes is the same shape as X and stores f(x, y) at every grid point.

EXAMPLE
slopes[i, j] == X[i, j] - Y[i, j]
19Length of (1, slope)

The tangent direction at a point is (1, slope) — one step right, slope steps up. Its length is √(1 + slope²). We need it to normalise so all arrows look the same size.

EXAMPLE
If slope = 3, mag = √10 ≈ 3.162
20x-component of unit tangent

Divide 1 by the length to get a tangent that points purely along x for shallow slopes and shrinks for steep ones. matplotlib's quiver needs both components.

21y-component of unit tangent

The vertical component of the unit tangent. Steep slopes make this close to ±1; shallow slopes keep it close to 0.

EXAMPLE
slope = 3 ⇒ V = 3/√10 ≈ 0.949
24Figure

A 9-by-6-inch canvas gives enough room for the arrows to breathe without bunching up.

25quiver call

quiver(X, Y, U, V, colors) draws an arrow at each (X, Y) with components (U, V), coloured by the fifth argument. pivot='mid' centres the arrow on its sample point so it visually represents the tangent line through that point.

27Colour legend

Cool / warm colours encode the underlying slope so even when arrows look the same length the magnitude is still readable.

30scipy.integrate.odeint

Internally an adaptive multi-step solver — far more accurate than the Euler method we use for intuition. We borrow it to draw the 'true' solution curves on top of the field.

31Dense x for plotting curves

400 x-samples give the solution curve a smooth look even when the actual integrator only stores a handful of internal points.

32Loop over initial conditions

Five seeds chosen to land in the four 'regions' of the picture: above and below y = x − 1, plus one ON that special line. Notice how each curve obeys the local arrows — that is the entire point of a direction field.

33Solve the IVP

odeint expects f(y, x) — note the argument order is the opposite of our f(x, y). The lambda swaps the order, hands back the slope, and odeint integrates it.

EXAMPLE
y0 = 1.0 ⇒ sol[:, 0][−1] ≈ 3.0 (matches y = x − 1 + 2e^{−x})
34Draw the curve

Black-on-warm-arrows reads well; alpha=0.7 keeps the field visible underneath.

21 lines without explanation
1import numpy as np
2import matplotlib.pyplot as plt
3
4# The differential equation we want to visualise: dy/dx = f(x, y)
5# Try changing this line to feel how the field morphs.
6def f(x, y):
7    return x - y                # slope at the point (x, y)
8
9# 1. Lay down a grid of points where we will sample slopes.
10x_vals = np.linspace(-4, 4, 21)
11y_vals = np.linspace(-3, 3, 17)
12X, Y = np.meshgrid(x_vals, y_vals)
13
14# 2. At every grid point, ask the equation: "what slope here?"
15slopes = f(X, Y)
16
17# 3. Build a UNIT direction vector (1, slope) and normalise so all
18#    arrows are the same length. The colour will encode the magnitude.
19mag = np.sqrt(1.0 + slopes ** 2)
20U = 1.0 / mag                   # x-component of the tangent
21V = slopes / mag                # y-component of the tangent
22
23# 4. Draw the field.
24plt.figure(figsize=(9, 6))
25plt.quiver(X, Y, U, V, slopes, cmap="coolwarm",
26           pivot="mid", scale=30, width=0.003)
27plt.colorbar(label="slope dy/dx")
28
29# 5. Overlay a few solution curves by integrating from chosen seeds.
30from scipy.integrate import odeint
31xs = np.linspace(-4, 4, 400)
32for y0 in [-2.5, -1.0, 0.0, 1.0, 2.5]:
33    sol = odeint(lambda y, x: f(x, y), y0, xs)
34    plt.plot(xs, sol[:, 0], "k-", linewidth=1.4, alpha=0.7)
35
36plt.title("Direction field for dy/dx = x - y, with five solution curves")
37plt.xlabel("x"); plt.ylabel("y")
38plt.xlim(-4, 4); plt.ylim(-3, 3)
39plt.grid(alpha=0.3)
40plt.show()

Three habits to internalise from this code: (1) the equation lives in a single function f(x,y)f(x,\, y), (2) the field is plotted before any solutions, and (3) numerical solutions are drawn on top of the field, never instead of it. Always lay down the scaffolding first — the field reveals what to expect; the solver confirms it.


PyTorch: Differentiable ODEs

Once an ODE solver is written in PyTorch tensor ops, the entire trajectory becomes differentiable with respect to anything inside ff — including the initial condition. This is the key idea behind Neural ODEs: treat a deep network as a continuous-time flow and learn its right-hand side. Here is the smallest non-toy example: a hand-written RK4 integrator that lets autograd propagate gradients through it.

Backprop through an RK4 integrator
🐍differentiable_ode.py
1Import torch

Brings in tensors and autograd. We are not using torchdiffeq here on purpose — building it by hand makes the autograd machinery visible.

5RHS as a tensor function

Because f is a pure torch op, every call records a node in the computational graph. That is what lets us differentiate through the integrator at the end.

EXAMPLE
f(tensor(1.0), tensor(0.5)) == tensor(0.5)
6Type hints

Both x and y are tensors of the same shape — usually scalar here, but the same code generalises to vector-valued ODE systems.

9Define one RK4 step

RK4 evaluates the slope at four cleverly chosen points and forms a weighted average. The four-evaluation cost buys a much smaller per-step error than Euler.

10k1: slope at the current point

Same as the first thing Euler does. If we stopped here we would be doing Euler with the result we discard at line 15.

EXAMPLE
at (x, y) = (0, 0.5): k1 = 0 − 0.5 = −0.5
11k2: slope at a half-step probe (using k1)

Where would we land halfway if we trusted k1? Evaluate the slope THERE. This is the heart of higher-order methods — use earlier estimates to look ahead.

12k3: refined half-step (using k2)

Same probe location as k2 but using the freshly updated half-step slope. Most of the accuracy gain of RK4 comes from these two probes.

13k4: slope at the far end

Predict where we would arrive using k3, evaluate the slope there. The four samples will be combined with Simpson-rule weights.

14Weighted update

1/6 · (k1 + 2k2 + 2k3 + k4) is Simpson's rule applied to the slope samples. This single step is fourth-order accurate in h.

EXAMPLE
y_new = y + (h/6) · (slope average over the interval)
17integrate(): glue many steps together

Plain Python loop — no special ODE solver. We append every (x, y) pair to a list so we can plot or differentiate through them.

19Number of steps

If we want to go from x0 = 0 to x1 = 2 with h = 0.05 we will take 40 RK4 steps.

EXAMPLE
n_steps = int(2.0 / 0.05) = 40
20Start tracking xs

We seed the lists with the initial values. xs[0] is a torch tensor so we can concatenate later.

21Start tracking ys

y0 is whatever the caller hands in — possibly a parameter with requires_grad=True (see line 31).

22Step loop

We pull the most recent (x, y), advance by one RK4 step, and store both. Every iteration adds four edges to the autograd graph.

23Current x

xs[-1] is the most recently appended x. After step i it equals x0 + i·h.

EXAMPLE
iteration 10: x = 0.5
24Current y

ys[-1] is the most recently computed y. This is what we pass into rk4_step.

25Compute next y

rk4_step receives the autograd-tracked y, so the resulting new_y carries the gradient lineage all the way back to y0.

26Advance x

Plain tensor addition. x is not learnable here, but if it were (e.g. an irregular sampling) the same machinery would work.

27Stack into tensors

Lists of scalar tensors become 1D tensors of length n_steps+1, ready for vector ops or plotting.

30Make y0 a parameter

requires_grad=True is the magic word. Now y0 lives on autograd's tape, and every downstream operation will remember 'who you came from'.

31Run the integrator

Same integrate() as before — autograd does not need a special version. The trajectory ys is a length-41 tensor whose last entry is ys[-1].

34Pick a target

A teacher-style boundary condition: 'I want the curve to end up at 2.5.' This is the kind of objective shooting methods use.

35Squared error at the endpoint

A scalar loss is required for backward(). Here it depends on every RK4 step that came before, all the way back to y0.

EXAMPLE
If ys[-1] = 1.5 and target = 2.5, loss = 1.0
36Backprop through the ODE

loss.backward() walks the entire graph — every f, every weighted sum, every step — and accumulates ∂loss/∂y0 in y0.grad. This is the trick behind Neural ODEs.

38Read off y0

Before optimisation, y0 is still whatever we set it to (0.5). With an optimiser we would now do y0 -= lr · y0.grad to shrink the loss.

EXAMPLE
y0 = 0.5
39Endpoint value

What the trajectory actually reached at x = 2. The gradient at the bottom tells us which way to push y0 to move this value toward 2.5.

40Gradient at the seed

A single number that summarises how a one-unit nudge to y0 changes the endpoint loss. Differentiating through an integrator is the foundation of modern continuous-time deep learning.

14 lines without explanation
1import torch
2
3# Same DE as before, but now its right-hand side is a torch tensor op,
4# so every step is differentiable end-to-end.
5def f(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
6    return x - y
7
8# A single RK4 step. Works on tensors, plays nicely with autograd.
9def rk4_step(x: torch.Tensor, y: torch.Tensor, h: float) -> torch.Tensor:
10    k1 = f(x,           y)
11    k2 = f(x + h / 2,   y + (h / 2) * k1)
12    k3 = f(x + h / 2,   y + (h / 2) * k2)
13    k4 = f(x + h,       y + h * k3)
14    return y + (h / 6.0) * (k1 + 2 * k2 + 2 * k3 + k4)
15
16def integrate(y0: torch.Tensor, x0: float, x1: float, h: float = 0.05):
17    """Return (xs, ys) tracing the IVP y'(x) = f(x, y), y(x0) = y0."""
18    n_steps = int((x1 - x0) / h)
19    xs = [torch.tensor(x0)]
20    ys = [y0]
21    for _ in range(n_steps):
22        x = xs[-1]
23        y = ys[-1]
24        ys.append(rk4_step(x, y, h))
25        xs.append(x + h)
26    return torch.stack(xs), torch.stack(ys)
27
28# y0 is a *parameter* we want to optimise — note requires_grad=True.
29y0 = torch.tensor(0.5, requires_grad=True)
30xs, ys = integrate(y0, x0=0.0, x1=2.0)
31
32# Suppose we want the curve to hit y(2) = 2.5. Differentiate the
33# terminal value with respect to y0 and gradient-descend on it.
34target = torch.tensor(2.5)
35loss = (ys[-1] - target).pow(2)
36loss.backward()
37
38print(f"y0 = {y0.item():.4f}")
39print(f"y(2) reached = {ys[-1].item():.4f}")
40print(f"dLoss/dy0   = {y0.grad.item():.4f}")
41# autograd has walked back through every RK4 step.
In practice you would reach for torchdiffeq, which uses the adjoint method to backpropagate in O(1) memory regardless of the number of steps. But the picture is exactly the one above: every slope evaluation is a node in the computational graph, and the gradient flows back along it.

Real-World Applications

DomainEquationWhat the field shows you
Newton's law of coolingdT/dt = -k(T - Tₐ)Horizontal ticks at T = Tₐ — the ambient temperature is the asymptote of every cooling curve, no matter where you start.
Logistic populationdP/dt = rP(1 - P/K)Two equilibria (P = 0 and P = K). The field reveals carrying capacity without any algebra.
RC charging circuitdV/dt = (Vs - V)/(RC)All curves are funnelled to the source voltage Vs — the charge time is read off the slope at the start.
Free-falling object (with drag)dv/dt = g - kvHorizontal ticks where v = g/k — that is terminal velocity. Both 0-start and high-speed-start curves approach it.
Tumour growth (Gompertz)dN/dt = αN ln(K/N)Field saturates as N → K. The inflection point of any solution lies on the isocline of maximum slope.

Machine Learning Connection

Direction fields are not just classical. Three modern uses keep them relevant:

1. Gradient flow as a direction field

Stochastic gradient descent is a discretised ODE: dθdt=L(θ)\dfrac{d\theta}{dt} = -\nabla L(\theta). Plotting L-\nabla L as a direction field on the loss surface lets you see the optimisation trajectory before you ever run a step. Saddle points, basins, and ridges all show up as features of the field.

2. Neural ODEs and continuous normalising flows

A Neural ODE replaces a discrete stack of residual blocks with a continuous-time flow dzdt=fϕ(z,t)\dfrac{dz}{dt} = f_\phi(z,\, t) whose right-hand side fϕf_\phi is a neural net. Training it is exactly the differentiable-integrator picture above — backprop through the entire trajectory.

3. Diffusion models as score fields

A diffusion model learns the score sϕ(x,t)=xlogpt(x)s_\phi(x,\, t) = \nabla_x \log p_t(x). The sampler then walks a reverse-time SDE whose drift is the score — again a direction field, this time across the data manifold.


Test Your Understanding

1. For dy/dx = y − x, where are the slopes zero?
On the nullcline y=xy = x the slope is yx=0y - x = 0. So every tick along the line y=xy = x is horizontal — this is where solution curves momentarily flatten.
2. Two solution curves through the same point — when can that happen?
Never, if ff is Lipschitz in yy. If two solutions agreed at one point they would share the slope there, and uniqueness then forces them to agree forever. Crossings can appear only when the field is badly behaved (e.g. dy/dx=ydy/dx = \sqrt{|y|} at y=0y = 0 — see Section 20.5).
3. Euler's method with h = 0.5 gives y₃ for y' = y, y(0) = 1?

Step by step:

  • y1=y0+hy0=1+0.51=1.5y_1 = y_0 + h \cdot y_0 = 1 + 0.5 \cdot 1 = 1.5
  • y2=1.5+0.51.5=2.25y_2 = 1.5 + 0.5 \cdot 1.5 = 2.25
  • y3=2.25+0.52.25=3.375y_3 = 2.25 + 0.5 \cdot 2.25 = 3.375

The true value is e1.54.482e^{1.5} \approx 4.482. Euler with h=0.5h = 0.5 is already 25% low — a vivid demonstration of why step size matters.

4. Why does the picture of dy/dx = y(1 − y) have two distinct horizontal lines?
Because y(1y)=0y(1 - y) = 0 at both y=0y = 0 and y=1y = 1. These are the two equilibria — the field is horizontal on both. Between them the slope is positive; outside, the slope flips, telling you y=1y = 1 is an attractor and y=0y = 0 is a repeller.
5. Sketching trick: the equation is dy/dx = x². What do the isoclines look like?
The isocline of slope cc is x2=cx^2 = c, i.e. x=±cx = \pm\sqrt{c} for c0c \ge 0. So the isoclines are vertical lines and there are NONE for negative slope — every tick in the picture points upward (or is horizontal on the y-axis). The corresponding family of solutions is y=x3/3+Cy = x^3/3 + C, all cubic curves shifted vertically.

Summary

The whole section in one sentence: a differential equation paints a field of slopes, and solution curves are the threads everywhere tangent to it.

IdeaWhat you should be able to do
Direction fieldDraw a small tangent at each grid point with slope f(x, y).
IsoclineRecognise that f(x, y) = c is a curve of constant slope c, and use it to sketch the field by hand.
Solution curveTrace a curve that is tangent to the field at every point — pinned down by an initial condition.
EquilibriumRead off solutions of f(x, y) = 0 directly from the picture.
StabilityUse the field around an equilibrium to tell whether it attracts or repels nearby solutions.
Euler's methodTurn 'follow the field' into a numerical recipe yₙ₊₁ = yₙ + h·f(xₙ, yₙ).
Differentiable solversImplement the recipe in PyTorch so gradients flow back through the entire trajectory.
Where this leads. Section 20.3 turns the symbolic dial: when can the field be integrated by hand using separation of variables? Section 20.4 sharpens Euler into Runge-Kutta. Section 20.5 asks the deepest question — when does a solution curve through a given point even exist, and is it unique? Every answer there will be a refinement of the picture you have just learned to read.
Loading comments...