C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Решение систем дифференциальных уравнений, Методом Рунге-Кутта
heady
Отправлено: 04.04.2005, 16:13


Не зарегистрирован







Hi, All! может кто-нить писал метод Рунге-Кутта на cpp? Очень нужно. Зарание благодарен.
exp
Отправлено: 06.04.2005, 12:24


Мастер участка

Группа: Участник
Сообщений: 304



метод Рунге-Кутты (пока для обыкновенного дифура):

пусть есть дифур и его начальные условия:
CODE

dy
------- = f(t,y), y(t0) = y0
dt

Надо его решить на отрезке [a; b]
Метод Рунге-Кутты (как правило второго порядка) предполагает вычисление 4-х поправок: n1, n2, n3, n4. Как? А вот так:
пусть разность между двумя рядом стоящими значениями аргумента
CODE

h = t[i+1]-t[i];

Пусть теперь мы находимся на i-том шаге вычислений и известны t[i] и y[i].

Твои действия:
CODE

i = 0;
t[i] = a;
НАЧАЛО_ЦИКЛА(ПОКА_t[i]_МЕНЬШЕ_ЛИБО_РАВЕН_a )
1) считаешь n1 = f(t[i],y[i])
2) считаешь n2 = f(t[i]+h/2,y[i]+n1*h/2)
3) считаешь n3 = f(t[i]+h/2,y[i]+n2*h/2)
4) считаешь n4 = f(t[i]+h,y[i]+n3*h)
5) вычисляешь шаговую поправку Delta_y = (n1+2*n2+2*n3+n4)/6.0f
6) прибавляешь ее к y[i] и получаешь y[i+1]: y[i+1] = y[i]+Delta_y
7) увеличиваешь значение аргумента;
КОНЕЦ_ЦИКЛА;


Наше время в эфире подходит к концу. В следующем выпуске: решение систем дифуров. Не переключайте;

PS: Подробнее об этом смотри "Вычислительные методы" или "методы вычислений", или "Вычмат", или "Вычмслительная математика".
Я пользуюсь "Основы численных методов" Вержбицкий В. М.

Отредактировано exp — 06/04/2005, 12:26
heady
Отправлено: 07.04.2005, 09:03


Не зарегистрирован







Спасибо! а как организовать проверку на неправильный интервал по x?
т.е. если текущий x для dy/dx недопустим...
exp
Отправлено: 09.04.2005, 09:59


Мастер участка

Группа: Участник
Сообщений: 304



Так и написать:
CODE

 if(x недопустим)
  {
  }
  else
  {
  }

smile.gif
Прости за такой ответ, но все зависит от условий самой задачи.
exp
Отправлено: 09.04.2005, 13:04


Мастер участка

Группа: Участник
Сообщений: 304



Продолжаем разговор о системах.

Допустим есть система

CODE
  _
 |     dY1
 |   -------  = F1(t, Y1,..., Yn)
 |     dt
 |
/   ......
\
 |   dYn
 |  -------  = Fn(t, Y1,..., Yn)
 |_  dt


Тогда тебе придется решать все эти уравнения одновременно, считая, что для очередного уравнения у тебя уже данные есть.
Т. Е.:
Пусть на i-том шаге ты знаешь Y1[i], Y2[i],..., Yn[i]. Тогда ты можешь посчитать Y1[i+1], Y2[i+1], ..., Yn[i+1] твоим любимым и ставшим уже практически родным методом Рунге-Кутты (см. 2-е сообщение).

ЗЫ:
Можно адаптировать метод Зейделя для решения систем неалгебраических уравнений к нашей теме.
Делается это так: Считаешь по данным Y1[i], Y2[i],..., Yn[i] значение Y1[i+1]. После чего используешь это значение для вычисления Y2[i+1], подставляя его вместо Y1[i]. И так далее пока не вычислишь Yn[i+1].
После этого увеличивай значение аргумента и снова считай Y1[i+2] ...................... пока не устанешь smile.gif

ЗЗЫ: Думаю понятно, что при решении первым методом тебе придется хранить значения Y1[i], Y2[i],..., Yn[i], вычисленные на i-той итерации для того, чтоб их использовать на (i+1)-й

ЗЗЗЫ: Будут вопросы — спрашивай.

Вернуться в Вопросы программирования в C++Builder