Repeatedly used 2D array in a Fortran 90 subroutine

安稳与你 提交于 2020-07-23 06:31:30

问题


I have a Fortran 90 program that is of the structure shown below. The step compute the 2D array myMatrix(1:N,1:N) in the subroutinne A is expensive. It depends only on the global variable N and it needs to be computed only once; the "other steps" in the subroutine will not change the value of myMatrix. Currently, myMatrix will be calculated whenever the subroutine is called.

Is there a way to write the program in a way that the 2D array myMatrix is calculated only once?

module constants
    integer :: N
end module constans

module A_module
use constants
contains
    subroutine A
    ! compute the 2D real array myMatrix(1:N,1:N)
    ! other steps that use myMatrix
    end subroutine A
end module A_module

program main
    use constants
    use A_module
    integer :: k

    do  k = 1,10000
        call A 
    end do

end program main

回答1:


Sure. Definite an init_a_matrix subroutine that initializes the matrix outside of the do loop.

subroutine init_a_matrix
   ! Do initialization here
end subroutine init_a_matrix

Then you have

call init_a_matrix
do  k = 1,10000
    call A 
end do

If you want to eliminate the redundant initialization of myMatrix in the subroutine A (since it only needs to be calculated once, upon the initial call of the subroutine), you can use the SAVE attribute and a LOGICAL flag. In subroutine A you do,

logical :: init_flag = .false.
real, save :: matrix_a(n,n)
if (init_flag .eqv. .false.) then
   ! Initialize matrix_a on the first call to the subroutine and reset init_flag.
   init_flag = .true.
end if



回答2:


If myMatrix is an unsaved, local variable of the subroutine A, then it will be necessary to recalculate its values on each entry of the subroutine: unsaved local variables become undefined when the subroutine completes execution.

However, there are a number of approaches to reuse the variable:

  • make it a saved local variable: saved local variables retain their definition
  • have it as a dummy argument, not a local variable (argument association): its definition comes from the caller
  • have it as some other form of non-local variable (other forms of association): its definition comes from another place

If it's a saved variable, compute it on the first entry to the subroutine and retains its definition on subsequent calls:

subroutine A
  <declaration>, save :: mymatrix
  logical, save :: first_entry = .TRUE.

  if (first_entry) then
     ! set up mymatrix
     first_entry = .FALSE.
  end if
  ! ...
end subroutine A

You can do much the same with mymatrix a module/host variable. You can either use the first_entry saved indicator or rely on the user (as in evets's answer) having an extra setup step:

module A_module
use constants
<declaration> myMatrix  ! Example with host association, automatically saved
contains
    subroutine A
    ! myMatrix is reused, either set up by a distinct call or on first entry
    ! other steps that use myMatrix
    end subroutine A
end module A_module

Or you can have the variable as a dummy argument:

mymatrix_actual = ...
do k = 1,10000
  call A(mymatrix_actual)  ! A now has the dummy variable
end do


来源:https://stackoverflow.com/questions/62855537/initialization-of-2d-arrays-within-subroutines

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!