0
PROGRAM MPI
IMPLICIT NONE
INTEGER, PARAMETER :: nn=100

DOUBLE PRECISION h, L
DOUBLE PRECISION, DIMENSION (2*nn) :: y, ynew
DOUBLE PRECISION, DIMENSION (nn) :: qnew,vnew
DOUBLE PRECISION, DIMENSION (2*nn) :: k1,k2,k3,k4
INTEGER j, k
INTEGER i
INTEGER n

n=100 !particles
L=2.0d0
h=1.0d0/n
y(1)=1.0d0

DO k=1,2*n          ! time loop

   CALL RHS(y,k1)
   CALL RHS(y+(h/2.0d0)*k1,k2)
   CALL RHS(y+(h/2.0d0)*k2,k3)
   CALL RHS(y+h*k3,k4)

   ynew(1:2*n)=y(1:2*n) + (k1 + 2.0d0*(k2 + k3) + k4)*h/6.0d0
END DO
         qnew(1:n)=ynew(1:n)
    vnew(1:n)=ynew(n+1:2*n)

    DO i=1,n
       IF (qnew(i).GT. L) THEN
       qnew(i) = qnew(i) - L
       ENDIF
    END DO

     write(*,*) 'qnew=', qnew(1:n)
     write(*,*) 'vnew=', vnew(1:n)

     END PROGRAM MPI

    !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    !   Right hand side of the ODE
    !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
             SUBROUTINE RHS(y,z)

             IMPLICIT NONE
             INTEGER, PARAMETER :: nn=100
             DOUBLE PRECISION, DIMENSION (2*nn) :: y
             DOUBLE PRECISION, DIMENSION (2*nn) :: z
             DOUBLE PRECISION, DIMENSION (nn) :: F
             DOUBLE PRECISION, DIMENSION (nn) :: g
             INTEGER n
             INTEGER m
             n=100
             m=1/n

     z(1:n)=y(n+1:2*n)
     CAll FORCE(g,F)
     z(n+1:2*n)=F(1:n)/m

             RETURN
             END
     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     !      Force acting on each particle
     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

              SUBROUTINE FORCE(g,F)

                         IMPLICIT NONE

                INTEGER, PARAMETER :: nn=100
                DOUBLE PRECISION, DIMENSION (nn) :: F
                DOUBLE PRECISION, DIMENSION (nn) :: q
                DOUBLE PRECISION, DIMENSION (nn) :: g
                DOUBLE PRECISION u
                INTEGER j, e
                INTEGER n
                n=100
                e=1/n

                DO j=2,n+1

                 CALL deriv((abs(q(j)-q(j-1)))/e,u)
                 g(j-1)=((y(j)-y(j-1))/(abs(y(j)-y(j-1))))*u
                 CALL deriv((abs(q(j)-q(j+1)))/e,u)
                 g(j+1)=((y(j)-y(j+1))/(abs(y(j)-y(j+1))))*u

                 F(j)=g(j-1)+g(j+1)

                END DO
              RETURN
              END

              SUBROUTINE deriv(c,u,n)

                         IMPLICIT NONE

                INTEGER, INTENT(in) :: n
                DOUBLE PRECISION, DIMENSION(n), INTENT(IN) :: c
                DOUBLE PRECISION, DIMENSION(n), INTENT(OUT) :: u
                INTEGER, PARAMETER :: p=2
                INTEGER, PARAMETER :: cr=100
                INTEGER :: i
                DOUBLE PRECISION L
                L=2.0d0

                DO i= 1,n
                      IF  (c(i) .LE. L) THEN
                          u(i)=cr*(L*(c(i)**(-p))-L**(1-p))
                      ELSE IF (c(i) .GT. L)  THEN
                           u(i)=0
                      END IF

                END DO

             RETURN
             END SUBROUTINE deriv

我在第 85 行和第 87 行只收到一个相同的错误。它说:

y 在 y(j-1) 和 y(j+1) 处没有隐式类型。

4

1 回答 1

5

