Have time in a pure manner in Fortran? - fortran

I am looking for a pure way to have access to time information. I thought about intrinsic functions and subroutines of standards compiler (date_and_time,cpu_time, system_clock, ltime, ctime, ...), the format do not really matter to me. I also thought about MPI function, but it is the same as intrinsic functions, there are all impure functions.
Here is a minimal example:
elemental subroutine add(message, text)
! function add
IMPLICIT NONE
character(len=:),allocatable,intent(inout) :: message
character(len=*), intent(in) :: text
character(len=1), parameter :: nl=char(10)
character(10) :: time
! character(8) :: date
! time= 'hhmmss.sss'
call DATE_AND_TIME(time)
Message= Message//time////text//nl
end subroutine add
and I get a logical error :
Error: Subroutine call to intrinsic ‘date_and_time’ at (1) is not PURE
Thus, I am wandering if a pure way to have a time information exists, or if it is impossible to have it purely (maybe because it has to use cpu information which, for a reason unknown to me, could be thread-unsafe).
Maybe, a subquestion, could be is there a solution to force the compiler to consider date_and_time pure (or any other function of that kind)?

The answer about a pure manner to get time is no. A function that returns the current time or date, is impure because at different times it will yield different results—it refers to some global state.
There are certainly tricks to persuade the compiler that a subroutine is pure. One is to flat out lie in an interface block.
But there are consequences from lying to the compiler. It can do optimizations which are unsafe to do and the results will be undefined (most often correct anyway, but...).
module m
contains
elemental subroutine add(text)
IMPLICIT NONE
character(len=*), intent(in) :: text
character(len=1), parameter :: nl=char(10)
character(10) :: time
intrinsic date_and_time
interface
pure subroutine my_date_and_time(time)
character(10), intent(out) :: time
end subroutine
end interface
call MY_DATE_AND_TIME(time)
end subroutine add
end module
program test
use m
call add("test")
end program
subroutine my_date_and_time(time)
character(10), intent(out) :: time
call date_and_time(time)
end subroutine
Notice I had to delete your message because that was absolutely incompatible with elemental.

Related

gfortran : check subroutine argument list (if call match definition)

I'm debugging fortran program with gfortran using -g -Og -fcheck=all
It still does not report errors, that the number and type of arguments in call differs from the definition
e.g. it pass things like this without errors:
Definition:
subroutine assemble_2c(iforce, itheory, natoms)
integer, intent(in) :: iforce
integer, intent(in) :: itheory
integer, intent(in) :: natoms
...
end subroutine
use
call assemble_2c()
also this:
subroutine assemble_2c()
...
end subroutine
use
call assemble_2c(iforce, itheory, natoms)
comming from C/C++ (Java, python... basically any other language) ... this seems to me as perhaps the most basic thing which compiler should check, so I'm really dismayed it does not.

Function declared in module using interface

