2011-04-26 59 views
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)。

+0

通常情况下,发布编译器给出的实际错误有帮助 – Mat 2011-04-26 18:16:23

+1

只剩下一个错误是一个相当大的问题 - 您正在用y(和事实证明,q)进行计算,除非您从未设置过任何错误代码中任何位置的值。当你调用deriv((abs(q(j)-q(j-1))/ e)时,它应该使用什么数字?为什么?当你调用g(j-1)=((y (j)-y(j-1))/ abs(y(j)-y(j-1)))),你甚至没有声明y是什么类型,更不用说插入任何值。应该去那里?子程序力怎么会知道? – 2011-04-26 21:00:36

回答

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) - 但你从来没有在任何地方设置deriv。所以可能应该被排除在外。所以让我们摆脱那个DOUBLE PRECISION deriv声明。另外,使用的L永远不会被声明,并且不会被声明。

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

此外,您正在使用的^运算符我假设您正在使用指数运算 - 但在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语句替换,还你不t需要明确地通过大小;这样,那么你可以用更清晰和更短的闪避:

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代码总数。让我们尝试在整个事情中表达你的意图并相应地重写可能不是任何人的最佳时间;你为什么不从这里开始研究一件特定的事情,并且问你是否有特定的问题。

+3

我第二次读这本书的建议。一个好的Fortran是由Metcalf等人撰写的“Fortran 95/2003解释”。 – 2011-04-26 19:31:56

相关问题