'Passing allocatable array into a subroutine

I am working on a f90 code that I didn't write. I am not a very experienced fortran user.

There is a part that bothers me a bit and I am not sure if it is a normal practice. Can someone help me to clarify a bit please ?

  • I have a structure with an allocatable array defined in a module.
  • This variable is passed un-allocated to a subroutine.
  • The subroutine then allocates its corresponding local variable.
  • In the main, the output of the passed structure variable is allocated.

What I am not sure I understand is how the main program is handling the size of the return variable as it is not defined before. Is it a common practice?

Personally, I would have think that a variable with a defined size should have been passed to the subroutine.

If I resume coarsly the code:

modulus_mod.f90:

module modulus_mod
public :: mod

type mod
real,allocatable,dimension(:,:)    :: rec
end type mod

end module modulus_mod

subtoto.f90:

subroutine subtoto(recloc)

implicit none

real,allocatable,dimension(:,:)    :: recloc

WRITE(*,*) 'in'
ALLOCATE( recloc(10,10) )
WRITE(*,*) 'inout'
recloc(:,:)=1.
WRITE(*,*) 'out'

endsubroutine subtoto

toto.f90:

program toto
use modulus_mod

implicit none
type(mod)  :: model

!>>> Here not allocated if tested
if(allocated(model%rec)) WRITE(*,*) 'allocated bf'
if(.NOT.allocated(model%rec)) WRITE(*,*) 'NOT allocated bf'

CALL subtoto(model%rec)

WRITE(*,*) 'out sub'
!>>>Here it should be allocated correctly if tested
if(allocated(model%rec)) WRITE(*,*) 'allocated af'
if(.NOT.allocated(model%rec)) WRITE(*,*) 'NOT allocated af'

end program toto


Solution 1:[1]

Trying to make a hands-on summary here:

  1. Variable is an allocatable dummy argument in a subroutine, for example:
subroutine sub(variable)
   real, allocatable, [intent(...)] :: variable(:)

here, status is controlled by the intent keyword:

  • intent(out): initially not allocated, when the subroutine is called
  • intent(in), intent(inout) or [no intent declared]: initial allocation status depends on what the variable was like outside of this routine

At any times, you can check both the status and the size of this variable by allocated(variable) and size(variable).

Note that size is undefined if the variable is not allocated, so you may want to use something like:

safe_size = merge(size(variable),-1,allocated(variable))

to prevent the undefined behavior.

  1. Variable is in a module: it is saved. Its status is not allocated at the beginning of the program; both status and contents can change during runtime (for example being changed by a subroutine or function, with the rules of 1.), but nothing is modified between these calls.

In your case, if you want your variable to always be allocated by the routine, you should specify an intent(out), like:

subroutine subtoto(recloc)
   implicit none
   real,allocatable,dimension(:,:), intent(out) :: recloc
   [...]
end subroutine subtoto

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Federico Perini