Please note that the recommended version of Scilab is 2025.0.0. This page might be outdated.
See the recommended documentation of this function
ode
программа решения обыкновенных дифференциальных уравнений
Последовательность вызова
y = ode(y0, t0, t, f) [y, w, iw] = ode([type,]y0, t0, t [,rtol [,atol]],f [,jac] [,w, iw]) [y, rd, w, iw] = ode("root", y0, t0, t [,rtol [,atol]], f [,jac], ng, g [, w, iw]) y = ode("discrete", y0, k0, kvect, f)
Аргументы
- y0
вектор или матрица вещественных значений, начальные условия.
- t0
вещественный скаляр, начальное время.
- t
вещественный вектор, моменты времени для которых находится решение.
- f
внешняя функция (функция, строка или список), правая сторона дифференциального уравнения.
- type
строка, тип используемой программы решения. Имеются следующие типы программ решения:
"adams"
,"stiff"
,"rk"
,"rkf"
,"fix"
,"discrete"
,"roots"
.- rtol
вещественная константа либо вещественный вектор того же размера, что и
y
, относительный допуск.- atol
вещественная константа либо вещественный вектор того же размера, что и
y
, абсолютный допуск.- jac
внешняя функция (функция, строка или список), якобиан функции
f
.- w, iw
вещественные векторы (ВХОДНЫЕ/ВЫХОДНЫЕ).
- ng
целое число.
- g
внешняя функция (функция, символьная строка или список).
- k0
целое число (начальное время).
- kvect
целочисленный вектор.
- y
вещественный вектор или матрица (ВЫХОДНАЯ).
- rd
вещественный вектор (ВЫХОДНОЙ).
Описание
ode
решает явные обыкновенные
дифференциальные уравнения, определённые как:
Это интерфейс для различных программ решения, в частности для ODEPACK.
В данной справке описывается использование
ode
для стандартных явных систем ОДУ.
Самый простой способ вызова ode
:
y = ode(y0, t0, t, f)
, где y0
-
вектор начальных условий, t0
- начальное время,
t
- вектор моментов времени, для которых вычисляется
решение y
и y
- матрица векторов
решения y=[y(t(1)),y(t(2)),...]
.
Входной аргумент f
определяет правую сторону
дифференциального уравнения первого порядка. Этот аргумент является
функцией с определённым заголовком.
Если
f
является Scilab-функцией, то её последовательность вызова должна быть:ydot = f(t,y)
где
t
- вещественный скаляр (время), аy
- вещественный вектор (состояние) иydot
- вещественный вектор (производная первого порядка dy/dt).Если
f
- строка, то это - имя компилированной процедуры Fortran или функции C. Например, если вызываетсяode(y0, t0, t, "fex")
, то вызывается подпрограммаfex
.Процедура Fortran должна иметь заголовок:
fex(n,t,y,ydot)
где
n
- целое число,t
-- скаляр двойной точности,y
иydot
- векторы двойной точности.Функция C должна иметь заголовок:
fex(int *n,double *t,double *y,double *ydot)
где
t
- время,y
- состояние, аydot
- производная состояния (dy/dt).Эта внешняя функция может быть собрана способом, независящим от ОС, используя ilib_for_link и динамически связана с Scilab с помощью функции link.
Может случиться, что симулятору
f
потребуются дополнительные аргументы. В этом случае можно использовать следующую возможность. Аргументf
может также быть спискомlst=list(simuf,u1,u2,...un)
, гдеsimuf
является Scilab-функцией с синтаксисом:ydot = f(t,y,u1,u2,...,un)
, аu1
,u2
, ...,un
- дополнительные аргументы, автоматически передаваемые симуляторуsimuf
.
Функция f
может возвращать вместо
вектора матрицуp x q
. С этой матричной нотацией
решается система n=p+q
ОДУ
dY/dt=F(t,Y)
, где Y
- матрица
p x q
. Затем начальные условия,
Y0
, должны быть так же матрицей
p x q
, а результат ode
- матрицей
p x q(T+1)
[Y(t_0),Y(t_1),...,Y(t_T)]
.
Допуски rtol
и atol
являются
порогами для относительной и абсолютной оценённых ошибок. Оценённая
ошибка y(i)
равна:
rtol(i)*abs(y(i))+atol(i)
и интегрирование выполняется
пока эта ошибка мала для каждого из элементов состояния. Если
rtol
и/или atol
является
константой, то rtol(i)
и/или atol(i)
являются набором констант. Значения по умолчанию для
rtol
и atol
соответственно равны
rtol=1.d-5
и atol=1.d-7
для
большинства программ решения, а для "rfk"
и
"fix"
rtol=1.d-3
и
atol=1.d-4
.
Для жёстких задач лучше указывать якобиан функции правой стороны в
качестве необязательного аргумента jac
.
Якобиан является внешней функцией, т. е. функцией со специальным
синтаксисом, либо именем процедуры Fortran или функции C
(символьная строка) с определённой последовательностью вызова, либо
списком.
Если
jac
является функцией, то синтаксис должен бытьJ=jac(t,y)
, гдеt
-- вещественный скаляр (время), аy
- вещественный вектор (состояние). Результирующая матрицаJ
должна вычислять df/dx, т. е.J(k,i) = dfk/dxi
, гдеfk
-k
-тый элементf
.Если
jac
является символьной строкой, то она ссылается на имя процедуры Fortran или функции C.Процедура Fortran должна иметь заголовок:
subroutine fex(n,t,y,ml,mu,J,nrpd) integer n,ml,mu,nrpd double precision t,y(*),J(*)
Функция C должна иметь заголовок:
void fex(int *n,double *t,double *y,int *ml,int *mu,double *J,int *nrpd,)
В большинстве случаев не нужно ссылаться на
ml
,mu
иnrpd
.Если
jac
является списком, то дляf
применяются те же договорённости.
Необязательные аргументы w
и
iw
являются векторами для хранения информации,
возвращаемой подпрограммой интегрирования (см. ode_optional_output).
Когда эти векторы указываются с правой стороны ode
,
интегрирование начинается заново с теми же параметрами, что и до
остановки.
Программам решения ODEPACK можно передать больше опций с помощью
переменной %ODEOPTIONS
. See odeoptions.
Программы решения
Тип задачи, которую надо решить и используемый метод зависят от
значения первого необязательного аргумента type
,
который может быть одной из следующих строк:
- <не задано>:
Программа решения
lsoda
из пакета ODEPACK вызывается по умолчанию. Она автоматически выбирает между нежёстким методом прогноза-исправления Адамса (predictor-corrector Adams method) и жёстким методом обратной дифференциальной формулой (ОДФ) ( Backward Differentiation Formula (BDF) method). Изначально она применяет нежёсткий метод и динамически проверяет данные для того, чтобы решить какой метод использовать.- "adams":
Используется для нежёстких задач. Вызывается программа решения
lsode
из пакета ODEPACK, и она использует метод Адамса.- "stiff":
Это для жёстких задач. Вызывается программа решения
lsode
из пакета ODEPACK, и она использует метод ОДФ.- "rk":
Адаптивный метод Рунге-Кутты 4-го порядка (RK4).
- "rkf":
Используется программа Шампайна и Уотса (Shampine и Watts), основанная на методе Рунге-Кутты-Фелберга пары 4 и 5-го порядка (RKF45). Она для нежёстких и среднежёстких задач, когда получаемые вычисления не дороги. Этот метод не следует, в общем случае, использовать, если пользователь требует высокую точность.
- "fix":
Та же программа решения, что и
"rkf"
, но пользовательский интерфейс очень прост, т. е. программе решения могут быть переданы только параметрыrtol
иatol
. Это самый простой метод для пробы.- "root":
Программа решения ОДУ с возможностью нахождения корней. Используется программа решения
lsodar
из пакета ODEPACK. Она является вариантом программы решенияlsoda
, где она ищет корни заданной векторной функции. См. справку по ode_root.- "discrete":
Моделирование дискретного времени. См. справку по ode_discrete.
Примеры
В следующем примере мы решим обыкновенное дифференциальное уравнение
dy/dt=y^2-y*sin(t)+cos(t)
с начальным условием
y(0)=0
. Используем программу решения по умолчанию.
function ydot=f(t, y) ydot=y^2-y*sin(t)+cos(t) endfunction y0=0; t0=0; t=0:0.1:%pi; y = ode(y0,t0,t,f); plot(t,y)
В следующем примере мы решаем уравнение dy/dt=A*y
.
Точное решение равно y(t)=expm(A*t)*y(0)
, где
expm
- матричная экспонента.
Неизвестное равно матрице y(t)
размером 2 на 1.
function ydot=f(t, y) ydot=A*y endfunction function J=Jacobian(t, y) J=A endfunction A=[10,0;0,-1]; y0=[0;1]; t0=0; t=1; ode("stiff",y0,t0,t,f,Jacobian) // Сравним с точным решением: expm(A*t)*y0
В следующем примере мы решаем ОДУ dx/dt = A*x(t) +
B*u(t)
с u(t)=sin(omega*t)
.
Обратите внимание, что дополнительные аргументы f
:
A
, u
, B
,
omega
передаются в f
в списке.
function xdot=linear(t, x, A, u, B, omega) xdot=A*x+B*u(t,omega) endfunction function ut=u(t, omega) ut=sin(omega*t) endfunction A=[1 1;0 2]; B=[1;1]; omega=5; y0=[1;0]; t0=0; t=[0.1,0.2,0.5,1]; ode(y0,t0,t,list(linear,A,u,B,omega))
В следующем примере мы решим дифференциальное уравнение Риккати
dX/dt=A'*X + X*A - X'*B*X + C
, где начальное
условие X(0)
является единичной матрицей 2 на 2.
function Xdot=ric(t, X, A, B, C) Xdot=A'*X+X*A-X'*B*X+C endfunction A=[1,1;0,2]; B=[1,0;0,1]; C=[1,0;0,1]; y0=eye(A); t0=0; t=0:0.1:%pi; X = ode(y0,t0,t,list(ric,A,B,C))
В следующем примере мы решаме дифференциальное уравнение
dY/dt=A*Y
, где неизвестная Y(t)
является матрицей 2 на 2. Точное решение равно expm
Y(t)=expm(A*t)
, где expm
--
матричная экспонента.
С компилятором
Следующий пример требует компилятор C.
// ---------- Простое одномерное ОДУ (внешняя функция на языке C) ccode=['#include <math.h>' 'void myode(int *n,double *t,double *y,double *ydot)' '{' ' ydot[0]=y[0]*y[0]-y[0]*sin(*t)+cos(*t);' '}'] mputl(ccode,TMPDIR+'/myode.c') // создаём C-файл // Компилируем ilib_for_link('myode','myode.c',[],'c',[],TMPDIR+'/loader.sce'); exec(TMPDIR+'/loader.sce') // пошаговая компоновка y0=0; t0=0; t=0:0.1:%pi; y = ode(y0,t0,t,'myode');
Смотрите также
- ode_discrete — программа решения обыкновенных дифференциальных уравнений, моделирование дискретного времени
- ode_root — программа решения обыкновенных дифференциальных уравнений с поиском корней
- dassl — дифференциальное алгебраическое уравнение
- impl — дифференциальное алгебраическое уравнение
- odedc — программа решения дискретно-непрерывных ОДУ
- odeoptions — установка опций для программ решения ОДУ
- csim — simulation (time response) of linear system
- ltitr — discrete time response (state space)
- rtitr — discrete time response (transfer matrix)
- intg — определённый интеграл
Литература
Alan C. Hindmarsh, "lsode and lsodi, two new initial value ordinary differential equation solvers", ACM-Signum newsletter, vol. 15, no. 4 (1980), pp. 10-11.
Используемые функции
Связанные процедуры могут быть найдены в директории SCI/modules/differential_equations/src/fortran: lsode.f lsoda.f lsodar.f
Report an issue | ||
<< numdiff | Дифференциальное счисление, интегрирование | ode_discrete >> |