由于主程序中的索引重命名,子程序不会在假定的形状数组中返回正确的数值 [英] Subroutine not returning correct numerical values in assumed shape array due to index renaming in the main program

查看:224
本文介绍了由于主程序中的索引重命名,子程序不会在假定的形状数组中返回正确的数值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  the_subroutine(my_argument)$ b $我的fortran 95子程序的参数是一个假定的形状数组b真实,维(:, :),意图(inout):: my_argument 
(...)

在主程序中,我有一个可分配数组。我为它分配并重命名索引。然后我调用子例程并将该(正确分配的)数组传递给子例程:

  allocate(the_array(5:1005,5 :1005))
调用the_subroutine(my_argument = the_array)

子程序做了一些计算,用值填充数组。在子程序结束前的最后一行中,我检查了一个随机值:

 ( ...)
print *,my_argument(213,126)!我得到2.873 ...
结束子程序the_subroutine

然后,在非常在子程序调用之后的第一行,我检查该值是否已被子例程正确传达给外部世界,但情况并非如此:

 调用the_subroutine(my_argument = the_array)
print *,the_array(213,126)!我得到3.798 ...完全不同的价值。

这个问题来自于在主程序中对数组进行了重新索引:

  allocate(the_array(5:1005,5:1005))

其中max_index - min_index = 1000-1,但子程序在内部看到数组,就好像我已经声明了正常的方式,即:

  allocate(the_array(1:1000,1:1000))

或者简单地说,allocate(the_array(1000,1000))

因此,内部数组中的元素(213,126)位于另一个位置主程序数组。有没有简单的方法呢?

解决方案

最后,我找到了解决方案。



首先,如果在Fortran 2003(或带有非标准扩展的Fortran 95)中工作,则可以简单地在子例程中声明假定的形状参数为ALLOCATABLE:

 子例程the_subroutine(my_argument)
real,dimension(:, :),allocatable,intent(inout):: my_argument

然后子程序正确地看到重命名的索引。但是,这在Fortran 95标准中是不允许的。



在Fortran 95中,我发现的最优雅的方式是使用指针:



$ $ $ $ $ $ $ $ $ $ $ $ $ $ $



$ b $ real $ b real,dimension(:, :),pointer :: the_pointer
[...]
allocate(the_array(5:1005,5:1005))
the_pointer => the_array
调用the_subroutine(my_argument = the_pointer)

并在子程序中:

 子程序the_subroutine(my_argument)
实数,维(:, :),指针:: my_argument

然后它完美地工作。在子程序中,MY_ARGUMENT被视为假定的形状数组。


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?

解决方案

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.

这篇关于由于主程序中的索引重命名,子程序不会在假定的形状数组中返回正确的数值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