Cagatay
Cagatay

Reputation: 1

subroutine calls with allocatable arrays

In my code, I have memory problems due to the machine that I use, so I want to allocate the least memory possible during passing arguments. My example code:

program test
double precision, ALLOCATABLE :: arrayA(:)
allocate (arrayA(n))

call mySub (arrayA)

deallocate (arrayA)

stop
end

subroutine mySub ( arrayB )
double precision, ALLOCATABLE :: arrayB(:)

allocate (arrayB(n))
! operations with arrayB

return
end

In main program, I have to use the heap memory. I also want to use heap memory in my subrotuine. Acc to search I did, it gives running error ( Attempting to allocate already allocated array 'arrayb').

Therefore, my purposes are to use heap memory also in my subroutines, and to allocate the least memory possible during argument passing from program to subroutine like in the code above. Now, I think I do copy assignment and as I know, it is not good. I checked module, interface and contains blocks but it is not so clear which one is good to save some space in memory with allocatabel arrays. I appreciate any help fits into my purpose.

Upvotes: 0

Views: 1372

Answers (3)

M Farhoudi
M Farhoudi

Reputation: 1

If a procedure has a dummy argument, that is an allocatable, then an explicit interface is required in any calling scope. You can provide that explicit interface, by putting an interface block, for your subroutine, inside the main program. A better alternative, is put the subroutine inside a module, and USE that module in the main program. The explicit interface is then automatically created.

Upvotes: 0

rabbit
rabbit

Reputation: 31

In Fortran (at least in Fortran 90 or former versions), it is not possible to allocate an array using a subroutine and return the allocated array to main program. In your case, you should not allocate the array in the subroutine. Thus your subroutine could be:

subroutine mySub ( arrayB )

double precision :: arrayB(:)

! operations with arrayB

return
end

Then you can pass any array that has the same rank as arrayB, but the actual argument must be already allocated in main, just as you did.

     program test

double precision, ALLOCATABLE :: arrayA(:)

allocate (arrayA(n))

call mySub (arrayA)

deallocate (arrayA)

stop
end

Upvotes: 0

You can't allocate the array again when it is already allocated. There is also no sense in doing so. Also, allocatable dummy arguments require explicit interface using modules or similar. But who knows how your actual code looks like.

What you want is to just pass it in a simple way as you had it originally

subroutine mySub ( arrayB, n )
  integer :: n
  double precision :: arrayB(n)

! operations with arrayB

That is just fine. No copy is made if you pass the contiguous array as you show it. Read about passing by reference. What's the difference between passing by reference vs. passing by value?

You can also use assumed shape arrays (:), but be careful, you need the explicit interface (best using modules).

Upvotes: 3

Related Questions