arraysfortransubroutinesub-arrayallocatable-array

Passing a subarray of allocatable array to a subroutine, with right bounds


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?


Solution

  • 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:)