2016-07-01 5 views
1

안녕하세요 저는 포트란 프로그램에서 일하고 있으며 이상한 문제를 해결했습니다. 특정 서브 루틴을 호출하기 전에 배열의 일부 값을 직접 출력하려고하면 올바른 값을 얻습니다. 그런 다음 서브 루틴을 시작하면 동일한 배열의 값을 출력하려고합니다. 서브 루틴을 마친 후에 배열의 값을 최종 출력하고 값이 예상 값으로 돌아옵니다. 아무도 왜 그 이유를 이해하도록 도와 줄 수 있습니까? 내 코드는 다음과 같습니다 :잘못된 값을 반환하는 포트란 서브 루틴

첫째, 주요 기능의 서브 루틴 호출, 값 내가 쓰기 문에서 출력하려는 ​​함께 : 이것은 다음 서브 루틴을 호출

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 

나는 간단하게 알아낼 수 없습니다.

답변

1

나는 그것을 알아 냈다. 부사장은 할당 된 메인 프로그램에서

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 
반환