Finding eigenvalues in a loop matlab - matlab

Ok this is how it's supposed to work. In the while loop eigenvalues are calculated for the increments of U in the variable lambda. The idea is to break the while loop once a real part of a variable lambda becomes positive and return the value of U for which this happens. I was trying to use a for loop to do it for a number of k1 values so that in the end I have a vector where in one column I have my k1 values and in the next column values of U for which lambda becomes positive. Hope you get the idea. The problem is that something doesn't seem to be working here and I really can't figure out what. Thanks for help
rho=1.225;
b=0.2;
m=5;
I_cg=0.05;
k1=2000;
k2=1000;
c1=10;
k_theta=2000;
c_theta=2;
c=2*b;
s=1;
x2=0.1;
xg=0.04;
M=[m -m*xg;-m*xg (m*(xg^2)+I_cg)];
kRoof = 60;
for kIndex = 0:kRoof
kStart = 2000;
k1 = kStart * kIndex;
U=0.1;
lambda=-1;
while (real(lambda)<0)
i=1;
U(i)=U+i;
q=0.5*rho*U(i)^2;
B=[((2*pi*q*s*c)/U(i))+c1 (pi*q*s*c)/(5*U(i));-pi*q*s*(c^2)/(2*U(i)) c_theta];
C=[k1+k2 -k2*x2+(2*pi*q*s*c);-k2*x2 (k2*(x2^2)+(k_theta)-(pi*q*s*(c^2)/2))];
A=[M B;zeros(2) M];
D=[zeros(2) C;-M zeros(2)];
lambda=eig(D,-A);
i=i+1
U=U+i
if imag(lambda)==0
disp(lambda)
end
end
end

Related

How to setup equation that involves a sum from x=1 to infinity and loops?

I am getting confused on how to properly set up this equation. To find a value of V(i,j). The end result would be plotting V over time. I understand that there needs to be loops to allow this equation to work, however I am lost when it comes to setting it up. Basically I am trying to take the sum from n=1 to infinity of (1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L)
I originally thought that I should make it a while loop to increment n by 1 until I reach say 10 or so just to get an idea of what the output would look like. All of the variables were unknown and values were added again to see what the plot would look like.
I have down another code where the equation is just dependent on i and j. However with this n term, I am thrown off. Any advice would be great as to setting up the equation. Thank you.
L=10;
x=linspace(0,L,30);
t1= 50;
X=30;
p=1
c=t1/1000;
V=zeros(X,t1);
V(1,:)=0;
V(30,:)=0;
R=((4*p*L^3)/c);
n=1;
t=1:50;
while n < 10
for i=1:31
for j=1:50
V(i,j)=R*sum((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L));
end
end
n=n+1;
end
figure(1)
plot(V(i,j),t)
Various ways of doing so:
1) Computing the sum up to one Nmax in one shot:
Nmax = 30;
Vijn = #(i,j,n) R*((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*j)/L)*sin((n*pi*i)/L));
i = 1:31;
j = 1:50;
n = 1:Nmax;
[I,J,N] = ndgrid(i,j,n);
V = arrayfun(Vijn,I,J,N);
Vc = cumsum(V,3);
% now Vc(:,:,k) is sum_n=1^{k+1} V(i,j,n)
figure(1);clf;imagesc(Vc(:,:,end));
2) Looping indefinitely
n = 1;
V = 0;
i = 1:31;
j = 1:50;
[I,J] = meshgrid(i,j);
while true
V = V + R*((1-(-1)^n)/(n^4 *pi^4)*sin((n*pi*c*J)/L).*sin((n*pi*I)/L));
n = n + 1;
figure(1);clf;
imagesc(V);
title(sprintf('N = %d',n))
drawnow;
pause(0.25);
end
Note that in your example you won't need many terms, since:
Every second term is zero (for even n, the term 1-(-1)^n is zero).
The terms decay with 1/n^4. In norms: n=1 contributes ~2e4, n=3 contributes ~4e2, n=5 contributes 5e1, n=7 contributes ~14, etc. Visually, there is a small difference between n=1 and n=1+n=3 but barely a noticeable one for n=1+n=3+n=5.
Given that so few terms are needed, the first approach is probably the better one. Also, skip the even indices, as you don't need them.

Variables are continuously zero while creating matrice with for loop

