我的代码中只剩下一个错误,

时间:2011-04-26 18:09:44

标签: fortran fortran90

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)处没有隐式类型。

1 个答案:

答案 0 :(得分: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

所以你已经使得一个双精度变量,但它也是子程序的名称。那是一个错误;也许你的意思是让这个函数返回一个双精度值;然后你几乎就在那里,你需要将程序标题更改为FUNCTION DERIV(c,u) - 但你永远不会在任何地方设置派生。所以很可能只是被遗漏了。所以,让我们摆脱那个DOUBLE PRECISION deriv声明。此外,从未声明使用的L,并且声明不是x的x。

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

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

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

因此,鉴于上述情况,我们希望deri子例程看起来像这样:

 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左右。让我们试图在整个事情中划分你的意图并相应地重写可能不是任何人的时间的最好用途;你为什么不从这里开始处理一件特别的事情,如果你有特定问题就问另一个问题。