Storing values with a while loop (matlab) - matlab

I have a while loop and I've been unable to determine how to store the values successfully. Any help would be greatly appreciated.
n = 0; a = 21; b = 0; c = 0; y = 37.6991; T = 18.5; z = 0.1591; d = 0; f = 15.3049; q = 2.2391e4; e = 5; x = 60;
while n < x
a = a + b
c = y*(T-a)/z;
d = f*c;
b = d/q;
n = n + e;
end
The value I'm trying to store is a, I can tell the values are correct inside the loop but just can't seem to store the values correctly.

Another approach would be to recognise that it is a relatively simple recurrence relation:
n = 0; a = 21; y = 37.6991; T = 18.5; z = 0.1591; f = 15.3049; q = 2.2391e4; e = 5; x = 60;
while n < x
a(end+1) = a(end) + f * y * (T - a(end)) / (q * z);
n = n + e;
end
This calculation can also be vectorised, but if you want exactly the same output you need to be a little bit careful:
n = 5:5:55; y = 37.6991; T = 18.5; z = 0.1591; f = 15.3049; q = 2.2391e4; a0 = 21;
alpha = f * y * T / (q * z);
beta = (1 - f * y / (q * z)).^(0:length(n))
a = a0 * beta + alpha * [0 cumsum(beta(1:end-1))];
The code seems to lose clarity (to me) when vectorised, so I would probably prefer the loop in this scenario.

