Foundations to FrontierPart VII: Applied mathematics and computationBezhig

W05: From differential equations to trustworthy simulation

5 exercises, each with a complete solution. 1 code listing. 1 note from the engine.

On this page
  1. Prerequisites and observable goals
  2. The central question: what is the simulation supposed to reproduce?
  3. Explicit Euler: a reasonable local approximation with a global weakness
  4. Velocity Verlet: split the acceleration update
  5. A small complete step
  6. Accuracy, stability, and model adequacy are separate
  7. Independent practice
  8. Complete solutions: W05
  9. Retention and readiness

Prerequisites and observable goals#

Before

M25, A05–A06, vectors, units, and W01’s state-update distinction.

After

Derive two discrete methods from a continuous model; analyze stability and energy separately; validate against an analytic trajectory and a step-halving experiment.

The central question: what is the simulation supposed to reproduce?#

A simulation consists of at least three objects: a mathematical model, a numerical method, and a particular implementation. The model specifies a continuous law under assumptions. The method approximates that law using finite steps. The implementation stores finite-precision state and executes updates. A defect in any layer can give wrong results, and testing one layer does not automatically validate the others.

Use a unit-mass harmonic oscillator as a bounded example. Position is x(t)x(t), velocity v(t)v(t), and angular frequency ω>0\omega>0. The equations are

x′=v,v′=−ω2x,x(0)=1,v(0)=0.x'=v,\qquad v'=-\omega^2x,\qquad x(0)=1,\quad v(0)=0.

The exact solution is x(t)=cos⁡(ωt)x(t)=\cos(\omega t) and v(t)=−ωsin⁡(ωt)v(t)=-\omega\sin(\omega t) in the chosen position units. Position and velocity do not have interchangeable units; ω\omega has units inverse time, so ω2x\omega^2x is an acceleration. This model idealizes a restoring force proportional to displacement, with no damping, driving force, collision, or changing parameter.

Define energy per unit mass E=12(v2+ω2x2)E=\tfrac12(v^2+\omega^2x^2). Differentiating along the exact solution gives

E′=vv′+ω2xx′=v(−ω2x)+ω2xv=0.E'=vv'+\omega^2xx'=v(-\omega^2x)+\omega^2xv=0.

Conservation follows from the specified equations. It does not prove that an arbitrary animation or numerical integrator conserves that energy.

Explicit Euler: a reasonable local approximation with a global weakness#

Using the old state for both right sides yields

xn+1=xn+hvn,vn+1=vn−hω2xn.x_{n+1}=x_n+hv_n,\qquad v_{n+1}=v_n-h\omega^2x_n.

For small hh, each resembles the first terms of a Taylor expansion. But substitute both into the discrete energy:

vn+12+ω2xn+12=(vn−hω2xn)2+ω2(xn+hvn)2=(1+h2ω2)(vn2+ω2xn2).\begin{align*} v_{n+1}^2+\omega^2x_{n+1}^2 &=(v_n-h\omega^2x_n)^2+\omega^2(x_n+hv_n)^2\\ &=(1+h^2\omega^2)(v_n^2+\omega^2x_n^2). \end{align*}

The cross terms cancel; the remaining squared-step terms are positive. Thus En+1=(1+h2ω2)EnE_{n+1}=(1+h^2\omega^2)E_n. For every nonzero positive step, this method gains energy on a nonzero state. Reducing hh reduces the drift over a fixed interval, but no positive fixed step makes this scheme energy-stable for arbitrarily many oscillations. “The force points inward” is not enough to prevent numerical growth.

This is not a claim that Euler is useless. It is a precise warning about one model and long-time behavior. For a decaying scalar equation y′=−kyy'=-ky, its stability condition is different. Analyze the differential equation and the update matrix actually being used.

Velocity Verlet: split the acceleration update#

An acceleration depending on position suggests a half velocity update, a position update, then the remaining half velocity update:

vn+1/2=vn−h2ω2xn,xn+1=xn+hvn+1/2,vn+1=vn+1/2−h2ω2xn+1.\begin{align*} v_{n+1/2}&=v_n-\frac h2\omega^2x_n,\\ x_{n+1}&=x_n+h v_{n+1/2},\\ v_{n+1}&=v_{n+1/2}-\frac h2\omega^2x_{n+1}. \end{align*}

The second half uses the new position. Store the intermediate explicitly; casually overwriting values may define another method. Expanding gives

(xn+1vn+1)=(1−q2/2h−hω2(1−q2/4)1−q2/2)(xnvn),q=hω.\binom{x_{n+1}}{v_{n+1}}= \begin{pmatrix} 1-q^2/2 & h\\ -h\omega^2(1-q^2/4)&1-q^2/2 \end{pmatrix} \binom{x_n}{v_n},\qquad q=h\omega.

This matrix has determinant 1 and trace 2−q22-q^2. Its eigenvalues lie on the unit circle with distinct oscillatory modes for 0<q<20<q<2. For q>2q>2, a real eigenvalue has magnitude greater than 1 and some states grow. At q=2q=2, a repeated eigenvalue can have a nontrivial Jordan block, so the endpoint does not supply a safe bounded-oscillation guarantee. Use the strict interval.

For 0<q<20<q<2, this scheme exactly preserves, in real arithmetic, the positive quadratic expression

E~=12[v2+ω2(1−q2/4)x2].\widetilde E=\tfrac12\left[v^2+\omega^2(1-q^2/4)x^2\right].

It generally does not preserve the original EE exactly. Because E~\widetilde E is positive definite in this range, it bounds xx and vv over arbitrarily many exact-arithmetic steps. Floating-point roundoff and changing step sizes introduce further issues. The distinction between a modified invariant and exact physical energy is important, not a technicality.

A small complete step#

With ω=1,h=.1,x0=1,v0=0\omega=1,h=.1,x_0=1,v_0=0, the half velocity is −.05-.05. Position becomes .995.995. Final velocity is −.05−.05(.995)=−.09975-.05-.05(.995)=-.09975. Compare with exact cos⁡(.1)≈.9950041653\cos(.1)\approx.9950041653 and −sin⁡(.1)≈−.0998334166-\sin(.1)\approx-.0998334166. These errors are small but nonzero. The computed physical energy is

12(.099752+.9952)=.49998753125,\tfrac12\bigl(.09975^2+.995^2\bigr)=.49998753125,

not exactly .5.5. The modified energy is .49875.49875 both before and after the step in exact rational arithmetic. Check the equations rather than describing any tiny numerical change as “energy conservation.”

Accuracy, stability, and model adequacy are separate#

A stable method can still have a phase error: the oscillation stays bounded but peaks at the wrong times. Under the Verlet stability relation, the numerical phase angle satisfies cos⁡θ=1−q2/2\cos\theta=1-q^2/2. Its effective frequency θ/h\theta/h differs from ω\omega for nonzero step. Energy bounds alone do not guarantee accurate event times or positions.

For a fixed final time TT, compute with steps h,h/2,h/4h,h/2,h/4 and compare all methods at that same time. A second-order method in its asymptotic regime often has error ratios approaching 4, because the global error scales like Ch2Ch^2. A ratio is evidence under a model, not proof of the order for every input. Roundoff, a near-zero leading error coefficient, instability, or a changed final time can spoil the naive interpretation. Use known analytic solutions where available; use independent methods and convergence studies for harder cases.

Even a highly accurate solution of this oscillator model would not validate a real suspension, vehicle, robot, or orbital system. The physical model may lack damping, nonlinearity, external forces, measurement uncertainty, and safety constraints. The lab is a reproducible numerical experiment, not safety-critical controller software. Later T04/T05 and GP2 reuse the same discipline of explicit assumptions and fault boundaries in other domains.

Independent practice#

