Это мой первый вопрос по инте rnet !!! Кроме того, это вопрос Фортана, и я только начал изучать этот язык. Поэтому, пожалуйста, прости мое невежество. В частности, я прошу прощения, если мой пример кода большой. Я сделал все возможное, чтобы уменьшить его размер до минимума, не подрывая его ясность.
Вот проблема: я пытаюсь создать динамическую c имитационную модель, которая использует функцию, которая будет вызываться несколько раз во время запуска модели. Сама функция представляет собой динамическую систему интеграции c, поэтому значения функций должны сохраняться на каждом временном шаге моделирования, чтобы их можно было использовать на следующем временном шаге.
Модель включает в себя простой запас (P), который уменьшается со временем с постоянной скоростью (10% за раз). Функция экспоненциальной задержки. Он принимает 4 аргумента: (ввод, время задержки, порядок задержки, ввод начальный). Обратите внимание, что выходные данные функции имеют 3 измерения. Первое измерение представляет различные экземпляры вызова задержки в программе. Второе измерение представляет порядок задержки. А третье измерение представляет время моделирования.
Основная задача здесь состояла в том, чтобы динамически распределять массивы, которые будут созданы функцией. Чтобы решить эту проблему, я попытался следовать приведенным здесь рекомендациям: Как увеличить размер массива на лету в Фортране? Программа, которую я написал, в некоторых случаях работает нормально, но не всегда , Например, если вы скомпилируете коды так, как они показаны ниже, вы получите правильный результат (правильное поведение - все переменные должны начинаться с 100 и постепенно уменьшаться). Но если вы измените порядок задержки в U с 5 на 6, тогда результаты будут неправильными (U начинается с 100, но затем колеблется, а иногда go выше 100).
Чего мне здесь не хватает? Что-то не так с тем, как я реализовал move_allo c? Или проблема в другом? Может ли это быть компилятор (gfortran), который выходит из строя? Заранее благодарен за помощь!
program model
implicit none
real, parameter :: start = 0, end = 10, dt = 0.25
integer, parameter :: n = int((end - start)/dt)
real, dimension(0:n+1) :: time, P, R, S, W, U
integer :: i
real, dimension(:,:,:), allocatable :: DN, temp
P(0) = 100
time(0) = start
open (unit=10, file='out.txt', status='replace', action='write', position='rewind')
write (10, *) 'Time, ', 'P, ', 'R, ', 'S, ', 'W, ', 'U'
do i = 0, n
P(i+1) = P(i) - .1*P(i)*dt
R(i) = delay(P(i), 3.0, 4, P(0))
S(i) = delay(P(i), 2.0, 4, P(0))
W(i) = delay(P(i), 4.0, 5, P(0))
U(i) = delay(P(i), 1.0, 5, P(0))
time(i+1) = time(i) + dt
write (10, *) time(i), ',', P(i), ',', R(i), ',', S(i), ',', W(i), ',', U(i)
end do
close (10)
contains
function delay(input, dtime, order, init)
real :: delay
real, intent(in) :: input, dtime, init
integer, save :: j, k
integer, intent(in) :: order
integer :: l
data j /0/
data k /0/
if (j == i) then
k = k + 1
allocate(temp(1:k, 1:order, 0:n+1))
if (allocated(DN)) temp(1:k-1, 1:order, 0:n+1) = DN
call move_alloc(temp, DN)
else
k = 1
j = i
end if
if (i == 0) then
do l = 1, order
DN(k, l, 0) = init * dtime / order
end do
end if
DN(k, 1, i+1) = DN(k, 1, i) + (input - DN(k, 1, i) * order / dtime) * dt
if (order > 1) then
do l = 2, order
DN(k, l, i+1) = DN(k, l, i) + (DN(k, l-1, i) - DN(k, l, i)) * order * dt / dtime
end do
end if
delay = DN(k, order, i) * order / dtime
end function delay
end program model