В моем коде осталась только одна ошибка, - PullRequest
0 голосов
/ 26 апреля 2011
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 (j-1) и в y (j + 1).

1 Ответ

5 голосов
/ 26 апреля 2011

Здесь много чего не так. Мы можем указать на некоторые вещи, но вам придется сесть с книгой и узнать о программировании, начиная с небольших программ и заканчивая их правильными, а затем наращивая.

Давайте посмотрим на последнюю подпрограмму в коде, который вы опубликовали выше. Я изменил синтаксис некоторых объявлений переменных только для того, чтобы сделать его короче, чтобы больше помещалось на экране сразу.

 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, который не является, объявляется.

Затем вы передаете этой подпрограмме две переменные, c и u, которые вы определили как двойную точность. Пока все хорошо, но затем вы начинаете их индексировать: например, c(i). Таким образом, они должны быть массивами двойной точности, а не просто скалярами. Глядя на цикл do, я предполагаю, что они оба должны иметь размер n - который должен быть передан, предположительно? , Кроме того, цикл do никогда не прерывается; должен быть end do после end if.

Далее, оператор ^, который вы используете, я предполагаю, что вы используете для возведения в степень - но в Фортране это **, а не ^. И это c^(-p) должно (я предполагаю здесь) быть c(i)**(-p)?

Наконец, вы устанавливаете u(c) - но это не очень разумно, так как c - это массив чисел двойной точности. Даже u (c (i)) не имеет смысла - вы не можете индексировать массив с двойной точностью числа. Предположительно, и я просто догадываюсь здесь, вы имеете в виду значение u, соответствующее только что вычисленному значению c - например, u(i), а не u(c)?

Итак, учитывая вышесказанное, мы ожидаем, что подпрограмма производного будет выглядеть следующим образом:

 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

Обратите внимание, что в современном фортране цикл 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 от общего количества кода. То, что мы пытаемся угадать ваши намерения и переписать их, вероятно, не лучшее использование чьего-либо времени; почему бы вам не продолжить работу над одной конкретной вещью и задать другой вопрос, если у вас есть конкретная проблема.

...