Griff
Griff

Reputation: 2124

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

Upvotes: 1

Views: 8517

Answers (1)

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

Upvotes: 6

Related Questions