avoid duplicating code by re-structuring if statement/do loop












4















Hi I am trying to impose a specific condition on my function at many different spatial points in my grid. However I am duplicating lots of code and it's becoming increasingly inefficient.



How can I do what I need to by simply using a do loop? The specific condition I am trying to impose on my function is the same at all the different spatial points so I figure theres a way to do all of this in a single loop. Or how can I combine all these If/else if statements into a single statement? There must be a more efficient way than what I am doing.



I provided a sample code below.



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









share|improve this question























  • Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

    – Ian Bush
    Nov 14 '18 at 7:59











  • @IanBush Thanks for your comment!

    – Jeff Faraci
    Nov 14 '18 at 15:28
















4















Hi I am trying to impose a specific condition on my function at many different spatial points in my grid. However I am duplicating lots of code and it's becoming increasingly inefficient.



How can I do what I need to by simply using a do loop? The specific condition I am trying to impose on my function is the same at all the different spatial points so I figure theres a way to do all of this in a single loop. Or how can I combine all these If/else if statements into a single statement? There must be a more efficient way than what I am doing.



I provided a sample code below.



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









share|improve this question























  • Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

    – Ian Bush
    Nov 14 '18 at 7:59











  • @IanBush Thanks for your comment!

    – Jeff Faraci
    Nov 14 '18 at 15:28














4












4








4








Hi I am trying to impose a specific condition on my function at many different spatial points in my grid. However I am duplicating lots of code and it's becoming increasingly inefficient.



How can I do what I need to by simply using a do loop? The specific condition I am trying to impose on my function is the same at all the different spatial points so I figure theres a way to do all of this in a single loop. Or how can I combine all these If/else if statements into a single statement? There must be a more efficient way than what I am doing.



I provided a sample code below.



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









share|improve this question














Hi I am trying to impose a specific condition on my function at many different spatial points in my grid. However I am duplicating lots of code and it's becoming increasingly inefficient.



How can I do what I need to by simply using a do loop? The specific condition I am trying to impose on my function is the same at all the different spatial points so I figure theres a way to do all of this in a single loop. Or how can I combine all these If/else if statements into a single statement? There must be a more efficient way than what I am doing.



I provided a sample code below.



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






performance if-statement fortran






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 20:38









Jeff FaraciJeff Faraci

290419




290419













  • Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

    – Ian Bush
    Nov 14 '18 at 7:59











  • @IanBush Thanks for your comment!

    – Jeff Faraci
    Nov 14 '18 at 15:28



















  • Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

    – Ian Bush
    Nov 14 '18 at 7:59











  • @IanBush Thanks for your comment!

    – Jeff Faraci
    Nov 14 '18 at 15:28

















Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

– Ian Bush
Nov 14 '18 at 7:59





Three simple ideas that come to mind are use .Or., use an include file or call (a probably internal) subroutine. Array syntax would simplify it as well. But I probably wouldn't start from here - I would set the whole grid "default" value and then use separate loops to modify the exceptional values, not an if in sight.

– Ian Bush
Nov 14 '18 at 7:59













@IanBush Thanks for your comment!

– Jeff Faraci
Nov 14 '18 at 15:28





@IanBush Thanks for your comment!

– Jeff Faraci
Nov 14 '18 at 15:28












1 Answer
1






active

oldest

votes


















4














If you are looking for conciseness, I'd say you can be much, much more concise than you are. The whole function you provided can be rewritten just like this:



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


As said by @IanBush, assigning the default values then modifying the special cases seems a good aproach. Also, array sections notation is one of the distinctive and powerful features of Fortran language, and can be used to increase expressiveness without compromising clarity.



Pure colons mean all values in this dimension, and a colon between values means only values within this range in this dimension.



So, when I write grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1) I mean: i'm assigning values from the array psi to grad; I include all values from the two first dimensions, but only a subset of the two last dimensions (I'm excluding the fisrt and last in each); also, they are mapped directly except for the third dimension, that maps to the next of the equivalent position in psi.



When I write grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]), I am specifying a list of indices instead of a range for the third and fourth dimensions. This will include the total combinations of the two lists: -nxx,-nyy, -nxx,nyy, -nxx,ny, nxx,-nyy...



