ZetCode

Fortran namelists

last modified November 14, 2026

A program with many settings needs a way to read them that is more forgiving than a fixed-column file. A namelist is a named group of variables that can be written and read as a unit, in a format that names each value: nx = 200 rather than a number in column five. The runtime matches the names in the input with the variables of the group, so the order does not matter, values may be missing, and extra whitespace is ignored. This article shows how to declare a namelist, write it to a configuration file, read it back with defaults for the values that are absent, use namelists without any file at all, and recognise the two ways such a read can fail.

Declaring and writing a namelist

The declaration namelist /config/ nx, ny, dt, verbose, title does two things at once: it gives the group the name config and lists the variables that belong to it. The group is then used through the nml= specifier of read and write, in the same place where a format usually stands. The program below fills the variables, writes the group to a file, and the file on disk shows the format: an opening &config, one assignment per line, and a closing slash.

m1.f90
program m1
    implicit none
    integer :: nx, ny
    real :: dt
    logical :: verbose
    character(len=20) :: title
    namelist /config/ nx, ny, dt, verbose, title
    integer :: u

    nx = 100
    ny = 50
    dt = 0.01
    verbose = .true.
    title = 'run one'
    open (newunit=u, file='config.nml', status='replace')
    write (u, nml=config)
    close (u)
    print *, 'wrote config.nml'
end program m1

The output is valid input: the same file can be read back by any program that declares a group with the same names and compatible types. The name of the group appears in upper case in this runtime, and the values are aligned with blanks, but neither detail matters to a reader, which ignores case and spacing. A character value is quoted and padded to its declared length, so run one leaves the file with its trailing blanks enclosed in quotes; the reader strips them when it stores the value.

$ gfortran m1.f90 -o m1
$ ./m1; cat config.nml
 wrote config.nml
&CONFIG
 NX=100        ,
 NY=50         ,
 DT=  9.99999978E-03,
 VERBOSE=T,
 TITLE="run one             ",
 /

Reading a configuration

Reading is done with read (u, nml=config), and the variables keep whatever value they had before the statement for every name that the input does not mention. This is what makes namelists pleasant for configuration: the program sets sensible defaults in its declarations, and the file overrides only what the user wants to change. The example below gives every variable a default, then reads a file that sets just two of them, and prints all five so that the untouched defaults are visible.

m2.f90
program m2
    implicit none
    integer :: nx, ny
    real :: dt
    logical :: verbose
    character(len=20) :: title
    namelist /config/ nx, ny, dt, verbose, title
    integer :: u, ios

    nx = 10
    ny = 10
    dt = 1.0
    verbose = .false.
    title = 'default'

    open (newunit=u, file='config.nml', status='replace')
    write (u, '(a)') '&config'
    write (u, '(a)') ' nx = 200,'
    write (u, '(a)') ' dt = 0.005'
    write (u, '(a)') '/'
    close (u)

    open (newunit=u, file='config.nml', status='old')
    read (u, nml=config, iostat=ios)
    close (u)
    print *, 'ios:', ios
    print *, 'nx, ny:', nx, ny
    print *, 'dt:     ', dt
    print *, 'verbose:', verbose
    print *, 'title:  ', trim(title)
end program m2

The status is zero, nx becomes 200, and ny, verbose and title keep their default values. The trailing comma after 200 is optional but harmless, and the input may be spread over as many lines as the writer likes. The value of dt prints as 0.005 with a small binary error in the last digits, which is the usual behaviour of a binary real, not a fault of the namelist reader.

$ gfortran m2.f90 -o m2
$ ./m2
 ios:           0
 nx, ny:         200          10
 dt:        4.99999989E-03
 verbose: F
 title:  default

Namelists in memory

A namelist does not need a file. Any character variable can be the unit of the read, exactly as in the internal files article, and the nml= specifier works there too. That is convenient for tests and for settings that arrive as a single line from a command-line option, and it avoids creating a file just to parse one string. The program below reads two namelist records from a character variable and prints which variables each one changed.

m3.f90
program m3
    implicit none
    integer :: count, step
    real :: scale
    namelist /params/ count, step, scale
    character(len=200) :: text
    integer :: ios

    count = 1
    step = 1
    scale = 1.0
    text = '&params count = 12, step = 3 /'
    read (text, nml=params, iostat=ios)
    print *, 'ios:', ios, 'count:', count, 'step:', step, 'scale:', scale

    count = 0
    text = '&params scale = 2.5, count = 4 /'
    read (text, nml=params, iostat=ios)
    print *, 'ios:', ios, 'count:', count, 'step:', step, 'scale:', scale
end program m3

The first record sets the two integers and leaves scale at one. The second record sets scale and count and leaves step at the three that the first record gave it, because the second read did not reset the variables first. Both groups fit on one line, with values separated by commas and the group closed by the slash, which is the same syntax as in a file. The group name after & must match the name in the declaration.

$ gfortran m3.f90 -o m3
$ ./m3
 ios:           0 count:          12 step:           3 scale:   1.00000000    
 ios:           0 count:           4 step:           3 scale:   2.50000000    

When the input is wrong

