Exercises: Capstone — Your Complete Parallel Scientific Simulation

This is a synthesis chapter, so its exercises are synthesis exercises: they make you verify a solver, run a convergence study, reason about scaling honestly, and write up a result the way a paper does. Several extend your own heat solver; several ask you to referee a claim the way a reviewer would. The best of them end not in a number but in a paragraph you could put in front of a skeptical colleague — because that, by now, is the skill.

Difficulty: ⭐ warm-up · ⭐⭐ standard · ⭐⭐⭐ deeper. Solutions: worked solutions to the daggered (†) and odd-numbered problems are in appendices/answers-to-selected.md; the compilable ones (38.9, 38.13, 38.17, 38.21, 38.25) are worked in full as code/exercise-solutions.f90. Every program compiles with gfortran -std=f2018 -Wall. Try each problem before you look, and — the honesty rule of the whole book — predict the output before you run it.


Part A — Assembling the Pieces ⭐

38.1 † The body of step was rewritten five times across the book (serial array sections → cache-tuned loop → OpenMP → coarray → MPI) while the driver never changed. State the single property of step that made that possible, and explain in two sentences why it is the reason a program can grow larger than one person can hold in their head.

38.2 List the five architectural roles in the assembled solver (driver, solver, physics, I/O, utility) and name the module or file that fills each. Which one performs no science itself, and why is that a feature?

38.3 † "Assembling the pieces" turned out to be almost no coding. What three things does the capstone actually require instead, and which of the three does a reviewer read first?

38.4 The final tree has a test/ directory holding a regression test against the analytical solution. Explain how a single test in test/ protects the physics of a solver you will keep editing for months.


Part B — Verification and Convergence ⭐⭐

38.5 † Define verification and validation in one sentence each, using the "solving the equations right / solving the right equations" framing. Our convergence study compares the code to an exact solution of the same heat equation — which of the two is that, and what would the other one require that this chapter does not have?

38.6 Show, by direct substitution, that $u(x,y,t) = \sin(\pi x)\sin(\pi y)\,e^{-2\alpha\pi^2 t}$ satisfies the 2D heat equation $\partial u/\partial t = \alpha\nabla^2 u$. Then confirm it satisfies zero-Dirichlet boundary conditions on the unit square.

38.7 † Your convergence study reports these maximum errors against the analytical solution at a fixed time: $h$: $1.60\times10^{-2}$; $h/2$: $4.05\times10^{-3}$; $h/4$: $1.01\times10^{-3}$. Compute the observed order of accuracy for each refinement. Is the solver behaving as the five-point stencil's theory predicts? What single number would you report in the paper?

38.8 (Find the bug — via the convergence study.) A colleague's heat solver gives "reasonable-looking" output, but their convergence study measures order 1, not 2, on every grid. List two distinct coding mistakes (from Chapters 24) that produce exactly this symptom, and explain why a convergence study catches them where eyeballing a heat map does not.

38.9 † (Type, compile, and run — predict first.) Read code/example-01-analytical-validation.f90. Predict its exact output — the numerical center value, the exact value, and the error — before compiling. Then explain why the error is large on this $5\times5$ grid and what one change would shrink it by roughly four.


Part C — Performance, Honestly ⭐⭐

38.10 (Back of the envelope.) Your solver's stencil sweep is $98\%$ of the runtime. Using Amdahl's Law, compute the maximum speedup on 4, 16, and infinitely many cores. Then, in one sentence, explain why your measured speedup on 16 cores will almost certainly be lower than the Amdahl number for this particular kernel.

38.11 Distinguish strong scaling from weak scaling. Which does the OpenMP solver on one node naturally demonstrate, and which does the MPI solver across a cluster? Why is weak scaling the honest way to sell a distributed solver?

38.12 † Define arithmetic intensity, and estimate it for the five-point stencil update (about ten flops per cell; on the order of tens of bytes moved per cell). Which ceiling of the roofline model does the kernel sit under, and what does that tell you to optimize — arithmetic or memory access?

38.13 † (Type, compile, and run — predict first.) Read code/example-02-convergence-factors.f90. Predict the ratio column, and state what value the ratios approach and what order of accuracy that implies. Why does the coarsest grid's ratio overshoot?

38.14 (Back of the envelope.) A run reports "12× faster on 16 cores." A reviewer asks two questions before believing it. What are they, and why does a speedup with no stated baseline and no build configuration mean nothing?


