- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have two allocatable arrays declared as:
[bash]real*4, allocatable :: Array1(:,:,:), Array2(:,:,:)[/bash]Later, based on user's input, it can happen that only one of them is allocated; the other one is not, because it is not needed:
[bash]if ( use1 ) allocate ( Array1(nx,ny,nz), stat=ierr ) if ( use2 ) allocate ( Array2(nx,ny,nz), stat=ierr )[/bash]Now, I have a subroutine which can work with both arrays and does so based on logical variables use1, use2. My question is whether I can declare the subroutine
[bash]subroutine doSomething ( nx, ny, nz, Array1, Array2, use1, use2 )and call it
integer*4 nx, ny, nz
real*4 Array1(nx,ny,nz)
real*4 Array2(nx,ny,nz)
logical*4 use1, use2
if ( use1 ) call doSomethingWith1 ( nx, ny, nz, Array1 )
if ( use2 ) call doSomethingWith1 ( nx, ny, nz, Array2 )[/bash]
[bash]call doDomething ( nx, ny, nz, Array1, Array2, use1, use2 )Put another way, I don't know how to handle passing those arrays which were not allocated. I am afraid that declaring them with a specific dimensions in the subroutine is not the right way.
[/bash]
Would anybody have any idea how this could and should be done?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
!----------------------------------------------------------------
subroutine doSomethingWith1 (Array)
real, allocatable, intent(INOUT) :: Array(:,:,:)
integer :: nx, ny, nz
if (ALLOCATED(Array)) then
nx = UBOUND(Array, DIM = 1)
ny = UBOUND(Array, DIM = 2)
nz = UBOUND(Array, DIM = 3)
else
return
endif
end subroutine
!----------------------------------------------------------------
Notice that nx,ny,nz become redundant as arguments, since you can use the SIZE or UBOUND intrinsics to inquire for their values ---or ignore them if Array is not allocated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
if( ALLOCATED(Array1) )calldoSomethingWith1(nx,ny,nz,Array1)
if( ALLOCATED(Array2) )calldoSomethingElseWith2 (nx,ny,nz,Array2)
and forget the call to doSomething?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will try using what John suggested; I like the fact that once I allocate or don't allocate an array, I can pass it to any subroutine where it is just declared as
[fxfortran]real, allocatable, intent(INOUT) :: Array(:,:,:)[/fxfortran]I would like to ask one more question - I tried to google passing allocatable arrays and I found information that "An allocatable array cannot be passed to a procedure when in an un-allocated state. But this can be done with a pointer array." Is this true?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
program allocatesub
implicit none
interface
subroutine doSomethingWith1 (Array)
real*4, allocatable, intent(INOUT) :: Array(:,:,:)
end subroutine
end interface
real*4, allocatable :: a1(:,:,:)
print *, 'Hello World'
call dosomethingwith1(a1)
allocate (a1(1,2,3))
call dosomethingwith1(a1)
deallocate(a1)
end program allocatesub
subroutine doSomethingWith1 (Array)
real*4, allocatable, intent(INOUT) :: Array(:,:,:)
integer :: nx, ny, nz
if (ALLOCATED(Array)) then
nx = UBOUND(Array, DIM = 1)
ny = UBOUND(Array, DIM = 2)
nz = UBOUND(Array, DIM = 3)
print *, 'Array allocated, dimensions are: ',nx,', ',ny,', ',nz
else
print *, 'Array NOT allocated'
return
endif
end subroutine
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That restriction was lifted for Fortran 95+. Keep in mind that when you pass an allocatable array to a procedure, the INTENT applies to the allocation status ---e.g., INTENT(OUT) means that the array is always deallocated on procedure entry.
And, as anthonyrichards said, you'll always need an explicit interface whenever arguments have the allocatable attribute. Such interface is provided by an interface block or by placing the procedure(s ) in a module.
You can check the following link for more details:
http://fortranwiki.org/fortran/show/Allocatable+enhancements
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- flag the calling routine at compile time with a warning/error, or
- issue a runtime warning instead of a severe error?
yr-fe1.lanl.gov> cat alloc.f90
[fortran]Program testalloc ! ! When compiled with Intel's "-check pointers" or ! "-C" options, this fails at runtime. Otherwise ! it runs fine. ! real, dimension (:), allocatable :: array call subrout(array) stop end subroutine subrout(receipt) print *, ' success' return end[/fortran]
yr-fe1.lanl.gov> ifort -V
Intel Fortran Compiler for applications running on Intel 64,
Version 10.0 Build 20070426 Package ID: l_fc_p_10.0.023
Copyright (C) 1985-2007 Intel Corporation. All rights reserved.
yr-fe1.lanl.gov> ifort alloc.f90
yr-fe1.lanl.gov> a.out
success
yr-fe1.lanl.gov> ifort -check pointers alloc.f90
yr-fe1.lanl.gov> a.out
forrtl: severe (408): fort: (8): Attempt to fetch from allocatable
variable ARRAY when it is not allocated
...truncated...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In your test case, since the subroutine never touches the argument "receipt", it appears to succeed. But it is still invalid.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The text I found in the standard (and in the Metcalf&Reid book) was that the "ALLOCATABLE attribute must not be used on a dummy argument". I get the same behavior from the Intel compiler when declaring the "receipt" array to have the allocatable attribute (ie. real, dimension (:), allocatable :: receipt). Of course, the standard never dictates when a compiler should issue an error message, so questions arise about consistent behavior. Should the generated code behave the same regardless of the runtime check? For illegal code, should a compiler user expect to see an error msg at compile time rather than run time? If the error is severe, why wait so long? Why would a severe error message be optional? What other severe errors do I miss by using only default compilation parameters?
The compiler itself is neither right nor wrong. We're just wondering why it behaves this way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The rule you are breaking is not one the compiler can see at compile time and isn't required to diagnose at all.
You may be missing a lot. Another option that can be useful is adding /gen_interface and /warn:interface. (In 11.1 you don't need /gen_interface). I'll comment that in 10.0 this feature is somewhat buggy, but it is very helpful. As of 10.1 (I think) it is the default in new VS projects.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page