Matlab: Negative number to the power of n where "n" is bigger than 1 gives an imaginary number - matlab

I am running a matlab code in order to solve a matrix in an iterative way, I am trying to solve x=A\b in every iteration until x --> 0 by changing A and b, in the first 3 iterations work fine until I reach a point where I start getting imaginary numbers in my solution.
Here is my code:
Q,H,n,R are predefined variables.
while(eps > 10^-6)
i=1;j=1;
while(i<11)
A11(i,j) = 1.852*R(i)*(abs(Q(i)))^(n-1);
i=i+1;
j=j+1;
end
A11(11,11) = 2*R(11)*abs(Q(11));
%calculate -dE & dq
dE = [200-H(1)-R(1)*Q(1)^1.852
H(1)-H(2)- R(2)*Q(2)^1.852
H(1)-H(3)-R(3)*Q(3)^1.852
H(2)-H(7)-R(4)*Q(4)^1.852
H(6)-H(5)-R(5)*Q(5)^1.852
H(7)-H(4)-R(6)*Q(6)^1.852
H(6)-H(7)-R(7)*(Q(7))^1.852
H(5)-H(4)-R(8)*Q(8)^1.852
H(3)-H(2)-R(9)*Q(9)^1.852
H(3)-H(4)-R(10)*Q(10)^1.852
0-H(3)+240- R(11)*Q(11)];
dq = [-Q(1)+Q(2)+Q(3)
-Q(2)-Q(9)+Q(4)+4
-Q(11)+Q(9)+Q(10)+6
-Q(10)-Q(6)-Q(8)+5
-Q(5)+Q(8)+5
-Q(3)+Q(7)+Q(5)+5
-Q(4)-Q(7)+Q(6)+3];
%formulate the full set of equations
zero=zeros(nn,nn);
b=[dE;dq];
upA = [A11,A12];
downA=[A21,zero];
A= [upA;downA];
%solve the equations (x=A\b)
x = A\b;
%update Q and H
i=1;j=1;
while (i<8 && j<12)
H(i)= x(11+i)+ H(i);
Q(j)= x(j)+ Q(j);
i=i+1;
j=j+1;
end
%check stopping criteria
j=1;sumeps=0;
while (j<12)
sumeps=sumeps+x(j);
j=j+1;
end
epscal = sumeps/12;
eps=abs(epscal)
end
I realized that i start getting problems when one of the values of vector Q turns negative, and when that value is raised to the power of 1.852 (while calculating dE) it gives an imaginary number!!
Maybe someone knows whre

That's correct. (-1)^N has an imaginary component whenever N has a fractional component.
Most obviously, (-1)^0.5 is just i.

It's not the fact hat the power is bigger than 1, it's the fact that the power is not an integer (i.e. X^2, X^3, ...). Imagine X^0.5 which equals sqrt(X). Obviously that yields an imaginary number for negative values of X.

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.

Matlab 1D wave equation FDM second order in time, fourth order in space

