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 行目に同じエラーが 1 つだけ表示されます。次のように表示されます。

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は宣言されます。

次に、倍精度として定義する2つの変数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

ただし、コードのこのセクションで意味することの3倍をすでに推測する必要があり、これはコード全体の約1/4にすぎないことに注意してください。私たちにあなたの意図を全体的に理解させ、それに応じて書き直してもらうことは、おそらく誰かの時間を最大限に活用することではありません。ここから先に進んで、特定の問題がある場合は、別の質問をしてみませんか。

于 2011-04-26T19:03:57.970 に答える