Here is my code;
%Blasius solution by Euler Method
%---------------
g0=zeros(101,1);
g1=zeros(101,1);
g2=zeros(101,1);
%---------------
g0(1)=0;
g1(1)=0;
% g1(101)=1;
g2(1)=2;
%---------------
G=zeros(101,3);
T=zeros(101,3);
G=[g0 g1 g2];
T=[g1 g2 (-1)*g0.*g2];
%Euler method%
for i=1:100
G(i+1) = G(i) + (T(i)*0.1);
end
What am I missing? I am trying to create the G matrix but it is always a 101*3 zero matrix. It looks like for loop doesn't work but I couldn't figure out why.
I figured out why your code is not working:
First of all you need to call row indices, not linear indices, i.e. change your loop to:
for ii=1:100
G(ii+1,:) = G(ii,:) + (T(ii,:)*0.1);
end
note that I also used ii as opposed to i, since using that as a variable is bad.
This results in T remaining constant, obviously, since you do not change it. You initialise it as a zero array and set only the second element on the first row to 2, but leave the rest as zeros. Adding a row of T to a row of G will therefore not do anything, since you are adding zeros to an existing row. This is why the second row of G becomes [0 0.2 2] and does not change anymore , since you are only adding zeros to it.
You probably forgot to add the line of code which assigns a new value to rows of T. Adhering to your suggestion in the comments:
for ii=1:100
G(ii+1,:) = G(ii,:) + (T(ii,:)*0.1);
T(ii+1,:) = G(ii,:);
end
Here is the new solution, we have spend hours but finally figure it out.
%Blasius solution by Euler Method
%---------------
g0=zeros(101,1);
g1=zeros(101,1);
g2=zeros(101,1);
g2(1)=2;
%---------------
G=zeros(101,3);
T=zeros(101,3);
G=[g0 g1 g2];
T=[g1 g2 ((-1)*g0.*g2)];
%Euler method%
for i=1:100
A=[g0(i) g1(i) g2(i)] ;
B=[g1(i)*0.1 g2(i)*0.1 (-1).*g0(i)*g2(i)*0.1];
C(i,:)=A+B;
g0(i+1)=C(i,1);
g1(i+1) =C(i,2);
g2(i+1) =C(i,3);
end

Solving for the square root by Newton's Method

yinitial = x
y_n approaches sqrt(x) as n->infinity
If theres an x input and tol input. Aslong as the |y^2-x| > tol is true compute the following equation of y=0.5*(y + x/y). How would I create a while loop that will stop when |y^2-x| <= tol. So every time through the loop the y value changes. In order to get this answer--->
>>sqrtx = sqRoot(25,100)
sqrtx =
7.4615
I wrote this so far:
function [sqrtx] = sqrRoot(x,tol)
n = 0;
x=0;%initialized variables
if x >=tol %skips all remaining code
return
end
while x <=tol
%code repeated during each loop
x = x+1 %counting code
end
That formula is using a modified version of Newton's method to determine the square root. y_n is the previous iteration and y_{n+1} is the current iteration. You just need to keep two variables for each, then when the criteria of tolerance is satisfied, you return the current iteration's output. You also are incrementing the wrong value. It should be n, not x. You also aren't computing the tolerance properly... read the question more carefully. You take the current iteration's output, square it, subtract with the desired value x, take the absolute value and see if the output is less than the tolerance.
Also, you need to make sure the tolerance is small. Specifying the tolerance to be 100 will probably not allow the algorithm to iterate and give you the right answer. It may also be useful to see how long it took to converge to the right answer. As such, return n as a second output to your function:
function [sqrtx,n] = sqrRoot(x,tol) %// Change
%// Counts total number of iterations
n = 0;
%// Initialize the previous and current value to the input
sqrtx = x;
sqrtx_prev = x;
%// Until the tolerance has been met...
while abs(sqrtx^2 - x) > tol
%// Compute the next guess of the square root
sqrtx = 0.5*(sqrtx_prev + (x/sqrtx_prev));
%// Increment the counter
n = n + 1;
%// Set for next iteration
sqrtx_prev = sqrtx;
end
Now, when I run this code with x=25 and tol=1e-10, I get this:
>> [sqrtx, n] = sqrRoot(25, 1e-10)
sqrtx =
5
n =
7
The square root of 25 is 5... at least that's what I remember from maths class back in the day. It also took 7 iterations to converge. Not bad.
Yes, that is exactly what you are supposed to do: Iterate using the equation for y_{n+1} over and over again.
In your code you should have a loop like
while abs(y^2 - x) > tol
%// Calculate new y from the formula
end
Also note that tol should be small, as told in the other answer. The parameter tol actually tells you how inaccurate you want your solution to be. Normally you want more or less accurate solutions, so you set tol to a value near zero.
The correct way to solve this..
function [sqrtx] = sqRoot(x,tol)
sqrtx = x;%output = x
while abs((sqrtx.^2) - x) > tol %logic expression to test when it should
end
sqrtx = 0.5*((sqrtx) + (x/sqrtx)); %while condition prove true calculate
end
end

Order of convergence Newton

