嗨,我想在网格中许多不同的空间点上对函数施加特定条件。但是,我正在复制大量代码,并且效率越来越低。
如何仅通过使用do循环来执行我需要做的事情?我要在函数上施加的特定条件在所有不同的空间点都相同,因此我认为有一种方法可以在单个循环中完成所有这些操作。或者如何将所有这些If / else if语句合并为一个语句?必须有比我正在做的事更有效的方法。
我在下面提供了示例代码。
FUNCTION grad(psi)
IMPLICIT NONE
INTEGER :: i,j,kk,ll
INTEGER, PARAMETER :: nx = 24, ny = 24
COMPLEX,DIMENSION(3,3,-nx:nx, -ny:ny) :: psi, grad
REAL :: pi
REAL :: f0
INTEGER :: nxx, nyy
nxx = nx/2
nyy = ny/2
pi = 4*atan(1.0)
f0 = pi**2*1.3
DO i=-nx+1,nx-1 !spatial points
DO j=-ny+1,ny-1 !spatial points
IF ( i == 0 .AND. j == 0 .AND. i == j) THEN ! I have lots of statements like this
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == nxx .AND. j == nyy .AND. i == j) THEN ! I have lots of statements like this
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == -nxx .AND. j == -nyy .AND. i == j) THEN ! I have lots of statements like this
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == nxx .AND. j == -nyy) THEN ! I have lots of statements like this
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == -nxx .AND. j == nyy) THEN
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == nxx .AND. j == ny) THEN
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == -nxx .AND. j == ny) THEN
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == nx .AND. j == -nyy) THEN
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE IF ( i == nx .AND. j == nyy) THEN
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j) - f0*psi(kk,1,i,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j) - f0*psi(kk,2,i,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j) - f0*psi(kk,3,i,j)
END DO
ELSE
DO kk=1,3
grad(kk,1,i,j) = psi(kk,1,i+1,j)
grad(kk,2,i,j) = psi(kk,2,i+1,j)
grad(kk,3,i,j) = psi(kk,3,i+1,j)
END DO
END IF
END DO
END DO
END FUNCTION grad
答案 0 :(得分:4)
如果您正在寻找简洁,我想您会比您简明得多。您提供的整个功能可以像这样重写:
Microsoft.ServiceFabric
正如@IanBush所说,分配默认值然后修改特殊情况似乎是一个很好的方法。此外,array sections notation是Fortran语言独特而强大的功能之一,可用于提高表达能力而又不影响清晰度。
纯冒号表示此维度中的所有值,而值之间的冒号表示仅此维度中此范围内的值。
所以,当我写function grad(psi)
implicit none
integer, parameter :: nx = 24, ny = 24, nxx = nx / 2, nyy = ny / 2
real, parameter :: pi = 4 * atan(1.0), f0 = pi ** 2 * 1.3
complex, dimension(3,3,-nx:nx,-ny:ny) :: psi, grad
grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1)
grad(:,:,0,0) = psi(:,:,1,0)
grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]) = psi(:,:,[-nxx+1,nxx+1],[-nyy,nyy,ny]) - f0 * psi(:,:,[-nxx,nxx],[-nyy,nyy,ny])
!grad(:,:,nx,[-nyy,nyy]) = psi(:,:,nx+1,[-nyy,nyy]) - f0 * psi(:,:,nx,[-nyy,nyy])
end
时,我的意思是:我是将数组grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1)
中的值分配给psi
;我包括了第一个维度中的所有值,但仅包括了两个最后维度中的一个子集(我不包括第一个维度和最后一个维度);此外,它们直接映射到第三个维度以外的地方,后者映射到grad
中的等效位置的下一个位置。
当我写psi
时,我指定的是索引列表,而不是第三维的索引范围。这将包括两个列表的总组合:grad(:,:,[-nxx,nxx],[-nyy,nyy,ny])
,-nxx,-nyy
,-nxx,nyy
,-nxx,ny
...
此表示法的一个优点是,由于它更明显且更接近数学表示法,因此更容易发现不一致之处。这就是为什么最后一行被注释掉的原因:索引nxx,-nyy
超出了您编写的代码的第8个和第9个条件的范围。我不知道您提供的示例代码是否为官方代码;如果是这样,则应该更正您的算法(并且,由于您仅从倒数第二个索引循环到倒数第二个索引,因此您实际上永远不会触及这些条件...)。
作为其他建议,您可以将自定义函数放在模块中,这样就可以将所有这些参数声明传递给模块范围。此外,您可以考虑假定形状的数组参数。