2016-07-01 22 views
1

私はfortranプログラムで作業していて、奇妙な問題に遭遇しました。特定のサブルーチンを呼び出す前に配列の値を直接出力しようとすると、正しい値が得られます。私はサブルーチンを開始すると同じ配列のいくつかの値を出力しようとし、0です。私は最終的にサブルーチンの後に配列の値を出力し、値は期待値に戻ります。なぜ誰かが私の理解を助けることができますか?私のコードは以下の通りです:間違った値を返すFortranサブルーチン

まず、メイン関数内のサブルーチンの呼び出し、値Iが書き込みステートメントで出力したいと:これは、次のサブルーチンを呼び出している

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 

そのうち私が掲載します関連する部分のみ:

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は、サブルーチン内の値を持っていない理由を私は単純に把握することはできません。

答えて

1

私はそれを理解しました。 VPは、割り当てられたメインプログラムで

VP(0:DIM,0:NPTMAX) 

として、サブルーチンで
VP(0:DIM-1,0:NPTMAX) 

!これによりエラーが発生しました。

2

手動で明示的な形状の配列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 

は以下

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 
返します
関連する問題