'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:
- 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 calledintent(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.
- Variable is in a module: it is
save
d. Its status isnot 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 |