Try this :
counter = 1;
n = 0; a = 21; b = 0; c = 0; y = 37.6991; T = 18.5; z = 0.1591; d = 0; f = 15.3049; q = 2.2391e4; e = 5; x = 60;
var = zeros(1,12);
while n < x
a = a + b;
c = y*(T-a)/z;
d = f*c;
b = d/q;
n = n + e;
var(counter) = a;
counter = counter+1;
end
I added a variable called var which is a vector that stores the values of a. In order t osave runtime i initialized it to the expected size of the variable var = zeros(1,12); (This is not strictly required but is recommended.

Related

Order of complexity of a matrix (matlab)

I need some help answering this question : How do I find the complexity of the matrix B and f knowing that I have this code :
d = 123456;
randn('state',d); rand('state',d);
n = 1000; A = diag(1+rand(1,n));
k = 5500; r = randperm(n*n,k);
A(r) = A(r) + rand(1,k);
L = tril(A); U = A-L;
x = rand(n,1);
b = A*x;
B = -L\U; f = L\b;
xit = zeros(n,1);
nit = 100;
res = zeros(nit,1);
incr = zeros(nit,1);
err = zeros(nit,1);
for it = 1:nit,
xit0 = xit;
xit = B*xit+f;
res(it) = norm(b-A*xit);
incr(it) = norm(xit-xit0);
err(it) = norm(xit-x);
end
Thanks in advance

Plotting level curves in MATLAB for a complex function

I am trying to plot the contour plots for the given function
syms r x y k z
[ph,r] = meshgrid((0:5:360)*pi/180,0:.5:10);
[X,Y] = pol2cart(ph,r);
Z = X+i*Y;
J = besselj(k,l.*r);
J2 = besselj(k,m.*r);
Y = bessely(k,l.*r);
Y2 = bessely(k,m.*r);
H = besselh(k,r);
F1 = symsum((J).*exp(1i*k*ph),k,-5,5);
F2 = symsum((J2+Y2).*exp(1i.*k.*ph),k,-5,5);
F3 = symsum(H.*exp(1i.*k.*ph),k,-5,5);
pwu = nan(size(F1), 'like', F1);
mask = 0 <= r & r < 0.5;
pwu(mask) = F1(mask);
mask = 0.5 <= r & r < 1;
pwu(mask) = F2(mask);
mask = r >= 1;
pwu(mask) = F3(mask);
U = subs(pwu, {l, m}, {1.5, 3});hold on
contour(X,Y,imag(double(U)),30)
axis equal
xlabel('r','FontSize',14);
ylabel('phi','FontSize',14);
but I keep getting errors for the form of the 4th last line. Apparently U cannot be converted to a double. Is there any other way to do this?
Thanks
This code works:
syms r x y k z
[ph,r] = meshgrid((0:5:360)*pi/180,0:.5:10);
[x,y] = pol2cart(ph,r);
Z = x+1i*y;
J = besselj(k,l.*r);
J2 = besselj(k,m.*r);
Y = bessely(k,l.*r);
Y2 = bessely(k,m.*r);
H = besselh(k,r);
F1 = symsum((J).*exp(1i*k*ph),k,-5,5);
F2 = symsum((J2+Y2).*exp(1i.*k.*ph),k,-5,5);
F3 = symsum(H.*exp(1i.*k.*ph),k,-5,5);
pwu = nan(size(F1), 'like', F1);
mask = 0 <= r & r < 0.5;
pwu(mask) = F1(mask);
mask = 0.5 <= r & r < 1;
pwu(mask) = F2(mask);
mask = r >= 1;
pwu(mask) = F3(mask);
U = subs(pwu, {l, m}, {1.5, 3});hold on
J0 = besselj(k,r);
u0 = symsum(1i.^(-k).*J0.*exp(1i*k*ph),k,-5,5);
W = U+u0;
contour(x, y, angle(double(W)), 30);
axis equal
xlabel('r','FontSize',14);
ylabel('phi','FontSize',14);
Thanks for your comments!

How to display a function with double values instead of symbolic?

I want the function P to look like this:
-1 + 0.6366*(x+pi/2) + (-0.000)*(x + pi/2)*(x)
and right now it looks like this
(5734161139222659*x)/9007199254740992 + (5734161139222659*pi)/18014398509481984 - (8131029572207409*x*(x + pi/2))/324518553658426726783156020576256 - 1.
How to convert S array so that the values are not symbolic?
syms P x
f = sin(x);
f = matlabFunction(f);
X = [-pi/2, 0, pi/2];
Y = f(sym(X));
P = MetN(X,Y,x)
P = matlabFunction(P);
function [P] = MetN(X,Y,x)
n = length(X);
for i = 1:n
A(i,1) = 1;
end
for i = 2:n
for j = 2: n
if i >= j
produs = 1;
for k =1:j-1
produs = produs * (X(i) - X(k));
end
A(i,j) = produs;
end
end
end
S = SubsAsc(A, Y);
S = double(S);
disp(S);
sym produs
P = double(sym(S(1)));
for i = 2:n
produs = 1;
for j = 1:i-1
produs = produs * (x - sym(X(j)));
end
disp(produs);
P = P + double(S(i))*produs;
end
end
function [x] = SubsAsc(A,b)
n = length(b);
x(1) = (1/A(1,1))*b(1);
for k = 2:n
s = 0;
for j = 1:k-1
s = s + A(k,j)*x(j);
end
x(k) = (1/A(k,k))*(b(k)-s);
end
end
The output you currently have is because symbolic uses exact arithmetic, so it outputs it as a rational number (hence the ugly fraction).
To have it output P using decimals, use vpa(). For instance output P using decimals to 5 significant digits
>> vpa(P, 5)
ans =
0.63662*x - 2.5056e-17*x*(x + 1.5708)
This will, however, also round pi, so you can't really have the best of both worlds here.

For loop output as an array

I wrote a code in Matlab which I predefine the variable "a" and then set up a for loop of 5 iterations where the variable "a" goes through some basic operations. However, the for loop output only saves the fifth iteration of "a." How do I save all 5 iterations in a 1x5 array?
The code is as follows:
a = 10;
k = 0.5;
n = 2;
for m = 1:5
a = a + (a*k) + n;
end
Edit:
I just found it that I have to create a new variable.
a = 10;
k = 0.5;
n = 2;
a_n = zeros(1,5);
for m = 1:5
a = a + (a*k) + n;
a_n(m) = a;
end
You may need to store value of a after each iteration into an another variable x
a = 10;
k = 0.5;
n = 2;
for m = 1:5
a = a + (a*k) + n;
x(m) = a;
end
x
Output:
x =
17.000 27.500 43.250 66.875 102.312
You would need to use a different variable to store the 5 iterations as an array.
Code would look something like this:
a = 10;
k = 0.5;
n = 2;
b = [];
for m = 1:5
a = (a + (a*k) + n)
b = [b a];
end
You can now print b for all 5 iteration values.
Here is an alternate way to update values into the 1-D matrix.

Perform step-by-step integral

I have this piece of code:
time = 614.4;
Uhub = 11;
HubHt = 90;
TI = 'A';
N1 = 4096;
N2 = 32;
N3 = 32;
L1 = Uhub*time;
L2 = 150;
L3 = 220;
V = L1*L2*L3;
gamma = 3.9;
c = 1.476;
b = 5.6;
if HubHt < 60
lambda1 = 0.7*HubHt;
else
lambda1 = 42;
end
L = 0.8*lambda1;
if isequal(TI,'A')
Iref = 0.16;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'B')
Iref = 0.14;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'C')
Iref = 0.12;
sigma1 = Iref*(0.75*Uhub + b);
else
sigma1 = str2num(TI)*Uhub/100;
end
sigma_iso = 0.55*sigma1;
%% Wave number vectors
ik1 = cat(2,(-N1/2:-1/2),(1/2:N1/2));
ik2 = -N2/2:N2/2-1;
ik3 = -N3/2:N3/2-1;
[x y z] = ndgrid(ik1,ik2,ik3);
k1 = reshape((2*pi*L/L1)*x,N1*N2*N3,1);
k2 = reshape((2*pi*L/L2)*y,N1*N2*N3,1);
k3 = reshape((2*pi*L/L3)*z,N1*N2*N3,1);
k = sqrt(k1.^2 + k2.^2 + k3.^2);
Now I should calculate
where
The procedure to calculate the integral is
At the moment I'm using this loop
E = #(k) (1.453*k.^4)./((1 + k.^2).^(17/6));
E_int = zeros(1,N1*N2*N3);
E_int(1) = 1.5;
for i = 2:(N1*N2*N3)
E_int(i) = E_int(i) + quad(E,i-1,i);
end
neglecting for the k>400 approximation. I believe that my loop is not right.
How would you suggest to calculate the integral?
I thank you in advance.
WKR,
Francesco
This is a list of correction from the more obvious to the possibly more subtle. (Indeed I start from what you wrote in the final part going upwards).
From what you write:
E = #(k) (1.453*k.^4)./((1 + k.^2).^(17/6));
E_int = zeros(1,N1*N2*N3);
E_int(1) = 1.5;
for i = 2:(N1*N2*N3)
%//No point in doing this:
%//E_int(i) = E_int(i) + quad(E,i-1,i);
%//According to what you write, it should be:
E_int(i) = E_int(i-1) + quad(E,i-1,i);
end
You could speed the whole thing up by doing
%//Independent integration on segments
Local_int = arrayfun(#(i)quad(E,i-1,i), 2:(N1*N2*N3));
Local_int = [1.5 Local_int];
%//integral additivity
E_int = cumsum(Local_int);
Moreover, if the known condition (point 2.) really is "... ( = 1.5 if k' = 0)", then the whole implementation should really be more like
%//Independent integration on segments
Local_int = arrayfun(#(i)quad(E,i-1,i), 2:(N1*N2*N3));
%//integral additivity + cumulative removal of queues
E_int = 1.5 - [0 fliplr(cumsum(fliplr(Local_int)))]; %//To remove queues