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) 2016 - Samuel GOUGEON
8 * Copyright (C) 2012 - 2016 - Scilab Enterprises
10 * This file is hereby licensed under the terms of the GNU GPL v2.0,
11 * pursuant to article 5.3.4 of the CeCILL v.2.1.
12 * This file was originally licensed under the terms of the CeCILL v2.1,
13 * and continues to be available under such terms.
14 * For more information, see the COPYING file which you should have received
15 * along with this program.
18 <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">
20 <refname>ode</refname>
22 программа решения обыкновенных дифференциальных уравнений
26 <title>Последовательность вызова</title>
29 [y, w, iw] = ode([type,]y0, t0, t [,rtol [,atol]],f [,jac] [,w, iw])
30 [y, rd, w, iw] = ode("root", y0, t0, t [,rtol [,atol]], f [,jac], ng, g [, w, iw])
31 y = ode("discrete", y0, k0, kvect, f)
34 <refsection role="parameters">
35 <title>Аргументы</title>
41 вектор или матрица вещественных значений, начальные условия.
49 вещественный скаляр, начальное время.
57 вещественный вектор, моменты времени для которых находится решение.
65 внешняя функция (функция, строка или список),
66 правая сторона дифференциального уравнения.
74 строка, тип используемой программы решения. Имеются следующие типы
75 программ решения: <literal>"adams"</literal>,
76 <literal>"stiff"</literal>, <literal>"rk"</literal>,
77 <literal>"rkf"</literal>, <literal>"fix"</literal>,
78 <literal>"discrete"</literal>, <literal>"roots"</literal>.
83 <term>atol, rtol</term>
86 absolute and relative tolerances on the final solution
87 <varname>y</varname> (decimal numbers). If each is a
88 single value, it applies
89 to each component of <varname>y</varname>. Otherwise,
90 it must be a vector of same size as size(y), and
91 is applied element-wise to <varname>y</varname>.
99 внешняя функция (функция, строка или список), якобиан функции
100 <varname>f</varname>.
107 <para>целое число.</para>
113 <para>внешняя функция (функция, символьная строка или список).</para>
119 <para>целое число (начальное время).</para>
125 <para>целочисленный вектор.</para>
131 <para>вещественный вектор или матрица (ВЫХОДНАЯ).</para>
137 <para>вещественный вектор (ВЫХОДНОЙ).</para>
143 <para>вещественные векторы (ВХОДНЫЕ/ВЫХОДНЫЕ).
144 See <link linkend="ode_optional_output">ode() optional output</link>
150 <refsection role="description">
151 <title>Описание</title>
153 <function>ode</function> решает явные обыкновенные
154 дифференциальные уравнения, определённые как:
160 \dfrac{dy}{dt} = f(t,y)\\
167 Это интерфейс для различных программ решения, в частности для ODEPACK.
170 В данной справке описывается использование
171 <function>ode</function> для стандартных явных систем ОДУ.
174 Самый простой способ вызова <function>ode</function>:
175 <code>y = ode(y0, t0, t, f)</code>, где <varname>y0</varname> -
176 вектор начальных условий, <varname>t0</varname> - начальное время,
177 <varname>t</varname> - вектор моментов времени, для которых вычисляется
178 решение <varname>y</varname> и <varname>y</varname> - матрица векторов
179 решения <literal>y=[y(t(1)),y(t(2)),...]</literal>.
182 Входной аргумент <varname>f</varname> определяет правую сторону
183 дифференциального уравнения первого порядка. Этот аргумент является
184 функцией с определённым заголовком.
189 Если <varname>f</varname> является Scilab-функцией, то её
190 последовательность вызова должна быть:
196 где <literal>t</literal> - вещественный скаляр (время), а
197 <varname>y</varname> - вещественный вектор (состояние) и
198 <varname>ydot</varname> - вещественный вектор (производная первого
204 Если <varname>f</varname> - строка, то это - имя компилированной
205 процедуры Fortran или функции C. Например, если вызывается
206 <code>ode(y0, t0, t, "fex")</code>, то вызывается подпрограмма
207 <literal>fex</literal>.
210 Процедура Fortran должна иметь заголовок:
216 где <varname>n</varname> - целое число, <varname>t</varname> --
217 скаляр двойной точности, <varname>y</varname> и
218 <varname>ydot</varname> - векторы двойной точности.
221 Функция C должна иметь заголовок:
224 fex(int *n,double *t,double *y,double *ydot)
227 где <varname>t</varname> - время, <varname>y</varname> - состояние,
228 а <varname>ydot</varname> - производная состояния (dy/dt).
231 Эта внешняя функция может быть собрана способом, независящим от ОС,
232 используя <link linkend="ilib_for_link">ilib_for_link</link> и
233 динамически связана с Scilab с помощью функции
234 <link linkend="link">link</link>.
239 Может случиться, что симулятору <varname>f</varname> потребуются
240 дополнительные аргументы. В этом случае можно использовать следующую
241 возможность. Аргумент <varname>f</varname> может также быть
242 списком <literal>lst=list(simuf,u1,u2,...un)</literal>, где
243 <literal>simuf</literal> является Scilab-функцией с синтаксисом:
244 <literal>ydot = f(t,y,u1,u2,...,un)</literal>, а
245 <literal>u1</literal>, <literal>u2</literal>, ...,
246 <literal>un</literal> - дополнительные аргументы, автоматически
247 передаваемые симулятору <literal>simuf</literal>.
252 Функция <varname>f</varname> может возвращать вместо
253 вектора матрицу<literal>p x q</literal>. С этой матричной нотацией
254 решается система <literal>n=p+q</literal> ОДУ
255 <literal>dY/dt=F(t,Y)</literal>, где <literal>Y</literal> - матрица
256 <literal>p x q</literal>. Затем начальные условия,
257 <literal>Y0</literal>, должны быть так же матрицей
258 <literal>p x q</literal>, а результат <function>ode</function> - матрицей
259 <literal>p x q(T+1)</literal>
260 <literal>[Y(t_0),Y(t_1),...,Y(t_T)]</literal>.
263 Допуски <varname>rtol</varname> и <varname>atol</varname> являются
264 порогами для относительной и абсолютной оценённых ошибок. Оценённая
265 ошибка <literal>y(i)</literal> равна:
266 <literal>rtol(i)*abs(y(i))+atol(i)</literal> и интегрирование выполняется
267 пока эта ошибка мала для каждого из элементов состояния. Если
268 <varname>rtol</varname> и/или <varname>atol</varname> является
269 константой, то <literal>rtol(i)</literal> и/или <literal>atol(i)</literal>
270 являются набором констант. Значения по умолчанию для
271 <varname>rtol</varname> и <varname>atol</varname> соответственно равны
272 <literal>rtol=1.d-5</literal> и <literal>atol=1.d-7</literal> для
273 большинства программ решения, а для <literal>"rfk"</literal> и
274 <literal>"fix"</literal> <literal>rtol=1.d-3</literal> и
275 <literal>atol=1.d-4</literal>.
278 Для жёстких задач лучше указывать якобиан функции правой стороны в
279 качестве необязательного аргумента <varname>jac</varname>.
280 Якобиан является внешней функцией, т. е. функцией со специальным
281 синтаксисом, либо именем процедуры Fortran или функции C
282 (символьная строка) с определённой последовательностью вызова, либо
288 Если <varname>jac</varname> является функцией, то синтаксис должен
289 быть <literal>J=jac(t,y)</literal>, где <literal>t</literal> --
290 вещественный скаляр (время), а <varname>y</varname> - вещественный
291 вектор (состояние). Результирующая матрица <literal>J</literal>
292 должна вычислять df/dx, т. е. <literal>J(k,i) = dfk/dxi</literal>, где
293 <literal>fk</literal> - <literal>k</literal>-тый элемент
294 <varname>f</varname>.
299 Если <varname>jac</varname> является символьной строкой, то она
300 ссылается на имя процедуры Fortran или функции C.
303 Процедура Fortran должна иметь заголовок:
306 subroutine fex(n,t,y,ml,mu,J,nrpd)
308 double precision t,y(*),J(*)
311 Функция C должна иметь заголовок:
314 void fex(int *n,double *t,double *y,int *ml,int *mu,double *J,int *nrpd,)
317 В большинстве случаев не нужно ссылаться на <literal>ml</literal>,
318 <literal>mu</literal> и <literal>nrpd</literal>.
323 Если <varname>jac</varname> является списком, то для
324 <varname>f</varname> применяются те же договорённости.
329 Необязательные аргументы <varname>w</varname> и
330 <varname>iw</varname> являются векторами для хранения информации,
331 возвращаемой подпрограммой интегрирования (см. <link linkend="ode_optional_output">ode_optional_output</link>).
332 Когда эти векторы указываются с правой стороны <function>ode</function>,
333 интегрирование начинается заново с теми же параметрами, что и до
337 Программам решения ODEPACK можно передать больше опций с помощью
338 переменной <literal>%ODEOPTIONS</literal>. See <link linkend="odeoptions">odeoptions</link>.
342 <title>Программы решения</title>
344 Тип задачи, которую надо решить и используемый метод зависят от
345 значения первого необязательного аргумента <varname>type</varname>,
346 который может быть одной из следующих строк:
350 <term><не задано>:</term>
353 Программа решения <literal>lsoda</literal> из пакета ODEPACK
354 вызывается по умолчанию. Она автоматически выбирает между
355 нежёстким методом прогноза-исправления Адамса
356 (predictor-corrector Adams method) и жёстким методом обратной
357 дифференциальной формулой (ОДФ) ( Backward Differentiation
358 Formula (BDF) method). Изначально она применяет нежёсткий метод и
359 динамически проверяет данные для того, чтобы решить какой метод
365 <term>"adams":</term>
368 Используется для нежёстких задач. Вызывается программа
369 решения <literal>lsode</literal> из пакета ODEPACK, и она
370 использует метод Адамса.
375 <term>"stiff":</term>
378 Это для жёстких задач. Вызывается программа решения
379 <literal>lsode</literal> из пакета ODEPACK, и она использует метод
387 <para>Адаптивный метод Рунге-Кутты 4-го порядка (RK4).</para>
394 Используется программа Шампайна и Уотса (Shampine и Watts),
395 основанная на методе Рунге-Кутты-Фелберга пары 4 и 5-го
396 порядка (RKF45). Она для нежёстких и среднежёстких задач,
397 когда получаемые вычисления не дороги. Этот метод не следует, в
398 общем случае, использовать, если пользователь требует
407 Та же программа решения, что и <literal>"rkf"</literal>, но
408 пользовательский интерфейс очень прост, т. е. программе решения
409 могут быть переданы только параметры <varname>rtol</varname> и
410 <varname>atol</varname>. Это самый простой метод для пробы.
418 Программа решения ОДУ с возможностью нахождения корней.
419 Используется программа решения <literal>lsodar</literal> из пакета
420 ODEPACK. Она является вариантом программы
421 решения <literal>lsoda</literal>, где она ищет корни заданной
422 векторной функции. См. справку по <link linkend="ode_root">ode_root</link>.
427 <term>"discrete":</term>
430 Моделирование дискретного времени. См. справку по <link linkend="ode_discrete">ode_discrete</link>.
436 <refsection role="examples">
437 <title>Примеры</title>
439 В следующем примере мы решим обыкновенное дифференциальное уравнение
440 <literal>dy/dt=y^2-y*sin(t)+cos(t)</literal> с начальным условием
441 <literal>y(0)=0</literal>. Используем программу решения по умолчанию.
443 <programlisting role="example"><![CDATA[
445 ydot=y^2-y*sin(t)+cos(t)
454 В следующем примере мы решаем уравнение <literal>dy/dt=A*y</literal>.
455 Точное решение равно <literal>y(t)=expm(A*t)*y(0)</literal>, где
456 <literal>expm</literal> - матричная экспонента.
457 Неизвестное равно матрице <literal>y(t)</literal> размером 2 на 1.
459 <programlisting role="example"><![CDATA[
463 function J=Jacobian(t,y)
470 ode("stiff",y0,t0,t,f,Jacobian)
471 // Сравним с точным решением:
475 В следующем примере мы решаем ОДУ <literal>dx/dt = A*x(t) +
478 с <literal>u(t)=sin(omega*t)</literal>.
479 Обратите внимание, что дополнительные аргументы <varname>f</varname>:
480 <literal>A</literal>, <literal>u</literal>, <literal>B</literal>,
481 <literal>omega</literal> передаются в <varname>f</varname> в списке.
483 <programlisting role="example"><![CDATA[
484 function xdot=linear(t,x,A,u,B,omega)
485 xdot=A*x+B*u(t,omega)
487 function ut=u(t,omega)
496 ode(y0,t0,t,list(linear,A,u,B,omega))
499 В следующем примере мы решим дифференциальное уравнение Риккати
500 <literal>dX/dt=A'*X + X*A - X'*B*X + C</literal>, где начальное
501 условие <literal>X(0)</literal> является единичной матрицей 2 на 2.
503 <programlisting role="example"><![CDATA[
504 function Xdot=ric(t,X,A,B,C)
505 Xdot=A'*X+X*A-X'*B*X+C
513 X = ode(y0,t0,t,list(ric,A,B,C))
516 В следующем примере мы решаме дифференциальное уравнение
517 <literal>dY/dt=A*Y</literal>, где неизвестная <literal>Y(t)</literal>
518 является матрицей 2 на 2. Точное решение равно <literal>expm</literal>
519 <literal>Y(t)=expm(A*t)</literal>, где <literal>expm</literal> --
520 матричная экспонента.
522 <programlisting role="example"><![CDATA[
523 function ydot=f(t,y,A)
530 ode(y0,t0,t,list(f,A))
531 // Сравнение с точным решением
533 ode("adams",y0,t0,t,f)
537 <title>С компилятором</title>
539 Следующий пример требует компилятор C.
541 <programlisting role="example"><![CDATA[
542 // ---------- Простое одномерное ОДУ (внешняя функция на языке C)
543 ccode=['#include <math.h>'
544 'void myode(int *n,double *t,double *y,double *ydot)'
546 ' ydot[0]=y[0]*y[0]-y[0]*sin(*t)+cos(*t);'
548 mputl(ccode,TMPDIR+'/myode.c') // создаём C-файл
550 ilib_for_link('myode','myode.c',[],'c',[],TMPDIR+'/loader.sce');
551 exec(TMPDIR+'/loader.sce') // пошаговая компоновка
555 y = ode(y0,t0,t,'myode');
559 <refsection role="see also">
560 <title>Смотрите также</title>
561 <simplelist type="inline">
563 <link linkend="odeoptions">odeoptions</link>
566 <link linkend="ode_optional_output">ode_optional_output</link>
569 <link linkend="ode_root">ode_root</link>
572 <link linkend="ode_discrete">ode_discrete</link>
575 <link linkend="dassl">dassl</link>
578 <link linkend="impl">impl</link>
581 <link linkend="odedc">odedc</link>
584 <link linkend="csim">csim</link>
587 <link linkend="ltitr">ltitr</link>
590 <link linkend="rtitr">rtitr</link>
593 <link linkend="intg">intg</link>
597 <refsection role="bibliography">
598 <title>Литература</title>
600 Alan C. Hindmarsh, "lsode and lsodi, two new initial value ordinary
601 differential equation solvers", ACM-Signum newsletter, vol. 15, no. 4
605 <refsection role="references">
606 <title>Используемые функции</title>
608 Связанные процедуры могут быть найдены в директории
609 SCI/modules/differential_equations/src/fortran:
610 lsode.f lsoda.f lsodar.f