Chapter 15 — Teaching Notes

One-line purpose. Deliver the book's emotional payoff for Python-native students — call Fortran from Python, and measure the speedup — while drilling the one technical idea that makes or breaks it: memory layout at the boundary (order='F').

Key ideas to emphasize

  • The two-language workflow is a division of labor, not a competition. Hammer the threshold concept: whole-program speed is set by the hot loop's language. Once students see that, the tired "Python vs Fortran" debate evaporates — you write the 10% that runs a billion times in Fortran and the rest in Python.
  • order='F' is the whole chapter's technical crux. f2py preserves indexing but copies a C-contiguous array on every call. This is the single most common way a "Fortran-accelerated" program ends up no faster than before. Make them feel it: same kernel, one keyword, order-of-magnitude difference.
  • intent does double duty. The habit from Ch. 6 (intent on every argument) is now the metadata f2py reads to build the Python signature. Reward students who already internalized it.
  • Honesty about the speedup. The number is 10–100×, an order of magnitude, and it is theirs to measure — not a promise. Model the assert np.allclose discipline: a speedup that changes the answer is a bug.
  • ctypes/cffi need bind(c). This is where Ch. 14 pays off — the C ABI is the universal adapter, and f2py's convenience is precisely that it builds the C mask for you.

Misconceptions to preempt

  • "f2py transposes my array because Fortran is column-major." (No — it preserves indexing and reconciles layout by copying. a[i,j]u(i+1,j+1).)
  • "If NumPy is fast, I never need Fortran." (True until a loop-carried dependency blocks vectorization — the heat time loop. Then pure Python falls off a cliff and Fortran is the answer.)
  • "The speedup is a fixed number like 50×." (It depends on hardware, compiler, flags, and size; only the order of magnitude is robust.)
  • "intent(inout) and intent(in) behave the same at the boundary." (No — intent(in) may copy silently; intent(inout) raises on a non-F-contiguous array, because it cannot write back through a copy.)
  • "1-D arrays have the order='F' problem too." (No — a 1-D array is both C- and F-contiguous.)

A live demonstration (8 minutes)

Build code/example-02-heat-step.f90 live: f2py -c -m heatlib example-02-heat-step.f90. In an interpreter, create the 4×4 field twice — once np.zeros((4,4)) (C-contiguous) and once with order='F' — call step on each, and show (a) the answers are identical (f2py preserves indexing) and (b) np.isfortran(...) differs. Then, if time, wrap a big-array version and %timeit both to expose the per-call copy. The wordless punch: same code, same answer, one keyword, very different speed. (If f2py's build fails on your Python, that itself is the teachable moment about the Meson backend — pip install meson ninja, --backend meson.)

Class-time budget (~55 min)

  • 8 min: the two-language workflow and the threshold concept (§15.1).
  • 12 min: f2py mechanics — the -c -m build, intent→signature, module namespacing (§15.2), with the live demo start.
  • 15 min: dtype and order='F' — the crux; the copy, intent(inout), the Find-the-Bug (§15.3).
  • 8 min: ctypes/cffi and why they need bind(c) (§15.4).
  • 12 min: the payoff — port, wrap, benchmark honestly; run benchmark.py if the room can (§15.5) + the Project Checkpoint.

Prerequisites to review

  • Ch. 5 §5.6 column-major order (first index fastest) — the direct parent of order='F'. Five minutes re-drawing the memory layout diagram pays for itself.
  • Ch. 6 intent and the canonical step(field, alpha, dt) — the kernel we wrap.
  • Ch. 14 iso_c_binding/bind(c) — needed for §15.4. If Ch. 14 is fresh, students are ready.
  • Practical: confirm students have NumPy and gfortran, and can run f2py --version, before class — the build environment (especially the Meson transition) is where live sessions stall.

Connections

Back: Ch. 5 (layout), Ch. 6 (intent/step), Ch. 14 (bind(c)). Forward: Ch. 16 (fpm and the ecosystem, next), Ch. 24 (the real stencil drops into the same step interface), Ch. 28 (rigorous benchmarking), Ch. 31 (Amdahl caps the payoff — Exercise 15.21), Ch. 33 (parallelize the wrapped kernel — CS-02 extension). This is the anchor climax the whole book foreshadowed since Ch. 1.