2011-04-26 35 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

相關問題