Hello I have written this to determine a root using Newton's method. The algorithm works. I also tried to implement an Experimental order of convergence EOC. It also works but I get the result that the order of convergence for Newton's method is 1 when in fact it is 2.
function [x,y,eoc,k]=newnew(f,df,x0,xe,eps,kmax)
x = x0;
y = feval(f,x);
for m=1:kmax
z = -y/feval(df,x);
x = x + z;
y = feval(f,x);
k = m;
for n=m
Ek=abs(x-xe);
end
for n=m+1
Ekp=abs(x-xe);
end
eoc=log(Ek)/log(Ekp);
if abs(y)<eps
return
end
end
disp('no convergence');
end
what is wrong?
When you say Ek=abs(x-xe) and Exp=abs(x-xe), they are exactly the same thing! That's why eoc evaluates to 1 every time.
Notice that you have no n in those equations. In fact, you don't need those extra for n=m loops either. Inside the for m=1:kmax loop, m is a single value not an array.
eoc needs to be calculated by comparing the previous loop iteration to the current one (since it doesn't make much sense to compare to a future loop iteration which hasn't happened yet). Because this looks like homework, I won't give you any code.. but this is a very strong hint.

Fixed Point Iteration

I am new to Matlab and I have to use fixed point iteration to find the x value for the intersection between y = x and y = sqrt(10/x+4), which after graphing it, looks to be around 1.4. I'm using an initial guess of x1 = 0. This is my current Matlab code:
f = #(x)sqrt(10./(x+4));
x1 = 0;
xArray(10) = [];
for i = 1:10
x2 = f(x1);
xArray(i) = x2;
x1 = x1 + 1;
end
plot(xArray);
fprintf('%15.8e\n',xArray);
Now when I run this it seems like my x is approaching 0.8. Can anyone tell me what I am doing wrong?
Well done. You've made a decent start at this.
Lets look at the graphical solution. BTW, this is how I'd have done the graphical part:
ezplot(#(x) x,[-1 3])
hold on
ezplot(#(x) sqrt(10./(x+4)),[-1 3])
grid on
Or, I might subtract the two functions, then looking for a zero of the difference, so where it crosses the x axis.
This is what the fixed point iteration does anyway, trying to solve for x, such that
x = sqrt(10/(x+4))
So how would I change your code to fix it? First of all, I'd want to use more descriptive names for the variables. You don't get charged by the character, and making your code easier to read & follow will pay off greatly in the future for you.
There were a couple of code issues. To initialize a vector, use a form like one of these:
xArray = zeros(1,10);
xArray(1,10) = 0;
Note that if xArray was ALREADY defined because you have been working on this problem, the latter form will only zero out that single element. So the first form is best by a large margin. It affirmatively creates an array, or overwrites an existing array if it is already present in your workspace.
Finally, I like to initialize an array like this with something special, rather than zero, so we can see when an element was overwritten. NaNs are good for this.
Next, there was no need to add one to x1 in your code. Again, I'd strongly suggest using better variable names. It is also a good idea to use comments. Be liberal.
I'd suggest the idea of a convergence tolerance. You can also have an iteration counter.
f = #(x)sqrt(10./(x+4));
% starting value
xcurrent = 0;
% count the iterations, setting a maximum in maxiter, here 25
iter = 0;
maxiter = 25;
% initialize the array to store our iterations
xArray = NaN(1,maxiter);
% convergence tolerance
xtol = 1e-8;
% before we start, the error is set to be BIG. this
% just lets our while loop get through that first iteration
xerr = inf;
% the while will stop if either criterion fails
while (iter < maxiter) && (xerr > xtol)
iter = iter + 1;
xnew = f(xcurrent);
% save each iteration
xArray(iter) = xnew;
% compute the difference between successive iterations
xerr = abs(xnew - xcurrent);
xcurrent = xnew;
end
% retain only the elements of xArray that we actually generated
xArray = xArray(1:iter);
plot(xArray);
fprintf('%15.8e\n',xArray);
What was the result?
1.58113883e+00
1.33856229e+00
1.36863563e+00
1.36479692e+00
1.36528512e+00
1.36522300e+00
1.36523091e+00
1.36522990e+00
1.36523003e+00
1.36523001e+00
1.36523001e+00
For a little more accuracy to see how well we did...
format long g
xcurrent
xcurrent =
1.36523001364783
f(xcurrent)
ans =
1.36523001338436
By the way, it is a good idea to know why the loop terminated. Did it stop for insufficient iterations?
The point of my response here was NOT to do your homework, since you were close to getting it right anyway. The point is to show some considerations on how you might improve your code for future work.
There is no need to add 1 to x1. your output from each iteration is input for next iteration. So, x2 from output of f(x1) should be the new x1. The corrected code would be
for i = 1:10
x2 = f(x1);
xArray(i) = x2;
x1 = x2;
end
f(x)x^3+4*x^2-10 in [1,2] find an approximate root