I am having some difficulty in solving a simple 2D Poisson equation in Matlab using spectral methods in one direction on finite difference in the other.
I am obtaining a scaled version of the correct answer but can't work out why although I think it has something to do with the wavenumber.
Any help would be greatly appreciated, the code can be seen below.
N = 32;
x = ((0:N-1)/N)*2*pi;
y = ((0:N-1)/N)*2*pi;
dx = 2*pi/N;
k = fftshift(-N/2:N/2-1);
[X,Y] = meshgrid(x,y);
f = (-2)*cos(X).*sin(Y);
f_comparison = cos(X).*sin(Y);
checker = 10;
u = zeros(N,N);
u_new = zeros(N,N);
f_hat = fftn(f);
while checker > 1*10^(-7);
u_new_hat = fftn(u_new);
for aa = 1:N
for a = 1:N
q1 = a+1;
q2 = a-1;
if q2 == 0
q2 = N;
end
if q1 == N+1
q1 = 1;
end
denom = ((dx^2)*((k(aa))^2))+2;
u_new_hat(a,aa) = (1/denom)*((u_new_hat(q1,aa))+(u_new_hat(q2,aa))-((f_hat(a,aa))*(dx^2)));
end
end
u_new = real(ifftn(u_new_hat));
for aa = 1:N
for a = 1:N
u_checker(a,aa) = abs(u_new(a,aa)-u(a,aa));
end
end
compare = max(u_checker);
checker = max(compare);
for aa = 1:N
for a = 1:N
u(a,aa) = u_new(a,aa);
end
end
end
%calculate scaling discrepency
ddd = f_comparison./u;
Related
I am in a numerical analysis class, and I am working on a homework question. This comes Timothy Sauer's Numerical Analysis, and is in the second suggested activity section. I have been talking with my professor about this code, and it seems the error and the approximation are wrong, but neither one of us are able to figure out why. The following code is what I am using, and this is in MatLab. Anyone know enough about Euler Bernoulli beams, and Matlab who can help out?
function ebbeamerror %This is for part three
disp(['tabe of errors at x=L for each n'])
disp([' n ',' Aprox ',' Actual value',' Error'])
disp(['======================================================='])
format bank
for k = 1:11
n = 10*(2^k);
D = sparse(1:n,1:n,6*ones(1,n),n,n);
G = sparse(2:n,1:n-1,-4*ones(1,n-1),n,n);
F = sparse(3:n,1:n-2,ones(1,n-2),n,n);
S = G+D+F+G'+F';
S(1,1) = 16;
S(1,2) = -9;
S(1,3) = 8/3;
S(1,4) = -1/4;
S(2,1) = -4;
S(2,2) = 6;
S(2,3) = -4;
S(2,4) = 1;
S(n-1,n-3)=16/17;
S(n-1,n-2)=-60/17;
S(n-1,n-1)=72/17;
S(n-1,n)=-28/17;
S(n,n-3)=-12/17;
S(n,n-2)=96/17;
S(n,n-1)=-156/17;
S(n,n)=72/17;
E = 1.3e10;
w = 0.3;
d = 0.03;
I = w*d^3/12;
g = -9.81;
f = 480*d*g*w;
h = 2/10;
L = 2;
x = (h^4)*f/(E*I);
x1 = ones(n ,1);
b = x*x1;
size (S);
size(b);
pause
y = S\b;
x=2;
a = (f/(24*E*I))*(x^2)*(x^2-4*L*x+6*L^2);
disp([n y(n) a abs(y(n)-a)])
end
end
I made Clamped Cubic Spline code.
But when I put
f_ = CubicSpline([0,1,2,3],[exp(0),exp(1),exp(2),exp(3)],exp(0),exp(3));
and get answer by sym2poly(f_(1))
result is quite different from my lecture note. And actually, my Cubic Spline result even doesn't match to the prime of bound...
Please I can't understand what is the problem in my code.
This is what I used for my algorithm.
function [f_] = CubicSpline(x0,f0,FPO,FPN)
syms x;
n = length(x0);
h = zeros(n,1);
alpha = zeros(n,1);
l = zeros(n,1);
u = zeros(n,1);
z = zeros(n,1);
a = zeros(n,1);
b = zeros(n,1);
c = zeros(n,1);
d = zeros(n,1);
for iter = 1:n-1
h(iter) = x0(iter+1)-x0(iter);
end
alpha(1) = 3*(f0(2)-f0(1))/h(1)-3*FPO;
alpha(n) = 3*FPN-3*(f0(n)-f0(n-1))/h(n-1);
for iter = 1:n
a(iter) = f0(iter);
end
for iter = 2:n-1
alpha(iter) = 3/h(iter)*(f0(iter+1)-f0(iter))-3/h(iter-1)*(f0(iter)-f0(iter-1));
end
l(1) = 2*h(1);
u(1) = 0.5;
z(1) = f0(1)/l(1);
for iter = 2:n-1
l(iter) = 2*(x0(iter+1)-x0(iter-1)) - h(iter-1)*u(iter-1);
u(iter) = h(iter)/l(iter);
z(iter) = (alpha(iter)-h(iter-1)*z(iter-1))/l(iter);
end
l(n) = h(n-1)*(2-u(n-1));
z(n) = (alpha(n)-h(n-1)*z(n-1))/l(n);
c(n) = z(n);
for iter = (n-1):-1:1
c(iter) = z(iter)-u(iter)*c(iter+1);
b(iter) = (f0(iter+1)-f0(iter))/h(iter)-h(iter)*(c(iter+1)+2*c(iter))/3;
d(iter) = (c(iter+1)-c(iter))/(3*h(iter));
end
for iter = 1:n-1
f_(iter) = a(iter) + b(iter)*(x-x0(iter)) + c(iter)*(x-x0(iter))^2 + d(iter)*(x-x0(iter))^3;
end
end
There is a typo in your code for step 4
z(1) = f0(1)/l(1);
should be
z(1) = alpha(1)/l(1);
This is my Approximate entropy Calculator in MATLAB. https://en.wikipedia.org/wiki/Approximate_entropy
I'm not sure why it isn't working. It's returning a negative value.Can anyone help me with this? R1 being the data.
FindSize = size(R1);
N = FindSize(1);
% N = input ('insert number of data values');
%if you want to put your own N in, take away the % from the line above
and
%insert the % before the N = FindSize(1)
%m = input ('insert m: integer representing length of data, embedding
dimension ');
m = 2;
%r = input ('insert r: positive real number for filtering, threshold
');
r = 0.2*std(R1);
for x1= R1(1:N-m+1,1)
D1 = pdist2(x1,x1);
C11 = (D1 <= r)/(N-m+1);
c1 = C11(1);
end
for i1 = 1:N-m+1
s1 = sum(log(c1));
end
phi1 = (s1/(N-m+1));
for x2= R1(1:N-m+2,1)
D2 = pdist2(x2,x2);
C21 = (D2 <= r)/(N-m+2);
c2 = C21(1);
end
for i2 = 1:N-m+2
s2 = sum(log(c2));
end
phi2 = (s2/(N-m+2));
Ap = phi1 - phi2;
Apen = Ap(1)
Following the documentation provided by the Wikipedia article, I developed this small function that calculates the approximate entropy:
function res = approximate_entropy(U,m,r)
N = numel(U);
res = zeros(1,2);
for i = [1 2]
off = m + i - 1;
off_N = N - off;
off_N1 = off_N + 1;
x = zeros(off_N1,off);
for j = 1:off
x(:,j) = U(j:off_N+j);
end
C = zeros(off_N1,1);
for j = 1:off_N1
dist = abs(x - repmat(x(j,:),off_N1,1));
C(j) = sum(~any((dist > r),2)) / off_N1;
end
res(i) = sum(log(C)) / off_N1;
end
res = res(1) - res(2);
end
I first tried to replicate the computation shown the article, and the result I obtain matches the result shown in the example:
U = repmat([85 80 89],1,17);
approximate_entropy(U,2,3)
ans =
-1.09965411068114e-05
Then I created another example that shows a case in which approximate entropy produces a meaningful result (the entropy of the first sample is always less than the entropy of the second one):
% starting variables...
s1 = repmat([10 20],1,10);
s1_m = mean(s1);
s1_s = std(s1);
s2_m = 0;
s2_s = 0;
% datasample will not always return a perfect M and S match
% so let's repeat this until equality is achieved...
while ((s1_m ~= s2_m) && (s1_s ~= s2_s))
s2 = datasample([10 20],20,'Replace',true,'Weights',[0.5 0.5]);
s2_m = mean(s2);
s2_s = std(s2);
end
m = 2;
r = 3;
ae1 = approximate_entropy(s1,m,r)
ae2 = approximate_entropy(s2,m,r)
ae1 =
0.00138568170752751
ae2 =
0.680090884817465
Finally, I tried with your sample data:
fid = fopen('O1.txt','r');
U = cell2mat(textscan(fid,'%f'));
fclose(fid);
m = 2;
r = 0.2 * std(U);
approximate_entropy(U,m,r)
ans =
1.08567461184858
I have a linear system Ay = b, which is created by matrix looks like this:
Here attempt to find the curves based on the matrix in the image description:
n = 10;
x0 = 0;
xn = 1;
h = 1/n;
y0 = 0;
y1 = 0;
x = zeros(1:n-1);
for i = 1:n-1;
x(i) = i*h
end
A =zeros(n-1);
for j = 1:n-2;
A(j,j+1) = (1+h/2);
A(j,j) = (h*exp(x(j))-2);
A(j+1,j) = (1-h/2);
end
A(n-1,n-1) = (h*exp(x(n-1))-2);
b = zeros(1,n-1); %Right-hand side vector
for i = 1:n-1
b(i)=h^2*((exp(x(i))-pi^2)*sin(pi*x(i))+pi*cos(pi*x(i)));
end
b=b';
y = zeros(1,n-1);
y = inv(A)*b % Solving for y
figure
plot(x,y,x,sin(x))
This is code that I create but the curves disappear, anyone can help me to check my code?
I'm trying to write a cubic spline interpolation program. I have written the program but, the graph is not coming out correctly. The spline uses natural boundary conditions(second dervative at start/end node are 0). The code is in Matlab and is shown below,
clear all
%Function to Interpolate
k = 10; %Number of Support Nodes-1
xs(1) = -1;
for j = 1:k
xs(j+1) = -1 +2*j/k; %Support Nodes(Equidistant)
end;
fs = 1./(25.*xs.^2+1); %Support Ordinates
x = [-0.99:2/(2*k):0.99]; %Places to Evaluate Function
fx = 1./(25.*x.^2+1); %Function Evaluated at x
%Cubic Spline Code(Coefficients to Calculate 2nd Derivatives)
f(1) = 2*(xs(3)-xs(1));
g(1) = xs(3)-xs(2);
r(1) = (6/(xs(3)-xs(2)))*(fs(3)-fs(2)) + (6/(xs(2)-xs(1)))*(fs(1)-fs(2));
e(1) = 0;
for i = 2:k-2
e(i) = xs(i+1)-xs(i);
f(i) = 2*(xs(i+2)-xs(i));
g(i) = xs(i+2)-xs(i+1);
r(i) = (6/(xs(i+2)-xs(i+1)))*(fs(i+2)-fs(i+1)) + ...
(6/(xs(i+1)-xs(i)))*(fs(i)-fs(i+1));
end
e(k-1) = xs(k)-xs(k-1);
f(k-1) = 2*(xs(k+1)-xs(k-1));
r(k-1) = (6/(xs(k+1)-xs(k)))*(fs(k+1)-fs(k)) + ...
(6/(xs(k)-xs(k-1)))*(fs(k-1)-fs(k));
%Tridiagonal System
i = 1;
A = zeros(k-1,k-1);
while i < size(A)+1;
A(i,i) = f(i);
if i < size(A);
A(i,i+1) = g(i);
A(i+1,i) = e(i);
end
i = i+1;
end
for i = 2:k-1 %Decomposition
e(i) = e(i)/f(i-1);
f(i) = f(i)-e(i)*g(i-1);
end
for i = 2:k-1 %Forward Substitution
r(i) = r(i)-e(i)*r(i-1);
end
xn(k-1)= r(k-1)/f(k-1);
for i = k-2:-1:1 %Back Substitution
xn(i) = (r(i)-g(i)*xn(i+1))/f(i);
end
%Interpolation
if (max(xs) <= max(x))
error('Outside Range');
end
if (min(xs) >= min(x))
error('Outside Range');
end
P = zeros(size(length(x),length(x)));
i = 1;
for Counter = 1:length(x)
for j = 1:k-1
a(j) = x(Counter)- xs(j);
end
i = find(a == min(a(a>=0)));
if i == 1
c1 = 0;
c2 = xn(1)/6/(xs(2)-xs(1));
c3 = fs(1)/(xs(2)-xs(1));
c4 = fs(2)/(xs(2)-xs(1))-xn(1)*(xs(2)-xs(1))/6;
t1 = c1*(xs(2)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(1))^3;
t3 = c3*(xs(2)-x(Counter));
t4 = c4*(x(Counter)-xs(1));
P(Counter) = t1 +t2 +t3 +t4;
else
if i < k-1
c1 = xn(i-1+1)/6/(xs(i+1)-xs(i-1+1));
c2 = xn(i+1)/6/(xs(i+1)-xs(i-1+1));
c3 = fs(i-1+1)/(xs(i+1)-xs(i-1+1))-xn(i-1+1)*(xs(i+1)-xs(i-1+1))/6;
c4 = fs(i+1)/(xs(i+1)-xs(i-1+1))-xn(i+1)*(xs(i+1)-xs(i-1+1))/6;
t1 = c1*(xs(i+1)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(i-1+1))^3;
t3 = c3*(xs(i+1)-x(Counter));
t4 = c4*(x(Counter)-xs(i-1+1));
P(Counter) = t1 +t2 +t3 +t4;
else
c1 = xn(i-1+1)/6/(xs(i+1)-xs(i-1+1));
c2 = 0;
c3 = fs(i-1+1)/(xs(i+1)-xs(i-1+1))-xn(i-1+1)*(xs(i+1)-xs(i-1+1))/6;
c4 = fs(i+1)/(xs(i+1)-xs(i-1+1));
t1 = c1*(xs(i+1)-x(Counter))^3;
t2 = c2*(x(Counter)-xs(i-1+1))^3;
t3 = c3*(xs(i+1)-x(Counter));
t4 = c4*(x(Counter)-xs(i-1+1));
P(Counter) = t1 +t2 +t3 +t4;
end
end
end
P = P';
P(length(x)) = NaN;
plot(x,P,x,fx)
When I run the code, the interpolation function is not symmetric and, it doesn't converge correctly. Can anyone offer any suggestions about problems in my code? Thanks.
I wrote a cubic spline package in Mathematica a long time ago. Here is my translation of that package into Matlab. Note I haven't looked at cubic splines in about 7 years, so I'm basing this off my own documentation. You should check everything I say.
The basic problem is we are given n data points (x(1), y(1)) , ... , (x(n), y(n)) and we wish to calculate a piecewise cubic interpolant. The interpolant is defined as
S(x) = { Sk(x) when x(k) <= x <= x(k+1)
{ 0 otherwise
Here Sk(x) is a cubic polynomial of the form
Sk(x) = sk0 + sk1*(x-x(k)) + sk2*(x-x(k))^2 + sk3*(x-x(k))^3
The properties of the spline are:
The spline pass through the data point Sk(x(k)) = y(k)
The spline is continuous at the end-points and thus continuous everywhere in the interpolation interval Sk(x(k+1)) = Sk+1(x(k+1))
The spline has continuous first derivative Sk'(x(k+1)) = Sk+1'(x(k+1))
The spline has continuous second derivative Sk''(x(k+1)) = Sk+1''(x(k+1))
To construct a cubic spline from a set of data point we need to solve for the coefficients
sk0, sk1, sk2 and sk3 for each of the n-1 cubic polynomials. That is a total of 4*(n-1) = 4*n - 4 unknowns. Property 1 supplies n constraints, and properties 2,3,4 each supply an additional n-2 constraints. Thus we have n + 3*(n-2) = 4*n - 6 constraints and 4*n - 4 unknowns. This leaves two degrees of freedom. We fix these degrees of freedom by setting the second derivative equal to zero at the start and end nodes.
Let m(k) = Sk''(x(k)) , h(k) = x(k+1) - x(k) and d(k) = (y(k+1) - y(k))/h(k). The following
three-term recurrence relation holds
h(k-1)*m(k-1) + 2*(h(k-1) + h(k))*m(k) + h(k)*m(k+1) = 6*(d(k) - d(k-1))
The m(k) are unknowns we wish to solve for. The h(k) and d(k) are defined by the input data.
This three-term recurrence relation defines a tridiagonal linear system. Once the m(k) are determined the coefficients for Sk are given by
sk0 = y(k)
sk1 = d(k) - h(k)*(2*m(k) + m(k-1))/6
sk2 = m(k)/2
sk3 = m(k+1) - m(k)/(6*h(k))
Okay that is all the math you need to know to completely define the algorithm to compute a cubic spline. Here it is in Matlab:
function [s0,s1,s2,s3]=cubic_spline(x,y)
if any(size(x) ~= size(y)) || size(x,2) ~= 1
error('inputs x and y must be column vectors of equal length');
end
n = length(x)
h = x(2:n) - x(1:n-1);
d = (y(2:n) - y(1:n-1))./h;
lower = h(1:end-1);
main = 2*(h(1:end-1) + h(2:end));
upper = h(2:end);
T = spdiags([lower main upper], [-1 0 1], n-2, n-2);
rhs = 6*(d(2:end)-d(1:end-1));
m = T\rhs;
% Use natural boundary conditions where second derivative
% is zero at the endpoints
m = [ 0; m; 0];
s0 = y;
s1 = d - h.*(2*m(1:end-1) + m(2:end))/6;
s2 = m/2;
s3 =(m(2:end)-m(1:end-1))./(6*h);
Here is some code to plot a cubic spline:
function plot_cubic_spline(x,s0,s1,s2,s3)
n = length(x);
inner_points = 20;
for i=1:n-1
xx = linspace(x(i),x(i+1),inner_points);
xi = repmat(x(i),1,inner_points);
yy = s0(i) + s1(i)*(xx-xi) + ...
s2(i)*(xx-xi).^2 + s3(i)*(xx - xi).^3;
plot(xx,yy,'b')
plot(x(i),0,'r');
end
Here is a function that constructs a cubic spline and plots in on the famous Runge function:
function cubic_driver(num_points)
runge = #(x) 1./(1+ 25*x.^2);
x = linspace(-1,1,num_points);
y = runge(x);
[s0,s1,s2,s3] = cubic_spline(x',y');
plot_points = 1000;
xx = linspace(-1,1,plot_points);
yy = runge(xx);
plot(xx,yy,'g');
hold on;
plot_cubic_spline(x,s0,s1,s2,s3);
You can see it in action by running the following at the Matlab prompt
>> cubic_driver(5)
>> clf
>> cubic_driver(10)
>> clf
>> cubic_driver(20)
By the time you have twenty nodes your interpolant is visually indistinguishable from the Runge function.
Some comments on the Matlab code: I don't use any for or while loops. I am able to vectorize all operations. I quickly form the sparse tridiagonal matrix with spdiags. I solve it using the backslash operator. I counting on Tim Davis's UMFPACK to handle the decomposition and forward and backward solves.
Hope that helps. The code is available as a gist on github https://gist.github.com/1269709
There was a bug in spline function, generated (n-2) by (n-2) should be symmetric:
lower = h(2:end);
main = 2*(h(1:end-1) + h(2:end));
upper = h(1:end-1);
http://www.mpi-hd.mpg.de/astrophysik/HEA/internal/Numerical_Recipes/f3-3.pdf