The "solve" function in MATLAB is not solving my equations correctly - matlab

I have a for loop creating a super equation that is the sum of a group of equations that could use variables A1 to A7. Each looping would increase the amount of As, which represents the amount of equations in that group. The super equation would then be solved.
cb = 1/5.25; %reverse of aspect ratio
cla = 2*pi; %the slope of lift vs aoa
aa = 5*pi/180; % radiant value of 5 degree
N = [3 5 7]; %list of possible N value
syms a1 a2 a3 a4 a5 a6 a7 temp
A = [a1 a2 a3 a4 a5 a6 a7]; %list of possible An
eqn = A; %list of possible equations
solved = A;
for i = 1:3
counter = N(i);
Acou = A(1:counter);
anslist = Acou;
eqncou = eqn(1:counter);
spandiv = (pi/2)/counter;
for j = 1:counter
for k = 1:counter
if rem(j,2)~=0
anslist(k) = A(k)*(sin(k*(spandiv*j)))+0.25*cb*cla*sin(k*(spandiv*j))/sin(spandiv*j);
else
anslist(k) = 0;
end
temp = temp + anslist(k);
end
eqncou(j) = temp == 0.25*cb*2*pi*aa;
end
solve(eqncou)
end
However, instead of seeing a solution in a1 to a3 or a5 or a7, a3, a5, and a7 are always missing from the solutions and instead, there is a temp in the solution. Could you tell me why?
ans =
struct with fields:
a1: [1×1 sym]
a2: [1×1 sym]
temp: [1×1 sym]
ans =
struct with fields:
a1: [1×1 sym]
a2: [1×1 sym]
a3: [1×1 sym]
a4: [1×1 sym]
temp: [1×1 sym]
ans =
struct with fields:
a1: [1×1 sym]
a2: [1×1 sym]
a3: [1×1 sym]
a4: [1×1 sym]
a5: [1×1 sym]
a6: [1×1 sym]
temp: [1×1 sym]
I want the output to just solve whatever given variable (A1 to A3, A1 to A5, etc), and don't output the temp. Is it possible?
EDIT: I have changed the code to force the solver to spit out the variable in A. However, it seems like my plan to construct an expression using for loops, then change that expression into an equation and put it into the solver has failed. The solver interprets my "temp" as a variable, rather than a solution:
cb = 1/5.25; %reverse of aspect ratio
cla = 2*pi; %the slope of lift vs aoa
aa = 5*pi/180; % radiant value of 5 degree
N = [3 5 7]; %list of possible N value
syms a1 a2 a3 a4 a5 a6 a7 temp
A = [a1 a2 a3 a4 a5 a6 a7]; %list of possible An
eqn = A; %list of possible equations
solved = A;
for i = 1:3
counter = N(i);
Acou = A(1:counter);
anslist = Acou;
eqncou = eqn(1:counter);
spandiv = (pi/2)/counter;
solved = Acou;
for j = 1:counter
for k = 1:counter
if rem(j,2)~=0
anslist(k) = A(k)*(sin(k*(spandiv*j)))+0.25*cb*cla*sin(k*(spandiv*j))/sin(spandiv*j);
else
anslist(k) = 0;
end
temp = temp + anslist(k);
end
eqncou(j) = temp == 0.25*cb*2*pi*aa;
end
Asol = vpasolve(eqncou, Acou);
if counter == 3
Asol.a1
Asol.a2
Asol.a3
end
end
The result for the first reiteration looks like this:
ans =
0.00000000000000014141003182998759606675517428884*temp + 0.0000000000000001598784692421062131291124254426
ans =
- 1.1547005383792516106614175041608*temp - 1.6047060746495452365715355746874
ans =
0
How to make 'temp' not a variable?

This should work. I don't if as expected, since your question is not entirely clear yet. Notice that all constants (as cb, cla) were declared as a symbolic object, to avoid fraction approximations of real numbers. The temp variable is initially declared as (symbolic) zero, to create the equation using the for loops.
Clearly, you should assign a variable to the solve command, in order to access the solution to the equations. You can also try to simplify the solution, you find it suitable.
cb = sym('1')/5.25; %reverse of aspect ratio
cla = 2*sym('pi'); %the slope of lift vs aoa
aa = 5*sym('pi')/180; % radiant value of 5 degree
N = [3 5 7]; %list of possible N value
syms a1 a2 a3 a4 a5 a6 a7
A = [a1 a2 a3 a4 a5 a6 a7]; %list of possible An
eqn = A; %list of possible equations
solved = A;
for i = 1:3
counter = N(i)
Acou = A(1:counter);
anslist = Acou;
eqncou = eqn(1:counter);
spandiv = (sym('pi')/2)/counter;
temp = sym('0');
for j = 1:counter
for k = 1:counter
if rem(j,2)~=0
anslist(k) = A(k)*(sin(k*(spandiv*j)))+0.25*cb*cla*sin(k*(spandiv*j))/sin(spandiv*j);
else
anslist(k) = 0;
end
temp = temp + anslist(k);
end
eqncou(j) = temp == 0.25*cb*2*pi*aa;
end
solve(eqncou,Acou)
end