One advantage of this notation is that, as it is more obvious and closer to the mathematical notation, it is easier to catch inconsistencies. That is why the last line is commented out: an index nx+1, as you would have in the 8th and 9th conditions in the code you wrote, would be out of bounds. I don't know if the sample code you presented is official; if it is, you should correct your algorithm (well, as you are looping only from the second to the second-last indices, you'd actually never touch those conditions...).



As an additional advice, you could put your custom functions in a module, so you could pass all those parameter declarations to the module scope. Moreover, you could then consider assumed-shape array arguments.






share|improve this answer


























  • This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

    – Jeff Faraci
    Nov 14 '18 at 15:27











  • I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

    – Jeff Faraci
    Dec 3 '18 at 17:23











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53289143%2favoid-duplicating-code-by-re-structuring-if-statement-do-loop%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














If you are looking for conciseness, I'd say you can be much, much more concise than you are. The whole function you provided can be rewritten just like this:



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


As said by @IanBush, assigning the default values then modifying the special cases seems a good aproach. Also, array sections notation is one of the distinctive and powerful features of Fortran language, and can be used to increase expressiveness without compromising clarity.



Pure colons mean all values in this dimension, and a colon between values means only values within this range in this dimension.



So, when I write grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1) I mean: i'm assigning values from the array psi to grad; I include all values from the two first dimensions, but only a subset of the two last dimensions (I'm excluding the fisrt and last in each); also, they are mapped directly except for the third dimension, that maps to the next of the equivalent position in psi.



When I write grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]), I am specifying a list of indices instead of a range for the third and fourth dimensions. This will include the total combinations of the two lists: -nxx,-nyy, -nxx,nyy, -nxx,ny, nxx,-nyy...



One advantage of this notation is that, as it is more obvious and closer to the mathematical notation, it is easier to catch inconsistencies. That is why the last line is commented out: an index nx+1, as you would have in the 8th and 9th conditions in the code you wrote, would be out of bounds. I don't know if the sample code you presented is official; if it is, you should correct your algorithm (well, as you are looping only from the second to the second-last indices, you'd actually never touch those conditions...).



As an additional advice, you could put your custom functions in a module, so you could pass all those parameter declarations to the module scope. Moreover, you could then consider assumed-shape array arguments.






share|improve this answer


























  • This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

    – Jeff Faraci
    Nov 14 '18 at 15:27











  • I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

    – Jeff Faraci
    Dec 3 '18 at 17:23
















4














If you are looking for conciseness, I'd say you can be much, much more concise than you are. The whole function you provided can be rewritten just like this:



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


As said by @IanBush, assigning the default values then modifying the special cases seems a good aproach. Also, array sections notation is one of the distinctive and powerful features of Fortran language, and can be used to increase expressiveness without compromising clarity.



Pure colons mean all values in this dimension, and a colon between values means only values within this range in this dimension.



So, when I write grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1) I mean: i'm assigning values from the array psi to grad; I include all values from the two first dimensions, but only a subset of the two last dimensions (I'm excluding the fisrt and last in each); also, they are mapped directly except for the third dimension, that maps to the next of the equivalent position in psi.



When I write grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]), I am specifying a list of indices instead of a range for the third and fourth dimensions. This will include the total combinations of the two lists: -nxx,-nyy, -nxx,nyy, -nxx,ny, nxx,-nyy...



One advantage of this notation is that, as it is more obvious and closer to the mathematical notation, it is easier to catch inconsistencies. That is why the last line is commented out: an index nx+1, as you would have in the 8th and 9th conditions in the code you wrote, would be out of bounds. I don't know if the sample code you presented is official; if it is, you should correct your algorithm (well, as you are looping only from the second to the second-last indices, you'd actually never touch those conditions...).



As an additional advice, you could put your custom functions in a module, so you could pass all those parameter declarations to the module scope. Moreover, you could then consider assumed-shape array arguments.






share|improve this answer


























  • This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

    – Jeff Faraci
    Nov 14 '18 at 15:27











  • I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

    – Jeff Faraci
    Dec 3 '18 at 17:23














4












4








4







If you are looking for conciseness, I'd say you can be much, much more concise than you are. The whole function you provided can be rewritten just like this:



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


As said by @IanBush, assigning the default values then modifying the special cases seems a good aproach. Also, array sections notation is one of the distinctive and powerful features of Fortran language, and can be used to increase expressiveness without compromising clarity.



