ode45 : Unable to perform assignment because brace indexing is not supported for variables of this type
2 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Japnit Sethi
am 3 Nov. 2019
Kommentiert: Japnit Sethi
am 3 Nov. 2019
I am still not able to understand what I am doing wrong !!
My problem is to make 2 plots x1(t) and x2(t) vs t, and x1(t) vs x2(t).
I have x1(0) = x2(0) = 1, my time span is 0 to 140 seconds and
My 2 non linear differential equations are:
![Capture.PNG](https://www.mathworks.com/matlabcentral/answers/uploaded_files/246200/Capture.png)
My input u is:
![Capture u.PNG](https://www.mathworks.com/matlabcentral/answers/uploaded_files/246201/Capture%20u.png)
My code is:
clc
clear all
close all
a = 2;
b = 3;
k = 1;
% input function
u = @(x1, x2) -(x1*tanh(x1) + k*x2 + k*a*x1 + k*x1^2 + (a^2)*(x1)*tanh(x1) + a*x2*tanh(x1) + 2*a*(x1^2)*tanh(x1) + 2*x1*x2*tanh(x1) + b*x1*x2)*(1+x2^2);
tspan = [0 140];
x0 = [1, 1]; % Initial Condition
[t,x] = ode45(@(x1, x2) odefcn(x1, x2, u, a, b), tspan, x0);
%Plots
figure
plot(t,x(:,1),'-r');
grid on;
title('State Response x1(t) and x2(t) w.r.t time');
xaxis('time(s)');
yaxis('x1(t) and x2(t) in m');
hold on;
plot(t,x(:,2),'-b');
legend('x1(t)', 'x2(t)')
hold off
figure
plot(x(:,1), x(:,2), '-b');
grid on;
title('State Response x1(t) vs x2(t)');
xaxis('x1(t) in m');
yaxis('x2(t) in m');
% Function Handle
function dxdt = odefcn(x1, x2, u, a, b)
dxdt = zeros(2,1);
dxdt(1) = (a*x1 + x2)*tanh(x1);
dxdt(2) = b*x1*x2 + (1/(1 +x2^2))*u;
end
Error I am getting is:
Unable to perform assignment because the left and right sides have a different number of elements.
Error in NLST_HW5_3>odefcn (line 37)
dxdt(1) = (a*x1 + x2)*tanh(x1);
Error in NLST_HW5_3>@(x1,x2)odefcn(x1,x2,u,a,b)
Error in odearguments (line 90)
f0 = feval(ode,t0,y0,args{:}); % ODE15I sets args{1} to yp0.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Error in NLST_HW5_3 (line 12)
[t,x] = ode45(@(x1, x2) odefcn(x1, x2, u, a, b), tspan, x0);
I do not understand why the left and right hand sides have different elements since I am just inputing single value into dxdt(1) and dxdt(2), there are no matrices or anything being used.
I would be grateful if anyone can explain me the reason for error and also help solve the problem !!
0 Kommentare
Akzeptierte Antwort
Walter Roberson
am 3 Nov. 2019
Bearbeitet: Walter Roberson
am 3 Nov. 2019
Your x0 is a vector of length 2. You have two boundary conditions. ode45 is going to pass a vector of that length, 2, as the second parameter to the function, x2. The first parameter will be scalar time, x1.
Your calculation involves a*x1 (remember x1 is time) + x2 (a vector) so it gives a vector result.
You could
ode45(@(t,x) odefcn(x(1), x(2), u, a, b), etc
However notice that your u is a function handle, and that you are multiplying by u. You cannot multiply by a function handle. You can multiply by u(x1, x2) though.
4 Kommentare
Walter Roberson
am 3 Nov. 2019
reduceDifferentialOrder converts derivatives into separate auxillary variables, so that each resulting equation is individually first-order (but possibly involving variables that are standing in for higher derivatives.) reduceDifferentialOrder is specific to the Symbolic Toolbox.
The massMatrixForm and \ is a way of rewriting the equations in terms of the variables that are standing in for the derivatives. massMatrixForm is specific to the Symbolic Toolbox.
odeFunction coverts the resulting expressions involving functions into an anonymous numeric function involving input variables. It is similar to matlabFunction that is used to convert symbolic expressions into anonymous numeric functions, but has the extra step of converting the function references from x1(t) into a input parameter reference. odeFunction is specific to the Symbolic Toolbox.
Weitere Antworten (1)
Steven Lord
am 3 Nov. 2019
Bearbeitet: Steven Lord
am 3 Nov. 2019
Let's step through your code section by section.
clc
clear all
close all
Many people start their code with these three lines, but I recommend only using each one when you actually need to clear the command window, clear all variables and breakpoints, or to close all figure windows. The biggest "hammer" of all three of those is clear all, and one way to avoid needing to use it is to write functions instead of scripts. Each function has its own workspace that is set up when you call the function and destroyed when that function call finishes. Think of a function workspace as a blank piece of paper -- each time you start writing on a new piece of paper, you usually don't need to worry about what you wrote on the last piece of paper.
a = 2;
b = 3;
k = 1;
% input function
u = @(x1, x2) -(x1*tanh(x1) + k*x2 + k*a*x1 + k*x1^2 + (a^2)*(x1)*tanh(x1) + ...
a*x2*tanh(x1) + 2*a*(x1^2)*tanh(x1) + 2*x1*x2*tanh(x1) + b*x1*x2)*(1+x2^2);
I just made this one span two lines so you could see the whole thing without scrolling in the Answers interface.
tspan = [0 140];
x0 = [1, 1]; % Initial Condition
[t,x] = ode45(@(x1, x2) odefcn(x1, x2, u, a, b), tspan, x0);
So odefcn gets called with five inputs.
The first is the time input (denoted in the ode45 documentation as t.) It is a scalar.
The second is the vector of states for your ODE. Since you have two equations (and two initial conditions) this vector will have two inputs
The third is the function handle u, which itself takes two inputs.
The fourth and fifth are scalars.
%Plots
figure
plot(t,x(:,1),'-r');
grid on;
title('State Response x1(t) and x2(t) w.r.t time');
xaxis('time(s)');
yaxis('x1(t) and x2(t) in m');
There are no functions xaxis and yaxis in MATLAB. You want the xlabel and ylabel functions instead.
hold on;
plot(t,x(:,2),'-b');
legend('x1(t)', 'x2(t)')
hold off
figure
plot(x(:,1), x(:,2), '-b');
grid on;
title('State Response x1(t) vs x2(t)');
xaxis('x1(t) in m');
yaxis('x2(t) in m');
% Function Handle
function dxdt = odefcn(x1, x2, u, a, b)
dxdt = zeros(2,1);
dxdt(1) = (a*x1 + x2)*tanh(x1);
dxdt(2) = b*x1*x2 + (1/(1 +x2^2))*u;
end
Remember what ode45 will pass into your odefcn as inputs. From above:
The first is the time input (denoted in the ode45 documentation as t.) It is a scalar.
The second is the vector of states for your ODE. Since you have two equations (and two initial conditions) this vector will have two inputs
The third is the function handle u, which itself takes two inputs.
The fourth and fifth are scalars.
So (a*x1 + x2)*tanh(x1) returns a (scalar * scalar + two-element-vector) + scalar or a two element vector. You can't fit a two element vector on the right side of the equation into one element of the vector dxdt.
You have similar problems when you try to define dxdt(2). b*x1*x2 is a two element vector and you want to use array division and exponentiation (./ and .^) instead of matrix division and exponentiation (/ and ^). See this documentation page for more information.
The line where you define dxdt(2) also has a problem in your use of u. You can't multiply a number (scalar, vector, matrix, or array) by a function handle. You can multiply a number by the value you get when you evaluate a function handle, however. So you probably want to multiply by u(x2(1), x2(2)) or something similar.
9 Kommentare
Walter Roberson
am 3 Nov. 2019
dxdt(4,:) = b*x(1).*x(2) + (1./(1 + (x(2).^2))).*u(x);
That line assumes that x(1) is the boundary condition for x1(t) and that x(2) is the boundary condition for x2(t) . But x(2) pertains to x1'(t) not to x2(t)
Siehe auch
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!