Related

Using vectorization to get a specific matrix output from two vectors

I wanted to know if there is a efficient way using MATLAB vectorization to generate a specific matrix from two vectors.
Suppose the vectors are
x = [u v]
y = [a1 a2 a3 b1 b2 b3]
where u, v, a1, a2, a3, b1, b2, b3 are some real numbers.
The 2-column matrix that I wish to generate using these vectors is
M = [u a1;
u a2;
u a3;
v a1;
v a2;
v a3;
u b1;
u b2;
u b3;
v b1;
v b2;
v b3]
In general, the length of x can be anything and the length of y is multiple of 3. Here is the code that I have now, but I think there should some better way (that possibly avoids the use of for-loop):
M = [];
Y = reshape(y, 3, []);
for j = 1:size(Y, 2)
[a, b] = meshgrid(x, Y(:, j));
L = [a(:) b(:)];
M = [M; L];
end
A solution using repmat and repelem :
M = [repmat(repelem(x(:),3),numel(y)/3,1) , ...
reshape(repmat(reshape(y,3,[]),numel(x),1),[],1)];
you have a pretty strange order in M. Is that order important? if not, or if you are happy to fix the order later yourself I have two solutions:
1) code
[a,b] = meshgrid(x,y);
M = [a(:) b(:)]
will give you:
M = [
u a1
u a2
u a3
u b1
u b2
u b3
v a1
v a2
v a3
v b1
v b2
v b3]
and
2) code M = combvec(x, y)' gives you:
M = [
u a1
v a1
u a2
v a2
u a3
v a3
u b1
v b1
u b2
v b2
u b3
v b3]

Equating symbolic coefficients

I would like to seek y particular of ODE y'' - y' - 2y = 4x^2
I made the following script:
syms x A0 A1 A2
ypa = A2*x^2+A1*x+A0; % y_p assume
cyp = diff(ypa,2) - diff(ypa) - 2*ypa % according to ODE
P1 = 4*x^2; P2 = cyp ; % Equating P1 and P2
C = coeffs(P1 - P2,x);
A0 = solve(C(1),A0)
A1 = solve(C(2),A1)
A2 = solve(C(3),A2)
I got the correct answer for A2 = -2. But I did not get for A0 (should be -3) and A1 (should be 2). How to get them automatically?
P.S I'm using MATLAB R2013a.
Instead of calling solve 3 times, once on each equation of C, you should call it once on the entire system of equations so that the proper substitutions are done to give you a numeric result for each variable:
>> [A0, A1, A2] = solve(C)
A0 =
-3
A1 =
2
A2 =
-2

Return vector from ODE45 has shorter length than initial conditions vector, while trying to solve coupled diffEQ

