Plotting function with a summation produces a wrong result - matlab

I have an equation that needs to be plotted, and the plot is coming out incorrectly.
The equation is as follows:
And the plot should look like this:
But my code:
clear; clc; close all;
eta = 376.7303134617706554679; % 120pi
ka = 4;
N = 24;
coeff = (2)/(pi*eta*ka);
Jz = 0;
theta = [0;0.0351015938948580;0.0702031877897160;0.105304781684574;0.140406375579432;0.175507969474290;0.210609563369148;0.245711157264006;0.280812751158864;0.315914345053722;0.351015938948580;0.386117532843438;0.421219126738296;0.456320720633154;0.491422314528012;0.526523908422870;0.561625502317728;0.596727096212586;0.631828690107444;0.666930284002302;0.702031877897160;0.737133471792019;0.772235065686877;0.807336659581734;0.842438253476592;0.877539847371451;0.912641441266309;0.947743035161167;0.982844629056025;1.01794622295088;1.05304781684574;1.08814941074060;1.12325100463546;1.15835259853031;1.19345419242517;1.22855578632003;1.26365738021489;1.29875897410975;1.33386056800460;1.36896216189946;1.40406375579432;1.43916534968918;1.47426694358404;1.50936853747890;1.54447013137375;1.57957172526861;1.61467331916347;1.64977491305833;1.68487650695319;1.71997810084804;1.75507969474290;1.79018128863776;1.82528288253262;1.86038447642748;1.89548607032233;1.93058766421719;1.96568925811205;2.00079085200691;2.03589244590177;2.07099403979662;2.10609563369148;2.14119722758634;2.17629882148120;2.21140041537606;2.24650200927091;2.28160360316577;2.31670519706063;2.35180679095549;2.38690838485035;2.42200997874520;2.45711157264006;2.49221316653492;2.52731476042978;2.56241635432464;2.59751794821949;2.63261954211435;2.66772113600921;2.70282272990407;2.73792432379893;2.77302591769378;2.80812751158864;2.84322910548350;2.87833069937836;2.91343229327322;2.94853388716807;2.98363548106293;3.01873707495779;3.05383866885265;3.08894026274751;3.12404185664236;-3.12404185664236;-3.08894026274751;-3.05383866885265;-3.01873707495779;-2.98363548106293;-2.94853388716807;-2.91343229327322;-2.87833069937836;-2.84322910548350;-2.80812751158864;-2.77302591769378;-2.73792432379893;-2.70282272990407;-2.66772113600921;-2.63261954211435;-2.59751794821949;-2.56241635432464;-2.52731476042978;-2.49221316653492;-2.45711157264006;-2.42200997874520;-2.38690838485035;-2.35180679095549;-2.31670519706063;-2.28160360316577;-2.24650200927091;-2.21140041537605;-2.17629882148120;-2.14119722758634;-2.10609563369148;-2.07099403979662;-2.03589244590177;-2.00079085200691;-1.96568925811205;-1.93058766421719;-1.89548607032233;-1.86038447642748;-1.82528288253262;-1.79018128863776;-1.75507969474290;-1.71997810084804;-1.68487650695319;-1.64977491305833;-1.61467331916347;-1.57957172526861;-1.54447013137375;-1.50936853747890;-1.47426694358404;-1.43916534968918;-1.40406375579432;-1.36896216189946;-1.33386056800461;-1.29875897410975;-1.26365738021489;-1.22855578632003;-1.19345419242517;-1.15835259853032;-1.12325100463546;-1.08814941074060;-1.05304781684574;-1.01794622295088;-0.982844629056025;-0.947743035161167;-0.912641441266309;-0.877539847371451;-0.842438253476592;-0.807336659581735;-0.772235065686877;-0.737133471792019;-0.702031877897161;-0.666930284002303;-0.631828690107445;-0.596727096212586;-0.561625502317728;-0.526523908422871;-0.491422314528013;-0.456320720633154;-0.421219126738296;-0.386117532843439;-0.351015938948581;-0.315914345053722;-0.280812751158864;-0.245711157264007;-0.210609563369149;-0.175507969474290;-0.140406375579432;-0.105304781684575;-0.0702031877897167;-0.0351015938948580;-2.44929359829471e-16];
for n = 0:N
if n == 0
kappa = 1;
else
kappa = 2;
end
num = (-1.^(n)).*(1i.^(n)).*(cos(n.*theta)).*(kappa);
Hankel = besselh(n,2,ka);
Jz = Jz + ((num./Hankel));
end
Jz = Jz.*coeff;
x = linspace(0,2*pi,length(theta));
plot(x,abs(Jz));
Produces the following incorrect plot:
Note that the values of theta are discrete angles around a circular cylinder.
The equation is the analytical solution to the current density for a TMz polarized cylinder in 2D.

