Matlab, expanding, simultaneous equation solving for a control system - matlab

I have this code in matlab
syms L1 L0 P1 P0 s
L = expand(s*(s^2+L1*s+L0)*(s-75)+1400*(P1*s+P0))
R = expand((s+75)*(s+150)^3)
I want to solve for P1, P0, L1 and L0
L = R
1400*P0 - 75*L0*s + 1400*P1*s + L0*s^2 - 75*L1*s^2 + L1*s^3 - 75*s^3 + s^4 = s^4 + 525*s^3 + 101250*s^2 + 8437500*s + 253125000
by observation:
1400*P0 = 253125000
ETC...
How do i pull simultaneous equations from L=R in Matlab and automatically solve for each variable?
Thanks

You could write the equation as L-R=0, then do something like C=coeffs(L-R,s). Then, something like the following code might solve the equations:
for i=1:length(C)
sol(i)=solve(C(i));
end
but it may be difficult to work out which element of sol refers to which variable. But if you are going to look at the output as the code runs it should be pretty obvious I'd imagine.

Related

Solving the system of non-linear equations in MATLAB by fsolve

I have a code that produces a vector in MATLAB, for example the following is a three component vector (n=3):
a1_1 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 - 0.153233)
(15*a1_1)/16 + a2_1/4 + a3_1/32 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 - 0.0282326)
(3*a1_1)/4 + a2_1/2 + a3_1/8 - sin((17*a1_1)/60 + a2_1/8 + a3_1/40 + 0.846767)
as you can see each component is a non-linear equation. The three component of the vector forms a system of three non-linear equations having it's variables named as a1_1, a1_2and a1_3. I want to solve this system by fsolve.
How do I do that for arbitrary n?
To use fsolve, your function must accept a vector input and return a vector of the same size. In your case you can accomplish this with an anonymous function:
f = #(a)[a(1) - sin(17*a(1)/60 + a(2)/8 + a(3)/40 - 0.153233);...
15*a(1)/16 + a(2)/4 + a(3)/32 - sin(17*a(1)/60 + a(2)/8 + a(3)/40 - 0.0282326);...
3*a(1)/4 + a(2)/2 + a(3)/8 - sin(17*a(1)/60 + a(2)/8 + a(3)/40 + 0.846767)];
n = 3;
a0 = zeros(n,1); % Initial guess
opts = optimoptions('fsolve','Display','iter','TolFun',1e-8);
[a_sol,a_val,exitflag] = fsolve(f,a0,opts)
This returns
a_sol =
-0.002818738864459
-0.687953796565011
9.488284986072076
Of course there may be more than one solution, especially for larger n. You can choose your initial guess to find the others. See the documentation for fsolve and optimoptions for further details on on specifying options.
Did you try using the solve command ?
[y1,...,yN] = solve(eqns,vars) solves the system of equations eqns for the variables vars. The solutions are assigned to the variables y1,...,yN. If you do not specify the variables, solve uses symvar to find the variables to solve for. In this case, the number of variables that symvar finds is equal to the number of output arguments N.

Math, 2 equations 2 unknowns, and matlab, plot

i am trying to solve these 2 equations with 2 unknowns.
i want to find the angle of a1(alpha1), a2(alpha2) in radians.
however when i solve it in maple i get 0.112 for a2 and 0.089 for a1.
but some other guys used matlab and they get something different with plot and 2 angles..
can someone tell me if i am right or he is?
MY equations:
equation 1: 4/(2*pi)*(cos(2*a1)+cos(2*a2))=0
equation 2: 4/(10*pi)*(cos(10*a1)+cos(10*a2))=0
his matlab:
j=0;
for i=0:pi/100:1
j=j+1;
a2(j)=i;
a1_1(j)=acos(-cos(2*i))/2;
a1_2(j)=acos(-cos(10*i))/10;
end
plot(a2,a1_1,'-k',a2,a1_2,'-b','LineWidth',1.4);
I wanna plot like him..but i am not sure his Equations a1_1 is correct?
by the way the main equation it came from:
bn = 4/(npi)(cos(na1)+cos(na2))=0
bn = 0 and n is 2th and 10th harmonics to be eliminated
cos(A)+cos(B) = 0
happens for
A + B = pi + 2*k*pi or A - B = pi + 2*k*pi
Both of the two original equations could resolve the the same of the two variants or to different variants. Resolving to the same equation, say the first, will produce
7*(a1+a2) = pi + 2*k7*pi and 13*(a1+a2) = pi + 2*k13*pi
which can only hold if
0 = 6*pi + 2*(13*k7-7*k13) <=> 3 = 7*k13-13*k7
which implies a1+a2 = pi + 2*m*pi. .
In the case of different to different variant, one obtains (modula sign variations of a1, a2)
7*(a1+a2) = pi + 2*k7*pi and 13*(a1-a2) = pi + 2*k13*pi
and thus
a1 = (pi/7+pi/13)/2 + k7*pi/7 + k13*pi/13
a2 = (pi/7-pi/13)/2 + k7*pi/7 - k13*pi/13
and all possible sign variations, since cosine is an even function. However, simultaneous sign variations are also covered by variations of k7 and k13. Thus you obtain additionally (up to) 2*7*13=182 solutions to your problem.

