Understanding 1D FFT on 3D data using MATLAB - matlab

Could someone kindly explain what the following MATLAB line do?
fft( data3D, N, dim );
data3D is an array of size (NY, NX, NZ). MATLAB documentation says
fft(X,[],DIM) or fft(X,N,DIM) applies the fft operation across the dimension DIM.
What exactly fft calculates across a dimension when the input is a 3D array?

To expand on #Oliver Charlesworth, the command fft(X,[],DIM) should do this:
fft_values=zeros(size(X)); %pre-allocate the output array
if (DIM==1)
for I=1:size(X,2)
for J=1:size(X,3)
fft_values(:,I,J) = fft(squeeze(X(:,I,J));
end
end
elseif (DIM==2)
for I=1:size(X,1)
for J=1:size(X,3)
fft_values(I,:,J) = fft(squeeze(X(I,:,J));
end
end
elseif (DIM==3)
for I=1:size(X,1)
for J=1:size(X,2)
fft_values(I,J,:) = fft(squeeze(X(I,J,:));
end
end
end

Related

Plotting multiple vectors of different lengths on the same figure

I am currently working on a project in MATLAB that compares two different numerical methods (direct and iterative), each for two different matrix sizes, to the actual analytic solution of the system. The first .m file included below provides an implementation of a tridiagonal matrix solver, where the main function plots a solution for two different sizes of tridiagonal matrices: a 2500x2500 matrix and 50x50 matrix.
function main
n=50;
for i=1:2
di=2*ones(n,1);
up=-ones(n,1);
lo=-ones(n,1);
b=ones(n,1)/(n*n);
[subl,du,supu]=tridiag_factor(lo,di,up);
usol = tridiag_solve(subl,du,supu,b);
%figure(i)
plot(usol);
hold on;
title(['tridiag ' num2str(n) ''])
n=2500;
end
function [subl,du,supu]=tridiag_factor(subd,d,supd)
n=length(d);
for i=1:n-1
subd(i)=subd(i)/d(i);
d(i+1)=d(i+1)-subd(i)*supd(i);
end
subl=subd; supu=supd; du=d;
function x = tridiag_solve(subl,du,supu,b)
% forward solve
n=length(b); z=b;
z(1)=b(1);
for i=2:n
z(i)=b(i)-subl(i)*z(i-1);
end
% back solve
x(n)=z(n);
for i=n-1:-1:1
x(i)=(z(i)-supu(i)*x(i+1))/du(i);
end
I have included a hold on statement after the first usol is plotted so I can capture the second usol on the same figure during the second iteration of the for loop. The next piece of code is a Jacobi method that iteratively solves a system for a tridiagonal matrix. In my case, I have constructed two tridiagonal matrices of different sizes which I will provide after this piece of code:
function [xf,r] = jacobi(A,b,x,tol,K)
%
% The function jacobi applies Jacobi's method to solve A*x = b.
% On entry:
% A coefficient matrix of the linear system;
% b right-hand side vector of the linear system;
% x initial approximation;
% eps accuracy requirement: sx=top when norm(dx) < eps;
% K maximal number of steps allowed.
% On return:
% x approximation for the solution of A*x = b;
% r residual vector last used to update x,
% if success, then norm(r) < eps.[
%
n = size(A,1);
fprintf('Running the method of Jacobi...\n');
for k = 1:K
% r = b - A*x;
for i=1:n
sum=0;
for j = 1:n
if j~=i
sum=sum+A(i,j)*x(j);
end
end
x(i)=(b(i)-sum)/(A(i,i));
end;
k=k+1;
r = b - A*x;
% fprintf(' norm(r) = %.4e\n', norm(r));
if (norm(r) < tol)
fprintf('Succeeded in %d steps\n', k);
return;
end;
end
fprintf('Failed to reached accuracy requirement in %d steps.\n', K);
xf=x;
%r(j) = r(j)/A(j,j);
%x(j) = x(j) + r(j);
Now, lastly, here is my code for the two tridiagonal matrices (and other related information for each system corresponding to the appropriate matrices) I wish to use in my two jacobi function calls:
% First tridiagonal matrix
n=50;
A_50=full(gallery('tridiag', n, -1, 2, -1));
% Second tridiagonal matrix
n=2500;
A_2500=full(gallery('tridiag', n, -1, 2, -1));
K=10000;
tol=1e-6;
b_A50=ones(length(A_50), 1);
for i=1:length(A_50)
b_A50(i,1)=0.0004;
end
x_A50=ones(length(A_50),1);
b_A2500=ones(length(A_2500), 1);
for i=1:length(A_2500)
b_A2500(i,1)= 1.6e-7;
end
x_A25000=ones(length(A_2500),1);
As stated in the question header, I need to plot the vectors produced from jacobi(A_50,b_A50,x_A50,tol,K), jacobi(A_2500,b_A2500,x_A25000,tol,K) and a mathematical function y=#(x) -0.5*(x-1)*x all on the same figure along with the two usol (for n=50 and n=2500) produced by the main function shown in the first piece of code, but I have had no luck due to the different lengths of vectors. I understand this is probably an easy fix, but of course my novice MATLAB skills are not sufficing.
Note: I understand x_A50 and x_A2500 are trivial choices for x, but I figured while I ask for help I better keep it simple for now and not create any more issues in my code.
In MATLAB traces sent to same plot must have same length.
I have allocated just one variable containing all traces, for the respective tridiagonals and resulting traces out of your jacobi function.
I have shortened from 2500 to 250, and the reason is that with 2500, compared to 50, the tridiag traces, and the short jacobi are so flat compared to the last trace than one has to recur to dB scale to find them on same graph window as you asked.
1st generate all data, and then plot all data.
So here you have the script plotting all traces in same graph :
clear all;close all;clc
n=[50 250];
us_ol=zeros(numel(n),max(n));
% generate data
for k=[1:1:numel(n)]
di=2*ones(n(k),1);
up=-ones(n(k),1);
lo=-ones(n(k),1);
b=ones(n(k),1)/(n(k)*n(k));
[subl,du,supu]=tridiag_factor(lo,di,up);
us_ol0 = tridiag_solve(subl,du,supu,b);
us_ol(k,[1:numel(us_ol0)])=us_ol0;
end
n_us_ol=[1:1:size(us_ol,2)];
str1=['tridiag ' num2str(n(1))];
str2=['tridiag ' num2str(n(2))];
legend(str1,str2);
grid on
% the jacobi traces
nstp=1e3;
tol=1e-6;
A1=zeros(max(n),max(n),numel(n));
for k=1:1:numel(n)
A0=full(gallery('tridiag', n(k), -1, 2, -1));
A1([1:1:size(A0,1)],[1:1:size(A0,2)],k)=A0;
end
b_A1=ones(max(n),max(n),numel(n));
for k=1:1:numel(n)
for i=1:n(k)
b_A1(i,1,k)=0.0004;
end
end
n_A1=[1:1:size(A1,1)];
jkb=zeros(numel(n),max(n));
for k=1:1:numel(n)
A0=A1([1:n(k)],[1:n(k)],k);
b_A0=b_A1([1:n(k)],[1:n(k)],k);
n0=[1:1:n(k)];
jkb0=jacobi(A0,b_A0,n0',tol,nstp)
jkb(k,[1:numel(jkb0)])=jkb0';
end
% plot data
figure(1)
ax1=gca
plot(ax1,n_us_ol,us_ol(1,:),n_us_ol,us_ol(2,:));
hold(ax1,'on')
plot(ax1,n_A1,jkb(1,:),n_A1,jkb(2,:))
grid on
legend('3/1','3/2','jkb1','jkb2')
title('3diags and jakobians graph')
As mentioned above, one has to zoom to find some of the traces
One way to combine really small traces with large traces is to use Y log scale
figure(2)
ax2=gca
plot(ax2,n_us_ol,10*log10(us_ol(1,:)),n_us_ol,10*log10(us_ol(2,:)));
hold(ax2,'on')
plot(ax2,n_A1,10*log10(jkb(1,:)),n_A1,10*log10(jkb(2,:)))
grid on
legend('3/1[dB]','3/2[dB]','jkb1[dB]','jkb2[dB]')
title('3diags and jakobians graph in dB')

Problem in 2D heat equation solution using FDM in Matlab

I am trying to solve the 2D time dependent heat equation using finite difference method in Matlab. The code is below:
%Spatial variable on x direction
Lx=1;
delta=0.1;
xmin=-Lx/2;
xmax=Lx/2;
Nx=(xmax-xmin)/delta;
x=linspace(xmin,xmax,Nx);
%Spatial variable on y direction
Ly=1;
delta=0.1;
ymin=-Ly/2;
ymax=Ly/2;
Ny=(ymax-ymin)/delta;
y=linspace(ymin,ymax,Ny);
%Total matrix size
N = (Nx * Ny);
%Time variable
dt=0.002;
tmin=0;
tmax=1;
nt=(tmax-tmin)/dt;
tspan=linspace(tmin,tmax,nt);
%Create a meshgrid
[X,Y] = meshgrid(x,y);
% Defining initial state:
T0=exp(-(X.^2+Y.^2));
%reshape the initial condition to a vector
T_reshape = reshape(T0,N,1);
% Constructing the 1D spatial matrix
A=zeros(N,N);
I = eye(N);
%the diagonal elements
for m=1:N %the number of rows
for n=1:N %the number of columns
if (m==n)
A(m,n)=-2/delta^2;
end
%Boundary conditions: A(1,N)==A(N,1)
if(n==N)&&(m==1)
A(m,n)=1;
end
if(n==1)&&(m==N)
A(m,n)=1;
end
end
end
%the off-diagonal elements
for n=1:N-1
A(n+1,n)=1/delta^2; %the value of each lower off-diagonal elements
end
for n=2:N
A(n-1,n)=1/delta^2; %the value of each upper off-diagonal element
end
%create the 2D matrix
B = kron(A,I)+kron(I,A);
% Solve the equation
[Time,Tem]=ode45('dTDistribution',tspan,T_reshape,[],B,delta);
The function that is being called here is as following:
%Define the function
function dT=dTDistribution(tspan,T_reshape,dummy,B,delta)
dT = B.*T_reshape;
end
My problem is that the dimension of my matrix B is different than the dimensions of the initial condition T_reshape, therefore, the multiplication of B.*T_reshape won't be possible. I'm wondering how can I change the dimension of T_reshape to make the multiplication valid. Hope anyone could help.
Thank you.
Thank you for looking at my problem, but I have figured out the mistake in the code. Since A is the 1D matrix, then its size should be either (Nx,Nx) or (Ny,Ny) and then when taking the tensor product to get B the 2D matrix its size will be (N,N). However in the code, A has the size of (N,N) and as a result B is blowing up making the multiplication afterwards not possible.
Thanks.

Matlab: Fourier coefficients

I have a problem with my code. My objective is to obtain the Fourier coefficients with the passage matrices. Then use the fft and check that my two results are the same. But I get different results and I don't understand why?
clear all;
N=[50];
for k=1:length(N)
Dx=1/(N(k)-1);
x=linspace(0,1-Dx,N(k));
for j=1:N(k)
f(j,k)=100.*exp(-20*x(j))*(x(j)-(x(j)).^2);
end
for j=1:N(k)
for m=1:N(k)
Mphsp(j,m)=exp((2*pi*i*(m-1)*(j-1))/N(k));
Mspph(j,m)=(1/N(k)).*exp(-(2*pi*i*(m-1)*(j-1))/N(k));
end
end
Idd=Mphsp*Mspph;
coeff(1:N(k),k)=Mspph*f(1:N(k),k);
coeff2(1:N(k),k)=fft(f(1:N(k),k));
verf(1:N(k),k)=coeff2(1:N(k),k)-coeff(1:N(k),k);
end
If anyone has any ideas? Please.
Your for loop is wrong. length(N) = 1, because N is a 1x1 matrix.
clear all;
N=[50];
for k=1:length(N)
I suppose you want to do something like
N = zeros(50, 1);
for k = 1:50
N(k) = k;
end
for k=1:length(N)
...

How do i create my own convolution code on Matlab without using the built-in function

I am trying to create a program on Matlab to show the convolution of 2 signals but without using the 'conv' function.
The input is ๐‘ฃ(๐‘ก)=๐‘’xp(-4t+4)*๐‘ข(๐‘กโˆ’1)+0.5๐‘ข(๐‘กโˆ’5)+2๐›ฟ(๐‘กโˆ’10)
I have worked out that h(t) = 4*exp(-4t)*u(t). I am trying to make a program on MATLAB to compute and display the convolution of two arrays representing two signals but without using the built-in 'conv' function.
I have a working code but it includes 'conv' and so I am trying to do it without using this.
t=linspace(0,11,1101);
%create more than 500 time-series values
vs=exp(-4*(t-1)).*heaviside(t-1)+0.5*heaviside(t-5)+2*dirac(t-10);
%Input signal array
h=4*exp(-4*t).*heaviside(t);
%Input signal array
vc=conv(vs,h);
t1=linspace(0,22,2201);
%Convolution of two arrays
subplot(3,1,1)
plot(t,vs)
xlabel('t')
ylabel('v_s(t)')
title('Input signal')
subplot(3,1,2)
plot(t,h)
xlabel('t')
ylabel('h(t)')
title('System impulse response')
subplot(3,1,3)
plot(t1,vc)
xlabel('t')
ylabel('v_c(t)')
title('Output signal')
Try replacing the conv line with this:
N = length(vs);
M = length(h);
lout=N+M-1;
vc=zeros(1,lout);
for i = 1:N
for k = 1:M
vc(i+k-1) = vc(i+k-1) + h(k)*vs(i);
end
end
It is a basic matlab implementation of the convolution formula

determine dimension of matrix under some conditions

suppose that we have matrix with size mXn, and i want to return matrix which contains elements of original matrix at odd indices,i wrote function which is called odd_index, for instance here is code
function B=odd_index(M);
% M- is given matrix
% purpose of this code is to return elements at odd indices
[m,n]=size(M);% calculate dimensions of matrix
B=[];%initialize matrices
% let run loops
i=1;
for k=1:m
for l=1:n
if (mod(k,2)==1 && mod(l,2)==1)
B(k,i)=M(k,l);
i=i+1;
end
end
end
B=B(B>0);
B=reshape(B,2,2);
end
for instance
(1,1,),(1,3),(3,1),(1,5),(5,1),(3,5),(5,3),(3,3),(5,5),(1,7)
and so on, what will be dimension of such matrix? i think it will be (m-2)X(n-4) but i am not sure about this and please could you help me?
solution will be by help of # Divakar
M(1:2:end,1:2:end)