Search code examples
arraysfortranallocationsubroutine

passing unknown sized array through subroutines in fortran (array allocated in subroutine)


I've got a program below which creates an array inside the first subroutine (CALCONE) then I want to pass that into the next subroutine (CALCTWO) then output it to file in the main program. I don't know where to put the INTENT(IN), INTENT(OUT) statements because the array needs to be allocated IN subroutine CALCONE (because in my program the length is determined in CALCONE) - I have left my attempt out to avoid confusion. Could someone help put them in the correct place. Once I have a template, I'll understand how it works for future. Thanks.

I've simplified the program and the variables represent other things which cannot be moved around. I just need a way to move an array between subroutines then write it out at the end of the main program.

 program TEST
 implicit none

 integer a,b,c,d,reclen

 a = 1
 b = 2
 c = 3
 d = 4

 call CALCONE(a,b,c,d,array)

 call CALCTWO(e,f,g,h,array)

 inquire(iolength=reclen)array 
 open(unit=8,file='array_output.dat', &
   form="unformatted",access="stream")
 write(unit=8)array       
 close(unit=8)

 END PROGRAM TEST

 SUBROUTINE CALCONE(adummy,bdummy,cdummy,ddummy,arraydummy)
 IMPLICIT NONE

 integer i,j,k
 integer e,f,g,h,N
 !ALLOCATE ARRAY HERE OR IN MAIN PROGRAM?
 real*8,   allocatable  :: arraydummy(:,:)

 e = a + 1
 f = b + 1
 g = c + 1
 h = d + 1

 ! N can only be is calculated here

 allocate(arraydummy(1:N,1:3))

 !POPULATE 'arraydummy'
 !PASS ARRAY BACK OUT TO NEXT SUBROUTINE FOR FURTHER PROCESSING IN CALCTWO
 END SUBROUTINE CALCTWO

 SUBROUTINE CALCTWO(edummy,fdummy,gdummy,hdummy,arraydummy)
 IMPLICIT NONE

 integer e,f,g,h
 !DEFINE HERE ALSO? i.e.
 !real*8,   allocatable  :: arraydummy(:,:)

 e = a + 1
 f = b + 1
 g = c + 1
 h = d + 1

 arraydummy = arraydummy*e*f*g*h

 END SUBROUTINE CALCTWO

Solution

  • You do not have to allocate the the array in the main program, but you definitely have to declare it there and you have to pass it as an argument (which you do). Notice, that symbol array is not defined in the main program.

    Be sure to privide en explicit interface to the subs. Because you use advanced features (allocatable dummy arguments) it is necessary. Best is to put them in a module.

    The array has to be defined as a dummy argument in both. I declared it as intent(out) in the first one, because it is allocated at the beginning. It is not strictly necessary.

    Another option would be to declare the array in the module and let it be shared by the module procedures.

    DISCLAIMER: I did not try to compile it.

     module subs
       integer,parameter :: rp = kind(1d0)
    
    
       contains
    
    
    
    
       SUBROUTINE CALCONE(adummy,bdummy,cdummy,ddummy,arraydummy)
       IMPLICIT NONE
    
       integer i,j,k
       integer e,f,g,h,N
       !ALLOCATE ARRAY HERE OR IN MAIN PROGRAM?
       real(rp),   allocatable, intent(out) :: arraydummy(:,:)
    
       e = a + 1
       f = b + 1
       g = c + 1
       h = d + 1
    
       !N can only be is calculated here
    
        allocate(arraydummy(1:N,1:3))
    
       !POPULATE 'arraydummy'
       !PASS ARRAY BACK OUT TO NEXT SUBROUTINE FOR FURTHER PROCESSING IN CALCTWO
       END SUBROUTINE CALCTWO
    
       SUBROUTINE CALCTWO(edummy,fdummy,gdummy,hdummy,arraydummy)
       IMPLICIT NONE
    
       integer e,f,g,h
       !DEFINE HERE ALSO? i.e.
       real(rp),   allocatable, intent(inout)  :: arraydummy(:,:)
    
       e = a + 1
       f = b + 1
       g = c + 1
       h = d + 1
    
       arraydummy = arraydummy*e*f*g*h
    
       END SUBROUTINE CALCTWO
    
    
     end module subs
    
     program TEST
    
     use subs
    
     implicit none
    
     integer a,b,c,d,reclen
    
     real(rp),allocatable :: array
    
     a = 1
     b = 2
     c = 3
     d = 4
    
     call CALCONE(a,b,c,d,array)
    
     call CALCTWO(e,f,g,h,array)
    
     inquire(iolength=reclen)array 
     open(unit=8,file='array_output.dat', &
       form="unformatted",access="stream")
     write(unit=8)array       
     close(unit=8)
    
     END PROGRAM TEST