I have a code as follows:
The function is declared in a module using an interface block
module my_subs
implicit none
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
end function cross
end interface
end module my_subs
program crosstest
use my_subs
implicit none
integer, dimension(3) :: m, n
integer, dimension(3) :: r
m = [1, 2, 3]
n = [4, 5, 6]
r = cross(m,n)
write(*,*) r
end program crosstest
function cross(a,b)
implicit none
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
cross(1) = a(2)*b(3) - a(3)*b(2)
cross(2) = a(3)*b(1) - a(1)*b(3)
cross(3) = a(1)*b(2) - a(2)*b(1)
end function cross
According to this website, the use of interface blocks allows main programs and external subprograms to interface appropriately. However, I tested different mismatch of array size scenarios, I got the following result:
Change dimension at line 6 to 2 and 4, the code cannot be compiled;
Change dimension at line 7 to 2, the code can be compiled and produce the correct output;
Change dimension at line 7 to 4, the code cannot be compiled;
Change dimension at line 27 to 2 and 4, the code can be compiled and produce the correct output;
Change dimension at line 28 to 2 and 4, the code can be compiled and produce the correct output;
I am confuse about the different scenarios I performed, because I suppose the use of interface can help me to detect any mismatch of array size. In this case, is it better for me to move the function cross(a,b) into the module my_subs using contains?
You can check the interface by putting some declarations in function cross that test whether the interface as declared in module my_subs matches what function cross thinks its interface should be:
interface in function cross:
module my_subs
implicit none
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(3), intent(in) :: a, b
end function cross
end interface
end module my_subs
program crosstest
use my_subs
implicit none
integer, dimension(3) :: m, n
integer, dimension(3) :: r
m = [1, 2, 3]
n = [4, 5, 6]
r = cross(m,n)
write(*,*) r
end program crosstest
function cross(a,b) result(res)
use my_subs, only: check => cross
implicit none
integer, dimension(3) :: res
integer, dimension(3), intent(in) :: a, b
procedure(check), pointer :: test => cross
res(1) = a(2)*b(3) - a(3)*b(2)
res(2) = a(3)*b(1) - a(1)*b(3)
res(3) = a(1)*b(2) - a(2)*b(1)
end function cross
gfortran zaps this in all cases of mismatch you tested. I'm not sure that it should: if TKR of a dummy argument matches, shouldn't the rules of sequence association produce a correct invocation of the procedure? I haven't used submodules, but I think that they might do roughly the same thing as my example does.
When using an interface block to provide an explicit interface within a scope (in this case, in the module, which is then used by the main program) it is a requirement on the programmer that the specified interface matches the actual procedure.1
As given first, these things match happily. Changing the size of the function result or dummy arguments of one statement of the procedure but not the other creates a mismatch. Such code is a violation of the Fortran standard.
In general, a compiler isn't required to detect this violation. It may take your interface block on faith or it may do some extra work to see whether it should believe you. This latter is possible, especially if the external procedure is given in the same file as the interface block. You may see some error messages relating to this.
Further, if the interface block is given, the compiler will test the reference to the procedure against the interface, not the procedure's actual definition.
One failing, on the programmer's part, is if the actual argument isn't compatible with the dummy argument. Such a case is when the dummy argument is an explicit shape array but the actual argument is smaller than the dummy argument. [It isn't an error to have the actual argument larger.]
This problem is one of your cases:
interface
function cross(a,b)
integer, dimension(3) :: cross
integer, dimension(4), intent(in) :: a, b ! Dummy extent 4
end function cross
end interface
print*, cross([1,2,3], [4,5,6]) ! Actuals extent 3
end
Again, a compiler isn't obliged to notice this for you. It's being nice in the case where it can detect the problem.
Now, in another case you are stating that the function result is an array of shape [4] or [2]. But you are trying to assign that to an array of shape [3]. That won't work.
In conclusion, if you use an interface block to provide an explicit interface for an external procedure make sure it is correct. Turning the external procedure into a module procedure means it's the compiler's responsibility, not yours, to have the correct interface visible.
1 "Matching" here means that the characteristics of the procedure as stated by the interface block are consistent with the procedure's definition. The extents of the function result and dummy arguments are part of this. A procedure defined pure needn't have the interface block stating it is pure.

Program stops due to array allocation in a function [duplicate]

The following code is returning a Segmentation Fault because the allocatable array I am trying to pass is not being properly recognized (size returns 1, when it should be 3). In this page (http://www.eng-tips.com/viewthread.cfm?qid=170599) a similar example seems to indicate that it should work fine in F95; my code file has a .F90 extension, but I tried changing it to F95, and I am using gfortran to compile.
My guess is that the problem should be in the way I am passing the allocatable array to the subroutine; What am I doing wrong?
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
PROGRAM test
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
IMPLICIT NONE
DOUBLE PRECISION,ALLOCATABLE :: Array(:,:)
INTEGER :: iii,jjj
ALLOCATE(Array(3,3))
DO iii=1,3
DO jjj=1,3
Array(iii,jjj)=iii+jjj
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
CALL Subtest(Array)
END PROGRAM
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
SUBROUTINE Subtest(Array)
DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:)
INTEGER :: iii,jjj
PRINT*,SIZE(Array,1),SIZE(Array,2)
DO iii=1,SIZE(Array,1)
DO jjj=1,SIZE(Array,2)
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
END SUBROUTINE
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
If a procedure has a dummy argument that is an allocatable, then an explicit interface is required in any calling scope.
(There are numerous things that require an explicit interface, an allocatable dummy is but one.)
You can provide that explicit interface yourself by putting an interface block for your subroutine inside the main program. An alternative and far, far, far better option is to put the subroutine inside a module and then USE that module in the main program - the explicit interface is then automatically created. There is an example of this on the eng-tips site that you provided a link to - see the post by xwb.
Note that it only makes sense for a dummy argument to have the allocatable attribute if you are going to do something related to its allocation status - query its status, reallocate it, deallocate it, etc.
Please also note that your allocatable dummy argument array is declared with intent(in), which means its allocation status will be that of the associated actual argument (and it may not be changed during the procedure). The actual argument passed to your subroutine may be unallocated and therefore illegal to reference, even with an explicit interface. The compiler will not know this and the behaviour of inquiries like size is undefined in such cases.
Hence, you first have to check the allocation status of array with allocated(array) before referencing its contents. I would further suggest to implement loops over the full array with lbound and ubound, since in general you can't be sure about array's bounds:
subroutine subtest(array)
double precision, allocatable, intent(in) :: array(:,:)
integer :: iii, jjj
if(allocated(array)) then
print*, size(array, 1), size(array, 2)
do iii = lbound(array, 1), ubound(array, 1)
do jjj = lbound(array, 2), ubound(array, 2)
print*, array(iii,jjj)
enddo
enddo
endif
end subroutine
This is a simple example that uses allocatable dummy arguments with a module.
module arrayMod
real,dimension(:,:),allocatable :: theArray
end module arrayMod
program test
use arrayMod
implicit none
interface
subroutine arraySub
end subroutine arraySub
end interface
write(*,*) allocated(theArray)
call arraySub
write(*,*) allocated(theArray)
end program test
subroutine arraySub
use arrayMod
write(*,*) 'Inside arraySub()'
allocate(theArray(3,2))
end subroutine arraySub

Calling function with configurable real precision

The goal:
Have a function work with configurable working precision.
When I try this:
program vierkantsvergelijking
implicit none
integer, parameter :: dp = kind(0.d0)
integer, parameter :: sp = kind(0.0)
print *, algoritme1(-5771.,2.,dp)
contains
function algoritme1(b,c,wp) result( solution)
integer :: wp ! working precision
real(kind=wp) :: b,c,D
real(kind=wp), dimension(2) :: solution
D = sqrt((b/2)**2 - c)
solution(1) = -b/2 + D
solution(2) = -b/2 - D
end function algoritme1
end program
I get:
Error: Type mismatch in argument 'b' at (1); passed REAL(4) to UNKNOWN
Why is this not working and how can I achieve my goal?
Yes, or rather no, that's not going to work, not no how. The Intel Fortran compiler complains, about this line:
real(kind=wp) :: b,c,D
that
A kind type parameter must be a compile-time constant. [WP]
It makes the same complaint about real(kind=wp), dimension(2) :: solution too. This is a deep-rooted feature of Fortran.
To do what you want you will have to define a generic interface, along these lines
interface algoritme1
procedure :: algoritme1_sp, algoritme1_dp
end interface
and write the code for both those procedures. The compiler can then determine which one is called by the function signature; presumably one would have sp arguments, the other dp arguments.
You might think that this all means that Fortran doesn't do generic procedures, I'll leave that question to the sophists and language nit-pickers. It would be worth your while to search around for generic programming in Fortran; even here on SO there are tricks and tips on how to better avoid writing multiple implementations of what the programmer believes (at odds with the compiler) to be the 'same' code.

OOP Fortran: saving pointers to intent(IN) variables

I have a Fortran module that I want to organize following OOP philosophy as much as possible, while still making it compatible with Fortran 2003. This module basically: (a) allocs/frees temporary array buffers, and (b) provides a function do_F which operates on some data. This function do_F uses these temporary buffers, but also depends several auxiliary types.
It is clear to me that I should put the buffers into a type, and initialize/free when appropriate. However, since each call to do_F takes several arguments, I am sure what is the best design strategy to use.
To be more concrete, consider the following implementations:
Pass a large number of types every time do_F is called
type object_t
! lots of private buffers
real, allocatable :: buf1(:,:,:), buf2(:,:,:), etc.
end type object_t
subroutine init_object(this)
type(object_t), intent(INOUT) :: this
allocate( this%buf1(..., ..., ...) )
!...
end subroutine init_object
subroutine do_F(this, data, aux1, aux2, ..., auxN)
type(object_t), intent(INOUT) :: this
type(data_t), intent(INOUT) :: data
type(aux1_t), intent(IN) :: aux1
!...
!do stuff on data using the buffers and values stored
! in aux1 .. auxN
end subroutine do_F
Save the pointers to the types that do_F needs
type object_t
! lots of private buffers
real, allocatable :: buf1(:,:,:), buf2(:,:,:), etc.
! pointers to auxiliary types
type(aux1_t), pointer :: aux1_ptr
!...
end type object_t
subroutine init_object(this, aux1, aux2, ..., auxN)
type(object_t), intent(INOUT) :: this
type(aux1_t), intent(IN), target :: aux1
!...
allocate( this%buf1(..., ..., ...) )
!...
this%aux1_ptr => aux1
!...
end subroutine init_object
subroutine do_F(this, data)
type(object_t), intent(INOUT) :: this
type(data_t), intent(INOUT) :: data
!do stuff on data using the buffers and values stored
! in this%aux1_ptr .. this%auxN_ptr
end subroutine do_F
My specific questions are:
Is the implementation #2 valid? PGI compiler didn't complain about it, but I heard that an intent(IN) is no longer well defined after the function returns
Is there a performance loss by using this scheme with pointers? Even if I don't write into these aux_ptr's, will the compiler be able to optimize my code as well as in case #1?
Some notes:
The function do_F is called ~100 times, and each call takes a couple of minutes and operates on large arrays.
Apart from do_F, there are also do_G and do_H functions that operate on the same data and use the same aux variables. That is why I wanted to reduce the number of variables passed to the function in the first place.
I don't want to combine all the aux variables into one type, because they are used throughout the rest of a large HPC code.
Thanks!
Intent IN variables are well defined after return, if they were before the call. The procedure is not allowed to change them. An exception are the values of pointer variables, where you can change the value of the target, but not the association status of the pointer for intent(IN) pointer dummy arguments.
I'm not sure about the efficiency though. Version 2 looks nicer after a quick read.