1 <?xml version="1.0" encoding="UTF-8"?>
3 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
4 * Copyright (C) 2008 - INRIA
5 * Copyright (C) 2011 - DIGITEO - Michael Baudin
6 * Copyright (C) 2012 - Scilab Enterprises - Adeline CARNIS
7 * This file must be used under the terms of the CeCILL.
8 * This source file is licensed as described in the file COPYING, which
9 * you should have received as part of this distribution. The terms
10 * are also available at
11 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
14 <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="ode" xml:lang="ru">
16 <refname>ode</refname>
18 программа решения обыкновенных дифференциальных уравнений
22 <title>Последовательность вызова</title>
25 [y, w, iw] = ode([type,]y0, t0, t [,rtol [,atol]],f [,jac] [,w, iw])
26 [y, rd, w, iw] = ode("root", y0, t0, t [,rtol [,atol]], f [,jac], ng, g [, w, iw])
27 y = ode("discrete", y0, k0, kvect, f)
31 <title>Аргументы</title>
37 вектор или матрица вещественных значений, начальные условия.
45 вещественный скаляр, начальное время.
53 вещественный вектор, моменты времени для которых находится решение.
61 внешняя функция (функция, строка или список),
62 правая сторона дифференциального уравнения.
70 строка, тип используемой программы решения. Имеются следующие типы
71 программ решения: <literal>"adams"</literal>,
72 <literal>"stiff"</literal>, <literal>"rk"</literal>,
73 <literal>"rkf"</literal>, <literal>"fix"</literal>,
74 <literal>"discrete"</literal>, <literal>"roots"</literal>.
82 вещественная константа либо вещественный вектор того же размера,
83 что и <varname>y</varname>, относительный допуск.
91 вещественная константа либо вещественный вектор того же размера,
92 что и <varname>y</varname>, абсолютный допуск.
100 внешняя функция (функция, строка или список), якобиан функции
101 <varname>f</varname>.
108 <para>вещественные векторы (ВХОДНЫЕ/ВЫХОДНЫЕ).</para>
114 <para>целое число.</para>
120 <para>внешняя функция (функция, символьная строка или список).</para>
126 <para>целое число (начальное время).</para>
132 <para>целочисленный вектор.</para>
138 <para>вещественный вектор или матрица (ВЫХОДНАЯ).</para>
144 <para>вещественный вектор (ВЫХОДНОЙ).</para>
150 <title>Описание</title>
152 <function>ode</function> решает явные обыкновенные
153 дифференциальные уравнения, определённые как:
159 \dfrac{dy}{dt} = f(t,y)\\
166 Это интерфейс для различных программ решения, в частности для ODEPACK.
169 В данной справке описывается использование
170 <function>ode</function> для стандартных явных систем ОДУ.
173 Самый простой способ вызова <function>ode</function>:
174 <code>y = ode(y0, t0, t, f)</code>, где <varname>y0</varname> -
175 вектор начальных условий, <varname>t0</varname> - начальное время,
176 <varname>t</varname> - вектор моментов времени, для которых вычисляется
177 решение <varname>y</varname> и <varname>y</varname> - матрица векторов
178 решения <literal>y=[y(t(1)),y(t(2)),...]</literal>.
181 Входной аргумент <varname>f</varname> определяет правую сторону
182 дифференциального уравнения первого порядка. Этот аргумент является
183 функцией с определённым заголовком.
188 Если <varname>f</varname> является Scilab-функцией, то её
189 последовательность вызова должна быть:
195 где <literal>t</literal> - вещественный скаляр (время), а
196 <varname>y</varname> - вещественный вектор (состояние) и
197 <varname>ydot</varname> - вещественный вектор (производная первого
203 Если <varname>f</varname> - строка, то это - имя компилированной
204 процедуры Fortran или функции C. Например, если вызывается
205 <code>ode(y0, t0, t, "fex")</code>, то вызывается подпрограмма
206 <literal>fex</literal>.
209 Процедура Fortran должна иметь заголовок:
215 где <varname>n</varname> - целое число, <varname>t</varname> --
216 скаляр двойной точности, <varname>y</varname> и
217 <varname>ydot</varname> - векторы двойной точности.
220 Функция C должна иметь заголовок:
223 fex(int *n,double *t,double *y,double *ydot)
226 где <varname>t</varname> - время, <varname>y</varname> - состояние,
227 а <varname>ydot</varname> - производная состояния (dy/dt).
230 Эта внешняя функция может быть собрана способом, независящим от ОС,
231 используя <link linkend="ilib_for_link">ilib_for_link</link> и
232 динамически связана с Scilab с помощью функции
233 <link linkend="link">link</link>.
238 Может случиться, что симулятору <varname>f</varname> потребуются
239 дополнительные аргументы. В этом случае можно использовать следующую
240 возможность. Аргумент <varname>f</varname> может также быть
241 списком <literal>lst=list(simuf,u1,u2,...un)</literal>, где
242 <literal>simuf</literal> является Scilab-функцией с синтаксисом:
243 <literal>ydot = f(t,y,u1,u2,...,un)</literal>, а
244 <literal>u1</literal>, <literal>u2</literal>, ...,
245 <literal>un</literal> - дополнительные аргументы, автоматически
246 передаваемые симулятору <literal>simuf</literal>.
251 Функция <varname>f</varname> может возвращать вместо
252 вектора матрицу<literal>p x q</literal>. С этой матричной нотацией
253 решается система <literal>n=p+q</literal> ОДУ
254 <literal>dY/dt=F(t,Y)</literal>, где <literal>Y</literal> - матрица
255 <literal>p x q</literal>. Затем начальные условия,
256 <literal>Y0</literal>, должны быть так же матрицей
257 <literal>p x q</literal>, а результат <function>ode</function> - матрицей
258 <literal>p x q(T+1)</literal>
259 <literal>[Y(t_0),Y(t_1),...,Y(t_T)]</literal>.
262 Допуски <varname>rtol</varname> и <varname>atol</varname> являются
263 порогами для относительной и абсолютной оценённых ошибок. Оценённая
264 ошибка <literal>y(i)</literal> равна:
265 <literal>rtol(i)*abs(y(i))+atol(i)</literal> и интегрирование выполняется
266 пока эта ошибка мала для каждого из элементов состояния. Если
267 <varname>rtol</varname> и/или <varname>atol</varname> является
268 константой, то <literal>rtol(i)</literal> и/или <literal>atol(i)</literal>
269 являются набором констант. Значения по умолчанию для
270 <varname>rtol</varname> и <varname>atol</varname> соответственно равны
271 <literal>rtol=1.d-5</literal> и <literal>atol=1.d-7</literal> для
272 большинства программ решения, а для <literal>"rfk"</literal> и
273 <literal>"fix"</literal> <literal>rtol=1.d-3</literal> и
274 <literal>atol=1.d-4</literal>.
277 Для жёстких задач лучше указывать якобиан функции правой стороны в
278 качестве необязательного аргумента <varname>jac</varname>.
279 Якобиан является внешней функцией, т. е. функцией со специальным
280 синтаксисом, либо именем процедуры Fortran или функции C
281 (символьная строка) с определённой последовательностью вызова, либо
287 Если <varname>jac</varname> является функцией, то синтаксис должен
288 быть <literal>J=jac(t,y)</literal>, где <literal>t</literal> --
289 вещественный скаляр (время), а <varname>y</varname> - вещественный
290 вектор (состояние). Результирующая матрица <literal>J</literal>
291 должна вычислять df/dx, т. е. <literal>J(k,i) = dfk/dxi</literal>, где
292 <literal>fk</literal> - <literal>k</literal>-тый элемент
293 <varname>f</varname>.
298 Если <varname>jac</varname> является символьной строкой, то она
299 ссылается на имя процедуры Fortran или функции C.
302 Процедура Fortran должна иметь заголовок:
305 subroutine fex(n,t,y,ml,mu,J,nrpd)
307 double precision t,y(*),J(*)
310 Функция C должна иметь заголовок:
313 void fex(int *n,double *t,double *y,int *ml,int *mu,double *J,int *nrpd,)
316 В большинстве случаев не нужно ссылаться на <literal>ml</literal>,
317 <literal>mu</literal> и <literal>nrpd</literal>.
322 Если <varname>jac</varname> является списком, то для
323 <varname>f</varname> применяются те же договорённости.
328 Необязательные аргументы <varname>w</varname> и
329 <varname>iw</varname> являются векторами для хранения информации,
330 возвращаемой подпрограммой интегрирования (см. <link linkend="ode_optional_output">ode_optional_output</link>).
331 Когда эти векторы указываются с правой стороны <function>ode</function>,
332 интегрирование начинается заново с теми же параметрами, что и до
336 Программам решения ODEPACK можно передать больше опций с помощью
337 переменной <literal>%ODEOPTIONS</literal>. See <link linkend="odeoptions">odeoptions</link>.
341 <title>Программы решения</title>
343 Тип задачи, которую надо решить и используемый метод зависят от
344 значения первого необязательного аргумента <varname>type</varname>,
345 который может быть одной из следующих строк:
349 <term><не задано>:</term>
352 Программа решения <literal>lsoda</literal> из пакета ODEPACK
353 вызывается по умолчанию. Она автоматически выбирает между
354 нежёстким методом прогноза-исправления Адамса
355 (predictor-corrector Adams method) и жёстким методом обратной
356 дифференциальной формулой (ОДФ) ( Backward Differentiation
357 Formula (BDF) method). Изначально она применяет нежёсткий метод и
358 динамически проверяет данные для того, чтобы решить какой метод
364 <term>"adams":</term>
367 Используется для нежёстких задач. Вызывается программа
368 решения <literal>lsode</literal> из пакета ODEPACK, и она
369 использует метод Адамса.
374 <term>"stiff":</term>
377 Это для жёстких задач. Вызывается программа решения
378 <literal>lsode</literal> из пакета ODEPACK, и она использует метод
386 <para>Адаптивный метод Рунге-Кутты 4-го порядка (RK4).</para>
393 Используется программа Шампайна и Уотса (Shampine и Watts),
394 основанная на методе Рунге-Кутты-Фелберга пары 4 и 5-го
395 порядка (RKF45). Она для нежёстких и среднежёстких задач,
396 когда получаемые вычисления не дороги. Этот метод не следует, в
397 общем случае, использовать, если пользователь требует
406 Та же программа решения, что и <literal>"rkf"</literal>, но
407 пользовательский интерфейс очень прост, т. е. программе решения
408 могут быть переданы только параметры <varname>rtol</varname> и
409 <varname>atol</varname>. Это самый простой метод для пробы.
417 Программа решения ОДУ с возможностью нахождения корней.
418 Используется программа решения <literal>lsodar</literal> из пакета
419 ODEPACK. Она является вариантом программы
420 решения <literal>lsoda</literal>, где она ищет корни заданной
421 векторной функции. См. справку по <link linkend="ode_root">ode_root</link>.
426 <term>"discrete":</term>
429 Моделирование дискретного времени. См. справку по <link linkend="ode_discrete">ode_discrete</link>.
436 <title>Примеры</title>
438 В следующем примере мы решим обыкновенное дифференциальное уравнение
439 <literal>dy/dt=y^2-y*sin(t)+cos(t)</literal> с начальным условием
440 <literal>y(0)=0</literal>. Используем программу решения по умолчанию.
442 <programlisting role="example"><![CDATA[
444 ydot=y^2-y*sin(t)+cos(t)
453 В следующем примере мы решаем уравнение <literal>dy/dt=A*y</literal>.
454 Точное решение равно <literal>y(t)=expm(A*t)*y(0)</literal>, где
455 <literal>expm</literal> - матричная экспонента.
456 Неизвестное равно матрице <literal>y(t)</literal> размером 2 на 1.
458 <programlisting role="example"><![CDATA[
462 function J=Jacobian(t,y)
469 ode("stiff",y0,t0,t,f,Jacobian)
470 // Сравним с точным решением:
474 В следующем примере мы решаем ОДУ <literal>dx/dt = A*x(t) +
477 с <literal>u(t)=sin(omega*t)</literal>.
478 Обратите внимание, что дополнительные аргументы <varname>f</varname>:
479 <literal>A</literal>, <literal>u</literal>, <literal>B</literal>,
480 <literal>omega</literal> передаются в <varname>f</varname> в списке.
482 <programlisting role="example"><![CDATA[
483 function xdot=linear(t,x,A,u,B,omega)
484 xdot=A*x+B*u(t,omega)
486 function ut=u(t,omega)
495 ode(y0,t0,t,list(linear,A,u,B,omega))
498 В следующем примере мы решим дифференциальное уравнение Риккати
499 <literal>dX/dt=A'*X + X*A - X'*B*X + C</literal>, где начальное
500 условие <literal>X(0)</literal> является единичной матрицей 2 на 2.
502 <programlisting role="example"><![CDATA[
503 function Xdot=ric(t,X,A,B,C)
504 Xdot=A'*X+X*A-X'*B*X+C
512 X = ode(y0,t0,t,list(ric,A,B,C))
515 В следующем примере мы решаме дифференциальное уравнение
516 <literal>dY/dt=A*Y</literal>, где неизвестная <literal>Y(t)</literal>
517 является матрицей 2 на 2. Точное решение равно <literal>expm</literal>
518 <literal>Y(t)=expm(A*t)</literal>, где <literal>expm</literal> --
519 матричная экспонента.
521 <programlisting role="example"><![CDATA[
522 function ydot=f(t,y,A)
529 ode(y0,t0,t,list(f,A))
530 // Сравнение с точным решением
532 ode("adams",y0,t0,t,f)
536 <title>С компилятором</title>
538 Следующий пример требует компилятор C.
540 <programlisting role="example"><![CDATA[
541 // ---------- Простое одномерное ОДУ (внешняя функция на языке C)
542 ccode=['#include <math.h>'
543 'void myode(int *n,double *t,double *y,double *ydot)'
545 ' ydot[0]=y[0]*y[0]-y[0]*sin(*t)+cos(*t);'
547 mputl(ccode,TMPDIR+'/myode.c') // создаём C-файл
549 ilib_for_link('myode','myode.c',[],'c',TMPDIR+'/Makefile',TMPDIR+'/loader.sce');
550 exec(TMPDIR+'/loader.sce') // пошаговая компоновка
554 y = ode(y0,t0,t,'myode');
558 <refsection role="see also">
559 <title>Смотрите также</title>
560 <simplelist type="inline">
562 <link linkend="ode_discrete">ode_discrete</link>
565 <link linkend="ode_root">ode_root</link>
568 <link linkend="dassl">dassl</link>
571 <link linkend="impl">impl</link>
574 <link linkend="odedc">odedc</link>
577 <link linkend="odeoptions">odeoptions</link>
580 <link linkend="csim">csim</link>
583 <link linkend="ltitr">ltitr</link>
586 <link linkend="rtitr">rtitr</link>
589 <link linkend="intg">intg</link>
594 <title>Литература</title>
596 Alan C. Hindmarsh, "lsode and lsodi, two new initial value ordinary
597 differential equation solvers", ACM-Signum newsletter, vol. 15, no. 4
602 <title>Используемые функции</title>
604 Связанные процедуры могут быть найдены в директории
605 SCI/modules/differential_equations/src/fortran:
606 lsode.f lsoda.f lsodar.f