I am trying to use ODE45 to find the solution to 2 rotating bars, rotating on vertical plane, that have a torsional spring that creates a moment on the bars only when the angle between them differs from 90 degrees. I am just using a1-b4 as the constants in the diffEQ and are just imputing their values into a matrix before sending it into the function. I keep betting back an error saying that I am sending 6 initial conditions, but only get 5 back from the ODE45 function. Any ideas on how to fix this?
%system1.m
function [dx] = system1(t,x,parameters)
dx = zeros(4,1);
a1 = parameters(1);
a2 = parameters(2);
a3 = parameters(3);
a4 = parameters(4);
b1 = parameters(5);
b2 = parameters(6);
b3 = parameters(7);
b4 = parameters(8);
dx(1) = x(2); %dtheta1 = angular velocity1
dx(2) = x(3); %d(angular velocity1) = angular acceleration1
dx(4) = x(5); %dtheta2 = angular velocity2
dx(5) = x(6); %d(angular velocity2) = angular acceleration2
dx(2) = a1*x(1)+a2*x(4)+a3*x(2)+a4*x(5); %motion equation 1
dx(5) = b1*x(1)+b2*x(4)+b3*x(2)+b4*x(5); %motion equation 2
%CA2Lou.m
%set parameters
clear;
a1 = -12;
a2 = 12;
a3 = 0;
a4 = 0;
b1 = 4;
b2 = -4;
b3 = 0;
b4 = 0;
parameters = [a1 a2 a3 a4 b1 b2 b3 b4];
%set final time
tf = .5;
options = odeset('MaxStep',.05);
%setting initial conditions
InitialConditions = [90 0 0 0 0 0];
[t_sol,x_sol] = ode45(#system1,[0 tf],InitialConditions,[],parameters);
Your size and indexing for dx don't match x. You initialize dx to 4 elements, even though x has 6. Then you assign values to 4 indices of dx (specifically, [1 2 4 5]) which results in a new size for dx of 5 elements, still one less than the 6 it expects.
You probably need to initialize dx like so:
dx = zeros(6, 1);
Then, your first and second motion equations should probably (I'm guessing) be placed in indices 3 and 6:
dx(3) = a1*x(1)+a2*x(4)+a3*x(2)+a4*x(5); %motion equation 1
dx(6) = b1*x(1)+b2*x(4)+b3*x(2)+b4*x(5); %motion equation 2

Matlab error in subs with polynomial

I have a problem with matlab.
I have the following vector (19x1):
z_star = [0.0005 0.0008 0.0243 -12.3255 21.4029 -14.0085 4.7985 -0.9602 -0.1417 1.0886 -2.3934 2.9913 -2.3456 1.2184 -0.4282 0.1011 -0.0154 0.0014 -0.0001]';
Then:
tf = 2;
vec = [1,tf,tf^2,tf^3,tf^4,tf^5,tf^6,tf^7,tf^8,tf^9,tf^10,tf^11,tf^12,tf^13,tf^14,tf^15,tf^16,tf^17,tf^18];
If I compute:
vec*z_star
the result is approximately 1.9995.
Then I write the following code:
syms b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 k
theta = b18*k^18+b17*k^17+b16*k^16+b15*k^15+b14*k^14+b13*k^13+b12*k^12+b11*k^11*b10*k^10+b9*k^9+b8*k^8+b7*k^7+b6*k^6+b5*k^5+b4*k^4+b3*k^3+b2*k^2+b1*k+b0;
N = 101;
t = linspace(0,tf,N);
theta = subs(theta,[b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18],(z_star)');
theta = subs(theta,k,t);
theta = double(theta);
The result that I get for theta(N) is a really big negative number.
Shouldn't that be the same 1.9995 as before? Why is it different?
Thank you.
First things first, I would rename tf to another variable as tf is a function used from the Control Systems toolbox that defines the transfer function of a system. Let's called it something like tf_num. Keeping z_start the same, I would also like replace your vec call to this:
z_star = [0.0005 0.0008 0.0243 -12.3255 21.4029 -14.0085 4.7985 -0.9602 -0.1417 1.0886 -2.3934 2.9913 -2.3456 1.2184 -0.4282 0.1011 -0.0154 0.0014 -0.0001]';
tf_num = 2;
vec = (tf_num).^(0:18);
vec is the same as how you defined it previously, but we are doing it completely vectorized. The above will define a vector where each element is tf to the power of 0, 1, 2, up to 18, which is what you defined originally. It's a lot cleaner and easier to maintain.
Now, when I compute vec*z_star, I don't get 1.9995. In fact, I get:
>> format long g;
>> vec*z_star
ans =
-4.89990000000326
You should probably check how you computed the number again to be sure.
Now, the reason why you're not getting the same number is because you have a slight typo in your theta equation:
.... + b11*k^11*b10*k^10 ....
You have a multiplication in between the 11th power and 10th power... that should probably be a plus.
When I corrected that typo, and run your code, this is what I get:
%// From before
z_star = [0.0005 0.0008 0.0243 -12.3255 21.4029 -14.0085 4.7985 -0.9602 -0.1417 1.0886 -2.3934 2.9913 -2.3456 1.2184 -0.4282 0.1011 -0.0154 0.0014 -0.0001]';
tf_num = 2;
vec = (tf_num).^(0:18);
%// Your code
syms b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 k
%// Note - change in equation from above
theta = b18*k^18+b17*k^17+b16*k^16+b15*k^15+b14*k^14+b13*k^13+b12*k^12+b11*k^11+b10*k^10+b9*k^9+b8*k^8+b7*k^7+b6*k^6+b5*k^5+b4*k^4+b3*k^3+b2*k^2+b1*k+b0;
N = 101;
t = linspace(0,tf_num,N);
theta = subs(theta,[b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18],(z_star)');
theta = subs(theta,k,t);
theta = double(theta);
Now, if we display the last element of theta, we get:
>> theta(N)
ans =
-4.89990000000002

Parametric Matrix Multiplication

Does matlab supports such multiplication??
I searched a lot and find these
>> X = #(a1,a2,a3,a4)[a1 a2;a3 a4];
>> Y = #(b1,b2,b3,b4)[b1 b2;b3 b4];
>> % Something like ==> X*Y
But this just solves an equation with "value" and does not solve parametric for me. Does matlab support such a multiplication?
Maybe more of a long comment than an answer, but are you looking for symbolic variables? It requires the Symbolic Math Toolbox.
Example:
clc
clear
syms a1 a2 a3 a4 b1 b2 b3 b4
A = [a1 a2;a3 a4]
B = [b1 b2;b3 b4]
C = (A*B)
C =
[ a1*b1 + a2*b3, a1*b2 + a2*b4]
[ a3*b1 + a4*b3, a3*b2 + a4*b4]
Is this what you mean by "parametric matrix"?