Pure colons mean all values in this dimension, and a colon between values means only values within this range in this dimension.



So, when I write grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1) I mean: i'm assigning values from the array psi to grad; I include all values from the two first dimensions, but only a subset of the two last dimensions (I'm excluding the fisrt and last in each); also, they are mapped directly except for the third dimension, that maps to the next of the equivalent position in psi.



When I write grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]), I am specifying a list of indices instead of a range for the third and fourth dimensions. This will include the total combinations of the two lists: -nxx,-nyy, -nxx,nyy, -nxx,ny, nxx,-nyy...



One advantage of this notation is that, as it is more obvious and closer to the mathematical notation, it is easier to catch inconsistencies. That is why the last line is commented out: an index nx+1, as you would have in the 8th and 9th conditions in the code you wrote, would be out of bounds. I don't know if the sample code you presented is official; if it is, you should correct your algorithm (well, as you are looping only from the second to the second-last indices, you'd actually never touch those conditions...).



As an additional advice, you could put your custom functions in a module, so you could pass all those parameter declarations to the module scope. Moreover, you could then consider assumed-shape array arguments.






share|improve this answer















If you are looking for conciseness, I'd say you can be much, much more concise than you are. The whole function you provided can be rewritten just like this:



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


As said by @IanBush, assigning the default values then modifying the special cases seems a good aproach. Also, array sections notation is one of the distinctive and powerful features of Fortran language, and can be used to increase expressiveness without compromising clarity.



Pure colons mean all values in this dimension, and a colon between values means only values within this range in this dimension.



So, when I write grad(:,:,-nx+1:nx-1,-ny+1:ny-1) = psi(:,:,-nx+2:nx,-ny+1:ny-1) I mean: i'm assigning values from the array psi to grad; I include all values from the two first dimensions, but only a subset of the two last dimensions (I'm excluding the fisrt and last in each); also, they are mapped directly except for the third dimension, that maps to the next of the equivalent position in psi.



When I write grad(:,:,[-nxx,nxx],[-nyy,nyy,ny]), I am specifying a list of indices instead of a range for the third and fourth dimensions. This will include the total combinations of the two lists: -nxx,-nyy, -nxx,nyy, -nxx,ny, nxx,-nyy...



One advantage of this notation is that, as it is more obvious and closer to the mathematical notation, it is easier to catch inconsistencies. That is why the last line is commented out: an index nx+1, as you would have in the 8th and 9th conditions in the code you wrote, would be out of bounds. I don't know if the sample code you presented is official; if it is, you should correct your algorithm (well, as you are looping only from the second to the second-last indices, you'd actually never touch those conditions...).



As an additional advice, you could put your custom functions in a module, so you could pass all those parameter declarations to the module scope. Moreover, you could then consider assumed-shape array arguments.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 14 '18 at 13:15

























answered Nov 14 '18 at 10:19









Rodrigo RodriguesRodrigo Rodrigues

3,0571720




3,0571720













  • This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

    – Jeff Faraci
    Nov 14 '18 at 15:27











  • I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

    – Jeff Faraci
    Dec 3 '18 at 17:23



















  • This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

    – Jeff Faraci
    Nov 14 '18 at 15:27











  • I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

    – Jeff Faraci
    Dec 3 '18 at 17:23

















This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

– Jeff Faraci
Nov 14 '18 at 15:27





This is exactly what I was looking for. As you've noticed, I'm not so familiar or comfortable with the colon notation. I need to think a bit about your answer and implement it, I'll likely have a few questions as I go through all of this. Thanks a lot for the clear concise answer.

– Jeff Faraci
Nov 14 '18 at 15:27













I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

– Jeff Faraci
Dec 3 '18 at 17:23





I just posted a new question that is an extension of this problem. stackoverflow.com/questions/53598732/…. I am trying to modify my code even more now since my list of indices is much bigger than this example. If you have any solution to it, thank you so much! This solution greatly helped me as is, and you're really helping me improve the efficiency of my code.

– Jeff Faraci
Dec 3 '18 at 17:23


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53289143%2favoid-duplicating-code-by-re-structuring-if-statement-do-loop%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Hercules Kyvelos

Tangent Lines Diagram Along Smooth Curve

Yusuf al-Mu'taman ibn Hud