array pointers with differing rank

I am working with some very complex, and rather old fortran code (most of it was written in fortran77 but some was earlier). I need to have the memory dynamically allocated and am therefore converting “COMMON” block statements to modules with use statements.
I have come to a problem where the rank of a given variable within the common block changes between routines (the overall memory footprint is the same however).

A highly simplified example of this would be

Subroutine sub1
COMMON /cblock/array(L,N,M)
!code using the array in a 3D manner
End

Subroutine sub2
COMMON /cblock/array(LNM)
!code using the array in a 1D manner
End

As you can see the array is of rank 3 in the first routine and of rank 1 in the second routine.

I have searched high and low for a method of making this function with allocatable arrays, but have not been successful.

It seems like with all the additional functionality built into the modern fortran standards there should be a way to duplicate what the common blocks did in an instance like this.

Thank you.

Hi tesfortran,

I think the best option for you is to use the “!DIR$ IGNORE_TKR” Directive. For full details please refer to the end of Chapter 6 in the PGI Compiler Reference Manual.

The other option is to move sub2 out of the module and then F77 calling conventions would be used.

Hope this helps,
Mat

I am not real sure if this will accomplish what I am looking for or not. I think I may need some more code to explain what I am doing.

take the following example old code

PROGRAM main
call init
call sub1
call sub2
.
.
.
End

Subroutine init
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(L,M,N)
COMMON /cblock2/array2(L,M,N)
DO k=1,N
DO j=1,M
DO i=1,L
array1=0.0
array2=0.0
End DO
End DO
End DO
End

Subroutine sub1
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(L,M,N)
COMMON /cblock2/array2(L,M,N)
.
!code using the array1 in a 3D manner
.
End

Subroutine sub2
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(LMN)
COMMON /cblock2/array2(L,M,N)
.
!code using the array1 in a 1D manner
.
End


In this code sub1 treats the block of memory (array1), which has a total number of elements of LMN, as a 3D array L by M by N. However, sub2 treats the memory as a 1D array. for a similar common block (cblock2), which was used consistently between routines, I moved the arrays to a module as follows in the newer code



PROGRAM main
call alloc
call init
call sub1
call sub2
.
.
.
End

Subroutine alloc
use cblock2
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(L,M,N)
ALLOCATE(array2(L,M,N)
End

Subroutine init
use cblock2
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(L,M,N)
DO k=1,N
DO j=1,M
DO i=1,L
array1=0.0
array2=0.0
End DO
End DO
End DO
End

Subroutine sub1
use cblock2
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(L,M,N)
.
!code using the array1 in a 3D manner
.
End

Subroutine sub2
use cblock2
PARAMETER(L=3,M=5,N=12)
COMMON /cblock1/array1(LMN)
.
!code using the array1 in a 1D manner
.
End


Module cblock2
real, allocatable :: array2(:,:,:)
End module cblock2


I would like to do a similar thing with the cblock1 but I am unsure as to how to use it as a 3d array in sub2 as it is declared as a 1D array in the use module
The old code treated the same memory as two completely different shapes/ranks depending on how they are declared in the individual common blocks but now with the “use” statement each routine sees the exact same declaration. I have tried an alias in the use statement (e.g. use cblock1, array1D(:)=>array1) but that does not seem to be correct syntax. All I want to do is duplicate the way that the old program used the memory but with dynamic array sizes.

If your suggestion could be used to accomplish this please give an example of what the code should look like before compiling with the “!DIR$ IGNORE_TKR” directive.

Thanks

You need to pass the arrays to sub2. Something like:

Module cblock1
PARAMETER(L=3,M=5,N=12)
real, allocatable :: array1(:,:,:)
End module cblock1

Module cblock2
use cblock1
real, allocatable :: array2(:,:,:)
End module cblock2 

PROGRAM main
use cblock1
use cblock2
call init
call sub1
call sub2(array2)
...
END program main

Subroutine sub1
use cblock1
use cblock2
.
!code using the array1 in a 3D manner
.
End 

Subroutine sub2 (array2)
use cblock1
real array2(*)
..
end

or something like

Module cblock
PARAMETER(L=3,M=5,N=12)
real, allocatable :: array1(:,:,:)
real, allocatable :: array2(:,:,:)

contains

Subroutine sub1
.
!code using the array1 in a 3D manner
.
End subroutine sub1


Subroutine sub2(A2)
!DIR$ IGNORE_TKR A2
real A2(*)
...
End subroutine sub2

End module cblock

PROGRAM main
use cblock
call init
call sub1
call sub2(array2)
...
END program main

I may be off a bit on my code here, but hopefully this will help get you started.

  • Mat