Appendix H: Libraries and Tools Reference

A working scientific programmer spends far more time composing libraries than writing loops. This appendix is the bench reference for that work: for each library and tool the book relies on, it gives what it is, when to reach for it, and the exact flag or command to use it. It is the practical companion to two neighbours — Appendix C installs the toolchain and catalogues the compiler flags, and Appendix J is the annotated reading list and history. This one is the linking reference: the module names, the -l flags, the config helpers, and the manifest keys, all in one place. Chapter 16 introduces this landscape narratively; here it is tabulated for fast lookup.

Everything named here is a real, current tool of computational science — Tier 1 in the book's citation policy. Two kinds of detail are softer and marked inline as Tier 2: any specific version number or tag (packages move — take the current one from the library's own README), and any speed comparison (an illustrative order of magnitude, never a promise). The link flags below assume the library is already installed (Appendix C covers installation); each has been kept consistent with the chapter that puts it to work.


H.1 Numerical libraries

BLAS and LAPACK — the floor everything stands on

BLAS (Basic Linear Algebra Subprograms) and LAPACK (Linear Algebra PACKage) are the load-bearing numerical libraries of scientific computing, and — the fact worth repeating — they are written in Fortran. BLAS provides the low-level kernels (vector, matrix-vector, and matrix-matrix operations, its Levels 1/2/3); LAPACK sits on top of BLAS to solve real problems: linear systems, eigenvalue problems, and singular value decompositions. When NumPy, MATLAB, or R does linear algebra, this compiled Fortran is what actually runs. You call them for real in Chapter 21.

Reach for LAPACK the moment you need to solve $A\mathbf{x} = \mathbf{b}$, factor a matrix, or find eigenvalues or singular values — anything beyond the whole-array matmul/dot_product intrinsics. Never hand-roll these; a career's worth of tuning is already in the library.

The naming scheme. Classic routine names pack three fields into a few characters:

[ s | d | c | z ] [ matrix-type ] [ operation ]
      precision        e.g. ge          e.g. sv
  • Precision: s single real, d double real, c single complex, z double complex.
  • Matrix type: ge general, sy symmetric, po symmetric positive-definite, tr triangular, gb general band, and more.
  • Operation: sv solve, trf factor, trs solve-from-factor, ev eigenvalues, svd singular values; the BLAS-3 mm matrix-multiply, BLAS-2 mv matrix-vector.

So dgesv reads double · general · solve, and once you see the pattern a wall of names becomes legible. The routines you will meet most:

Routine Decodes as What it does Level
dgemm double · general · matrix-multiply $C \leftarrow \alpha AB + \beta C$ (the tuned kernel everything leans on) BLAS-3
dgesv double · general · solve solve dense $A\mathbf{x} = \mathbf{b}$ via LU with partial pivoting LAPACK
dsyev double · symmetric · eigenvalues eigenvalues (and optionally eigenvectors) of a real symmetric matrix LAPACK
dgesvd double · general · SVD singular value decomposition of a general matrix LAPACK

Swap the leading d for s/c/z to change precision. Two argument conventions trip up newcomers and are covered in Chapter 21: the leading dimension (lda — the declared first dimension, i.e. the stride between columns) and the info status flag (0 success, < 0 a bad argument in your call, > 0 a numerical failure). Always check info.

Linking. The reference implementation from Netlib is correct but deliberately simple; a cache-tuned implementation is many times faster on a large matrix (Tier 2 — an illustrative order of magnitude, not a fixed figure), so ship a tuned BLAS in production.

You want Link with Notes
Reference BLAS + LAPACK -llapack -lblas correct and portable; fine for learning and small problems
OpenBLAS (tuned, open source) -lopenblas bundles an optimized LAPACK, so this one flag usually replaces -llapack -lblas
Intel MKL (tuned, Intel CPUs) use Intel's MKL Link Line Advisor the link line is genuinely intricate and hardware/threading-dependent — generate it, don't memorize it
$ gfortran -std=f2018 -Wall solve.f90 -o solve -llapack -lblas   # reference
$ gfortran -std=f2018 -Wall solve.f90 -o solve -lopenblas        # tuned (OpenBLAS)

