Gfortran attribute that requires an explicit interface for this procedure - fortran

I am new to Fortran, trying to compile a Atmospheric Wind model which is available here:
http://nssdcftp.gsfc.nasa.gov/models/atmospheric/hwm07/
I am using Ubuntu 12.04 and gfortan (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)).
The model contains 4 datafiles with .f90 extension and 3 of them compile just fine. The last one gives me the error:
$ gfortran -c hwm07e.f90
hwm07e.f90:168.22:
call HWMupdate(input,last,gfs,gfl,gfm,gvbar,gwbar,gbz,gbm,gzwght,glev,u
1
Error: Dummy argument 'ebz' of procedure 'hwmupdate' at (1) has an attribute that requires an explicit interface for this procedure
hwm07e.f90:168.22:
call HWMupdate(input,last,gfs,gfl,gfm,gvbar,gwbar,gbz,gbm,gzwght,glev,u
1
Error: Dummy argument 'ebz' of procedure 'hwmupdate' at (1) has an attribute that requires an explicit interface for this procedure
ebz and ebm are defined as targets which seems to be a source of the problem:
subroutine HWMupdate(input,last,fs,fl,fm,vbar,wbar,ebz,ebm,zwght,lev,u,v)
use NewModel
implicit none
...
real(8),intent(inout),target :: ebz(nbf,0:p)
real(8),intent(inout),target :: ebm(nbf,0:p)
...
ebz = 0.0
ebm = 0.0
bz => ebz(:,b)
bm => ebm(:,b)
In the included makefile.g95 it suggests to use g95 as the compiler, is it possible that it is not possible to compile this using gfortran?
Any suggestions are highly appreciated!
Thank you

The compiler is (and you are) correct here that the call to HWMupdate requires an explicit interface because of the target attribute on the dummy arguments. This doesn't mean that a compiler must reject the code: ifort for example can be persuaded to continue, and perhaps g95 also.
To get your compilation to continue, you could find a compiler flag to allow this: -fno-whole-file being possibly one option as this restricts gfortran's ability to do this checking. The documentation recommends against doing this, however.
If you aren't against changing the code then a better solution would be to provide an explicit interface.

Related

Fortran derived-type parameter with allocatables

I have a derived-type with pointer (or allocatable) component
type Tmy
real, dimension(:), pointer :: vals
integer :: nVals
end type Tmy
And I want to create a parameter, e.g. to pass it to a subroutine as intent(in):
type (Tmy), parameter, public :: my_missing = Tmy(null(), 0)
Currently a similar code compiles fine to me by GNU Fortran (Spack GCC) 9.4.0, but introduction of the parameter triggers numerous strange errors in another module that uses the current one. The using module has variables of the type, but no reference to the parameter. The first error is triggered in a derived-type declaration with default initialization:
550 | logical, dimension(:,:), pointer :: ifValid => null()
| 1
Error: Cannot change attributes of USE-associated symbol null at (1)
and follows by numerous similar errors and complains about missing members in various structures. If I comment out the parameter declaration the code compiles and runs just fine.
So the questions are:
How introducing a parameter in one module can trigger compilation errors in another module, given that the name my_missing is unique within the project? Or is it just a bug in the compiler?
Is introducing such a parameter a valid practice in Fortran?
If it is valid, what is the effect of assigning this parameter to a structure that has vals already allocated (in case if vals is declared as allocatable)?
PS Yes, I know that allocating pointers is a bad idea. I try to turn them to allocatables bit by bit..
UPD: The issue is reproducible with two different versions of gfortran, but only at one specific computer. Also I did not manage to compile any observable MWE so far..
UPD2: Thank you all, who commented so far. It seems clear that there is no breaking of Fortran standards in my examples here. MWE is of little use since the issue is reproducible only at one computer. I'll then ask for help from our HPC staff and come back once something interesting found.
TL;DR
Bug in gfortran-9 (9.4.0 from Spack, 9.5.0-1ubuntu1~22.04). Other gfortran compilers available for Ubuntu 22.04 (10.4.0-4ubuntu1~22.04,11.3.0-1ubuntu1~22.04, and 12.1.0-2ubuntu1~22.04) work just fine.
Details
I have managed to reproduce the issue in Ubuntu 20.04, by changing to gcc-9. Here is the way to reproduce it:
Make sure that gcc-9 is called for gfortran
Checkout and compile https://github.com/fmidev/silam-model/ See README there for more details
Edit source/namelist.silam.mod.f90 with adding after the definition of Tsilam_namelist (around l. 257):
! Enabling these lines causes a mysterious error at GNU Fortran 9.4.0 and 9.5.0
type(Tsilam_namelist), parameter, private :: silam_namelist_missing = Tsilam_namelist( &
& null(), int_missing, int_missing, int_missing, &
& silja_false, "Missing_namelist" &
& )
make clean
make full
The problematic lines were added in our development branch quite some time ago. The only way to pinpoint the line that triggers the bug was a bisect on many revisions. Luckily, the revision that introduced the trigger was small.
The specific bug in gcc-9 responsible for the problem is yet unknown, but it is more of an academic interest...
Thank everyone once again for valuable comments!

Why does MPICH 3.0's 'mpi' module omit explicit interfaces for some procedures?

I'm working on building an MPI-based molecular dynamics program against several MPI implementations (separately), and I've run into a snag with MPICH 3.0: it seems not to provide explicit interfaces for several MPI procedures. Some of the affected procedures are mpi_bcast(), mpi_ssend(), mpi_recv(), and mpi_finalize(). MPICH 3.0 does provide explicit interfaces for some procedures, however, such as mpi_init(). This example code demonstrates the problem:
program mpitest
use mpi
integer ierr
ierr = 0
call dummy_implicit(ierr)
call mpi_init(ierr)
if (ierr /= 0) then
write(*,*) 'MPI_Init() failed'
stop
endif
call mpi_finalize(ierr)
if (ierr /= 0) then
write(*,*) 'MPI_Finalize() failed'
endif
stop
end program
If I build this program on CentOS 7 against MPICH 3.0.4, I get this result:
$which mpif90
/usr/lib64/mpich/bin/mpif90
$ mpif90 -Wimplicit-interface -c -o mpitest.o mpitest.f90 mpitest.f90:6.31:
call dummy_implicit(ierr)
1 Warning: Procedure 'dummy_implicit' called with an implicit interface at (1) mpitest.f90:15.29:
call mpi_finalize(ierr)
1 Warning: Procedure 'mpi_finalize' called with an implicit interface at (1)
$
The warning about procedure dummy_implicit() is expected and correct, but I expect MPICH to provide an explicit interface for mpi_finalize(), just as it apparently does for mpi_init(). Moreover, I find that if I build the same program against MPICH 3.2 or OpenMPI 1.10.3 then an implicit interface warning is emitted only for procedure dummy_implicit().
This issue bears some resemblance to one reported against MPICH2, but that one (1) was reported against MPICH 2, not MPICH 3, and (2) was closed about 5 years ago.
I do want to ensure that I have explicit interfaces in scope for all my procedure calls. I can provide the missing ones manually if need be, but surely that's not the intended usage model, nor is it required for other MPI implementations.
What am I doing wrong? Do I really need to provide explicit interfaces manually?
There is no guarantee that the mpi Fortran module will contain explicit interface for particular procedure. Some are contained more commonly (those with fixed datatypes), some very rarely (those where buffers of various types are passed, just think how many versions would have to be generated...).
The number of procedures in the module will differ from library to library, from version to version and could also be affected by configuration before compiling the MPI library.
I just wouldn't use -Wimplicit-interface with MPI. I tried providing some interfaces myself, but then you will find out that at some other computer the interface is provided and you have a clash and it will not compile at all.
You can try the mpi_f08 module if your library supports it, it typically contains everything with an explicit interface. But that also requires some advanced features from the compiler and some of them are not widely supported yet.

Why does PGI not pick up on public attribute in this module?

Working with someone else's code here. It compiles just fine with gfortran. Under Portland Group, though, I get an error:
pgf90 -DsysLinux -DcompPGF90 -I/home/cables/GITM/share/Library/src -c -r8 -fast ModUtilities.F90
PGF90-S-0084-Illegal use of symbol mpi_wtime - not public entity of module (ModUtilities.F90: 419)
0 inform, 0 warnings, 1 severes, 0 fatal for sleep
The offending line looks like:
use ModMpi, ONLY : MPI_wtime
(There's obviously a lot of MPI stuff going on here, but I don't think that's the point.) So I go to the source code for ModMpi, which is ModMpi.f90, where I see no reference to MPI_WTIME, but I see:
use ModMpiInterfaces
So finally, I go to the source for ModMpiInterface and I find the line:
public:: mpi_wtime
OK, I was able to get a compile from PGI by editing ModMpi.f90 and declaring mpi_wtime to be public. But still, I wonder: Why did gfortran assume (apparently) that mpi_wtime was public, but PGI had to be told this explicitly? Why does PGI not assume that the original public declaration holds throughout the "use chain"?
I presume that one behavior or the other is closer to the Fortran standard. Which would that be?
For exactly the same Fortran source code (as opposed to some sort of MPI library) compiler behaviour should be the same here.
Whether or not an entity is a public entity of a module is specific to each module that defines or accesses (via USE) that entity. Module A might declare "something" and specify that it is public, module B might USE module A and then specify that same "something" is then private. Any code using module A will be able to access "something", any code only using module B will not.
The default accessibility of things declared in a module is PUBLIC, but that default can be changed by a PRIVATE statement (one without any following identifiers). If such a private statement appeared, you would see the behaviour you describe with the PGI compiler.
Implicit typing (i.e. from source code without IMPLICIT NONE) can also confuse things here.

GFortran equivalent of ieee_exceptions

I am trying to write a program that will stop whenever an invalid operation is performed, no matter how it is compiled with GFortran. With ifort I could do something like this:
use ieee_exceptions
....
logical :: halt
....
call ieee_get_halting_mode(IEEE_USUAL,halt)
call ieee_set_halting_mode(IEEE_USUAL,.True.)
....
! Something that may stop the program
....
call ieee_set_halting_mode(IEEE_USUAL,halt)
Does GFortran have a module similar to ifort's ieee_exceptions? Or even better is there a way of stopping the halting mode without knowing how the program will be compiled or which compiler will be used?
GFortran supports the ieee_exceptions module as of the GCC 5 release.
If you're stuck on an older GFortran release, a workaround would be to implement functions in C/asm that get/set the FP trapping status register and call those from Fortran.
PS.: GFortran does have a switch (-fpe-trap) for globally enabling traps for FP exceptions, see http://gcc.gnu.org/onlinedocs/gfortran/Debugging-Options.html . But, since you explicitly said "no matter how it is compiled with gfortran", I guess you don't want to use that.

Passing an internal procedure as argument

I want to solve a differential equation lots of times for different parameters. It is more complicated than this, but for the sake of clarity let's say the ODE is y'(x) = (y+a)*x with y(0) = 0 and I want y(1). I picked the dverk algorithm from netlib for solving the ODE and it expects the function on the right hand side to be of a certain form. Now what I did with the Intel Fortran compiler is the following (simplified):
subroutine f(x,a,ans)
implicite none
double precision f,a,ans,y,tol,c(24),w(9)
...
call dverk(1,faux,x,y,1.d0,tol,ind,c,1,w)
...
contains
subroutine faux(n,xx,yy,yprime)
implicite none
integer n
double precision xx,yy(n),yprime(n)
yprime(1) = (yy(1)+a)*xx
end subroutine faux
end subroutine f
This works just fine with ifort, the sub-subroutine faux sees the parameter a and everything works as expected. But I'd like the code to be compatible with gfortran, and with this compiler I get the following error message:
Error: Internal procedure 'faux' is not allowed as an actual argument at (1)
I need to have the faux routine inside f, or else I don't know how to tell it the value of a, because I can't change the list of parameters, since this is what the dverk routine expects.
I would like to keep the dverk routine and understand how to solve this specific problem without a workaround, since I feel it will become important again when I need to integrate a parameterized function with different integrators.
You could put this all in a module, and make a a global module variable. Make faux a module procedure. That way, it has access to a.
module ode_module
double precision::a
contains
subroutine f(x,a,ans)
implicit none
double precision f,ans,y,tol,c(24),w(9)
call dverk(1,faux,x,y,1.d0,tol,ind,c,1,w)
end subroutine
subroutine faux(n,xx,yy,yprime)
implicite none
integer n
double precision xx,yy(n),yprime(n)
yprime(1) = (yy(1)+a)*xx
end subroutine faux
end module
You can check here which compilers support this F2008 feature:
http://fortranwiki.org/fortran/show/Fortran+2008+status
On that page, search for "Internal procedure as an actual argument" .
Passing an internal procedure is allowed by Fortran 2008. That means that your code is correct Fortran and just a more recent compiler is needed.
At the time when this question was posted the support for that in existing compilers was patchy. Some did support it, some did not. This changed considerably and at the time of writing this revision of the answer one can normally use it without needing to think about compiler support any more.
You are not limited to sharing the data in a module. You just have to make sure, that the containing procedure is still running. It is not possible to save the pointer and make a so called 'closure' known from LISP and many modern languages. In languages like Fortran or C the enclosing environment for future calls is not saved and pointers to internal functions become invalid.
The advantage of internal procedure over module procedure is that you can share the data without sharing it in the whole module.
It works well will reasonably old versions of GCC (gfortran), Intel Fortran and Cray Fortran (personally tested) and possibly others. I remember not being able to compile by PGI and Oracle Fortran. As shown by Daniel, it can be checked at http://fortranwiki.org/fortran/show/Fortran+2008+status (search Internal procedure as an actual argument). The most recent version of this table is periodically published in ACM SIGPLAN Fortran Forum.
There is some interesting info in this article https://stevelionel.com/drfortran/2009/09/02/doctor-fortran-in-think-thank-thunk/
Be aware that the implementation of this feature normally requires executable stack due to the use of trampolines. One does not normally think about that but if the OS forbids executable stack, the executable might fail (there were issues in initial versions of Windows Subsystem for Linux, for example).