In the parallel program I'm writing, I defined a lot of multidimensional allocatable
arrays (actually just 1D, 2D or 3D) which are allocated with negative lower bounds during the execution.
The reason why I did that is that each process handles, in a 2D example, a 14 by 14 A
matrix and shares an overlap of 2 layers with the four neighboring processes, so the matrix is allocated with bounds (-1:12,-1:12)
, where the "internal" part of the matrix corresponds to indices from 1 to 10. (Italic represent choice/input dependency).
The problem is that in doing this I didn't realize that it would have been impossible to rely on this Fortran2003 feature, thus making impossible to call mysub(A(:,i),...)
in the caller unit and refer to the dummy counterpart of A
in the subroutine using the actual bounds (-1 and 12), since A(:,i)
is an expression, and not just a variable.
The problem is solved if I pass the whole array A
to the subroutine, as explained in the previous linked answer, but this would force me to write a "bigger" and less universal subroutine, which, on the contrary, is meant to act on one-dimensional subarrays.
Is it possible to pass a subarray of an allocatable
array (e.g. A(:,1)
) to a subroutine in a way that the subroutine is aware of the bounds of the actual variable?
As far as I know: no, it is not possible.
Be aware that very often, you do not want to care about the actual lower bound of an array in a subroutine. If you have a subroutine that sums an array or something similar, you just want to loop from 1 to the size of the array. And you want to be able to pass any arrays to such subroutines.
If you need to start from a specific index in a subroutine you can always
1. Declare the lower bound as a magic constant
real, intent(inout) :: array(-1:,-1:,-1:)
Maybe not too nice, but I use it in my main production code because I started it that way years ago.
2. Declare the lower bound as a constant in a module and use that
use contants
real, intent(inout) :: array(lb:,lb:,lb:)
3. Pass the lower bound as a dummy argument
integer, intent(in) :: lb
real, intent(inout) :: array(lb:,lb:,lb:)