spectral solution to 1D KdV equation - matlab

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.

Related

Applying ode15s to solve a spatial discretization using finite difference for multiple variables

I am trying to run the following ode15s with three variables, C1, q1 and phi1. However, I keep on receiving the following warning:
Warning: Failure at t=1.163115e-13. Unable to meet integration
tolerances without reducing the step size below the smallest value
allowed (4.038968e-28) at time t.
The simulation runs correctly if I do not include the dq1_over_dt term in the ode15s solver, so issue is definitely there. If the simulation runs correctly, the result is a Y matrix of 486X360 dimensions.
Any practical advice is welcomed.
%-------------------------------------------------------------------------%
% Chromatography Simulation 1
% By Santiago Taguado
% Chromatogram Simulation
%-------------------------------------------------------------------------%
close all; clear variables; clc;
% Global variables (meaning reported below)
global u Dax N h isopar K eps v Dphi phi_in Cin mod_gradient
%-------------------------------------------------------------------------%
% Chromatography with variable boundaries
%-------------------------------------------------------------------------%
L = 25; % Length (cm)
Q = 2.513; % Flow Rate (mL/min)
D = 0.8; % Diameter of Column (cm)
S = pi()*(D/2)^2; % Column Cross Section (cm2)
eps = 0.7; % Void Fraction
u = Q/S; % superficial velocity (cm/min)
v = u/eps; %intersitial velocity
Dax = 0.039/u; % axial dispersion (cm)
Dphi = 0.039/u; % axial dispersion (cm)
N = 120; % number of grid points (-)
alpha1 = 149421.036; % Parameter 1
alpha2 = -3.054; % Sensibility variable 1
alpha3 = 500; % Parameter 2
alpha4 = 500; % Sensibility variable 2
isopar = [alpha1 alpha2 alpha3 alpha4];
K = 3; % Linear Driving Force
eps = 0.7; % Void Fraction
%-------------------------------------------------------------------------%
% Preprocessing
%-------------------------------------------------------------------------%
h = L/(N-1); % grid spacing (cm)
nt = 3000; % number of time steps
t_load = 8; % loading time,min
t_tot = 49;
dt = t_tot/(nt-1);
%-------------------------------------------------------------------------%
% Solution via ode15s solver for Loading Phase
%-------------------------------------------------------------------------%
C1 = [0; zeros(N-1,1)]; % Initial Conditions
q1 = [0;zeros(N-1,1)];
phi = [0;zeros(N-1,1)];
Y = [C1;q1;phi];
phi_in = 0.02;
Cin = 1.085; % initial concentration (mg/mL)
mod_gradient = 0;
tspan = 0:dt:t_load;
[t, Y] = ode15s(#ODESystem, tspan, Y);
%-------------------------------------------------------------------------%
% ODE system
%-------------------------------------------------------------------------%
function dY = ODESystem(t,Y)
global u Dax N h Dphi v phi_in Cin mod_gradient eps isopar
C1 = Y(1:N);
q1 = Y(N+1:N*2);
phi = Y(N*2+1:N*3);
dC1_over_dt = zeros(N,1);
dq1_over_dt = zeros(N,1);
dphi_over_dt = zeros(N,1);
% Boundary # x=0
dC1_over_dt(1) = (Cin(1) + Dax/u/h*C1(2))/(1+Dax/u/h);
dq1_over_dt(1) = 0;
dphi_over_dt(1) = (phi_in + mod_gradient*t + Dphi/v/h*phi(2))/(1+Dphi/v/h);
% Internal points
for i=2:N-1
% Isotherm Value
H1 = isopar(1)*phi(i)^isopar(2); H1(isinf(H1)) = 0;
q_inf1 = isopar(3)*H1/(1+H1); q_inf1(isnan(q_inf1)) = 0;
denom = 1 + C1(i)*H1/q_inf1; denom(isnan(denom)) = 1;
qstar1 = C1(i)*H1/denom;
dq1_over_dt(i) = eps/(1-eps)*(qstar1 - q1(i));
% Species, 1
dC1_over_dx = (C1(i-1)-C1(i))/(h);
d2C1_over_dx2 = (C1(i+1)-2.*C1(i)+C1(i-1))/h^2;
% Modifier,1
dphi_over_dx = (phi(i-1)-phi(i))/(h);
d2phi_over_dx2 = (phi(i+1)-2.*phi(i)+phi(i-1))/h^2;
dphi_over_dt(i) = u*dphi_over_dx + ...
Dphi*d2phi_over_dx2;
dC1_over_dt(i) = v*dC1_over_dx + Dax*d2C1_over_dx2;
end
% Boundary # x=L
dC1_over_dt(N) = dC1_over_dt(N-1);
dq1_over_dt(N) = dq1_over_dt(N-1);
dphi_over_dt(N) = dphi_over_dt(N-1);
dY = [dC1_over_dt;dq1_over_dt;dphi_over_dt];
end

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.

Plotting function with a summation produces a wrong result

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).

NaN response in ode45 Matlab

I'm using ode45 to solve position variables against time, but after the initial conditions, I only get NaN response for all the 4 variables.
Here is my function code:
function dxdt = ode(t,x)
global m b a x_teta k_lin k_tor Ip U Pinf gama
m = 5; % Mass
b = 1.5; % Semi-chord
a = 0; % Reference point to displacement -1 <= a <= 1
x_teta = 0; % Static unbalanced parameter -> e - a
k_lin = 10; % Linear stiffness
k_tor = 10; % Torsional stiffness
Ip = 5; % Inertia
U = 10; % Velocity
Pinf = 1.184; % Air density
gama = 2*pi*Pinf*b*U^2; % Constant numbers from L
% x(1) = h % x(2) = dh/dt % x(3) = teta % x(4) = dteta/dt
dxdt = [x(2);(-gama*x(3)-k_lin*x(1)-m*b*x_teta*(1/Ip)*(b*(.5+a)*gama*x(3)-k_tor*x(3)))/(m+(m^2*b^2*x_teta^2)/Ip);x(4);(-gama*x(3)-k_lin*x(1)-(b*(.5+a)*gama*x(3)-k_tor*x(3))/(b*x_teta))/(m*b*x_teta-(Ip)/(b*x_teta))]
And the implementation code:
tspan = 0:.01:20; x0 = [60; 0; 5; 0];
[t,x] = ode45(#ode,tspan,x0)
I suspect there's something wrong about the physics for setting up this ODE.
In this expression for the 4th element of dxdt, there is a division by x_teta, which is set to zero.
dxdt(4) = (-gama*x(3)-k_lin*x(1)-(b*(.5+a)*gama*x(3)-k_tor*x(3))/(b*x_teta))/(m*b*x_teta-(Ip)/(b*x_teta))
This division by zero leads to one NaN, and propagates to the other elements as the ODE is iteratively solved.

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)')