Tip — route matmul to a real BLAS. gfortran's -fexternal-blas flag sends large matmul calls to an external dgemm instead of the compiler's built-in version, so you inherit the tuned kernel without rewriting a line. It only helps above a size threshold; measure before relying on it (Chapter 21).

FFTW — fast Fourier transforms

FFTW ("Fastest Fourier Transform in the West") is the de-facto standard fast Fourier transform, turning an $O(n^2)$ transform into $O(n \log n)$. Unlike BLAS/LAPACK it is a C library, but it ships a first-class Fortran interface built on iso_c_binding and is called from Fortran constantly — a textbook example of the C interoperability of Chapter 16's ecosystem.

Reach for FFTW whenever your science moves between real space and frequency space: spectral PDE solvers, signal and image processing, digital filtering, correlation. Its Fortran interface is plan-based — you build a plan once, execute it many times, then destroy it:

use, intrinsic :: iso_c_binding
include 'fftw3.f03'        ! the Fortran 2003 interface FFTW installs
! ... plan = fftw_plan_dft_1d(n, in, out, FFTW_FORWARD, FFTW_ESTIMATE)
!     call fftw_execute_dft(plan, in, out)
!     call fftw_destroy_plan(plan)
You want Link with
Double-precision FFTW -lfftw3
Single-precision FFTW -lfftw3f

The exact plan/execute API (real-to-complex transforms, multidimensional plans, threading with -lfftw3_threads or -lfftw3_omp) is in FFTW's own manual; the shape above is the piece to remember.

Large and sparse: ScaLAPACK and PETSc (brief)

When a problem outgrows a single node, or is sparse, dense LAPACK is the wrong tool. Two libraries dominate — both are big enough to be their own courses, so this is only a signpost. Chapter 21 touches sparse formats where these belong.

Library What it is Reach for it when
ScaLAPACK distributed-memory LAPACK for dense problems (built on MPI + the BLACS/PBLAS layers) a dense factorization or eigenproblem is too large for one machine's memory
PETSc a large MPI-based toolkit for sparse linear/nonlinear systems and PDEs, with scalable solvers and preconditioners you assemble large sparse systems and need parallel Krylov solvers and preconditioners

Both are typically linked through their own build systems or pkg-config files rather than a single -l flag; consult each project's documentation (Appendix J lists where they live).


H.2 Scientific data libraries

Once a run produces more than a few megabytes, plain text stops scaling and you move to a portable, self-describing binary format. The two standards, their APIs, and when to choose which, are the subject of Chapter 25; here are the practical link details. Both are C libraries with an official, separately packaged Fortran interface — and forgetting to install that separate Fortran package is the classic "undefined reference" trap.

Library Fortran module API prefix By-hand link Config helper (preferred)
NetCDF-Fortran use netcdf nf90_* -lnetcdff -lnetcdf `nf-config --fflags --flibs`
HDF5 (Fortran) use hdf5 h5*_f -lhdf5_fortran -lhdf5 the h5fc compiler wrapper

Note the doubled f in -lnetcdff — that is the Fortran layer, distinct from the C core -lnetcdf. Prefer the config helpers, which emit the exact flags for your install so you never hard-code a path:

$ gfortran -std=f2018 -Wall write_nc.f90 `nf-config --fflags --flibs` -o write_nc   # NetCDF
$ h5fc      -std=f2018 -Wall write_h5.f90 -o write_h5                                # HDF5

When to choose which (from Chapter 25):

  • NetCDF — the standard for gridded climate, weather, and ocean data. Simpler API (nf90_createnf90_def_dimnf90_def_varnf90_put_attnf90_enddefnf90_put_varnf90_close), and the CF metadata conventions that make one lab's file readable by another decades later. Every nf90_* call returns an integer status — check it against nf90_noerr every time.
  • HDF5 — the standard for large, hierarchical simulation output: groups and datasets like a filesystem inside one file, with built-in chunking and deflate compression. Every h5*_f call takes a trailing hdferr; h5open_f/h5close_f must bracket all HDF5 work. NetCDF-4, incidentally, is built on top of HDF5.

Pitfall — the Fortran interface is a separate package. "NetCDF is installed" usually means the C core is installed; the netcdf-fortran package (and, for HDF5, the Fortran build) is a distinct install. A link that fails on a library you are sure you have is almost always the missing Fortran layer.