Two mistakes are common in hand-written configuration: a name that the program does not know, usually a typo, and a value that cannot be converted to the variable's type. Without iostat both stop the program at run time. With it, both produce a positive status and leave the variables as they were, which lets the program report the problem and fall back to the defaults. The program below tries each mistake in turn.

m4.f90
program m4
    implicit none
    integer :: n
    real :: tol
    namelist /options/ n, tol
    character(len=120) :: text
    integer :: ios

    n = 5
    tol = 0.001
    text = '&options n = 5, bogus = 3 /'
    read (text, nml=options, iostat=ios)
    print *, 'unknown name, ios =', ios, 'n =', n

    n = 5
    tol = 0.001
    text = '&options tol = "abc" /'
    read (text, nml=options, iostat=ios)
    print *, 'bad value,    ios =', ios, 'tol =', tol, 'n =', n
end program m4

Both reads report 5010 on this runtime, a positive status that means the input did not match the group; the exact number is processor dependent, so a program should test it against zero rather than for a particular value. In both cases the variables keep the values they had before the failed read. Without iostat either statement would stop the program, which is why a configuration reader supplies it and reports the failing record to the user; the text of the message can be captured with iomsg, as the files article shows for open.

$ gfortran m4.f90 -o m4
$ ./m4
 unknown name, ios =        5010 n =           5
 bad value,    ios =        5010 tol =   1.00000005E-03 n =           5

Arrays and repetition

A namelist variable may be an array, and its values are written and read in element order. The input can also select a section with the usual colon notation, so grid(2:4) = 7, 8, 9 changes three elements and leaves the others alone. Writing a namelist into a character variable shows how the runtime formats arrays: the elements are separated by commas, and a run of equal values is shortened with a repeat count, so the two zeroes of origin become 2*0.00000000. The program below uses both features.

m5.f90
program m5
    implicit none
    integer :: grid(5)
    real :: origin(2)
    namelist /mesh/ grid, origin
    character(len=300) :: text

    grid = [1, 2, 3, 4, 5]
    origin = [0.0, 0.0]
    write (text, nml=mesh)
    print *, 'internal write:'
    print *, trim(text)

    grid = 0
    origin = -1.0
    text = '&mesh grid(2:4) = 7, 8, 9, origin = 1.5, 2.5 /'
    read (text, nml=mesh)
    print *, 'grid:  ', grid
    print *, 'origin:', origin
end program m5

The internal write produces one long record with the group name, the array values separated by commas and the two origin values written with a repeat count because they are equal. The read then fills elements two to four of the grid and both elements of origin, leaving the first and last grid elements at the zero they were set to. An array section in the input must not run past the end of the array, because the runtime checks the bounds only when the data is stored, at which point the program stops.

$ gfortran m5.f90 -o m5
$ ./m5
 internal write:
  &MESH  GRID=1          ,2          ,3          ,4          ,5          ,    ORIGIN= 2*0.00000000      ,  /
 grid:             0           7           8           9           0
 origin:   1.50000000       2.50000000    

Comments and repeated values

Two more conveniences make namelists usable for files that people edit by hand. A ! starts a comment that runs to the end of the line, and a repeat count r*c stands for r copies of the value c, where the value may be a number or a quoted string. The program below reads a group with both, building its text with new_line('a') so that every statement sits on its own line, the way it would in a real file.

m6.f90
program m6
    implicit none
    integer :: steps, counts(4)
    character(len=20) :: label
    namelist /run/ steps, counts, label
    character(len=400) :: text
    integer :: ios

    steps = 0
    counts = 0
    label = 'none'
    text = '&run' // new_line('a') // &
           '  steps = 12,      ! how many steps' // new_line('a') // &
           '  counts = 3*2, 7  ! three twos and a seven' // new_line('a') // &
           '  label = ''trial''' // new_line('a') // &
           '/'
    read (text, nml=run, iostat=ios)
    print *, 'ios:   ', ios
    print *, 'steps: ', steps
    print *, 'counts:', counts
    print *, 'label: ', trim(label)
end program m6

The status is zero, the first three elements of counts become 2 and the fourth becomes 7, and the quoted label keeps its four letters. The doubled quotes inside the concatenation are how a literal quote is written in a Fortran string, so ''trial'' in the source produces 'trial' in the text. Comments are useful for recording units or allowed ranges next to the value, and they do not affect the read.

$ gfortran m6.f90 -o m6
$ ./m6
 ios:              0
 steps:           12
 counts:           2           2           2           7
 label: trial

Next steps

Namelists are a readable way to store settings, while the files article covers general text files and the stream and binary files article covers the compact form. Tables of numbers are better handled by the CSV and text data article, and grouped data of mixed types by the derived types article. The internal files article explains the character-variable unit used in the in-memory examples.

Source

Fortran 2018 standard (J3/18-007r1)

GNU Fortran manual

Fortran-lang: learning resources

In this article we have grouped variables into namelists, written a configuration file, read it back with defaults for the missing values, used the same mechanism on a string in memory, recognised unknown names and bad values through iostat, and stored arrays with sections, comments and repeat counts. The previous article, Fortran stream and binary files, covers the opposite end of the spectrum, where nothing is readable but everything is exact.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Fortran tutorials.