Fortran 子例程返回错误值

Fortran subroutine returning wrong values

嘿,我正在研究一个堡垒运行 程序并且 运行 遇到了一个奇怪的问题。当我尝试在调用特定子例程之前直接输出数组的某些值时,我得到了正确的值。然后我尝试在启动子例程时输出同一数组的一些值,它们为 0。我最终在子例程之后输出数组的值,并且这些值返回到预期值。谁能帮我理解为什么?我的代码如下:

首先,在主函数中调用子程序,在write语句中输出我想要的值:

if (iter .eq. 5) then
  write(*,*) 'vp vals: ',vp(0,23471), vp(0,23475)
end if 

CALL GRID_DIVISION( &
&            NPTMAX, DIM, TYPEMAX, NEIGHMAX, NPTC, GRIDLIMIT, &
&            GRIDN, GRIDNUM, GRID, GNEIGH, XP, PTTYPE, TYPE, &
&            GRIDP, TEMP_GRIDP, GNEIGHMAX, PAINT, VP, ITER, gridvel &
&          )

if (iter .eq. 5) then
  write(*,*) 'vp vals: ',vp(0,23471), vp(0,23475)
end if 

这是在调用以下子例程,我将只post相关部分:

SUBROUTINE GRID_DIVISION( &
&            NPTMAX, DIM, TYPEMAX, NEIGHMAX, NPTC, GRIDLIMIT, &
&            GRIDN, GRIDNUM, GRID, GNEIGH, XP, PTTYPE, TYPE, &
&            GRIDP, TEMP_GRIDP, GNEIGHMAX, PAINT,VP,ITER, gridvel &
&          )
  IMPLICIT NONE
  INTEGER, INTENT(IN)    :: NPTMAX, DIM, TYPEMAX, NEIGHMAX, GNEIGHMAX
  INTEGER, INTENT(IN)    :: NPTC
  INTEGER, INTENT(IN)    :: GRIDLIMIT
  INTEGER, INTENT(IN)    :: GRIDN(0: DIM - 1)
  INTEGER, INTENT(IN)    :: GRIDNUM
  INTEGER, INTENT(IN)    :: PTTYPE(0: NPTMAX)
  INTEGER, INTENT(IN)    :: TYPE(0: TYPEMAX)
  INTEGER, INTENT(INOUT) :: GRIDP(0: NPTMAX)
  INTEGER, INTENT(INOUT) :: GNEIGH(1: GRIDLIMIT, 0: GNEIGHMAX)
  REAL   , INTENT(IN)    :: GRID(1: GRIDLIMIT, 0: DIM - 1, 0: 1)
  REAL   , INTENT(IN)    :: XP(0: DIM - 1, 0: NPTMAX)
  REAL   , INTENT(IN)    :: VP(0: DIM - 1, 0: NPTMAX)
  INTEGER, INTENT(INOUT) :: TEMP_GRIDP(0: NPTMAX)
  INTEGER, INTENT(INOUT) :: PAINT(0:NPTMAX)
  INTEGER, INTENT(INOUT) :: ITER
  real, intent(inout)    :: gridvel(GRIDNUM,0:1)
  INTEGER :: II, JJ, KK
  INTEGER :: DNUM
  INTEGER :: GRIDXP
  INTEGER :: SGRIDXP
  INTEGER :: EGRIDXP
  INTEGER :: SGRIDYP
  INTEGER :: EGRIDYP
  INTEGER :: SEARCH
  INTEGER :: SCOUNT
  INTEGER :: FCOUNT
  INTEGER :: ERROR
  INTEGER, PARAMETER :: CELL = 2 

  if (iter .eq. 5) then
    write(*,*) 'vp vals: ',vp(0,23471), vp(0,23475)
  end if 
...
end subroutine

本节之后还有更多内容未输出。当我 运行 代码时,我在本节的第 5 次迭代中的输出是:

vp vals:    75.00000        75.00000
vp vals:     0.00000000E+00  0.0000000E+00
vp vals:    75.00000        75.00000

我实在想不通为什么我的数组VP在子程序中没有值。

我明白了。 VP 分配为

VP(0:DIM,0:NPTMAX) 

在主程序中

VP(0:DIM-1,0:NPTMAX) 

在子程序中!这导致了错误。

手动设置显式数组 a(0:N-1,0:M) 极易出错。我建议使用假定形状数组 a(:,:) 来传递参数。此外,当您将数组作为参数传递给子例程时,实际参数的上限和下限不会在调用中保持不变,除非下限为 1。但是,在传递指针时,下限和上限会保持不变。例如,

program main

  use, intrinsic :: iso_fortran_env, only: &
       stdout => OUTPUT_UNIT, &
       compiler_version, &
       compiler_options

  ! Explicit typing only
  implicit none

  real               :: foo(10,10)
  real, target       :: bar(0:9,0:9)
  real, pointer      :: ptr(:,:) => null()

  call peek_assumed_shape(foo, 'peek_assumed_shape: foo(10,10)')
  call peek_assumed_shape(bar, 'peek_assumed_shape: bar(0:9,0:9)')

  ptr => bar
  call peek_pointer(ptr, 'peek_pointer: ptr => bar')

  ptr(42:,42:) => bar
  call peek_pointer(ptr, 'peek_pointer: ptr(42:,42:) => bar')

  nullify( ptr )

  write (stdout, '(/4a/)') &
       'This file was compiled using compiler version ', compiler_version(), &
       ' and compiler options ', compiler_options()

contains


  subroutine peek_assumed_shape(array, description)
    ! Calling arguments
    real,              intent (in) :: array(:,:)
    character (len=*), intent (in) :: description

    write (stdout, '(/a)') description
    write (stdout, *) 'dim=1 ', lbound(array, dim=1), ubound(array,dim=1)
    write (stdout, *) 'dim=2 ', lbound(array, dim=2), ubound(array,dim=2)


  end subroutine peek_assumed_shape

  subroutine peek_pointer(array, description)
    ! Calling arguments
    real, pointer,     intent (in) :: array(:,:)
    character (len=*), intent (in) :: description

    if (associated(array)) then
       write (stdout, '(/a)')  description
       write (stdout, *) 'dim=1 ', lbound(array, dim=1), ubound(array,dim=1)
       write (stdout, *) 'dim=2 ', lbound(array, dim=2), ubound(array,dim=2)
    end if

  end subroutine peek_pointer

end program main

returns以下

peek_assumed_shape: foo(10,10)
 dim=1            1          10
 dim=2            1          10

peek_assumed_shape: bar(0:9,0:9)
 dim=1            1          10
 dim=2            1          10

peek_pointer: ptr => bar
 dim=1            0           9
 dim=2            0           9

peek_pointer: ptr(42:,42:) => bar
 dim=1           42          51
 dim=2           42          51

This file was compiled using compiler version GCC version 5.4.0 20160609 and compiler options -mtune=generic -march=x86-64 -O3 -Wall -std=f2008ts