I think that your result is actually correct and this is a simple problem with plotting or with how you specify theta. Since this is a periodic function, lets draw a few more periods:
function q52693512
eta = 376.7303134617706554679; % 120pi
ka = 4;
N = 24;
coeff = (2)/(pi*eta*ka);
Jz = 0;
theta = linspace(-3*pi, 3*pi, 180);
for n = 0:N
kappa = 1 + (n>0);
num = (-1.^(n)).*(1i.^(n)).*(cos(n.*theta)).*(kappa);
Hankel = besselh(n,2,ka);
Jz = Jz + ((num./Hankel));
end
Jz = Jz.*coeff;
figure(); plot(theta, abs(Jz));
You might already be able to see that the desired results is in there but shifted by half a period with respect to our result. This is clearer if we look again at the center (it's exactly the shape you want, if ignoring the horizontal axis values).
Try looking for some justification for ϕ being equal to theta ± π/2 (or something like that).

Related

Negative values obtained in the solution of the 1D advection-dispersion equation using FD method

I am trying to solve the 1D ADE
This is my code so far:
clc; clear; close all
%Input parameters
Ao = 1; %Initial value
L = 0.08; %Column length [m]
nx = 40; %spatial gridpoints
dx = L/nx; %Length step size [m]
T = 20/24; %End time [days]
nt = 100; %temporal gridpoints
dt = T/nt; %Time step size [days]
Vel = dx/dt; %Velocity in each cell [m/day]
alpha = 0.002; %Dispersivity [m]
De = alpha*Vel; % Dispersion coeff. [m2/day]
%Gridblocks
x = 0:dx:L;
t = 0:dt:T;
%Initial and boundary conditions
f = #(x) x; % initial cond.
% boundary conditions
g1 = #(t) Ao;
g2 = #(t) 0;
%Initialization
A = zeros(nx+1, nt+1);
A(:,1) = f(x);
A(1,:) = g1(t);
gamma = dt/(dx^2);
beta = dt/dx;
% Implementation of the explicit method
for j= 1:nt-1 % Time Loop
for i= 2:nx-1 % Space Loop
A(i,j+1) = (A(i-1,j))*(Vel*beta + De*gamma)...
+ A(i,j)*(1-2*De*gamma-Vel*beta) + A(i+1,j)*(De*gamma);
end
% Insert boundary conditions for i = 1 and i = N
A(2,j+1) = A(1,j)*(Vel*beta + De*gamma) + A(2,j)*(1-2*De*gamma-Vel*beta) + A(3,j)*(De*gamma);
A(nx,j+1) = A(nx-1,j)*(Vel*beta + 2*De*gamma) + A(nx,j)*(1-2*De*gamma-Vel*beta)+ (2*De*gamma*dx*g2(t));
end
figure
plot(t, A(end,:), 'r*', 'MarkerSize', 2)
title('A Vs time profile (Using FDM)')
xlabel('t'),ylabel('A')
Now, I have been able to solve the problem using MATLAB’s pdepe function (see plot), but I am trying to compare the result with the finite difference method (implemented in the code above). I am however getting negative values of the dependent variable, but I am not sure what exactly I could be doing wrong. I therefore will really appreciate if anyone can help me out here. Many thanks in anticipation.
PS: I can post the code I used for the pdepe if anyone would like to see it.

spectral solution to 1D KdV equation

I am trying to solve the solution of a 1D KdV equation (ut+uux+uxxx=0) starting from a two solitons initial condition using Fourier spectral method. My code blows up the solution for a reason that I cannot figure out. I would appreciate any help. This is my main code file:
%Spatial variable on x direction
L=4; %domain on x
delta=0.05; %spatial step size
xmin=-L; %minimum boundary
xmax=L; %maximum boundary
N=(xmax-xmin)/delta; %number of spatial points
x=linspace(xmin,xmax,N); %spatial vector
% 1D Initial state
sigma1 = 2; sigma2 = 4;
c1 = 2; c2 = 1;
h1 = 1; h2 = 0.3;
U = h1*sech(sigma2*(x+c1)).^2+h2*sech(sigma1*(x-c2)).^2;
%Fast Fourier Transform to the initial condition
Ut = fftshift(fft(U));
Ut = reshape(Ut,N,1);
%1D Wave vector disretisation
k = (2*pi/L)*[0:(N/2-1) (-N/2):-1];
k(1) = 10^(-6);
k = fftshift(k);
k = reshape(k,N,1);
%first derivative (advection)
duhat = 1i *k .*Ut;
du = real(ifft(ifftshift(duhat))); %inverse of FT
%third derivative (diffusion)
ddduhat = -1i * (k.^3) .*Ut;
dddu = real(ifft(ifftshift(ddduhat))); %inverse of FT
% Time variable
dt = 0.1; %time step
tspan = [0 4];
%solve
Time = 50;
for TimeIteration = 1:2:Time
t= TimeIteration * dt;
[Time,Sol] = ode45('FFT_rhs_1D',tspan,U,[],du,dddu);
Sol = Sol(TimeIteration,:);
%plotting
plot(x,abs(Sol),'b','LineWidth',2);
end
And this is the function that solves the equation:
function rhs = FFT_rhs_1D(tspan,U,dummy,du,dddu)
%solve the right hand side
rhs = - U .* du - dddu;
end
Thank you.

Issue with Discrete Double Fourier Series in MATLAB

The formula for the discrete double Fourier series that I'm attempting to code in MATLAB is:
The coefficient in front of the trigonometric sum (Fourier amplitude) is what I'm trying to extract from the fitting of the data through the double Fourier series seen above. Using my current code, the original function is not reconstructed, therefore my coefficients cannot be correct. I'm not certain if this is of any significance or insight, but the second term for the A coefficients (Akn(1))) is 13 orders of magnitude larger than any other coefficient.
Any suggestions, modifications, or comments about my program would be greatly appreciated.
%data = csvread('digitized_plot_data.csv',1);
%xdata = data(:,1);
%ydata = data(:,2);
%x0 = xdata(1);
lambda = 20; %km
tau = 20; %s
vs = 7.6; %k/s (velocity of CHAMP satellite)
L = 4; %S
% Number of terms to use:
N = 100;
% set up matrices:
M = zeros(length(xdata),1+2*N);
M(:,1) = 1;
for k=1:N
for n=1:N %error using *, inner matrix dimensions must agree...
M(:,2*n) = cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata);
M(:,2*n+1) = sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
end
C = M\ydata;
%least squares coefficients:
A0 = C(1);
Akn = C(2:2:end);
Bkn = C(3:2:end);
% reconstruct original function values (verification check):
y = A0;
for k=1:length(Akn)
y = y + Akn(k)*cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata) + Bkn(k)*sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
% plotting
hold on
plot(xdata,ydata,'ko')
plot(xdata,yk,'b--')
legend('Data','Least Squares','location','northeast')
xlabel('Centered Time Event [s]'); ylabel('J[\muA/m^2]'); title('Single FAC Event (50 Hz)')

