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.