Related
The IBVP is
u_t+2u_x=0 , 0<x<1, t>0
u(x,0)=sin(pi*x)
u(0,t)=g(t)=sin(-2*pi*t)
I have to first implement the scheme using 4th-order central difference SBP operator in space and RK4 in time with spacing xi=i*h, i=0,1,...,N and update g(t) at every RK stage. Also, using the code compute the convergence rate on a sequence of grids.
Below I have shown my working which is not helping me find the convergence rate so can anyone help me with finding my mistakes.
%Parameters
nstp = 16; %number of grid points in space
t0 = 0; %initial time
tend = 1; %end time
x0 = 0; %left boundary
xN = 1; %right boundary
x = linspace(0,1,nstp); %points in space
h = xN-x0/nstp-1; %grid size
cfl = 4;
k = cfl*h; %length of time steps
N = ceil(tend/k); %number of steps in time
k = tend/N; %length of time steps
u0 = sin(pi*x); %initial data
e = zeros(nstp);
e(1) = 1;
e0 = e(:,1);
m = zeros(nstp);
m(1) = sin(-2*pi*tend);
g = m(:,1);
%4th order central SBP operator in space
m=10; %points
H=diag(ones(m,1),0);
H(1:4,1:4)=diag([17/48 59/48 43/48 49/48]);
H(m-3:m,m-3:m)=fliplr(flipud(diag([17/48 59/48 43/48 49/48])));
H=H*h;
HI=inv(H);
D1=(-1/12*diag(ones(m-2,1),2)+8/12*diag(ones(m-1,1),1)- ...
8/12*diag(ones(m-1,1),-1)+1/12*diag(ones(m-2,1),-2));
D1(1:4,1:6)=[-24/17,59/34,-4/17,-3/34,0,0; -1/2,0,1/2,0,0,0;
4/43,-59/86,0,59/86,-4/43,0; 3/98,0,-59/98,0,32/49,-4/49];
D1(m-3:m,m-5:m)=flipud( fliplr(-D1(1:4,1:6)));
D1=D1/h;
%SBP-SAT scheme
u = -2*D1*x(1:N-1)'-(2*HI*(u0-g)*e);
%Runge Kutta for ODE
for i=1:nstp %calculation loop
t=(i-1)*k;
k1=D*u;
k2=D*(u+k*k1/2);
k3=D*(u+k*k2/2);
k4=D*(u+k*k3);
u=u+(h*(k1+k2+k3+k4))/6; %main equation
figure(1)
plot(x(1:N-1),u); %plot
drawnow
end
%error calculcation
ucorrect = sin(pi*(x-2*tend)); %correct solution
ucomp = u(:,end); %computed solution
errornorm = sqrt((ucomp-ucorrect)'*H*(ucomp-ucorrect)); %norm of error**
One egregious error is
h = xN-x0/nstp-1; %grid size
You need parentheses here, else you compute h as xN-(x0/nstp)-1=1-(0/nstp)-1=0.
Or avoid this all and use the actual grid step. Also, if nstp is the number of steps or segments in the subdivision, the number of nodes is one larger. And if you define x0,xN then you should also actually use them.
x = linspace(x0,xN,nstp+1); %points in space
h = x(2)-x(1); %grid size
As to the SBP-SAT approach, the space discretization gives
u_t(t) + 2*D_1*u(t) = - H_inv * (dot(e_0,u(t)) - g(t))*e_0
which should give the MoL ODE function as
F = #(u,t) -2*D1*u - HI*e0*(u(1)-g(t))
The matrix construction has to be adapted to have the correct extends for these changed operations.
The implement RK4 as
k1 = F(u,t)
k2 = F(u+0.5*h*k1, t+0.5*h)
...
In total this gives a modified script below. Stable solutions only occur for cfl=1 or below. With that the errors seemingly behave like 4th order. The factor for the initial condition also works best in the range 0.5 to 1, larger factors tend to increase the error at x=0, at least in the initial time steps. With the smaller factors the error is uniform over the interval.
%Parameters
xstp = 16; %number of grid points in space
x0 = 0; %left boundary
xM = 1; %right boundary
x = linspace(x0,xM,xstp+1)'; %points in space
h = x(2)-x(1); %grid size
cfl = 1;
t0 = 0; %initial time
tend = 1; %end time
k = cfl*h; %length of time steps
N = ceil(tend/k); %number of steps in time
k = tend/N; %length of time steps
u = sin(pi*x); %initial data
e0 = zeros(xstp+1,1);
e0(1) = 1;
g = #(t) sin(-2*pi*t);
%4th order central SBP operator in space
M=xstp+1; %points
H=diag(ones(M,1),0); % or eye(M)
H(1:4,1:4)=diag([17/48 59/48 43/48 49/48]);
H(M-3:M,M-3:M)=fliplr(flipud(diag([17/48 59/48 43/48 49/48])));
H=H*h;
HI=inv(H);
D1=(-1/12*diag(ones(M-2,1),2)+8/12*diag(ones(M-1,1),1)- ...
8/12*diag(ones(M-1,1),-1)+1/12*diag(ones(M-2,1),-2));
D1(1:4,1:6) = [ -24/17, 59/34, -4/17, -3/34, 0, 0;
-1/2, 0, 1/2, 0, 0, 0;
4/43, -59/86, 0, 59/86, -4/43, 0;
3/98, 0, -59/98, 0, 32/49, -4/49 ];
D1(M-3:M,M-5:M) = flipud( fliplr(-D1(1:4,1:6)));
D1=D1/h;
%SBP-SAT scheme
F = #(u,t) -2*D1*u - 0.5*HI*(u(1)-g(t))*e0;
clf;
%Runge Kutta for ODE
for i=1:N %calculation loop
t=(i-1)*k;
k1=F(u,t);
k2=F(u+0.5*k*k1, t+0.5*k);
k3=F(u+0.5*k*k2, t+0.5*k);
k4=F(u+k*k3, t+k);
u=u+(k/6)*(k1+2*k2+2*k3+k4); %main equation
figure(1)
subplot(211);
plot(x,u,x,sin(pi*(x-2*(t+k)))); %plot
ylim([-1.1,1.1]);
grid on;
legend(["computed";"exact"])
drawnow
subplot(212);
plot(x,u-sin(pi*(x-2*(t+k)))); %plot
grid on;
hold on;
drawnow
end
%error calculcation
ucorrect = sin(pi*(x-2*tend)); %correct solution
ucomp = u; %computed solution
errornorm = sqrt((ucomp-ucorrect)'*H*(ucomp-ucorrect)); %norm of error**
I am programming a simple perceptron in matlab but it is not converging and I can't figure out why.
The goal is to binary classify 2D points.
%P1 Generate a dataset of two-dimensional points, and choose a random line in
%the plane as your target function f, where one side of the line maps to +1 and
%the other side to -1. Let the inputs xn 2 R2 be random points in the plane,
%and evaluate the target function f on each xn to get the corresponding output
%yn = f(xn).
clear all;
clc
clear
n = 20;
inputSize = 2; %number of inputs
dataset = generateRandom2DPointsDataset(n)';
[f , m , b] = targetFunction();
signs = classify(dataset,m,b);
weights=ones(1,2)*0.1;
threshold = 0;
fprintf('weights before:%d,%d\n',weights);
mistakes = 1;
numIterations = 0;
figure;
plotpv(dataset',(signs+1)/2);%mapping signs from -1:1 to 0:1 in order to use plotpv
hold on;
line(f(1,:),f(2,:));
pause(1)
while true
mistakes = 0;
for i = 1:n
if dataset(i,:)*weights' > threshold
result = 1;
else
result = -1;
end
error = signs(i) - result;
if error ~= 0
mistakes = mistakes + 1;
for j = 1:inputSize
weights(j) = weights(j) + error*dataset(i,j);
end
end
numIterations = numIterations + 1
end
if mistakes == 0
break
end
end
fprintf('weights after:%d,%d\n',weights);
random points and signs are fine since plotpv is working well
The code is based on that http://es.mathworks.com/matlabcentral/fileexchange/32949-a-perceptron-learns-to-perform-a-binary-nand-function?focused=5200056&tab=function.
When I pause the infinite loop, this is the status of my vairables:
I am not able to see why it is not converging.
Additional code( it is fine, just to avoid answers asking for that )
function [f,m,b] = targetFunction()
f = rand(2,2);
f(1,1) = 0;
f(1,2) = 1;
m = (f(2,2) - f(2,1));
b = f(2,1);
end
function dataset = generateRandom2DPointsDataset(n)
dataset = rand(2,n);
end
function values = classify(dataset,m,b)
for i=1:size(dataset,1)
y = m*dataset(i,1) + b;
if dataset(i,2) >= y, values(i) = 1;
else values(i) = -1;
end
end
end
I want to find Orientation, MajorAxisLengthand MinorAxisLength of contour which is plotted with below code.
clear
[x1 , x2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [1,3];
sigm = [2,0;0,2];
xx_size = length(mu);
tem_matrix = ones(size(x1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {x1,x2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(x1));
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
% regionprops(z_plat,'Centroid','Orientation','MajorAxisLength','MinorAxisLength');
In my opinion, I may have to use regionprops command but I don't know how to do this. I want to find direction of axis of contour and plot something like this
How can I do this task? Thanks very much for your help
Rather than trying to process the graphical output of contour, I would instead recommend using contourc to compute the ContourMatrix and then use the x/y points to estimate the major and minor axes lengths as well as the orientation (for this I used this file exchange submission)
That would look something like the following. Note that I have modified the inputs to contourc as the first two inputs should be the vector form and not the output of meshgrid.
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
% 0 0 0
major_length = [ellipsedata.long_axis];
% 4.7175 3.3380 2.1539
minor_length = [ellipsedata.short_axis];
% 4.7172 3.3378 2.1532
As you can see, the contours are actually basically circles and therefore the orientation is zero and the major and minor axis lengths are almost equal. The reason that they look like ellipses in your post is because your x and y axes are scaled differently. To fix this, you can call axis equal
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
axis equal
Thank you #Suever. It help me to do my idea.
I add some line to code:
clear
[X1 , X2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [-1,0];
a = [3,2;1,4];
a = a * a';
sigm = a;
xx_size = length(mu);
tem_matrix = ones(size(X1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {X1,X2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(X1));
figure;contour(X1, X2, z_plat,3, 'LineWidth', 2,'color','m');
hold on;
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
major_length = [ellipsedata.long_axis];
minor_length = [ellipsedata.short_axis];
tet = orientations(1);
x1 = mu(1);
y1 = mu(2);
a = sin(tet) * sqrt(major_length(1));
b = cos(tet) * sqrt(major_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);
tet = ( pi/2 + orientations(1) );
a = sin(tet) * sqrt(minor_length(1));
b = cos(tet) * sqrt(minor_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);
I only have about two weeks of experience with programming/Matlab, so I'm just a beginner. In my code I would like to plot mu as a function of alpha. When I display mu it shows the 10 values of mu for each value of alpha. However, when I plot the graph it gives the values of mu as seperate points. But I want the points to be connected with just one line. How can I solve this problem?
n=40; %number of months
p=0.23; %probability of success
num_of_simulations=100;
s=rng; x = rand(1,n)<p;
rng(s);
hold on;
for alpha=0.01:0.01:0.1;
for i=1:num_of_simulations
x = rand(1,n)<p;
S0=5000; %initial value
Y(1)=S0*alpha; %deposit
for k=1
if x(1,1)==1;
S(1, i)=S0+2*Y(1);
else
S(1, i)=S0-Y(1);
end
end
for k=2:n
Y(k)=S(k-1, i)*alpha;
if x(1,k)==1;
S(k, i)=S(k-1, i)+2*Y(k);
else
S(k, i)=S(k-1, i)-Y(k);
end
end
Sn(i)=S(n,i); %end value for each simulations
end
mu=mean(Sn);
disp(mu);
plot(alpha,mu);
end
The reason your points aren't connected is because you plot each point separately. If we take a different approach and take alpha = 0.01:0.01:0.1; out of the for loop definition and then change the for loop definition to for j=1:numel(alpha) we can still loop over every element of alpha. Now we need to change each use of alpha in the loop to alpha(j) so that we are referring to the current element of alpha and not every element. Following on from this we need to change mu to mu(j). What this means is that when the entire loop has finished we have all of the values of alpha and mu stored and 1 call to plot(alpha, mu) will plot the data with the points connected as in
This also enables us to remove hold on; too as we only plot once.
I've included the complete edited code here for you to see. The changes are minuscule and should make sense.
clear all
close all
n = 40; %number of months
p = 0.23; %probability of success
num_of_simulations = 100;
s = rng;
x = rand(1, n) < p;
rng(s);
alpha = 0.01:0.01:0.1;
for j = 1:numel(alpha)
for i = 1:num_of_simulations
x = rand(1, n) < p;
S0 = 5000; %initial value
Y(1) = S0*alpha(j); %deposit
for k = 1
if x(1, 1) == 1;
S(1, i) = S0 + 2*Y(1);
else
S(1, i) = S0 - Y(1);
end
end
for k = 2:n
Y(k) = S(k-1, i)*alpha(j);
if x(1, k) == 1;
S(k, i) = S(k-1, i) + 2*Y(k);
else
S(k, i) = S(k-1, i) - Y(k);
end
end
Sn(i) = S(n, i); %end value for each simulations
end
mu(j) = mean(Sn);
disp(mu(j));
end
plot(alpha, mu);
I have plotted an histogram for the value 'Q' in my code below. I want the histogram to be from 0,1,2,3 format in the x-axis. At the movement I am not getting any value at 0. Ideally I want it to be shifted to the left and have the same plot starting from 0.
%Queue Buffer%
N = 1000;
Q = zeros(N,1);
Q2= 0;
s = 20;
for Ti = 2:N
Q(Ti) = Q2;
a = randi([0 32],1);
a1 = a - s;
a2 = Q(Ti) + a1;
Q2 = max(0,a2);
end
t = 0:N-1;
xout=hist(Q,9);
bar(xout, 'barwidth', 1, 'basevalue', 0);
https://dl-web.dropbox.com/get/Photos/qbuff.jpg?w=50ea6776
Either use
hist(Q,t);
Or
xout=hist(Q,t);
bar(t,xout);
bar([0:length(xout)-1], xout, 'barwidth', 1, 'basevalue', 1);