F foundation C standard course work T transfer S optional stretch L runnable lab or project. Attempt the complete set before opening its solutions.

W05.01CSolution

Derive the Euler energy multiplier for the oscillator without skipping cross terms. Starting at energy .5.5 with h=.1,ω=1h=.1,\omega=1, give the exact energy after 10 steps in terms of a power, and explain why a plausible-looking path does not establish conservation.

W05.02CSolution

Carry out one velocity-Verlet step for x=2,v=1,ω=2,h=.1x=2,v=1,\omega=2,h=.1. Compute both physical energies and the modified energies before and after. Which quantity is exactly preserved by the real-arithmetic update?

W05.03TSolution

Use the Verlet matrix’s determinant and trace to derive the strict stable-oscillation condition. Explain why determinant 1 alone is insufficient, and why the endpoint hω=2h\omega=2 should not be included in a general boundedness claim.

W05.04TSolution

A report compares a run ending at time 10 with a smaller-step run ending at time 10.03 and claims a convergence ratio from their final positions. Diagnose the problem and design a corrected validation using analytic position, velocity, phase/event timing, and energy.

W05.05LSolution

Implement the bounded oscillator lab in integration_code/starters/simulation.py. Validate finite state, positive step/frequency, and a bounded integer step count. Return timestamped position, velocity, and physical energy. Compare to analytic values at a fixed final time, perform step halving, and include one deliberately unstable step-size test described as a diagnostic rather than a production operating mode.

Optional small hints

For .02, calculate the half-step velocity before the new position. For .03, the characteristic polynomial is λ2−(2−q2)λ+1\lambda^2-(2-q^2)\lambda+1. For .04, first make the compared physical question identical.

Complete solutions: W05#

Compare the first step where your work differs. A corrected answer is not yet an independent success.

W05.01Show solution

A systematic numerical energy source

Expanding gives v2−2hvω2x+h2ω4x2+ω2x2+2hω2xv+h2ω2v2v^2-2hv\omega^2x+h^2\omega^4x^2+\omega^2x^2+2h\omega^2xv+h^2\omega^2v^2. The mixed terms sum to zero. Factor the remainder as (1+h2ω2)(v2+ω2x2)(1+h^2\omega^2)(v^2+\omega^2x^2) and divide by two. After 10 steps the energy is exactly 12(1.01)10\tfrac12(1.01)^{10} in ideal arithmetic, about .552311.552311. A short plotted trajectory can hide a roughly 10.5% energy gain; visual plausibility is not the conservation equation. Different plot scales and viewing intervals can hide or amplify the apparent defect.

Back to W05.01
W05.02Show solution

Modified conservation is not identical physical conservation

The half velocity is 1−.05(4)(2)=.61-.05(4)(2)=.6. New position is 2+.1(.6)=2.062+.1(.6)=2.06. New velocity is .6−.05(4)(2.06)=.188.6-.05(4)(2.06)=.188. Physical energy begins at (1+4(4))/2=8.5(1+4(4))/2=8.5 and ends at (.1882+4(2.062))/2=8.504872(.188^2+4(2.06^2))/2=8.504872. With q=.2q=.2, the modified position coefficient is 4(1−.22/4)=3.964(1-.2^2/4)=3.96. Initially E~=(1+3.96(4))/2=8.42\widetilde E=(1+3.96(4))/2=8.42; afterward it is (.1882+3.96(2.062))/2=8.42(.188^2+3.96(2.06^2))/2=8.42. Exact decimal rational calculation verifies this equality. The physical energy changed, even though the modified invariant did not.

Back to W05.02
W05.03Show solution

Area preservation alone does not bound an orbit

