Chapter 4 — Key Takeaways (Control Flow)

A one-page reference to the constructs that let a Fortran program decide and repeat. Modern, block-structured, no goto.

The constructs at a glance

Construct Skeleton One-line job
if construct if (c) then … else if (c2) then … else … end if branch on conditions; first true wins
logical if if (c) stmt one guarded statement, no end if
select case select case (x) / case (…) / case default / end select dispatch on one discrete value
counted do do i = a, b, s … end do loop a known number of times
do while do while (c) … end do loop while a condition holds (tested first)
infinite do do … if (c) exit … end do loop with a mid-body exit
cycle cycle / cycle name skip to the next iteration
exit exit / exit name leave the (named) loop
named construct name: do … / end do name target exit/cycle at an outer loop
where where (mask) … elsewhere … end where masked whole-array assignment
do concurrent do concurrent (i = a:b) … end do assert iterations are independent

Operators (the vocabulary of conditions)

Kind Operators
Relational == /= < <= > >=
Logical .and. .or. .not. .eqv. .neqv.

The dots are part of the spelling. A relational or logical expression has type logical.

Which loop should I use?

Situation Use
I know the iteration count counted do i = 1, n
Loop until a condition fails, count unknown do while (c)
Condition can only be tested mid-body (e.g. after computing the new value) infinite do + exit
Skip some iterations cycle inside any loop
Break out of an outer loop name it, exit name
Change part of an array by a condition where (details in Ch. 5)
Iterations are provably independent do concurrent (perf payoff in Ch. 29)

select case vs. an if-chain

  • Use select case when you compare one discrete value (integer/character/logical) against fixed alternatives; use an if-chain for different conditions.
  • Labels may be a value case (3), a list case (1, 2, 5), or a range case (60:69), case (:0).
  • Labels must be disjoint (the compiler enforces it) and the type must not be real.
  • No fall-through: exactly one block runs — no break to forget, unlike C's switch.

Common pitfalls

Pitfall Fix
if (x == 0.1_dp) on reals test a tolerance: if (abs(x - 0.1_dp) < 1.0e-9_dp) (why: Ch. 20)
do t = 0.0, 1.0, 0.1 (real counter) deleted from the standard; count with an integer, t = t0 + real(step, dp)*dt
bare exit meant to leave an outer loop name the loop and write exit name
overlapping select case ranges make labels disjoint (else compile error)
do concurrent with a(i) = a(i-1) + 1 iterations aren't independent — use an ordinary do
writing new forall obsolescent in 2018 — use where, do concurrent, or a = b*2

Numbers & rules worth memorizing

  • A counted do i = 1, n runs n times — bounds are inclusive on both ends (unlike Python's range).
  • The trip count is fixed at loop entry; changing the bound inside does not lengthen the loop.
  • The loop counter is always an integer.
  • Operator precedence in conditions: .not. > .and. > .or. (so a==0 .and. b/=0 .or. c==0 means (a==0 .and. b/=0) .or. c==0).
  • select case compiles to a possible jump table (O(1)); an if-chain of k cases averages ~k/2 tests.

Compile flag reminder (from Ch. 2)

$ gfortran -std=f2018 -Wall -fcheck=all -g control.f90 -o control

-fcheck=all catches an out-of-bounds index inside a loop during development (drop it for production runs).

Python / C quick map

Fortran Python C
else if elif else if
select case (no fall-through) match / dict switch (needs break)
do i = 1, n (inclusive) for i in range(1, n+1) for (i=1; i<=n; i++)
cycle / exit continue / break continue / break
.and. .or. .not. and or not && \|\| !
where (m) a = … a[m] = … (NumPy) manual loop

Project piece added this chapter

The heat solver's time-stepping skeleton: a do loop over time steps, and inside it a nested grid sweep with an if (or cycle) separating boundary points (held fixed) from interior points (updated later). No numerics yet — the physics lands in Chapter 24. The loop nest keeps the first index innermost, the column-major habit that pays off in Ch. 5 and Ch. 27. For a 4×3 grid: 10 boundary points, 2 interior.