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