GFortran equivalent of ieee_exceptions - fortran

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.

Related

How can I change MPI error handler before MPI_init?

I have a Fortran code which is predominantly used for running large MPI calculations, but occasionally I want to run it on a machine which does not have MPI available for quick data processing tasks.
I have a logical variable which determines whether or not the program is being run in MPI mode or not, and when it is false the code will not call any MPI subroutines. The way I determine whether or not to run in MPI mode at the moment is by testing to see if a dummy file "NO_MPI" exists which I dislike due to its inelegance and the fact that I usually forget that I need to create this file when running in a non-MPI environment.
When the code is run in a non-MPI environment the MPI_init subroutine will fail and cause the program to crash. So what I would like to do is call it with the optional error output:
call MPI_init(ierr)
and then if an error is returned continue with the node in non-MPI mode.
The issue is that the default MPI error handler will abort the program without returning an error. For any other MPI subroutine the solution would be:
call MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN)
to tell MPI not to abort and return the error code. However I cannot call this subroutine before MPI_init without getting the error
Attempting to use an MPI routine before initializing MPICH.
Is there any way to change the default error handler before calling MPI_init, perhaps specifying it with a compiler flag? I am using the IFORT compiler with MPICH.
I feel that there must be some way of testing the error code from MPI_init, otherwise what is the point of allowing MPI_init to accept the optional error return as an argument when the default behaviour is to abort without returning errors?

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.

how to stop a fortran program abnormally

When an exception occurs I would like to terminate abnormally my program. Right now, when an exception happens a write statement with an explanatory sentence is called, and then a stop statement is called.
I am debugging the program with idb (intel debugger), when the exception happens I get the write statement, but idb treats the program as terminated normally. I would like that when the exception happens the program is terminated abnormally and so that I can look to the memory with backtrace in the place where the exception happened.
I have tried changing stop in stop 1, so that a non zero value is returned, but this doesn't work
EDIT:
I have implemented the solution in one of the answer:
interface
subroutine abort() bind(C, name="abort")
end subroutine
end interface
print *,1
call abort()
print *,2
end
with this solution I still do not get any backtrace when I am using ifort 13.0.1, but this works perfectly with ifort 14.0.2.
I have resorted to use idb instead of gdb, because often the latter cannot read the values of allocatable arrays in fortran.
There are non-standard extensions for this. Gfortran uses backtrace() to print a backtrace anywhere, for the Intel's equivalent see the wander95's answer https://stackoverflow.com/a/38905855/721644.
In ifort and gfortran you can call the abort() subroutine and you will get backtrace if you used the -traceback (Intel) or -g -fbacktrace (gfortran) compiler option.
You could also call the C abort() directly using the C interoperability. (also non-standard and may not work in all circumstances):
interface
subroutine abort() bind(C, name="abort")
end subroutine
end interface
print *,1
call abort()
print *,2
end
With Fortran 2008 the ERROR STOP statement has been introduced. It's mainly used for Coarray Fortran programs to initiate error termination on all images.
Found this old question by accident. If you want abnormal termination with the intel compiler, you can use the routine tracebackqq. The call sequence can be:
call TRACEBACKQQ(string=string,user_exit_code=user_exit_code)
To quote the manual:
Provides traceback information. Uses the IntelĀ® Fortran run-time library traceback facility to generate a stack trace showing the program call stack as it appeared at the time of the call to TRACEBACKQQ( )
I've never used idb, I've only used gdb, so this might not work. I just put a read statement in at the error point, so that the program stops and waits for input. Then I can CTRL-C it, which causes gdb to pause execution, from which I can get a backtrace, move up and down the stack, look at variables, etc.

Assertions in Fortran

Does Fortran have a standard function/keyword equivalent for C assert?
I could not find assert mentioned in Fortran2003 standard I have. I have found few ways how to use pre-processor, but in this answer it is suggested to write own assertions. Is it possible to create such user function/subroutine without using pre-processor?
I expect that these assertions are disabled for release builds.
Conditional compilation has never really caught on in Fortran and there isn't a standard pre-processor. If getting your pre-processor to switch in and out a dummy assert routine isn't something you want to tackle you could ...
Define a global parameter such as:
logical, parameter :: debugging = .true.
If you are of a nervous disposition you could put this into a module and use-associate it into every scope where it is needed; to my mind using a global parameter seems a reasonable approach here.
Then write guarded tests such as
if (debugging) call assert(...)
Once you want to release the code, set the value of debugging to .false. I expect, though I haven't tested this so you may care to, that any current Fortran compiler can remove dead code when it encounters an expression equivalent to
if (.false.) call assert(...)
and that your released code will pay no penalty for a dummy call to an assert routine.
Another approach might be to create a module, let's call it assertions, along these lines:
module assertions
contains
subroutine assert_prd(args)
! declare args
end subroutine
subroutine assert_dbg(args)
! declare args
! now do do some assertion checking and exception raising, etc
end subroutine
end module assertions
You could then rename the subroutines when you use-associate them, such as:
use, non_intrinsic :: assertions, assert=>assert_dbg
and change that to assert=>assert_prd when you want to turn off assertion checking. I suspect though that compilers may not eliminate the call to the empty subroutine entirely and that your production code might pay a small penalty for every assertion it encounters.
Beyond this, see the paper by Arjen Markus that #AlexanderVogt has referred you to.
To my knowledge, there is no such statement or function/subroutine in Standard Fortran. But - as you have said - you can use your own subroutines/function and/or OOP in Fortran to realize this goal. See Arjen Markus' excellent paper on this topic.
For fixed form sources, one can use -fd-lines-as-comments for release builds and -fd-lines-as-code for debug build (Intel Fortran -d-lines)
and use custom assert:
D if (assert_condition) then
D write(*,*) 'assert message'
D call exit(1)
D endif

How to check whether the output has been redirected in Fortran?

I would like to know how to check whether the standard output has been redirected or not when writting Fortran code. Because I have added encodes in the output to make them colorful, which does not work when redirection happens. So if so, the encodes should be disabled.
Thanks in advance!
If the non-standard solution suggested by #Janneb doesn't appeal I'd suggest passing an argument to the Fortran program which tells it where to send its output. The program could then determine whether or not to enable writing your encodes. If you opt for this route you can use the (Fortran 2003) intrinsic subroutine get_command_argument.
The easiest way that works, but may be compiler-specific, is to use a compiler extension for accessing the isatty() function (in gfortran, the ISATTY intrinsic). Consider the following code
program test_isatty
use iso_fortran_env
write(*, *) isatty(output_unit)
end program test_isatty
Running it
$ ./isatty
T
$ ./isatty > foo
$ cat foo
F
In case your Fortran compiler does not have an isatty extension, but comes with an extension to get the system file descriptor (fd) corresponding to a Fortran unit (in gfortran, the FNUM intrinsic), you can use that to get the fd for the standard output unit, and then you can use ISO_C_BINDING to call isatty() on the fd.