这里有很多错误。我们可以指出一些事情,但是您将不得不坐下来阅读一本书并学习编程,从较小的程序开始并正确处理它们,然后再进行构建。

让我们看看您在上面发布的代码中的最后一个例程。我已经更改了一些变量声明的语法,只是为了让它更短,以便更适合屏幕。

 SUBROUTINE deriv(c,u)
 IMPLICIT NONE
 DOUBLE PRECISION :: deriv, c, u
 INTEGER :: p, x, cr, n

 L=2.0d0
 cr=100
 p=2
 n=100

 DO i= 1,n
 IF  (c(i).LE. L) THEN
     u(c)=cr*(L*c^(-p)-L^(1-p))
     ELSE IF (c(i) .GT. L)  THEN
     u(c)=0
 END IF

 RETURN
 END

因此,您已将 deriv 设为双精度变量,但它也是子例程的名称。这是一个错误;也许你打算让它成为一个返回双精度值的函数;那么您就快到了,您需要将过程标题更改为FUNCTION DERIV(c,u)-- 但您从未在任何地方设置 deriv 。所以很可能应该被排除在外。所以让我们摆脱那个DOUBLE PRECISION deriv声明。此外,使用的 L 从未被声明,而未声明的 x 则被声明。

然后将两个变量 c 和 u 传递给该子程序,定义为双精度。到目前为止一切顺利,但随后您开始为它们编制索引:例如,c(i). 所以它们应该是双精度数组,而不仅仅是标量。看看 do 循环,我猜它们都应该有大小n——大概应该传入?. 此外,do 循环永远不会终止;end do之后应该有一个end if

此外,您正在使用的^运算符我假设您正在使用求幂 - 但在 Fortran 中,那是**,而不是^。那c^(-p)应该(我猜这里)是c(i)**(-p)

最后,您正在设置u(c)- 但这不是很明智,因为 c 是一个双精度数字数组。甚至 u(c(i)) 也没有意义——你不能用双精度数索引一个数组。大概,我只是在这里猜测,你的意思是u与刚刚计算的值相对应的值c——例如u(i),不是u(c)

因此,鉴于上述情况,我们希望 deriv 子例程如下所示:

 SUBROUTINE deriv(c,u,n)
 IMPLICIT NONE
 INTEGER, INTENT(in) :: n
 DOUBLE PRECISION, DIMENSION(n), intent(IN) :: c
 DOUBLE PRECISION, DIMENSION(n), intent(OUT) :: u

 INTEGER, PARAMETER :: p=2, cr=100
 DOUBLE PRECISION, PARAMETER :: L=2.0
 INTEGER :: i

 DO i= 1,n
     IF  (c(i) .LE. L) THEN
         u(i)=cr*(L*c(i)**(-p)-L**(1-p))
     ELSE IF (c(i) .GT. L)  THEN
         u(i)=0
     END IF
 END DO

 RETURN
 END SUBROUTINE deriv

请注意,在现代 fortran 中,do 循环可以替换为 where 语句,而且您不需要显式传递大小;所以你可以摆脱更清晰和更短的:

 SUBROUTINE DERIV(c,u)
 IMPLICIT NONE
 DOUBLE PRECISION, DIMENSION(:), intent(IN) :: c
 DOUBLE PRECISION, DIMENSION(size(c,1)), intent(OUT) :: u

 INTEGER, PARAMETER :: p=2, cr=100
 DOUBLE PRECISION, PARAMETER :: L=2.0

 WHERE (c <= L)
     u=cr*(L*c**(-p)-L**(1-p))
 ELSEWHERE
     u=0
 ENDWHERE

 RETURN
 END SUBROUTINE DERIV

但是请注意,我已经不得不猜测您在这部分代码中的意思的三倍,而这只是代码总数的大约 1/4。让我们尝试在整个事情中推测您的意图并相应地重写可能不是对任何人时间的最佳利用;你为什么不从这里着手处理一件特定的事情,如果你有一个特定的问题,再问另一个问题。

于 2011-04-26T19:03:57.970 回答