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 * Copyright (C) 2012 - 2016 - Scilab Enterprises
9 * This file is hereby licensed under the terms of the GNU GPL v2.0,
10 * pursuant to article 5.3.4 of the CeCILL v.2.1.
11 * This file was originally licensed under the terms of the CeCILL v2.1,
12 * and continues to be available under such terms.
13 * For more information, see the COPYING file which you should have received
14 * along with this program.
17 <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">
19 <refname>ode</refname>
21 программа решения обыкновенных дифференциальных уравнений
25 <title>Последовательность вызова</title>
28 [y, w, iw] = ode([type,]y0, t0, t [,rtol [,atol]],f [,jac] [,w, iw])
29 [y, rd, w, iw] = ode("root", y0, t0, t [,rtol [,atol]], f [,jac], ng, g [, w, iw])
30 y = ode("discrete", y0, k0, kvect, f)
34 <title>Аргументы</title>
40 вектор или матрица вещественных значений, начальные условия.
48 вещественный скаляр, начальное время.
56 вещественный вектор, моменты времени для которых находится решение.
64 внешняя функция (функция, строка или список),
65 правая сторона дифференциального уравнения.
73 строка, тип используемой программы решения. Имеются следующие типы
74 программ решения: <literal>"adams"</literal>,
75 <literal>"stiff"</literal>, <literal>"rk"</literal>,
76 <literal>"rkf"</literal>, <literal>"fix"</literal>,
77 <literal>"discrete"</literal>, <literal>"roots"</literal>.
85 вещественная константа либо вещественный вектор того же размера,
86 что и <varname>y</varname>, относительный допуск.
94 вещественная константа либо вещественный вектор того же размера,
95 что и <varname>y</varname>, абсолютный допуск.
103 внешняя функция (функция, строка или список), якобиан функции
104 <varname>f</varname>.
111 <para>вещественные векторы (ВХОДНЫЕ/ВЫХОДНЫЕ).</para>
117 <para>целое число.</para>
123 <para>внешняя функция (функция, символьная строка или список).</para>
129 <para>целое число (начальное время).</para>
135 <para>целочисленный вектор.</para>
141 <para>вещественный вектор или матрица (ВЫХОДНАЯ).</para>
147 <para>вещественный вектор (ВЫХОДНОЙ).</para>
153 <title>Описание</title>
155 <function>ode</function> решает явные обыкновенные
156 дифференциальные уравнения, определённые как:
162 \dfrac{dy}{dt} = f(t,y)\\
169 Это интерфейс для различных программ решения, в частности для ODEPACK.
172 В данной справке описывается использование
173 <function>ode</function> для стандартных явных систем ОДУ.
176 Самый простой способ вызова <function>ode</function>:
177 <code>y = ode(y0, t0, t, f)</code>, где <varname>y0</varname> -
178 вектор начальных условий, <varname>t0</varname> - начальное время,
179 <varname>t</varname> - вектор моментов времени, для которых вычисляется
180 решение <varname>y</varname> и <varname>y</varname> - матрица векторов
181 решения <literal>y=[y(t(1)),y(t(2)),...]</literal>.
184 Входной аргумент <varname>f</varname> определяет правую сторону
185 дифференциального уравнения первого порядка. Этот аргумент является
186 функцией с определённым заголовком.
191 Если <varname>f</varname> является Scilab-функцией, то её
192 последовательность вызова должна быть:
198 где <literal>t</literal> - вещественный скаляр (время), а
199 <varname>y</varname> - вещественный вектор (состояние) и
200 <varname>ydot</varname> - вещественный вектор (производная первого
206 Если <varname>f</varname> - строка, то это - имя компилированной
207 процедуры Fortran или функции C. Например, если вызывается
208 <code>ode(y0, t0, t, "fex")</code>, то вызывается подпрограмма
209 <literal>fex</literal>.
212 Процедура Fortran должна иметь заголовок:
218 где <varname>n</varname> - целое число, <varname>t</varname> --
219 скаляр двойной точности, <varname>y</varname> и
220 <varname>ydot</varname> - векторы двойной точности.
223 Функция C должна иметь заголовок:
226 fex(int *n,double *t,double *y,double *ydot)
229 где <varname>t</varname> - время, <varname>y</varname> - состояние,
230 а <varname>ydot</varname> - производная состояния (dy/dt).
233 Эта внешняя функция может быть собрана способом, независящим от ОС,
234 используя <link linkend="ilib_for_link">ilib_for_link</link> и
235 динамически связана с Scilab с помощью функции
236 <link linkend="link">link</link>.
241 Может случиться, что симулятору <varname>f</varname> потребуются
242 дополнительные аргументы. В этом случае можно использовать следующую
243 возможность. Аргумент <varname>f</varname> может также быть
244 списком <literal>lst=list(simuf,u1,u2,...un)</literal>, где
245 <literal>simuf</literal> является Scilab-функцией с синтаксисом:
246 <literal>ydot = f(t,y,u1,u2,...,un)</literal>, а
247 <literal>u1</literal>, <literal>u2</literal>, ...,
248 <literal>un</literal> - дополнительные аргументы, автоматически
249 передаваемые симулятору <literal>simuf</literal>.
254 Функция <varname>f</varname> может возвращать вместо
255 вектора матрицу<literal>p x q</literal>. С этой матричной нотацией
256 решается система <literal>n=p+q</literal> ОДУ
257 <literal>dY/dt=F(t,Y)</literal>, где <literal>Y</literal> - матрица
258 <literal>p x q</literal>. Затем начальные условия,
259 <literal>Y0</literal>, должны быть так же матрицей
260 <literal>p x q</literal>, а результат <function>ode</function> - матрицей
261 <literal>p x q(T+1)</literal>
262 <literal>[Y(t_0),Y(t_1),...,Y(t_T)]</literal>.
265 Допуски <varname>rtol</varname> и <varname>atol</varname> являются
266 порогами для относительной и абсолютной оценённых ошибок. Оценённая
267 ошибка <literal>y(i)</literal> равна:
268 <literal>rtol(i)*abs(y(i))+atol(i)</literal> и интегрирование выполняется
269 пока эта ошибка мала для каждого из элементов состояния. Если
270 <varname>rtol</varname> и/или <varname>atol</varname> является
271 константой, то <literal>rtol(i)</literal> и/или <literal>atol(i)</literal>
272 являются набором констант. Значения по умолчанию для
273 <varname>rtol</varname> и <varname>atol</varname> соответственно равны
274 <literal>rtol=1.d-5</literal> и <literal>atol=1.d-7</literal> для
275 большинства программ решения, а для <literal>"rfk"</literal> и
276 <literal>"fix"</literal> <literal>rtol=1.d-3</literal> и
277 <literal>atol=1.d-4</literal>.
280 Для жёстких задач лучше указывать якобиан функции правой стороны в
281 качестве необязательного аргумента <varname>jac</varname>.
282 Якобиан является внешней функцией, т. е. функцией со специальным
283 синтаксисом, либо именем процедуры Fortran или функции C
284 (символьная строка) с определённой последовательностью вызова, либо
290 Если <varname>jac</varname> является функцией, то синтаксис должен
291 быть <literal>J=jac(t,y)</literal>, где <literal>t</literal> --
292 вещественный скаляр (время), а <varname>y</varname> - вещественный
293 вектор (состояние). Результирующая матрица <literal>J</literal>
294 должна вычислять df/dx, т. е. <literal>J(k,i) = dfk/dxi</literal>, где
295 <literal>fk</literal> - <literal>k</literal>-тый элемент
296 <varname>f</varname>.
301 Если <varname>jac</varname> является символьной строкой, то она
302 ссылается на имя процедуры Fortran или функции C.
305 Процедура Fortran должна иметь заголовок:
308 subroutine fex(n,t,y,ml,mu,J,nrpd)
310 double precision t,y(*),J(*)
313 Функция C должна иметь заголовок:
316 void fex(int *n,double *t,double *y,int *ml,int *mu,double *J,int *nrpd,)
319 В большинстве случаев не нужно ссылаться на <literal>ml</literal>,
320 <literal>mu</literal> и <literal>nrpd</literal>.
325 Если <varname>jac</varname> является списком, то для
326 <varname>f</varname> применяются те же договорённости.
331 Необязательные аргументы <varname>w</varname> и
332 <varname>iw</varname> являются векторами для хранения информации,
333 возвращаемой подпрограммой интегрирования (см. <link linkend="ode_optional_output">ode_optional_output</link>).
334 Когда эти векторы указываются с правой стороны <function>ode</function>,
335 интегрирование начинается заново с теми же параметрами, что и до
339 Программам решения ODEPACK можно передать больше опций с помощью
340 переменной <literal>%ODEOPTIONS</literal>. See <link linkend="odeoptions">odeoptions</link>.
344 <title>Программы решения</title>
346 Тип задачи, которую надо решить и используемый метод зависят от
347 значения первого необязательного аргумента <varname>type</varname>,
348 который может быть одной из следующих строк:
352 <term><не задано>:</term>
355 Программа решения <literal>lsoda</literal> из пакета ODEPACK
356 вызывается по умолчанию. Она автоматически выбирает между
357 нежёстким методом прогноза-исправления Адамса
358 (predictor-corrector Adams method) и жёстким методом обратной
359 дифференциальной формулой (ОДФ) ( Backward Differentiation
360 Formula (BDF) method). Изначально она применяет нежёсткий метод и
361 динамически проверяет данные для того, чтобы решить какой метод
367 <term>"adams":</term>
370 Используется для нежёстких задач. Вызывается программа
371 решения <literal>lsode</literal> из пакета ODEPACK, и она
372 использует метод Адамса.
377 <term>"stiff":</term>
380 Это для жёстких задач. Вызывается программа решения
381 <literal>lsode</literal> из пакета ODEPACK, и она использует метод
389 <para>Адаптивный метод Рунге-Кутты 4-го порядка (RK4).</para>
396 Используется программа Шампайна и Уотса (Shampine и Watts),
397 основанная на методе Рунге-Кутты-Фелберга пары 4 и 5-го
398 порядка (RKF45). Она для нежёстких и среднежёстких задач,
399 когда получаемые вычисления не дороги. Этот метод не следует, в
400 общем случае, использовать, если пользователь требует
409 Та же программа решения, что и <literal>"rkf"</literal>, но
410 пользовательский интерфейс очень прост, т. е. программе решения
411 могут быть переданы только параметры <varname>rtol</varname> и
412 <varname>atol</varname>. Это самый простой метод для пробы.
420 Программа решения ОДУ с возможностью нахождения корней.
421 Используется программа решения <literal>lsodar</literal> из пакета
422 ODEPACK. Она является вариантом программы
423 решения <literal>lsoda</literal>, где она ищет корни заданной
424 векторной функции. См. справку по <link linkend="ode_root">ode_root</link>.
429 <term>"discrete":</term>
432 Моделирование дискретного времени. См. справку по <link linkend="ode_discrete">ode_discrete</link>.
439 <title>Примеры</title>
441 В следующем примере мы решим обыкновенное дифференциальное уравнение
442 <literal>dy/dt=y^2-y*sin(t)+cos(t)</literal> с начальным условием
443 <literal>y(0)=0</literal>. Используем программу решения по умолчанию.
445 <programlisting role="example"><![CDATA[
447 ydot=y^2-y*sin(t)+cos(t)
456 В следующем примере мы решаем уравнение <literal>dy/dt=A*y</literal>.
457 Точное решение равно <literal>y(t)=expm(A*t)*y(0)</literal>, где
458 <literal>expm</literal> - матричная экспонента.
459 Неизвестное равно матрице <literal>y(t)</literal> размером 2 на 1.
461 <programlisting role="example"><![CDATA[
465 function J=Jacobian(t,y)
472 ode("stiff",y0,t0,t,f,Jacobian)
473 // Сравним с точным решением:
477 В следующем примере мы решаем ОДУ <literal>dx/dt = A*x(t) +
480 с <literal>u(t)=sin(omega*t)</literal>.
481 Обратите внимание, что дополнительные аргументы <varname>f</varname>:
482 <literal>A</literal>, <literal>u</literal>, <literal>B</literal>,
483 <literal>omega</literal> передаются в <varname>f</varname> в списке.
485 <programlisting role="example"><![CDATA[
486 function xdot=linear(t,x,A,u,B,omega)
487 xdot=A*x+B*u(t,omega)
489 function ut=u(t,omega)
498 ode(y0,t0,t,list(linear,A,u,B,omega))
501 В следующем примере мы решим дифференциальное уравнение Риккати
502 <literal>dX/dt=A'*X + X*A - X'*B*X + C</literal>, где начальное
503 условие <literal>X(0)</literal> является единичной матрицей 2 на 2.
505 <programlisting role="example"><![CDATA[
506 function Xdot=ric(t,X,A,B,C)
507 Xdot=A'*X+X*A-X'*B*X+C
515 X = ode(y0,t0,t,list(ric,A,B,C))
518 В следующем примере мы решаме дифференциальное уравнение
519 <literal>dY/dt=A*Y</literal>, где неизвестная <literal>Y(t)</literal>
520 является матрицей 2 на 2. Точное решение равно <literal>expm</literal>
521 <literal>Y(t)=expm(A*t)</literal>, где <literal>expm</literal> --
522 матричная экспонента.
524 <programlisting role="example"><![CDATA[
525 function ydot=f(t,y,A)
532 ode(y0,t0,t,list(f,A))
533 // Сравнение с точным решением
535 ode("adams",y0,t0,t,f)
539 <title>С компилятором</title>
541 Следующий пример требует компилятор C.
543 <programlisting role="example"><![CDATA[
544 // ---------- Простое одномерное ОДУ (внешняя функция на языке C)
545 ccode=['#include <math.h>'
546 'void myode(int *n,double *t,double *y,double *ydot)'
548 ' ydot[0]=y[0]*y[0]-y[0]*sin(*t)+cos(*t);'
550 mputl(ccode,TMPDIR+'/myode.c') // создаём C-файл
552 ilib_for_link('myode','myode.c',[],'c',[],TMPDIR+'/loader.sce');
553 exec(TMPDIR+'/loader.sce') // пошаговая компоновка
557 y = ode(y0,t0,t,'myode');
561 <refsection role="see also">
562 <title>Смотрите также</title>
563 <simplelist type="inline">
565 <link linkend="ode_discrete">ode_discrete</link>
568 <link linkend="ode_root">ode_root</link>
571 <link linkend="dassl">dassl</link>
574 <link linkend="impl">impl</link>
577 <link linkend="odedc">odedc</link>
580 <link linkend="odeoptions">odeoptions</link>
583 <link linkend="csim">csim</link>
586 <link linkend="ltitr">ltitr</link>
589 <link linkend="rtitr">rtitr</link>
592 <link linkend="intg">intg</link>
597 <title>Литература</title>
599 Alan C. Hindmarsh, "lsode and lsodi, two new initial value ordinary
600 differential equation solvers", ACM-Signum newsletter, vol. 15, no. 4
605 <title>Используемые функции</title>
607 Связанные процедуры могут быть найдены в директории
608 SCI/modules/differential_equations/src/fortran:
609 lsode.f lsoda.f lsodar.f