I wrote a function to solve the 1D wave equation with FDM. Therefore i used second order accuracy in time and fourth order in space and an explicit FD scheme.
I already implemented the solver function in Matlab with an matrix-vector-multiplication approach (alternative this can be done iterative) with periodic boundary conditions.
To verify the code i used the Method of Manufactured Solution. My approach is to assume the solution as
p(t,x)=sin(x+t)+sin(x-t)
which is periodic and sufficient smooth and differentiable. I implemented a source term f which is as well as the initial data input for the following function
function [x,t,P_End]= MMS(f,I,G,L,v,T,J,CFL,x)
% Initialisation
deltax=x(2)-x(1);
deltat=CFL*deltax/abs(v);
c=(v*deltat/deltax)^2;
t=(0:deltat:T);
N=length(t);
A=zeros(J,J);
for k=1:J
% periodic boundary condition
if k==1
A(1,1)=-c*5/2;
A(1,2)=c*4/3;
A(1,3)=c/12;
A(1,J-1)=c/12;
A(1,J)=c*4/3;
elseif k==J
A(J,1)=c*4/3;
A(J,2)=c/12;
A(J,J-2)=c/12;
A(J,J-1)=c*4/3;
A(J,J)=-c*5/2;
elseif k==2
A(2,J)=c/12;
A(2,1)=c*4/3;
A(2,2)=-c*5/2;
A(2,3)=c*4/3;
A(2,4)=c/12;
elseif k==J-1
A(J-1,1)=c*1/12;
A(J-1,J-1)=-c*5/2;
A(J-1,J)=c*4/3;
A(J-1,J-2)=c*4/3;
A(J-1,J-3)=c*1/12;
else
A(k,k-2)=c/12;
A(k,k-1)=c*4/3;
A(k,k)=-c*5/2;
A(k,k+1)=c*4/3;
A(k,k+2)=c/12;
end
end
%Allocate memory
P_0=zeros(J,1);
b=zeros(J,1);
H=zeros(J,1);
%Initial data read in
for i=1:J
P_0(i)=I(x(i));
b(i)=f(x(i),t(1));
H(i)=G(x(i));
end
%Calculation of first time step separate because to time steps back
%are needed in the iteration
P_1=0.5*A*P_0+(deltat^2/2)*b+2*deltat*H+P_0;
P_n_minus_1=P_0;
P_n=P_1;
P_End=zeros(N,J); % Solution matrix
P_End(1,:)=P_0;
P_End(2,:)=P_1;
for n=2:N
for i=1:J
b(i)=f(x(i),t(n));
end
%Iterative calculation for t_2,...,t_N
P_n_plus_1=A*P_n+(deltat^2)*b-P_n_minus_1+2*P_n;
%Overwriting
P_n_minus_1=P_n;
P_n=P_n_plus_1;
P_End(n,:)=P_n_plus_1;
end
end
The function call is then
clear all; clc; close all;
%% Initialisierung
% Grid points in space x_0,...x_L
x = -2 : 0.01 : 2;
J = length(x);
xDelta = x(2) - x(1);
T = 2;
v = 0.5; %velocity constant
CFL = 0.5; %Courant Friedrich Lewis number
%Source term right-hand side of the wave equation
f = #(x,t) abs(v^2-1)*(sin(x+t)+sin(x-t));
%Initial data for the estimated sound pressure function p(t,x), t=0
I = #(x) 2*sin(x);
% \partial p/ \partial t , t=0
G = #(x) 0;
[x,t,P_End]= MMS(f,I,G,v,T,J,CFL,x);
This initial data and source term input leads to a solution that proceed like the assumed solution but in range ob `+/- 10^24.
What an i doing wrong here? I already reviewed the code hundred of times but could not detect any code mistakes.
Thanks for any hints!

Matlab : Help in entropy estimation of a disretized time series

This Question is in continuation to a previous one asked Matlab : Plot of entropy vs digitized code length
I want to calculate the entropy of a random variable that is discretized version (0/1) of a continuous random variable x. The random variable denotes the state of a nonlinear dynamical system called as the Tent Map. Iterations of the Tent Map yields a time series of length N.
The code should exit as soon as the entropy of the discretized time series becomes equal to the entropy of the dynamical system. It is known theoretically that the entropy of the system is log_2(2). The code exits but the frst 3 values of the entropy array are erroneous - entropy(1) = 1, entropy(2) = NaN and entropy(3) = NaN. I am scratching my head as to why this is happening and how I can get rid of it. Please help in correcting the code. THank you.
clear all
H = log(2)
threshold = 0.5;
x(1) = rand;
lambda(1) = 1;
entropy(1,1) = 1;
j=2;
tol=0.01;
while(~(abs(lambda-H)<tol))
if x(j - 1) < 0.5
x(j) = 2 * x(j - 1);
else
x(j) = 2 * (1 - x(j - 1));
end
s = (x>=threshold);
p_1 = sum(s==1)/length(s);
p_0 = sum(s==0)/length(s);
entropy(:,j) = -p_1*log2(p_1)-(1-p_1)*log2(1-p_1);
lambda = entropy(:,j);
j = j+1;
end
plot( entropy )
It looks like one of your probabilities is zero. In that case, you'd be trying to calculate 0*log(0) = 0*-Inf = NaN. The entropy should be zero in this case, so you you can just check for this condition explicitly.
Couple side notes: It looks like you're declaring H=log(2), but your post says the entropy is log_2(2). p_0 is always 1 - p_1, so you don't have to count everything up again. Growing the arrays dynamically is inefficient because matlab has to re-copy the entire contents at each step. You can speed things up by pre-allocating them (only worth it if you're going to be running for many timesteps).

Why the number is not randomized using Matlab

I am trying to write a Matlab code to simulate a dice and compute its mean and standard deviation.
The problem is that no matter how many times we run this code, the result of randi(6) keeps the same. It made me crazy.
n=20;
m=0;
c=0;
for i=1:10000
while m<n
x=randi(6);
c=c+1;
m=m+x;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
end
I think you forgot to set m back to ZERO at the end of the for. If you want the sequence of randi to change you should take a look at the function "rng".
n=20;
m=0;
c=1;
for i=1:100
while m<n
x(i, c)=randi(6);
m=m+x(i,c);
c=c+1;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
m = 0;
end
You forgot to reset m and c back to 0 once the while loop terminates. m is set to 0 outside of the for loop only once, and so when m finally surpasses n, m never changes. As such, simply set m = 0 in your for loop before the while loop happens. You also need to set c to 0 because you want to count events each time the for loop iterates.
I'm also not sure how you could think that diff(i) = 2.5 for all i. This difference is a probabilistic value. Also, I don't see how you could get a floating point number in the difference because you are generating integers and accumulating integers for each trial. I think you need to examine what this value should be.
So:
n=20;
%//m=0;
%//c=0;
for i=1:10000
m = 0; %// Change here
c = 0; %// Change here too
while m<n
x=randi(6);
c=c+1;
m=m+x;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
end

Gauss-Seidel method doesn't work for large sparse arrays?

Once again I have a problem with the Gauss-Seidel Method in Matlab. Here it is:
function [x] = ex1_3(A,b)
format long
sizeA=size(A,1);
x=zeros(sizeA,1);
%Just a check for the conditions of the Gauss-Seidel Method (if it has dominant diagonal)
for i=1:sizeA
sum=0;
for j=1:sizeA
if i~=j
sum=sum+abs(A(i,j));
end
end
if abs(A(i,i))<sum
fprintf('\nGauss-Seidel''s conditions not met!\n');
return
end
end
%Actual Gauss-Seidel Method
max_temp=10^(-6); %Pass first iteration
while max_temp>(0.5*10^(-6))
xprevious=x;
for i=1:sizeA
x(i,1)=b(i,1);
for j=1:sizeA
if i~=j
x(i,1)=x(i,1)-A(i,j)*x(j,1);
end
end
x(i,1)=x(i,1)/A(i,i);
end
x
%Calculating infinite norm of vector x-xprevious
temp=x-xprevious;
max_temp=temp(1,1);
for i=2:sizeA
if abs(temp(i,1))>max_temp
max_temp=abs(temp(i,1));
end
end
end
It actually works fine for a 100x100 matrix or smaller. However, my tutor wants it to work for 100000x100000 matrices. At first it was difficult to even create the matrix itself, but I managed to do it with a little help from here:
Matlab Help Center
Now, I call the ex1_3 function with A as a parameter, but it goes really slow. Actually it never ends. How can I make it work?
Here's my code for creating the specific matrix my tutor wanted:
The important part is just that it meets these conditions:
A(i; i) = 3, A(i - 1; i) = A(i; i + 1) = -1 n=100000
b=ones(100000,1);
b(1,1)=2;
b(100000,1)=2;
i=zeros(299998,1); %Matrix with the lines that we want to put nonzero elements
j=zeros(299998,1); %Matrix with the columns that we want to put nonzero elements
s=zeros(299998,1); %Matrix with the nonzero elements.
number=1;
previousNumberJ=0;
numberJ=0;
for k=1:299998 %Our index in i and j matrices
if mod((k-1),3)==0
s(k,1)=3;
else
s(k,1)=-1;
end
if k==1 || k==2
i(k,1)=1;
j(k,1)=k;
elseif k==299997 || k==299998
i(k,1)=100000;
j(k,1)=(k-200000)+2;
else
if mod(k,3)==0
number=number+1;
numberJ=previousNumberJ+1;
previousNumberJ=numberJ;
end
i(k,1)=number;
j(k,1)=numberJ;
numberJ=numberJ+1;
end
end
A=sparse(i,j,s); %Creating the sparse array
x=ex1_3(A,b);
the for loop works very slowly in Matlab, perhaps you may want to try the matrix form of the iteration:
function x=gseidel(A,b)
max_temp=10^(-6); %Pass first iteration
x=b;
Q=tril(A);
r=b-A*x;
for i=1:100
dx=Q\r;
x=x+1*dx;
r=b-A*x;
% convergence check
if all(abs(r)<max_temp) && all(abs(dx)<max_temp), return; end
end
For your A and b, it only takes 16 steps to converge.
tril extracts the lower triangular part of A, you can also obtain this Q when you build up the matrix. Since Q is already the triangular matrix, you can solve the equation Q*dx=r very easily if you are not allowed to use \ function.