H.3 Parallel libraries

Two models scale a Fortran code beyond one core. OpenMP (shared-memory threads) is a compiler feature — the -fopenmp flag in Appendix C, not a library — so it is not listed here. The two that are libraries or runtimes:

Library / runtime What it is How you build & run Chapter
Open MPI a widely used MPI implementation wrappers mpifort (or mpif90) to compile; mpirun -np N ./exe to run 34
MPICH another major MPI implementation (same standard) identical wrappers and launcher; MPI code is portable across the two 34
OpenCoarrays the runtime that makes gfortran coarrays run across images (over MPI) compile -fcoarray=lib via the caf wrapper; run cafrun -n N ./exe 32

MPI (the Message Passing Interface) is a specification, not one library — Open MPI and MPICH are two implementations of it, and modern Fortran talks to either through the mpi_f08 module. It is the backbone of distributed-memory HPC and the whole subject of Chapter 34, where the heat solver is decomposed across processes.

Coarrays are Fortran's own parallel model, built into the language rather than bolted on as a library (Chapter 32). To run them across multiple images with gfortran you need the OpenCoarrays runtime and -fcoarray=lib; -fcoarray=single (Appendix C) compiles coarray code to a single image for serial testing with no runtime at all.

$ mpifort -O2 heat_mpi.f90 -o heat_mpi && mpirun -np 4 ./heat_mpi   # MPI, 4 processes
$ caf     -O2 heat_ca.f90  -o heat_ca  && cafrun -n 4 ./heat_ca     # coarrays, 4 images

H.4 Build and packaging tools

How a project is built is its own decision, and the right answer depends on the project. The four common choices, in rough order of least-to-most ceremony:

Tool Reach for it when Invoke it with Handles module order?
fpm new projects, libraries, anything you can shape to its conventions fpm build / fpm run / fpm test yes, automatically
CMake large or mixed-language projects, especially with C/C++; ubiquitous in HPC cmake -B build && cmake --build build yes (you configure it)
Meson modern projects wanting CMake's power with less boilerplate meson setup build && meson compile -C build yes
Make small projects, or legacy codes that already use it a hand-written Makefile; make noyou track dependencies

For your own new work, start with fpm, the Fortran Package Manager: it discovers your sources (app/ programs, src/ library, test/ tests), works out module compilation order for you, and fetches git dependencies — all from one fpm.toml manifest:

name = "heat-solver"
version = "0.1.0"
license = "MIT"

[dependencies]
stdlib = { git = "https://github.com/fortran-lang/stdlib" }

Tip — pin what you publish. A bare git dependency tracks the latest commit, which can change under you. For anything reproducible, pin a tag, branch, or rev, and take the exact spec from the library's current README rather than from memory — the repository URL is stable, but a specific tag string is a Tier 2 detail to confirm at the source (Chapter 37 makes the case for reproducible builds).

You meet CMake, Meson, and Make again in the wild in Chapter 16's survey and whenever you contribute to an existing code — because then you build it their way.


H.5 Testing and documentation

Numerical code that is not tested is numerical code you do not actually trust. These are the tools that pin behavior and explain it; all three come together in Chapter 37.

Tool Purpose How you use it When to prefer it
pFUnit unit testing, developed at NASA Goddard; can run tests in parallel under MPI annotated test files (processed to Fortran), integrated via CMake testing large or parallel scientific code
test-drive a lightweight, fpm-native unit-test framework add as an fpm dev-dependency; write simple test procedures small-to-medium projects already using fpm
FORD generate browsable HTML docs from source and special comments pip install ford, then run ford on a project file documenting any Fortran project

FORD (FORtran Documenter) reads documentation comments that use doubled markers — !> before an entity or !! after a declaration — and produces a linked, searchable website with call graphs. Because those markers are ordinary Fortran comments, adding them never affects the build:

!> Compute the arithmetic mean of a 1-D array.
pure function mean_value(x) result(m)
  real(dp), intent(in) :: x(:)   !! the input samples
  real(dp)             :: m       !! the returned mean
  m = sum(x) / real(size(x), dp)
end function mean_value

