Reputation: 690
The argument of my fortran 95 subroutine is an assumed shape array with intent inout:
the_subroutine(my_argument)
real, dimension(:,:), intent(inout) :: my_argument
(...)
In the main program, I have an allocatable array. I allocate it and also rename indexes. Then I call the subroutine and pass that (correctly allocated) array to the subroutine:
allocate(the_array( 5:1005 , 5:1005 ))
call the_subroutine(my_argument=the_array)
The subroutine does certain calculations and fills the array with values. In the very last line before the end of the subroutine, I check a random value:
(...)
print*, my_argument(213,126) ! I get 2.873...
end subroutine the_subroutine
Then, in the very first line after the subroutine call, I check if the value has been correctly communicated by the subroutine to the outer world, but that is not the case:
call the_subroutine(my_argument=the_array)
print*, the_array(213,126) ! I get 3.798... A completely different value.
The problem arises from having re-indexed the array in the main program as:
allocate(the_array( 5:1005 , 5:1005 ))
where max_index - min_index = 1000-1, but the subroutine "sees" the array internally as if I had declared the normal way, i.e.:
allocate(the_array( 1:1000, 1:1000))
Or simply, allocate(the_array( 1000, 1000 ))
Therefore, the element (213,126) in the internal array is in another location as in the main program array. Is there any easy way out of this?
Upvotes: 2
Views: 315
Reputation: 6989
another approach to the problem: make the array a derived type and the subroutine a method of the type:
module example
implicit none
type a
real, allocatable::y(:,:)
end type a
contains
subroutine sub(this)
type(a)::this
write(*,*)lbound(this%y)
end subroutine
end module
program p
use example
implicit none
type (a) my_array
allocate(my_array%y(5:6,7:8))
call sub(my_array)
deallocate(my_array%y)
allocate(my_array%y(2:3,1:2))
call sub(my_array)
end
5 7
2 1
as you see now the subroutine automatically knows the correct dimensions. Obviously now the subroutine can only work with the derived type array.
Upvotes: 0
Reputation: 690
Finally, I found the solution.
First, if working in Fortran 2003 (or Fortran 95 with non-standard extensions), you may simply declare the assumed shape argument in the subroutine as ALLOCATABLE:
subroutine the_subroutine(my_argument)
real, dimension(:,:), allocatable, intent(inout) :: my_argument
Then the subroutine "sees" the renamed index correctly. However this is not allowed in the Fortran 95 standard.
In Fortran 95, the most elegant way I found for this is by making use of a pointer:
program example
implicit none
real, dimension(:,:), allocatable, target :: the_array
real, dimension(:,:), pointer :: the_pointer
[...]
allocate(the_array(5:1005,5:1005))
the_pointer => the_array
call the_subroutine(my_argument=the_pointer)
And in the subroutine:
subroutine the_subroutine(my_argument)
real, dimension(:,:), pointer :: my_argument
Then it works perfectly. Inside the subroutine, MY_ARGUMENT is treated exactly as if it was an assumed shape array.
Upvotes: 0
Reputation: 6989
use lbound
to pass the bounds to the subroutine:
implicit none
real,allocatable:: x(:,:)
allocate(x(5:10,5:10))
call sub(x,lbound(x))
write(*,*)'o',x(5,5)
contains
subroutine sub(x,lb)
implicit none
integer lb(2)
real, dimension(lb(1):,lb(2):)::x
x(5,5)=42.
end subroutine
end
o 42.0000
Upvotes: 2
Reputation: 21431
The default lower bound for an assumed shape array is one.
If you want a different lower bound, then you need to declare the array dummy argument appropriately.
subroutine the_subroutine(my_argument)
real, dimension(5:,5:), intent(inout) :: my_argument
! ^ ^
(The rules for the bounds of the dummy argument are different for deferred shape arrays - array dummy arguments which also have the POINTER or ALLOCATABLE attributes.)
Upvotes: 2