fortran - 有什么方法可以避免 Fortran 90 中的嵌套 do 循环吗?

标签 fortran fortran90

我正在读取分子沿时间轨迹的一些速度。我正在尝试计算 v_i(t)*v_j(t+nΔt),其中 i 和 j 不一定是同一个原子。

我使用嵌套的 do 循环来进行计算,这是根据不同时间步长、不同分子和不同原子的定义。我有多个嵌套的 do 循环,这会减慢代码速度并导致内存问题。如果可能的话,我想避免这些问题。如何使用 Fortran 90 改进我的代码?

   PROGRAM BUILD

   IMPLICIT NONE
   INTEGER :: I,K,L,L1,L2,M1,M2,T,T1,T2,NCON,NMOL,NSIT,SPLIT,LOOP
   REAL(8) :: X,Y,Z,V1,V2,V3,R,TRASH
   REAL(8),ALLOCATABLE :: VX(:,:,:),VY(:,:,:),VZ(:,:,:)
   REAL(8),ALLOCATABLE :: NORM(:,:,:,:,:),V(:,:,:,:,:)

   ! Input

   NCON = 100001 ! Number of configurations
   NMOL = 524 ! Number of molecules
   NSIT = 6 ! Number of sites on each molecule

   SPLIT = 50 ! Number of subgroups of configurations
   LOOP = (NCON-1)/SPLIT ! Number of configurations in each subgroup

   !       *       *       *       *       *       *       *       *       *

   ! Allocate memory

   ALLOCATE ( VX(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( VY(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( VZ(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( V(0:LOOP,NMOL,NMOL,NSIT,NSIT) )
   ALLOCATE ( NORM(0:LOOP,NMOL,NMOL,NSIT,NSIT) )
   ALLOCATE ( VIVJ(0:LOOP,NSIT,NSIT) )
   ALLOCATE ( N(0:LOOP,NSIT,NSIT) )

   ! Initialize

   VX = 0.0D0
   VY = 0.0D0
   VZ = 0.0D0
   V = 0.0D0
   NORM = 0.0D0
   VIVJ = 0.0D0
   N = 0.0D0

   ! Read trajectories

   OPEN(UNIT=15,FILE='HISTORY',STATUS='UNKNOWN',ACTION='READ')
   DO I = 1,SPLIT
      WRITE(*,*) I,SPLIT
      DO T = 0,LOOP-1
         DO L = 1,NMOL
            DO K = 1,NSIT
               READ(15,*) V1,V2,V3

               VX(T,L,K) = V1
               VY(T,L,K) = V2 
               VZ(T,L,K) = V3

            END DO

         END DO

      END DO

      ! Calculate functions

      DO T1 = 1,LOOP

         DO T2 = T1,LOOP

            DO L1 = 1,NMOL

               DO M1 = 1,NSIT

                  DO L2 = 1,NMOL

                     DO M2 = 1,NSIT

                        ! Includes all atoms, both intermolecular and intramolecular

                        ! Keep all of the molecules
                        V(T2-T1,L1,L2,M1,M2) = V(T2-T1,L1,L2,M1,M2) + & 
                                         VX(T1,L1,M1)*VX(T2,L2,M2) + & 
                                         VY(T1,L1,M1)*VY(T2,L2,M2) + & 
                                         VZ(T1,L1,M1)*VZ(T2,L2,M2)

                        ! Accounting
                        NORM(T2-T1,L1,L2,M1,M2) = NORM(T2-T1,L1,L2,M1,M2) + 1.0D0

                     END DO

                  END DO

               END DO

            END DO

         END DO

      END DO

   CLOSE(15)

   DEALLOCATE(VX)
   DEALLOCATE(VY)
   DEALLOCATE(VZ)
   DEALLOCATE(V)
   DEALLOCATE(NORM)

   END PROGRAM

最佳答案

Fortran 存储数组的顺序与 C 和大多数其他语言不同。

do T = ...
    do L = ...
        do K = ...
            array(T, L, K) = ...
        end do
    end do
end do

总是比

慢得多
do K = ...
    do L = ...
        do T = ...
            array(T, L, K) = ...
        end do
    end do
end do

在所有其他条件相同的情况下。

关于fortran - 有什么方法可以避免 Fortran 90 中的嵌套 do 循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55319556/

相关文章:

python - 在 Python 中读取直接访问二进制文件格式

pointers - =>(等于大于)在 Fortran 中是什么意思?

复数的 Fortran 格式说明符

arrays - 按列将数组写入文件

vim - 在 Vim 中缩进 Fortran 代码

compiler-errors - gfortran 编译双复变量的问题

c++ - 将字符串从 Fortran 传递到 C++

java - 使用Java解析FORTRAN输出文件

algorithm - 如何在连接组件标记算法 i Fortran 中存储等价

fortran - 如何提高这个巨大的嵌套循环的性能? (Fortran 90)