This page is the "walk through every door" companion to the parent note. There we built the tools. Here we stress-test them: every sign, every degenerate input, every limiting case, one word problem, one exam trap.
Forecast: guess the number before reading. (Hint: the antiderivative is x3+x.)
Recognise the exact answer first.∫02(3x2+1)dx=[x3+x]02=8+2=10.
Why this step? Whenever an exact answer exists, compute it — it becomes the yardstick for the numeric one.
Forecast: an infinite interval — will quad even survive? What's the exact area?
Exact value.∫0∞e−xdx=[−e−x]0∞=0−(−1)=1.
Why this step? The tail e−x decays to zero fast, so the area is finite even though the interval is not. That's the condition for quad to work with np.inf.
Why this step?quad internally maps the infinite ray onto a finite interval (a change of variable) before applying Gauss–Kronrod. You never see it; you just pass np.inf.
Forecast: at x=0 the integrand is +∞. Does the area explode too, or converge?
Test convergence with the exact integral.∫01x−1/2dx=[2x]01=2−0=2.
Why this step? An integrable singularity: the spike is infinitely tall but infinitely thin, and the areas add to a finite 2. Contrast 1/x, whose integral would diverge.
Why this step? The adaptive part of "adaptive Gauss–Kronrod" clusters sample points near x=0 where the function wiggles violently, so it still converges.
Figure (s01): the red curve 1/x rockets to infinity at the left wall, yet the blue shaded area is bounded — it fills up to the yellow dashed line at height 2, the exact value of the integral.
Look at the figure: the red curve rockets up near the left wall, yet the shaded blue area is bounded by the dashed line at height 2.
Forecast:sin is positive on [0,π] and negative on [π,2π]. Guess both answers.
Full period first.∫02πsinxdx=[−cosx]02π=−1−(−1)=0.
Why this step?quad computes signed area. The hill on [0,π] and the equal valley on [π,2π] cancel exactly.
Half period.∫0πsinxdx=[−cosx]0π=1−(−1)=2.
Why this step? This isolates the positive hump so nothing cancels — shows the difference between signed area and "how much curve there is."
Forecast: one has zero width, one has the limits backwards. Predict both signs.
Zero-width interval.∫33x2dx=0.
Why this step? Width b−a=0 ⇒ no area regardless of the function. quad(lambda x: x**2, 3, 3) returns 0.0. This is the degenerate edge case that catches people who feed in equal limits by accident.
Reversed limits. By the definition ∫ab=−∫ba: ∫51x2dx=−∫15x2dx=−[3x3]15=−(3125−31)=−3124.
Why this step?quad honours the orientation of the interval, so a backwards interval flips the sign. −124/3≈−41.333.
Forecast: the spike is now in the middle, not at an endpoint. Will a plain quad(f, -1, 1) notice it, and what is the exact area?
Exact value by symmetry. The integrand is even, so ∫−11∣x∣−1/2dx=2∫01x−1/2dx=2⋅2=4.
Why this step? We reuse Ex 3's endpoint result on each half, doubling by symmetry. The area is finite: 4.
Why this step?quad places its samples adaptively, but it can miss a razor-thin interior spike because no sample landed near x=0. Passing points=[0] forces it to split the interval at the kink, treating 0 as an endpoint of each half where singularities are handled cleanly. Equivalently you could do quad(f,-1,0)[0] + quad(f,0,1)[0] by hand.
Why not just quad(f,-1,1)? Without points, quad may return a value with a large err or a warning, because it never adapted near the interior blow-up.
Forecast: both limits are infinite. Does quad accept -np.inf and np.inf together, and what famous number comes out?
Exact value. This is the classic Gaussian integral: ∫−∞∞e−x2dx=π≈1.7725.
Why this step? The tails decay like e−x2 (faster than any exponential), so the area over the whole line is finite — the precondition for a doubly-infinite quad.
Why this step?quad maps both infinite tails onto finite intervals internally. You literally write -np.inf, np.inf; no manual splitting needed for this smooth, symmetric integrand.
Forecast: decay with rate 2. Roughly how big is y(1)?
Exact solution.y˙=−2y⇒y(t)=3e−2t, so y(1)=3e−2≈0.406.
Why this step? Linear decay has a closed form; use it as the ground truth for the numeric run.
Solve numerically with tight tolerances.
sol = solve_ivp(lambda t, y: -2*y, [0,5], [3.0], method='RK45', t_eval=[0,1,2,3,4,5], rtol=1e-10, atol=1e-12)sol.y[0][1] # y at t=1 ≈ 0.4060
Why this step? We set rtol/atol tightly (pitfall P2 above) so the numeric y(1) matches the analytic 0.406 closely. t_eval only picks where we report, not the internal step size (pitfall P3).
Forecast: with those initial conditions the motion is a pure cosine. What is x(π)?
Reduce to first order. Let y0=x, y1=x˙. Then
y˙0=y1,y˙1=−ω2y0.Why this step? As restated in the pitfalls box, solvers accept only first-order systems. We trade one 2nd-order equation for two 1st-order ones stacked in a vector.
Analytic solution.x(t)=cos(2t), so x(π)=cos(2π)=1.
Why this step?ω=2, zero initial velocity ⇒ pure cosine amplitude 1. Gives us the checkpoint.
Energy invariant.E=21x˙2+21ω2x2. At t=0: E=21(0)+21(4)(1)=2. It must stay 2 forever.
Why this step? Conservation is a physics-level sanity check independent of the solver's internals — if E drifts, the integration is inaccurate.
Figure (s03): blue is position x(t)=cos2t, yellow is velocity x˙(t)=−2sin2t, green is total energy — a flat line at 2, showing the high-order solver conserves it.
Blue is x(t)=cos2t, yellow is x˙(t)=−2sin2t; the green energy line stays flat.
Forecast: the −1000 factor pulls y toward cost almost instantly. Which solver copes, and which one takes thousands of steps?
Spot the exact particular solution. Try y=cost: then y˙=−sint and the RHS becomes −1000(cost−cost)−sint=−sint. It matches, and y(0)=cos0=1… but our start is y(0)=0, so there's a fast transient that snaps up to cost within ∼1/1000 of a second, after which y(t)≈cost.
Why this step? This is the definition of stiff (see Stiff differential equations): a superfast decay (1/1000 s) riding on a slow oscillation (2π s).
Run RK45 and inspect its work. An explicit method needs h≲2/1000 for stability, so it takes thousands of tiny steps.
Why this step?sol.nfev (number of RHS evaluations) and sol.t.size (accepted steps) are the diagnostics that substantiate the "grinds to tiny steps" claim — this is pitfall P4 in numbers, not just words. It succeeds, but at huge cost.
BDF (implicit) sails through in a handful of steps.
Why this step? After the transient, y≈cost; at t=1, cos1=0.5403. Implicit BDF is stable at large h regardless of the 1000, so its nfev/step count is a small fraction of RK45's.
Forecast: it heads toward room temperature 20. After 10 min will it be near 20, or still hot?
Model in solver form. State is scalar T; RHS is f(t,T)=−0.1(T−20).
Why this step? Word problems must be translated into T˙=f(t,T) with a numeric initial condition T(0)=90.
Exact solution for the checkpoint.T(t)=20+(90−20)e−0.1t=20+70e−0.1t. At t=10: T=20+70e−1=20+70(0.36788)=45.7504∘C.
Why this step? Newton cooling is linear ⇒ closed form; use it to validate.
Forecast: which library wants f(t, y) and which wants f(y, t)? Which output is transposed?
solve_ivp — time first.
sol = solve_ivp(lambda t, y: -2*y, [0,5], [3.0], t_eval=[1.0], rtol=1e-10)sol.y[0][0] # value at t=1, rows = states
Why this step? Pitfall P1 (see the definition box up top): "solve_ivp = time super first" → f(t, y). Output sol.y has shape (n_states, n_times).
odeint — state first, old = reversed.
y = odeint(lambda y, t: -2*y, 3.0, [0.0, 1.0])y[1][0] # value at t=1, rows = TIMES here
Why this step?odeint is the legacy LSODA wrapper: f(y, t) and output shape (n_times, n_states) — both orderings are transposed relative to solve_ivp.
Both must give the same physics. Exact y(1)=3e−2=0.4060.
Why this step? The trap is purely about interface, not answer — get the argument order right and both return 0.406.