Plot the phase structure function of a phase screen by definition

I have already had a phase screen (a 2-D NxN matrix and LxL in size scale, ex: N = 256, L = 2 meters).
I would like to find phase structure function - D(r) defined by D(delta(r)) = <[x(r)-x(r+delta(r))]^2> (<.> is ensemble averaging, r is position in phase screen in meter, x is phase value at a point in phase screen, delta(r) is variable and not fix) in Matlab program. Do you have any suggestion for my purpose?
P/S: I tried to calculate D(r) via the autocorrelation (is defined as B(r)), but this calculation still remaining some approximations. Therefore, I want to calculate precisely the result of D(r). May you please see this image to better understand the definition of D(r) and B(r). Below is my function code to calculate B(r).
% Code copied from "Numerical Simulation of Optical Wave Propagation with Examples in Matlab",
% by Jason D. Schmidt, SPIE Press, SPIE Vol. No.: PM199
% listing 3.7, page 48.
% (Schmidt defines the ft2 and ift2 functions used in this code elswhere.)
function D = str_fcn2_ft(ph, mask, delta)
% function D = str_fcn2_ft(ph, mask, delta)
N = size(ph, 1);
ph = ph .* mask;
P = ft2(ph, delta);
S = ft2(ph.^2, delta);
W = ft2(mask, delta);
delta_f = 1/(N*delta);
w2 = ift2(W.*conj(W), delta_f);
D = 2 * ft2(real(S.*conj(W)) - abs(P).^2, delta) ./ w2 .*mask;`
%fire run
N = 256; %number of samples
L = 16; %grid size [m]
delta = L/N; %sample spacing [m]
F = 1/L; %frequency-domain grid spacing[1/m]
x = [-N/2 : N/2-1]*delta;
[x y] = meshgrid(x);
w = 2; %width of rectangle
%A = rect(x/2).*rect(y/w);
A = lambdaWrapped;
%A = phz;
mask = ones(N);
%perform digital structure function
C = str_fcn2_ft(A, mask, delta);
C = real(C);
One way of directly computing this function D(r) is through random sampling: you pick two random points on your screen, determine their distance and phase difference squared, and update an accumulator:
phi = rand(256,256)*(2*pi); % the data, phase
N = size(phi,1); % number of samples
L = 16; % grid size [m]
delta = L/N; % sample spacing [m]
D = zeros(1,sqrt(2)*N); % output function
count = D; % for computing mean
for n = 1:1e6 % find a good amount of points here, the more points the better the estimate
coords = randi(N,2,2);
r = round(norm(coords(1,:) - coords(2,:)));
if r<1
continue % skip if the two coordinates are the same
end
d = phi(coords(1,1),coords(1,2)) - phi(coords(2,1),coords(2,2));
d = mod(abs(d),pi); % you might not need this, depending on how A is constructed
D(r) = D(r) + d.^2;
count(r) = count(r) + 1;
end
I = count > 0;
D(I) = D(I) ./ count(I); % do not divide by 0, some bins might not have any samples
I = count < 100;
D(I) = 0; % ignore poor estimates
r = (1:length(D)) * delta;
plot(r,D)
If you need even more precision, consider interpolating. Compute random coordinates as floating-point values, and interpolate the phase to get the values in between samples. D then needs to be longer, indexed as round(r*10) or something like that. You will need many more random samples to fill up that much larger accumulator.

Why is my matlab plot not evolving using finite difference method?

I am trying to use a finite difference method to solve the heat equation for a given function u0. I want to evolve it in time using plots to see each frame change but when I run it all I see is the same frame over and over. I am aware of the error at the ends due to me not giving "u" a first or last index which will cause more overall error in the solution. I am not very good at matlab so I am not sure if I am writing my nested piece correctly.
% set up domain in time and space
t_step = .1;
tspan = [0 :t_step:1000];
L = 10; %length of domain
n = 64;
dx = 2*pi/(n-1); %spacing
x = 0:dx:2*pi;
x = x'; %make x vertical vector
% initial conditions for the function
u0 = sin(2*pi*x/L)+0*cos(3*2*pi*x/L) + 0.2*(cos(5*2*pi*x/L))+0*randn(size(x));
plot(x,u0);title('initial condition');pause;
t = 0;
for m = 1:tspan(end)
u = u0;
t = t + t_step;
for j= 2:n-1
u(j,m) = u0(j-1) - 2*u0(j) + u0(j+1)/dx^2; %u(1) and n left out
end
plot(x,u(:,m))
pause(0.01);
end