Make sure MATLAB does not recalculate symbolic expression

I am building (my first...) MatLab program, it needs to differentiate an equations symbolically and then use this solution many many times (with different numeric inputs).
I do not want it to recalculate the symbolic differentiation every time it needs to put in a new set of numeric values. This would probably greatly add to the time taken to run this program (which - given its nature, a numeric optimiser, will probably already be hours).
My question is how can I structure my program such that it will not recalculate the symbolic differentiation?
The class in question is:
function [ result ] = GradOmega(numX, numY, numZ, numMu)
syms x y z mu
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega);
%//Substitute the given numeric values back into the funtion
result = subs(symGradient, {x,y,z,mu}, {numX, numY, numZ, numMu});
end
I know that I could just symbolically calculate the derivative and then copy-paste it into the code e.g.
gradX = x + ((2*mu + 2*x)*(mu - 1))/(2*((mu + x)^2 + y^2 + z^2)^(3/2)) - (mu*(2*mu + 2*x - 2))/(2*((mu + x - 1)^2 + y^2 + z^2)^(3/2));
gradY = y - (mu*y)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (y*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
gradZ = z - (mu*z)/((mu + x - 1)^2 + y^2 + z^2)^(3/2) + (z*(mu - 1))/((mu + x)^2 + y^2 + z^2)^(3/2);
But then my code is a bit cryptic, which is a problem in a shared project.
There is a related query here: http://uk.mathworks.com/matlabcentral/answers/53542-oop-how-to-avoid-recalculation-on-dependent-properties-i-hope-a-mathwork-developer-could-give-me-a
But I'm afraid I couldn't follow the code.
Also I am much more familiar with Java and Python, if that helps explain anything.
You could wrap your function into some kind of Function-Factory, which does not return numerical results, but a function that can be evaluated:
(I had to replace the call syms with sym('mu'), because for some reason it kept calling a mutools function in line omega = .... I did also change the call to gradient to make sure the arguments are in correct order, and mu will be treated as constant.)
function GradOmega = GradOmegaFactory()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
symGradient = gradient(omega,{'x','y','z'});
GradOmega = matlabFunction(symGradient, 'vars', {'x','y','z','mu'});
end
Then you would call it via:
GradOmega = GradOmegaFactory();
result1 = GradOmega(numX1, numY1, numZ1, numMu1);
result2 = GradOmega(numX2, numY2, numZ2, numMu2);
result3 = GradOmega(numX3, numY3, numZ3, numMu3);
...
Even better:
You could go even more fancy and use a wrapper function GradOmega which builds such a function inside and makes it persistent, to get the same interface you had with your initial approach. The first time you call the function GradOmega the symbolic expression is evaluated, but on each consecutive call you will only have to evaluate the generated function handle, which means it should be nearly as fast as if you hard-coded it.
function result = GradOmega(numX, numY, numZ, numMu)
persistent numericalGradOmega;
if isempty(numericalGradOmega)
numericalGradOmega = GradOmegaFactory();
end
result = numericalGradOmega(numX, numY, numZ, numMu);
end
Use this like you would use your original version
result = GradOmega(numX, numY, numZ, numMu);
Just copy and paste both functions into a single GradOmega.m file. (GradOmega should be the first function in the file.)
Another tip: You can even evaluate this function using vectors. Instead of calling GradOmega(1,2,3,4) and GradOmega(5,6,7,8) afterwards, you can save the time overhead via the call GradOmega([1,5], [2,6], [3,7], [4,8]) using row vectors.
Yet another tip: To clean up your code even more, you could also put the first lines into a separate symOmega.m file.
function omega = symOmega()
x = sym('x');
y = sym('y');
z = sym('z');
mu = sym('mu');
omega = 0.5*(x^2+y^2+z^2) + (1-mu)/((x+mu)^2+y^2+z^2)^0.5 + mu/((x+mu-1)^2+y^2+z^2)^0.5;
This way you don't have to have a copy of this symbolic expression in every file you use it. This can be beneficial if you also want to evaluate Omega itself, as you then can make use of the same Factory-approach listed in this answer. You would end up with the following files: symOmega.m, Omega.m and GradOmega.m, where only the file symOmega.m has the actual mathematical formula and the other two files make use of symOmega.m.

maxima multiple trigonometric equations

I'm trying to solve an equation using maxima 13.04.2 but the answer isn't what I expect.
Example:
y2=A2*cos(2*pi*f2*t+phase2) we know A2=.4,f2=6.4951,t=1, trying to find **phase2**
y2=.4*cos(2*pi*6.4951+phase2)
I tried to solve the y2 equation for phase2 in maxima but it got rid of the cos function
kill(all);
A:A; phase:phase; solve(A*cos(2*pi*f*t+phase)=0,phase);
The answer that came back was
I thought something like this was suppose to come back
y2 = A2×cos(2πf2t + φ2) ⇒
y2/A2 = cos(2πf2t + φ2) ⇒
arccos(y2/A2) = 2πf2t + φ2 ⇒
arccos(y2/A2) - 2πf2t = φ2
so I could then plug in the vales
A2 = 0.4, f2 = 6.4951, t = 1 and get the phase
Any ideas how to get maxima to get the correct format?
PS: Yes I know I can do it by hand but I have thousands of equations like this and I plan on using octave arrays to call maxima to solve them and bring the answers back into octave.
Well, it seems straightforward.
(%i1) e:A*cos(2*%pi*f*t + phi) = y;
(%o1) cos(2 %pi f t + phi) A = y
(%i2) solve (e, phi);
solve: using arc-trig functions to get a solution.
Some solutions will be lost.
y
(%o2) [phi = acos(-) - 2 %pi f t]
A
(%i3) subst ([A = 0.4, f = 6.4951, t = 1], %o2);
(%o3) [phi = acos(2.5 y) - 12.9902 %pi]
Couple of notes. (1) solve can solve this equation, which is good, but bear in mind that it is fairly limited in its capability, and you can probably make up other equations that it can't solve. There are some other options for solving equations in Maxima, but it general that is a weak area. (2) Maybe instead of switching back and forth between Maxima and Octave, you can just code equation %o2 in Octave and evaluate that for different values of the parameters.

how do I find the value of a parameter when others are given and integral is zero using matlab?

I have a function
function y = testf(x,F,phi,M,beta,alpha)
y = -((F+(1 + phi.*cos(2.*pi.*x))).*M.^3.*(cosh((1 + phi.*cos(2.*pi.*x)).*M)+M.*beta.*sinh((1 + phi.*cos(2.*pi.*x)).*M)))./((1 + phi.*cos(2.*pi.*x)).*M.*cosh((1 + phi.*cos(2.*pi.*x)).*M)+(-1+(1 + phi.*cos(2.*pi.*x)).*M.^2.*beta).*sinh((1 + phi.*cos(2.*pi.*x)).*M))- (alpha.*(M.^2.*(F+(1 + phi.*cos(2.*pi.*x))).*(-1+2.*(1 + phi.*cos(2.*pi.*x)).^2.*M.^2+ cosh(2.*(1 + phi.*cos(2.*pi.*x)).*M)-2.*(1 + phi.*cos(2.*pi.*x)).*M.*sinh(2.*(1 + phi.*cos(2.*pi.*x)).*M)))./(8.*((1 + phi.*cos(2.*pi.*x)).*M.*cosh((1 + phi.*cos(2.*pi.*x)).*M)+(-1+(1 + phi.*cos(2.*pi.*x)).*M.^2.*beta).*sinh((1 + phi.*cos(2.*pi.*x)).*M)).^2));
integrating with
q = quad(#(x) testf (x, F, phi,M, beta, alpha), 0, h);
when q = 0 and x,F,phi,M,beta, how do I find alpha and draw the streamline?
It would be great if you gave some numbers, but here is how you would start this. It assumes you are using a version of Matlab that has MuPad as the Symbolic Engine.
First of all, I wouldn't use quad because symbolic expressions will be involved, use int instead.
If I understood you correctly, have the values of x, F, phi, M, beta and you would like to solve for alpha when q = 0
%define the known variables first
syms alpha %defining symbolic object
Now, the following may not work because it's a huge function:
q = int(y,x,0,h)
If it did, all you have to do is solve and evaluate the results for alpha (this may not work as well):
alpha = eval( solve( 'q' , alpha ) )
If the above didn't achieve anything, you might what to look at the 'IgnoreAnalyticConstraints' option.