Reputation: 525
In a rather old style Fortran project, I often see this pattern, when an array is passed by its first item:
program test
implicit none
integer :: a(10)
a(:) = 1
call sub(a(1), 10) ! here
contains
subroutine sub(a, length)
integer, intent(in) :: length
integer, intent(in) :: a(length)
print *, a
end subroutine
end program
where it could be:
call sub(a, 10) ! here
which is valid even in Fortran 77.
Note the size of the array has to be passed and used explicitly, this will not work for assumed shape array:
subroutine sub(a)
integer, intent(in) :: a(:)
print *, a
end subroutine
For me this is confusing, as the call suggests a scalar is passed to the subroutine. I suppose it works because the array is passed by reference.
Is there any reason to pass arrays like this, especially now?
Upvotes: 2
Views: 223
Reputation: 60088
One uses this feature when using the older interface to the non-blocking MPI routines.
Say you want to pass subarray A(10,10:19)
which is a part of a bigger array A(1:100,1:100)
.
If you pass
use mpi
call ISend(A(10,10:19), 10, MPI_REAL, ...
you pass a temporary copy of array A and the address of the temporary copy will not be valid at the time of the MPI_Wait. Therefore, instead, you create an MPI derived type, that describes the offsets in the array to be sent and you use it as
use mpi
call ISend(A(10,10), 1, derived_type, ...
Of course, with the most modern MPI libraries and compilers you use use mpi_f08
. However, most HPC codes in the wild do not use it yet.
Another solution is to use an MPI derived type that includes the absolute address of the subarray and just pass A
. Sometimes it is practical, sometimes it is not. It depends on how much the subarrays passed vary throughout the code.
Be aware that there are other issues present in non-blocking MPI in the old interface and it helps if you explicitly mark the routines as ASYNCHRONOUS
.
Upvotes: 3
Reputation: 32451
Consider the following example:
implicit none
integer a(2,2)
a = RESHAPE([1,2,3,4],[2,2])
call sub(a(2,1))
print '(2I3)', TRANSPOSE(a)
contains
subroutine sub(b)
integer, intent(out) :: b(2)
b = -1
end subroutine sub
end
Here, the element sequence represented by the actual argument a
is a(2,1), a(1,2), a(2,2)
, and the first two are associated with the dummy argument b
.
For arrays of rank greater than one, this element sequence use may make things (much) easier to specify certain consecutive elements of the actual argument. For a rank-1 array we can write a(3:)
instead of a(3)
, say, as the actual argument. For higher rank arrays we haven't that option.
I won't express an opinion on whether this is a good use this feature.
Upvotes: 2