программа решения дискретно-непрерывных ОДУ
yt = odedc(y0, nd, stdel, t0, t, f)
вещественный вектор-столбец (начальные условия),
y0=[y0c;y0d], где y0d
имеет nd элементов.
целое число, размер y0d
вещественный вектор с одним или двумя элементами
stdel=[h, delta] (с delta=0
в качестве значения по умолчанию).
вещественный скаляр (начальное время).
вещественный вектор-(строка), моменты времени, в которые вычислено
yt.
внешняя функция, то есть функция или символьная строка или список
с последовательностью вызова: yp = f(t,yc,yd,flag).
Эта форма внешней функции используется для передачи параметров в функцию. Она должна быть в следующем виде:
list(f, p1, p2,...)
где синтаксис функции f теперь
yp = f(t, yc, yd, flag, p1, p2,...)
f по-прежнему возвращает значение функции в
виде функции (t, yc, yd, flag, p1, p2,...),
а p1, p2,... являются параметрами функции.
она должна ссылаться на имя модуля C или fortran, в
предположении, что <f_name> является указанным именем.
Последовательность вызова Fortran должна быть
<f_name>(iflag, nc, nd, t, y, ydp)
double precision t, y(*), ydp(*)
integer iflag, nc, nd
C-синтаксис должен быть
void <f_name> (int *iflag, int *nc,
int *nd, double *t, double *y, double *ydp)
Как в случае Fortran, так и в случае C входными аргументами являются:
iflag = 0 или
1
nc = число непрерывных состояний
yc
nd = число дискретных состояний
yd
t = время
y = [yc; yd; param].
param может быть использован для получения дополнительных
аргументов, которые были указаны при вызове odedc
(y = odedc([y0c; y0d], nd, stdel, t0, t, list('fexcd', param)))
В качестве выходного аргумента ydp, процедура должна вычислять
ydp[0:nc-1] = d/dt ( yc(t) )
для iflag=0 и
ydp[0:nd-1] = yd(t+)
для iflag=1.
y = odedc([y0c;y0d], nd, [h,delta], t0, t, f) вычисляет решение
смешанной дискретно-непрерывной системы.
Состояние дискретной системы ydk
вложено в кусочно-постоянную функцию времени yd(t) в виде:
yd(t) = ydk для t в
[tk = h*(delta+k) ,
tk+1 = h*(delta+k+1) ).
Теперь моделируемые уравнения имеют вид, для t в [ tk , tk+1 ):
dyc/dt = f(t, yc(t), yd(t), 0) yc(t0) = y0c
и в моменты времени tk дискретная переменная
yd обновляется как
yd(tk+)
= f(yc(tk-), yd(tk-), 1).
Заметьте, что, используя определение yd(t), последнее уравнение даёт
ydk
= f(tk, yc(tk-), yd(tk-1), 1)
(yc непрерывно во времени :
yc(tk-) = yc(tk)).
Параметры вызова f фиксированы:
ycd = f(t,yc,yd,flag); эта функция должно возвращать либо производную
вектора yc, если flag=0, либо обновлять
yd, если flag=1.
ycd = dot(yc) должна быть вектором того же размера, что и
yc, если flag=0 и ycd = update(yd)
должна быть вектором того же размера, что и yd, если
flag=1.
t -- это вектор моментов времени, в которых вычисляется решение
y.
y -- это вектор y = [y(t(1)), y(t(2)),...].
Эта функция может быть вызвана с теми же самыми необязательными параметрами,
что и функция ode
(указанные nd и stdel даны в последовательности
вызова как второй и третий параметры). В частности, могут быть установлены флаги
интегрирования, допуски. Необязательные параметры могут быть установлены с помощью
функции odeoptions.
Внешние процедуры могут быть динамически скомпонованы (см. link).
//Линейная система с переключающимися входами deff('xdu = phis(t,x,u,flag)', 'if flag==0 then xdu = A*x + B*u; else xdu = 1 - u; end'); x0 = [1;1]; A = [-1,2;-2,-1]; B = [1;2]; u = 0; nu = 1; stdel = [1,0]; u0 = 0; t = 0:0.05:10; xu = odedc([x0;u0], nu, stdel, 0, t, phis); x = xu(1:2,:); u = xu(3,:); nx = 2; plot2d(t, x', [1:nx], '161') plot2d2('onn', t', u', [nx+1:nx+nu], '000'); //Внешняя процедура Fortran (см. fydot2.f): norm(xu-odedc([x0;u0],nu,stdel,0,t,'phis'), 1) //Дискретизированная обратная связь // // | xcdot=fc(t,xc,u) // (система) | // | y=hc(t,xc) // // // | xd+=fd(xd,y) // (обр. связь) | // | u=hd(t,xd) // deff('xcd = f(t,xc,xd,iflag)',... ['if iflag==0 then ' ' xcd = fc(t,xc,e(t)-hd(t,xd));' 'else ' ' xcd = fd(xd,hc(t,xc));' 'end']); A = [-10,2,3;4,-10,6;7,8,-10]; B = [1;1;1]; C = [1,1,1]; Ad = [1/2,1;0,1/20]; Bd = [1;1]; Cd = [1,1]; deff('st = e(t)', 'st = sin(3*t)') deff('xdot = fc(t,x,u)', 'xdot = A*x+B*u') deff('y = hc(t,x)', 'y = C*x') deff('xp = fd(x,y)', 'xp = Ad*x + Bd*y') deff('u = hd(t,x)', 'u = Cd*x') h = 0.1; t0 = 0; t = 0:0.1:2; x0c = [0;0;0]; x0d = [0;0]; nd = 2; xcd = odedc([x0c;x0d], nd, h, t0, t, f); norm(xcd - odedc([x0c;x0d], nd, h, t0, t, 'fcd1')) // Быстрое вычисление (см. fydot2.f) plot2d([t',t',t'], xcd(1:3,:)'); scf(2); plot2d2("gnn",[t',t'],xcd(4:5,:)'); scf(0); | ![]() | ![]() |