I am working with a code originally written in Fortran 77 that makes use of namelists (supported by compiler extension at the time of its writing - this feature only became standard in Fortran 90) for reading input files. The namelist input files have groups of namelist variables in between (multiple) plain text headers and footers (see example.nml
). Some groups of namelist variables are only read if certain conditions are met for previously read variables.
When reading all the namelist groups in a file in sequence, executables compiled with gfortran, ifort and nagfor all behave the same and give the expected output. However, when a given namelist group in the input file is to be skipped (the optional reading), gfortran and ifort executables handle this as desired, while the executable compiled with nagfor raises a runtime error:
Runtime Error: reader.f90, line 27: Expected NAMELIST group /GRP3/ but found /GRP2/ Program terminated by I/O error on unit 15 (File="example.nml",Formatted,Sequential)
As a minimal working example reproducing the problem, consider the namelist file example.nml
and driver program reader.f90
given below, in which NUM2
from namelist group GRP2
should only be read if NUM1
from namelist group GRP1
equals 1
:
example.nml:
this is a header
&GRP1 NUM1=1 /
&GRP2 NUM2=2 /
&GRP3 NUM3=3 /
this is a footer
reader.f90:
program reader
implicit none
character(len=40) :: hdr, ftr
integer :: num1, num2, num3, icode
! namelist definition
namelist/grp1/num1
namelist/grp2/num2
namelist/grp3/num3
! open input file
open(unit=15, file='example.nml', form='formatted', status='old', iostat=icode)
! read input data from namelists
read(15, '(a)') hdr
print *, hdr
read(15, grp1)
print *, num1
if (num1 == 1) then
read(15, grp2)
print *, num2
end if
read(15,grp3)
print *, num3
read(15, '(a)') ftr
print *, ftr
! close input file
close(unit=15)
end program reader
All executables give this expected output when NUM1=1
:
this is a header
1
2
3
this is a footer
However, when e.g. NUM1=0
, the executables compiled with gfortran and ifort give the desired output:
this is a header
0
3
this is a footer
while the executable compiled with nagfor (which is known for being strictly standard conforming), reads the header and first namelist group:
this is a header
0
but then terminates with the previously mentioned runtime error.
As indicated by the error message, example.nml
is accessed sequentially, and if that is the case, /GRP2/ is the next record to be read, not /GRP3/ as the program logic asks for, so the error message makes sense to me.
So my question is this:
- Can the shown behaviour be attributed to standard (non-)conformance enforced by nagfor and not gfortran and ifort?
- If so, does this mean that the non-sequential reading observed with gfortran and ifort is due to extensions supported by these compilers (and not nagfor)? Can this be turned on/off using compiler flags?
- The simplest workaround I can think of (minimal change to a large existing program), would be to add a dummy
read(15,*)
in anelse
branch for theif
statement inreader.f90
. This seems to work with all the mentioned compilers. Would this make the code standard conforming (Fortran 90 or later)?
These are the compiler versions and options that were used to compile the executables:
- GNU Fortran (Ubuntu 9.1.0-2ubuntu2~18.04) 9.1.0:
gfortran -Wall -Wextra -fcheck=all -g -Og -fbacktrace reader.f90
- Intel(R) Visual Fortran, Version 16.0 Build 20160415:
ifort -Od -debug:all -check:all -traceback reader.f90
- NAG Fortran Compiler Release 6.1(Tozai) Build 6116:
nagfor -O0 -g -C reader.f90