Part D — Presenting It ⭐⭐

38.15 † Write the section headings of a computational-science paper, in order, and say in a few words what each answers. Why is verification placed before results?

38.16 A reviewer reads with a short checklist. Name the five things they look for, and identify the one that is non-negotiable — the one whose absence sinks a paper no matter how clever the method.

38.17 † (Type, compile, and run — predict first.) Read the soln_17 routine in code/exercise-solutions.f90. For alpha = 1, h = 0.1, predict the maximum stable timestep and the stability verdict for dt = 0.004 and dt = 0.002. Which one crosses the CFL cliff, and by how much?

38.18 Draft the one-paragraph abstract for your finished solver: what it solves, the method, the key verification result, the parallel back-ends, and the honest performance claim. Keep it to about five sentences — the discipline of an abstract is saying only what the evidence supports.


Part E — Design It: Finish the Solver ⭐⭐⭐

38.19 † (Design it.) Write the test/test_solver.f90 regression test that pins one point of the convergence curve: initialize the $5\times5$ analytical sine mode, take one step, and assert the center cell equals $0.7657$ to a tolerance of $10^{-4}$, printing PASS or FAIL. Why is asserting against the analytical value stronger than asserting against a previously-saved number?

38.20 (Design it.) The solver writes VTK every save_every steps. Sketch the driver's time loop so it (a) writes a frame at step 0, (b) writes every save_every steps after, and (c) accumulates a .pvd collection tagging each frame with its physical time $t = n\,\Delta t$. Which chapter's frame_name and write_vtk do you reuse unchanged?

38.21 † (Type, compile, and run — predict first.) Read the soln_21 routine in code/exercise-solutions.f90. Predict the interior-cell count and the flops-per-step for a $1000\times1000$ grid. Then estimate the total flops to march $10{,}000$ steps, and say why that number alone does not tell you the runtime.

38.22 (Design it.) Extend the write-up plan for a validation study (not just verification): describe, in words, an experiment or reference dataset you could compare the solver to, and what agreement (and disagreement) would tell you about the model rather than the code.


Part F — Back of the Envelope and the Roofline ⭐⭐⭐

38.23 † (Back of the envelope.) Refining an explicit heat solver's grid from $500\times500$ to $1000\times1000$ (halving $h$) at fixed final time: by what factor does the work grow? Account for both the larger grid and the CFL-forced smaller timestep. Why is this the "$\Delta t \sim h^2$ tax," and what kind of scheme escapes it?

38.24 (Back of the envelope.) A node has a memory bandwidth of, say, $100$ GB/s and a peak of $1000$ GFLOP/s, so its machine balance is about $10$ flop/byte. Your stencil's intensity is well under $1$ flop/byte. Using the roofline picture, roughly what fraction of the node's peak FLOP/s can this kernel ever reach, and why does that make "add more cores" hit a wall?


Part G — Interleaved ⭐⭐⭐

38.25 † (Interleaved — Chapters 24 & 33 — compilable.) Read the soln_25 routine in code/exercise-solutions.f90. It shows that one FTCS step at the point $(2,3)$ of the analytical mode equals $G$ times that point's initial value. Predict both printed numbers. Explain how this "eigenvector property" is what makes the whole-field verification collapse to a single number, and connect it to the amplification factor $G$ of Chapter 24's von Neumann analysis.

38.26 (Interleaved — Chapter 33.) The OpenMP step must produce the identical field the serial step does. Explain why that determinism is required (not merely reassuring), and name the one scoping mistake in the parallel loop that would silently break it. How does default(none) protect you?

38.27 † (Interleaved — Chapter 37.) The analytical solution is used two different ways: once for verification and repeatedly for regression testing. Explain the difference in how each uses it, and why recording the compiler, flags, grid, and step count is part of making either one reproducible.

38.28 (Interleaved — the whole book.) In one paragraph each, name the chapter that gave your solver: its precision (dp), its data structure (field_t), its physics (the stencil), its speed (loop order/SIMD), its parallelism (OpenMP/MPI), its output (VTK), and its tests. This is your solver's biography — and the outline of the paper's implementation section.


Solutions to the daggered and odd-numbered problems are in appendices/answers-to-selected.md; the compilable ones (38.9, 38.13, 38.17, 38.21, 38.25) are worked in full as code/exercise-solutions.f90. For every verification or performance problem, state what is a measurement and what is an expectation — the honesty is part of the answer.