Chapter 5 — Key Takeaways (Arrays)

A one-page reference to the chapter that makes Fortran fast. Keep it beside you until the syntax is reflex.

The vocabulary

Term Meaning
rank number of dimensions (vector = 1, matrix = 2; up to 15)
extent number of elements along one dimension
shape the list of all extents, e.g. [3, 4]
array section a slice a(lo:hi:stride) — a first-class array you can read, write, pass
whole-array operation an operator/intrinsic applied to a whole array elementwise (c = a + b)
array constructor an inline array value, [1.0_dp, 2.0_dp, 3.0_dp]
implied-do a loop inside a constructor, [(i*i, i=1,n)]
allocatable array run-time-sized array, deferred shape a(:), auto-freed on scope exit
column-major order Fortran's memory layout: the first index varies fastest

Declaration and sections

real(dp) :: v(5)              ! rank 1, indices 1..5 (one-based default)
real(dp) :: a(3, 4)           ! rank 2, 3 rows x 4 columns
real(dp) :: b(-1:1)           ! custom bounds
real(dp), allocatable :: g(:,:)   ! deferred shape; allocate(g(nx, ny)) later
Section Selects
a(2, :) all of row 2
a(:, 3) all of column 3
a(1:2, 2:3) the 2×2 sub-block
v(1:10:2) every 2nd element, indices 1,3,5,7,9
m(:, size(m,2)) the last column, size-agnostic

The intrinsics introduced

Intrinsic Does
size(a) / size(a, d) total elements / extent of dimension d
shape(a) / rank(a) shape as an array / number of dimensions
sum(a) / product(a) sum / product of elements (sum(a, dim=), sum(a, mask=))
maxval / minval largest / smallest element
maxloc / minloc position of the max / min (use dim=1 for a scalar on rank-1)
count(mask) how many elements satisfy a logical condition
matmul(A, B) the matrix product ($C_{ij}=\sum_k A_{ik}B_{kj}$)
dot_product(x, y) the scalar $\sum_i x_i y_i$
transpose(A) rows ↔ columns
reshape(src, shp[, order=]) reflow a 1-D constructor into higher rank
spread(src, dim, ncopies) replicate an array along a new dimension
merge(t, f, mask) elementwise pick between two arrays

Which construct, when

You want to… Reach for
add / scale / transform a whole array whole-array op: c = a + b, y = sqrt(x)
the elementwise product a * b
the matrix product matmul(a, b) (never a * b)
a running total / extreme / tally sum / maxval / count
operate on only some elements where (mask) …, or a masked sum/count
size an array at run time allocatable + allocate

Pitfalls

  • One-based, not zero-based. The first element is a(1); there is no a(0) by default. Translating a C for (i=0; i<n; i++) gives do i = 1, n. Compile with -fcheck=all to catch out-of-bounds.
  • a * b is elementwise, not matrix multiply. For linear algebra name it: matmul, dot_product.
  • Conformance is enforced. a(3) = b(4) will not compile; whole-array ops need matching shapes.
  • Integer reductions truncate on divide. sum(k)/size(k) on an integer array does integer division; use sum(k)/real(size(k), dp) for a true mean (the Chapter 3 trap, on arrays).
  • Column-major loop order. The inner loop runs over the first index. Wrong order compiles, gives the right answer, and can be ~10× slower.

The one rule to memorize

Fortran is COLUMN-MAJOR: the first index varies fastest in memory.
=> store column by column; put the FIRST index on the INNER loop.

   do j = 1, n          ! outer: columns
     do i = 1, n        ! inner: rows  <-- with the memory grain (FAST)
       a(i, j) = ...
     end do
   end do

Numbers worth carrying

  • A real(dp) value is 8 bytes; a cache line (~64 bytes) holds 8 of them.
  • An $n \times n$ matmul costs about $2n^3$ flops — fine small, call LAPACK large (Ch. 21).
  • Loop-order (column-major vs against-the-grain) is an illustrative ~10×, measured in Ch. 27.

Project piece added this chapter

The heat solver's temperature field becomes a 2D allocatable array u(:,:), and its Laplacian is one whole-array statement of shifted sections:

lap(2:n-1, 2:n-1) = u(1:n-2, 2:n-1) + u(3:n, 2:n-1)     &
                  + u(2:n-1, 1:n-2) + u(2:n-1, 3:n)      &
                  - 4.0_dp * u(2:n-1, 2:n-1)

Numerics (the $1/\Delta x^2$ scaling, boundary conditions, timestep, CFL stability) are deferred to Chapter 24. Saved as heat-solver/heat_solver.f90.