Let q=hω>0q=h\omega>0. The trace lies strictly between −2-2 and 2 precisely when 0<q<20<q<2. With determinant 1, the roots are conjugate unit-modulus numbers in that range, giving bounded oscillatory powers of this fixed matrix. A determinant-one matrix such as diag⁡(2,1/2)\diag(2,1/2) instead expands one direction exponentially; determinant alone controls area, not every length. At q=2q=2 the matrix is (−1h0−1)\begin{pmatrix}-1&h\\0&-1\end{pmatrix}, whose powers include a term proportional to the number of steps when the velocity component is nonzero. Thus the endpoint can grow linearly in position. This is a linear-model real-arithmetic statement, not a general adaptive-integrator theorem.

Back to W05.03
W05.04Show solution

Compare the same modeled event at the same time

The two final positions answer different time queries. A phase shift of .03 can dominate discretization differences, so their ratio is not an order estimate. Choose a fixed TT and step counts with Nh=TNh=T, or use an explicitly analyzed final shortened step/interpolation. Compare position and velocity with cos⁡(ωT)\cos(\omega T) and −ωsin⁡(ωT)-\omega\sin(\omega T), study maximum errors over matched timestamps, estimate event/phase timing separately, and report physical versus modified energy. Repeat with smaller steps until the expected ratio is plausible above roundoff. State model assumptions and do not interpret convergence to the wrong physical model as validation of reality.

Back to W05.04
W05.05Show solution

A reproducible reference

The reference implements the three updates in their stated order and records the old initial state as well as later samples. The analytic helper provides an independently derived target rather than another integrator with the same potential bug. Nonfinite values are rejected; bounded inputs do not imply that every allowed step is stable, so the caller must analyze hωh\omega.

integration_code/solutions/simulation.pyPython
"""W05: velocity Verlet for x''=-omega^2*x, unit mass, fixed time step."""
import math


def verlet(x=1.,v=0.,omega=1.,dt=.1,steps=100):
    if not all(math.isfinite(z) for z in (x,v,omega,dt)) or omega<=0 or dt<=0:
        raise ValueError("finite state, positive frequency and step required")
    if type(steps) is not int or not 0<=steps<=100000:
        raise ValueError("bounded nonnegative step count required")
    energy0=.5*(v*v+omega*omega*x*x)
    if not math.isfinite(energy0):
        raise ValueError("initial energy is not finite; rescale the problem")
    rows=[(0.,x,v,energy0)]
    for k in range(1,steps+1):
        half=v-.5*dt*omega*omega*x
        new_x=x+dt*half
        new_v=half-.5*dt*omega*omega*new_x
        x,v=new_x,new_v
        energy=.5*(v*v+omega*omega*x*x)
        if not all(math.isfinite(z) for z in (x,v,energy,k*dt)):
            raise ValueError("nonfinite trajectory; check step and scale")
        rows.append((k*dt,x,v,energy))
    return rows


def exact(t,x0=1.,v0=0.,omega=1.):
    if not all(math.isfinite(z) for z in (t,x0,v0,omega)) or omega<=0:
        raise ValueError("finite inputs and positive frequency required")
    phase=omega*t
    if not math.isfinite(phase):
        raise ValueError("nonfinite phase; rescale the problem")
    result=(x0*math.cos(phase)+(v0/omega)*math.sin(phase),
            -omega*x0*math.sin(phase)+v0*math.cos(phase))
    if not all(math.isfinite(z) for z in result):
        raise ValueError("nonfinite analytic state; rescale the problem")
    return result


if __name__=='__main__':
    for dt in (.1,.05,.025):
        t,x,v,e=verlet(dt=dt,steps=round(1/dt))[-1]
        target=exact(t)
        print(dt,math.hypot(x-target[0],v-target[1]),e)

Tests include the first step, invalid inputs, energy behavior, and fixed-time error ratios under step halving. They establish selected numerical behavior for this oscillator. They do not prove the absence of all accumulated roundoff or validate a physical system. Record units, frequency, initial conditions, step count, and final time with the resulting table so a reader can reproduce the exact question.

Back to W05.05

Retention and readiness#

Explain why a locally plausible derivative step can create global energy growth. Name the conserved quantity actually checked. Before trusting a simulation, state model error, discretization error, and finite-precision error separately.