Common Struggles

The recurring places students get stuck when learning Modern Fortran, why each happens, and how to address it. Most of these are also flagged as ⚠️ Common Pitfall callouts in the relevant chapters; this page collects them so you can anticipate the whole arc.

From other languages

Integer division (1/2 == 0). (Chapter 3.) Students coming from Python 3, where / is always float division, are bitten immediately. Emphasize that in Fortran the type of the operands determines the operation: 1/2 is integer arithmetic and truncates. Drill real(i)/real(j), 1.0_dp/2.0_dp, and mixed cases early; it recurs in every numerical chapter.

1-based indexing. (Chapter 5.) C, Python, and Java programmers expect a(0). Fortran arrays start at 1 by default (and can start anywhere). Most off-by-one bugs in the first weeks trace here. Have students say array bounds aloud ("one to n") until it sticks.

Column-major vs. row-major. (Chapters 5, 27.) The single most consequential difference from C. In Fortran the first index varies fastest, so nested loops should have the first index innermost. Students who learned C loop the wrong way and see a 10× slowdown they can't explain. Teach it as a rule in Chapter 5 and measure it in Chapter 27 — the measurement is what makes it stick.

Modern-style discipline

Forgetting implicit none. (Chapter 2.) Without it, a typo like temperatrue silently becomes a new real variable. Insist on implicit none in every unit from day one, and turn on -Wall. A good habit: have students deliberately introduce a typo, watch it not be caught without implicit none, then add it.

Kind parameters and literals. (Chapter 3.) Students write 3.14 (default precision) in real(dp) code and lose accuracy, or forget the _dp suffix. Enforce real(dp) and 1.0_dp-style literals from the first program; explain that 0.1 and 0.1_dp can differ.

intent fatigue. (Chapter 6.) Students see intent(in/out/inout) as boilerplate. Reframe it as a free bug-catcher: the compiler enforces it. Show a case where intent(in) catches an accidental write.

allocatable vs. pointer. (Chapter 11.) Coming from languages full of references, students reach for pointer when allocatable is correct. Teach the default rule ("allocatable unless you truly need aliasing") and the reasons (automatic deallocation, no aliasing, better optimization).

The two great numerical hazards

Floating-point equality and precision. (Chapter 20.) if (x == 0.1_dp) and "why isn't my sum exact?" Teach comparison with a tolerance and the epsilon intrinsic early; the whole of Part V depends on students respecting this.

Stability / the CFL condition. (Chapter 24.) The first time students run the heat solver with too large a time step, it explodes into NaNs. This is not a bug — it is instability, and it is a teachable moment. Have them derive the CFL limit and then deliberately violate it to see the blow-up.

Format and I/O

Edit descriptors. (Chapter 7.) Format strings ('(f8.2)', '(i0)', es, /) are terse and error- prone. Encourage list-directed I/O (print *) for debugging and reserve formatted I/O for final output. Have students predict the exact spacing of an output line, then check it — this is also how the book's "expected output" comments were written.

Legacy-mindset creep

Writing FORTRAN 77 in a modern file. (Part IV.) After studying old code, students unconsciously adopt COMMON, GOTO, or implicit typing. Keep the "modern vs. legacy" distinction sharp: legacy constructs are things we read, not things we write (outside a labeled example).

Parallelism

Race conditions and data scoping. (Chapters 32–34.) The hardest conceptual leap: a shared variable updated by many threads/images gives wrong, non-deterministic answers. Use a reduction example (a parallel sum that comes out wrong without it) as the wake-up call. Emphasize that a parallel bug may only appear sometimes — the worst kind.

Parallelizing slow serial code. (Chapters 27–31.) Students want to jump to MPI. Insist on the order: make it correct, make it fast serially, then parallelize. Amdahl's Law (Chapter 31) is the argument.

A meta-note

Nearly every struggle above is a place where a compile-and-run beats a lecture. Because the book never executed its own code, "run the example and confirm the book's prediction" is always available as an in-class exercise — and when a student's output disagrees with the book, you have either a teachable mistake or a genuine erratum, both worth the class's attention.