The common idea across the test frameworks is the one Chapter 37 leans on: pin the code's behavior with automated checks so that when you later optimize (Part VII) or parallelize (Part VIII) the solver, a single fpm test tells you instantly whether you changed a number you were not supposed to change.


H.6 The standard library and community tools

The modern connective tissue of Fortran — most of it built in the open by the fortran-lang community — is what turns the language from "a text editor and an inherited Makefile" into a comfortable place to work.

Tool What it is How you use it
stdlib the community standard library: routines the intrinsics don't cover add as an fpm dependency; use modules like stdlib_stats, stdlib_linalg, stdlib_sorting, stdlib_strings, stdlib_io, stdlib_math
fortls the Fortran language server (LSP) — completion, hover docs, go-to-definition, live errors pip install fortls, then pair with an editor extension (the "Modern Fortran" extension for VS Code; Vim/Neovim/Emacs also speak LSP)
Compiler Explorer godbolt.org — see the assembly your code compiles to paste a snippet, select gfortran, read the optimizer's output; no install
LFortran lfortran.org — a modern LLVM-based, interactive Fortran compiler run Fortran statement-by-statement like a REPL; it powers the in-browser play.fortran-lang.org. Still maturing — a superb teaching and exploration tool, not yet a drop-in production compiler

Of these, install fortls first — a language server is the single highest-value day-to-day upgrade to the Fortran editing experience. Reach for stdlib in any real project instead of re-writing means, sorts, and text-table readers by hand (it is a dependency you declare via fpm, exactly as in §H.4). Keep Compiler Explorer bookmarked for the performance chapters, and treat LFortran as the place to try a new idea or a Fortran 2023 feature interactively.


H.7 A typical scientific project stack

Put together, a modern Fortran project of the kind this book builds toward assembles from one component per layer. There is nothing mandatory about these particular choices — but this is a sensible, entirely free default that composes cleanly, and it is roughly the stack behind the capstone solver.

Layer Typical choice Why / how
Compiler gfortran (or Intel ifx in CI for a second opinion) free, portable, everywhere — Appendix C
Build & packaging fpm zero-config, resolves module order, fetches dependencies
Numerics LAPACK/BLAS via OpenBLAS (-lopenblas); FFTW (-lfftw3) if you transform inherit tuned kernels instead of hand-optimizing
Data I/O NetCDF (gridded/geoscience) or HDF5 (large hierarchical output) portable, self-describing, compressed — Chapter 25
Parallelism OpenMP within a node (-fopenmp); MPI (Open MPI/MPICH) or coarrays (OpenCoarrays) across nodes node-level threads plus cluster-level messaging — Chapters 32/34
Testing test-drive (light) or pFUnit (parallel-capable) pin behavior; fpm test in CI — Chapter 37
Documentation FORD HTML manual generated from !>/!! comments
Editor fortls + the Modern Fortran extension completion, diagnostics, navigation

H.8 Quick linking cheat-sheet

Every library flag in one place. Compiler and parallel flags themselves live in Appendix C; this table is the libraries half.

Library Add to the compile line Introduced / used in
Reference LAPACK + BLAS -llapack -lblas Ch. 21
OpenBLAS (tuned; includes LAPACK) -lopenblas Ch. 21
Intel MKL generate with the MKL Link Line Advisor Ch. 21
Route matmul to external BLAS -fexternal-blas (a gfortran flag) Ch. 21
FFTW (double / single) -lfftw3 / -lfftw3f spectral methods
NetCDF-Fortran `nf-config --fflags --flibs` (or -lnetcdff -lnetcdf) Ch. 25
HDF5 Fortran build with h5fc (or -lhdf5_fortran -lhdf5) Ch. 25
MPI build with mpifort; run with mpirun -np N Ch. 34
Coarrays (multi-image) -fcoarray=lib via caf; run with cafrun -n N Ch. 32
stdlib, and any fpm dependency declare in fpm.toml; fpm build links it Ch. 16, 37

The through-line is Chapter 16's lesson: Fortran's real power is the mature, composable set of libraries and tools around the language. You solve the algebra with LAPACK, transform with FFTW, store with NetCDF or HDF5, scale with MPI or coarrays, build and share with fpm, and trust the result because it is tested and documented — each tool doing one thing well and expecting to be composed with the rest.