Matlab: как использовать массив в функции dsolve?

У меня есть система ОДУ из двух уравнений, но я хочу минимизировать ее, используя только одно уравнение с результатом другого.

1)

t=linspace(0,2,3);
syms x(t) y(t);
inits='x(0)=2,y(0)=0';
[x,y]=dsolve('Dx=y','Dy=(y*2)-x', inits)

x = 2*exp(t) - 2*t*exp(t);
y = -2*t*exp(t)

xx=eval(vectorize(x));

xx = 2.0000; 0; -14.7781

yy=eval(vectorize(y));

yy = 0; -5.4366; -29.5562

После того, как я получил результаты, я попытался решить это только с помощью одного уравнения и использовать массив xx в уравнении Dy.

2)

inits='y(0)=0';
[y]=dsolve('Dy=(y*2)-xx', inits);

у = хх/2 - (хх*ехр(2*т))/2

yy=eval(vectorize(y));

yy = 0; 0; 396.0397

Значения не такие, как в первом примере. Как получить тот же результат, используя массив?


person Karolis Valiulis    schedule 25.03.2013    source источник


Ответы (1)


Одна проблема заключается в том, что переменная xx не является символьной, поэтому символьный решатель рассматривает ее как константу.

Более серьезная проблема заключается в том, что вы действительно не определили, как именно вы хотите, чтобы Matlab обрабатывал значения xx как непрерывную функцию, когда это просто вектор из трех точек! Тот факт, что вы даже ожидаете, что вывод будет таким же для второго случая, указывает мне на какое-то недоразумение.

Но чтобы сделать это определенным, давайте предположим, что вы хотите, чтобы он обрабатывал xx как непрерывный сигнал ZOH (нулевой порядок). Чтобы справиться с этим символически, я считаю, что вам нужно явно построить сигнал ZOH, используя функции Хевисайда.

В качестве альтернативы вы можете решить это численно, используя, например, ode45.

t  = [0,1,2];
xx = [2, 0, -14.7781];
dydy = @(t,y) 2*y - xx(1+trunc(t));
y = ode45(dydt, [0,2], 0);

Это вернет значения yy [0, -6,39, -47,21] при значениях t [0, 1, 2] соответственно.

Это хорошо соответствует теоретическим значениям (вычисленным вручную) [0, 1-e^2, e^2-e^4] для системы ZOH.

Как видите, приведенный выше ответ гораздо больше соответствует исходному решению yy = [0, -5,4366, -29,5562]. Однако, естественно, эти две системы различаются, так как на первую подается непрерывный экспоненциальный по времени сигнал, тогда как на вторую систему подается приближение с очень грубой дискретизацией!

Вы делаете их более похожими, сэмплируя с большей скоростью (более точный временной интервал), а также интерполируя точки между выборками чем-то лучшим, чем ZOH.

Обновление: Спасибо. Может быть, вы можете помочь мне с созданием непрерывного сигнала ZOH? Как это сделать?

В приведенном выше примере я создал ZOH в своей производной функции (dydx), используя три заданные точки в векторе xx и обращаясь к ним с помощью «xx(1+trunc(t))». Это использует trunc (truncate), чтобы явно удерживать входную константу в течение времени между выборками (не целочисленными).

Поскольку ваш ODE является линейным, вы также можете использовать функцию Matlab «lsim()», которая позволяет вам напрямую указывать вектор времени и входной вектор, а также напрямую указывать тип входной интерполяции (включая ZOH, который на самом деле является дефолт).

Например:

t=[0,1,2]
x=[2,0,-2*e^2]
num=-1
den=[1,-2]
mytf = tf(num,den)
y = lsim(mytf,x,t,0,'zoh');

Как и в случае с моим предыдущим численным решением ode45, это дает идентичное решение,

y = [0.00000; -6.38906; -47.20909]

Обновление (еще раз) Спасибо. Может быть, вы можете помочь мне с созданием непрерывного сигнала ZOH? Как это сделать?

Re символический решатель. У меня нет доступа к символьной библиотеке Matlab, но если вы действительно хотите использовать символьный решатель, то, как я объяснял ранее, вы можете построить сигнал ZOH с непрерывным временем, используя функцию heaviside (единичный шаг). Что-то вроде следующего должно сделать это:

syms xzoh(t)
xzoh = xx(1)*heaviside(t) + (xx(2)-xx(1))*heaviside(t-1) + (xx(3)-xx(2))*heaviside(t-2)
person Stuart    schedule 27.03.2013
comment
Спасибо. Может быть, вы можете помочь мне с созданием непрерывного сигнала ZOH? Как это сделать? - person Karolis Valiulis; 09.04.2013
comment
Затем я пишу mytf = tf(num,den) в Matlab, получаю ошибку: Неопределенная функция 'tf' для входных аргументов типа 'double' - person Karolis Valiulis; 09.04.2013
comment
Он должен работать. Взгляните на документацию по tf() здесь. mathworks.com.au/help/control/ref/tf.html< /а> - person Stuart; 09.04.2013
comment
Кроме того, что возвращает ваша копия Matlab, если вы набираете help tf в командной строке? - person Stuart; 09.04.2013
comment
Пишет документацию функции tf - person Karolis Valiulis; 09.04.2013
comment
Не могу проверить, у меня октава. Но функция tf() должна работать одинаково как для Octave, так и для Matlab. Можете ли вы подтвердить с помощью вашей документации, что tf(num,den) является допустимым синтаксисом. - person Stuart; 09.04.2013
comment
Предполагая, что tf(num,den) является допустимым синтаксисом в вашей версии Matlab, дважды проверьте правильность векторов num и den. num и den должны быть векторами-строками. Попробуйте ввести их напрямую, а не вырезать и вставить, и посмотрите, имеет ли это какое-то значение. - person Stuart; 09.04.2013
comment
Попробуйте ввести num=[0, -1] и den=[1, -2] и посмотрите, работает ли это с tf(). - person Stuart; 09.04.2013
comment
Я переустановил Matlab, и функция работает хорошо. Кажется, что-то не так с каталогами. Я также попытался решить это немного по-другому. Я написал функцию: f = @(new_x) interp1(t,xx, new_x); Он дает точные результаты в виде вектора xx. Но когда я добавляю его в dsolve, я получаю некоторые ошибки. f = @(new_x) interp1(t,xx, new_x); [y]=dsolve('Dy=(y*2)-f', inits); yy = eval (векторизация (y)); ??? Ошибка при использовании ==> eval Неопределенная функция или метод «rdivide» для входных аргументов типа «function_handle». - person Karolis Valiulis; 10.04.2013