I am unable to get converging values using a Gauss-Seidel algorithm for my specific 2-D Helmholtz equation:
Here is the code:
%Final Project Helmhotz 2-D:
%d^2u/dx^2+d^2u/dy^2+Lambda*u=F(x,y)
%Over domain of ax < x < bx and ay < y < by
%Using Gauss-Seidel
clc
clear;
%Given variables
lamda1=0.5; %Given
ax=0; %Given
ay=0; %Given
Pi=4*atan(1); %Given
bx=2*Pi; %Given
by=2*Pi; %Given
v=0; %Given (du/dy #y=by = 0)
%Initial Problem Setup
Nx=20; %Initial number of points in x
Ny=Nx; %Initial number of points in y
Lx=bx; %Length of x
Ly=by; %Length of y
deltax=Lx/(Nx+1); %Step size in x
deltay=Ly/(Ny+1); %Step size in y
%Constants
fbay = (by-ay)*(by-ay)*cos(Pi*ay/by);
gbay = ay*(by-ay)*(by-ay);
cons1 = bx-ax;
dy2=deltay*deltay;
dx2=deltax*deltax;
dx2dy2=deltax*deltax*deltay*deltay;
denominator=2*deltay*deltay+2*deltax*deltax;
denoma=denominator-dx2dy2*lamda1;
x=0:deltax:2*pi;
y=0:deltay:2*pi;
%Solution Matrix
U1 = zeros(Nx+2,Ny+2); % Create solution matix with initial guess of ZERO
%Boundary Conditions
for j = 1:Ny+2 %u(x=ax,y)=fb(y) boundary condition
U1(1,j)=(by-deltay*(j-1))*(by-deltay*(j-1))*cos(Pi*deltay*(j-1)/by);
end
for j=1:Ny+2 %u(x=bx,y)=gb(y) boundary condition
U1(Nx+2,j)=(deltay*(j-1))*(by-deltay*(j-1))*(by-deltay*(j-1));
end
for i=1:Nx+2 %u(x,y=ay) boundary conditoin
U1(i,1)=fbay+(deltax*(i-1)-ax)/cons1*(gbay-fbay);
end
%Part 1 Using Gauss Siedel
F1=zeros(Nx+2,Ny+2);
for i=1:Nx+2
for j=1:Ny+2
F1(i,j)=cos(Pi/2*(2*(deltax*(i-1)-ax)/(bx-ax)+1))*sin(Pi*(deltay*(j-1)-ay)/(by-ay));
end
end
for z=1:100
for i=2:Nx+1
for j=2:Ny+1
%%%%% Different Equations for U if wanted %%%%%%%%%%%%%%%%%%%%
%U1(i,j)=(deltax*deltax*F1(i,j)-(U1(i-1,j)+U1(i+1,j)+U1(i,j-1)+U1(i,j+1)))/(-4+deltax*deltax*lamda1);
%U1a(i,j)=(Cons4*F1(i,j)-dy2*U1(i+1,j)-dy2*U1(i-1,j)-dx2*U1(i,j+1)-dx2*U1(i,j-1))/(Cons5a);
U1(i,j)=((U1(i-1,j)+U1(i+1,j)+U1(i,j-1)+U1(i,j+1))-deltax*deltax*F1(i,j))/(4-deltax*deltax*lamda1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%U1(i,j)=(dy2*U1(i-1,j)+dy2*U1(i+1,j)+dx2*U1(i,j-1)+dx2*U1(i,j+1))/(denoma)-(dx2dy2*F1(i,j))/(denoma);
end
%%%%%%%%%%%% Different Neumann Conditions if wanted %%%%%%%%%%%%%%
%U1(i,Ny+2)=(deltax*deltax*F1(i,Ny+2)-(U1(i-1,Ny+2)+U1(i+1,Ny+2)+U1(i,Ny+1)+(U1(i,Ny+1)-2*deltax*v)))/(-4+deltax*deltax*lamda1);
%U1a(i,Ny+2)=(Cons4*F1(i,Ny+2)-dy2*U1(i+1,Ny+2)-dy2*U1(i-1,Ny+2)-dx2*U1(i,Ny+1)-dx2*U1(i,Ny+1))/(Cons5a);
U1(i,Ny+2)=((U1(i-1,Ny+2)+U1(i+1,Ny+2)+U1(i,Ny+1)+U1(i,Ny+1))-deltax*deltax*F1(i,Ny+2))/(4-deltax*deltax*lamda1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%U1(i,Ny+2)=((dy2)*U1(i-1,Ny+2)+(dy2)*U1(i+1,Ny+2)+(dx2)*U1(i,Ny+1)+(dx2)*U1(i,Ny+1))/(denoma)-(dx2dy2*F1(i,Ny+2))/(denoma);
end
end
figure()
surf(x,y,U1);
Whenever I run this code for more than 100 iterations, the values start to diverge from the boundary conditions. I'm not sure why and neither is my professor.
I have also posted pictures of my given problem, boundary conditions, and another image that shows my discretization.
Shows my discretization
Shows my given problem and boundary conditions
Related
I wrote this code to solve one-dimensional heat transfer with dufort frankel method and want to compare with exact solution.
But exact solution gives an error. And when i run the code before the exact solution it is correct.
clc
clear
close all
%Declaration point..........................................................
nx=25; %number of point in the x direction
Ta=100; %temperatur (centigrade)
T=zeros(nx,1)+Ta; %initialization of temperator
T_in =0; %inlet temperature
T_out=0; %output temperature
Alpha=0.01; %coefficient (m^2/s)
L=1; %length (m)
x=linspace(0,L,nx); %x grid
dx=L/nx-1; %grid spacing
T(1)= T_in; %BC
T(nx)= T_out; %BC
dt=0.01; %time step from stability for DF
d=Alpha*dt/dx^2; %diffusion number
maxtime=10; %maximum time
nT=maxtime/dt; %time spacing
N=10; %number of series for exact computartion
%Time loop..................................................................
T0=T;
T1=T;
for n=1:nT
display(['Time step:',num2str(n),'time',num2str(n*dT)]);
T= DF(nx,T0,T1,d);
T0=T1;
T1=T;
end
%Exact solution............................................................
Ta = zeros(nx, nt);
for i=1:nx
for j = 1:nt
T(i,j) = sin(pi*x(i))*exp(-pi^2*t(j);
end
end
figure()
contourf(Ta,200,'linecolor','non')
%Error function............................................................
function [Err] = Error[T_exact,T,x];
Err=sqrt(sum(((T(2:end-1)-T_exact(2:end-1))./T_exact(2:end-1)).^2)/(N-2));
end
I am currently trying to solve a 2nd order 2D advection equation using the upwind scheme. At first the task is to plot a quiver() plot and then over lay it on top of a contourf(). When using the data for velocity u and v into the upwind scheme I am getting straight line outputs as seen below. However I am using an initial condition of phi0 = cos(x). When checking the values for X,Y,u,v they all have different values at (i,j) locations. I see that my phi0 and phi are staying constant down each column but the output of the advection should be different at different times. I followed my 1D 2nd order code which works perfectly, but cannot seem to get a advected moving graph. Any advice on my setup or if you can point out where I am going wrong with this plot would be a big help!
clear all
clc
%Problem 1
%Part B
%Creating a quiver plot for the 2D vector profile
L=2*pi;%Length Lx=Ly = 2pi
L0=0;
N=31; % Nx=Ny=31
%get a value of dx=dy to know distance between steps
dx=L/N;
dy=L/N
x=L0-dx*2:dx:L+dx*2;
y=L0-dy*2:dy:L+dy*2;
[X,Y]=meshgrid(x,y);
u=cos(X).*sin(Y);
v=-sin(X).*cos(Y);
figure
hold on
%Part B & C using the courtf plot Phi=cos(x)
phi0=cos(X);
contourf(X,Y,phi0)
colormap autumn
colorbar
xlabel('Length from 0 to 2*pi with dx spacing')
ylabel('Length from 0 to 2*pi with dy spacing')
title('Quiver plot on the phi=cos(x) Contour Plot')
quiver(X,Y,u,v)
hold off
figure(2)
plot(x,phi0)
%%
%Writing a code to sovle 2D advection for part D
t=0; %initial time
tmax=10; %Maximum time
dt=0.01; %time step
phi=phi0;
phip1=phi0;
%phi(:)=phi; %Initial Condition
nsteps = tmax/dt
%Add periodic boundary conditions for both x & y direction
for n=1 : nsteps
phi(1,:) = phi(end-2,:);
phi(2,:) = phi(end-3,:);
phi(end,:) = phi(3,:);
phi(end-1,:) = phi(4,:);
%Y ghost cells
phi(:,1) = phi(:,end-2);
phi(:,1) = phi(:,end-3);
phi(:,end) = phi(:,3);
phi(:,end-1) = phi(:,4);
for i=3:N+1
for j=3:N+1
if u > 0 & v>0
phip1(i,j)= phi(i,j) - u(i)*dt/(2*dx) * (3*phi(i,j)-4*phi(i-1,j)+phi(i-2,j))- v(j)*dt/(2*dx) *(3*phi(i,j)-4*phi(i,j-1)+phi(i,j-2))
elseif u <0 & v<0
phip1(i,j)= phi(i,j) - u(i)*dt/(2*dx) * (-3*phi(i,j)+4*phi(i+1,j)-phi(i+2,j))- v(j)*dt/(2*dx) *(-3*phi(i,j)+4*phi(i,j+1)-phi(i,j+2))
elseif u >0 & v <0
phip1(i,j)= phi(i,j) - u(i)*dt/(2*dx) * (3*phi(i,j)-4*phi(i+1,j)+phi(i+2,j))- v(j)*dt/(2*dx) *(-3*phi(i,j)+4*phi(i,j-1)-phi(i,j-2))
elseif u <0 & v >0
phip1(i,j)= phi(i,j) - u(i)*dt/(2*dx) * (-3*phi(i,j)+4*phi(i-1,j)-phi(i-2,j))- v(j)*dt/(2*dx) *(3*phi(i,j)-4*phi(i,j+1)+phi(i,j+2))
end
end
end
t=t+dt;
phi=phip1;
plot(x,phi)
%pause(0.5)
end
The problem I see is that you are plotting phi (which is 2D) against x (which is 1D).
I am not 100% sure on the right section you want to plot but something along the lines of this should work: plot(x,phi0(1,:)). What this does is to plot the first slice of phi in the y direction.
EDIT
To visualize phi0 as function of both X and Y, you can use either surf(X,Y,phi0) or mesh(X,Y,phi0).
I am trying to determine the pose (x,y,theta) of a differential drive robot using ode45. The code I have below solves for the x position, but I am having an issue with the initial condition. I set it to 0 since at time 0 the robot is assumed to be at the origin, but I get an error. How do I set the initial condition for ode45 such that I get the expected output?
I tried to make the initial conditions vector of the same length as dxdt by setting initial conditions as a 41x1 zeros matrix, but I didn't understand the output and I don't believe I did it correctly.
% Given conditions for a differential drive robot:
B = 20; % (cm) distance along axle between centers of two wheels
r = 10; % (cm) diameter of both wheels
w_l = 5*sin(3*t); % (rad/s) angular rate of left wheel
w_r = 5*sin(3*t); % (rad/s) angular rate of right wheel
v_l = r*w_l; % (cm/s) velocity of left wheel
v_r = r*w_r; % (cm/s) velocity of right wheel
v = (v_r+v_l)/B; % (cm/s) velocity of robot
theta = 90; % constant orientation of robot since trajectory is straight
% Solve differential equation for x:
dxdt = v*cos(theta); % diff equaition for x
tspan = [0 20]; % time period to integrate over
x0 = 0; % initial condition since robot begins at origin
[t,x] = ode45(#(t,y) dxdt, tspan, x0);
I want to solve the differential equation dxdt for 0 to 20 seconds with an initial condition of 0. I expect the output to give me a vector of time from 0 to 20 and an array of for x. The problem I believe lies with the initial condition. MATLAB gives me an error in the live editor telling me, " #(t,y)dxdt returns a vector of length 69, but the length of initial conditions vector is 1. The vector returned by #(t,y)dxdt and the initial conditions vector must have the same number of elements."
The issue is not the initial condition. You need to define dxdt as a function i.e.
% Define differential equation
function derivative = dxdt(t,y)
% Given conditions for a differential drive robot:
B = 20; % (cm) distance along axle between centers of two wheels
r = 10; % (cm) diameter of both wheels
w_l = 5*sin(3*t); % (rad/s) angular rate of left wheel
w_r = 5*sin(3*t); % (rad/s) angular rate of right wheel
v_l = r*w_l; % (cm/s) velocity of left wheel
v_r = r*w_r; % (cm/s) velocity of right wheel
v = (v_r+v_l)/B; % (cm/s) velocity of robot
theta = 90; % constant orientation of robot since trajectory is straight
derivative = v*cos(theta); % diff equation for x
end
Then when you use ode45 you should tell it to pass the t and y variables as arguments to dxdt like
[t,x] = ode45(#(t,y) dxdt(t,y), tspan, x0);
This should then work. In this case, as dxdt only takes the default arguments, you could also write
[t,x] = ode45(#dxdt, tspan, x0);
The error you got indicates that at some point you made dxdt into a vector of length 69, whilst MATLAB was expecting to get back 1 value for dxdt when it passed one t and one y to your dxdt 'function'. Whenever you get errors like this, I'd recommend putting
clear all
`clearvars` % better than clear all - see am304's comment below
at the top of your script to avoid polluting your workspace with previously defined variables.
I am trying to create a figure showing the solution I obtained through Jacobi iteration along with the true solution, as well as the error of the Jacobi solution.
The figure I'm trying to create should consist of two plots.
I used the subplot command, to split the figure into
an upper and lower axes and I wrote the for loop that calculates the Jacobi iterations and the error. The loop is going to iterate 400 times using x0 as the initial guess. Before this, I calculated the true solution to the system Ax = b.
N = 30;
iter = 400;
A = toeplitz([-2 1 zeros(1, N-2)], [-2 1 zeros(1, N-2)]);
bk = ones(N,1);
for jj = 1:N
bk(jj) = cos(5*jj) + (1/2)*sin(7*jj);
end
x = A\bk;
D = diag(diag(A));
T = A - D;
x0 = zeros(N,1);
error = zeros(iter,1);
M = -D\T;
g = D\bk;
for nn = 1:iter
x0 = M*x0 + g;
error(nn) = norm(x - x0,2);
end
subplot(2,1,1)
plot(x0(1:N,1),'ro');
ylabel('Solution','FontSize',22);
title('Solution by Jacobi Iteration','FontSize',22);
xlim([0 pi]);
ylim([-5 5]);
xticks(0:0.5:3);
yticks(-5:5:5);
subplot(2,1,2)
plot(error(1:N),'ro')
ylabel('Error','FontSize',22);
xlabel('t','FontSize',22);
xlim([0 pi]);
ylim([0 0.1]);
xticks(0:0.5:3);
yticks(0:0.05:0.1);
The upper window should show the true solution in red circles connected by solid lines. The lower window show show the error as red
circles connected by dotted lines. When I ran my code, only 3 red circles appeared in the upper window and nothing was plotted in the lower window. I'm still bad at plotting iterations of a loop. Can someone help me with plotting the solutions and errors I calculated?
The xlim and ylim statements are not representative of the data.
x0 and x have N elements (30 here), and the elements of x and x0 span -2 to 2 in this setup.
error has iter elements (400 here), and the elements of error go from 4 to about 0.01.
For these plots, the element index maps to the horizontal x-axis, and their values to the y-axis. I think this plot setup should give you the result you desire (I probably changed more than actually needed):
subplot(2,1,1);
plot(1:N, x0(1:N,1), 'ro', 1:N, x,'k+');
title('Solution by Jacobi Iteration','FontSize',22);
ylabel('Solution','FontSize',22);
xlim([1, N]);
ylim([-3, 3]);
xticks(1:N);
yticks(-3:0.5:3);
subplot(2,1,2)
semilogy(1:iter, error(1:iter),'ro')
ylabel('Error','FontSize',22);
xlabel('t','FontSize',22);
xlim([1 iter]);
ylim([0 4]);
xticks(0:25:400);
Problem
I have to plot a beam/cantilever using Matlab. Where my inputs are:
Length of the beam
Position of the loads (input is a vector)
Forces of the load (input is a vector)
Whether is it a cantilever or not. Because I have different equations for calculating the displacement.
My Solution
I have come to an idea on how I can actually plot the cantilever, but I can not formulate it into a code in MATLAB. I have spent hours trying to write something on Matlab but I have gotten nowhere. (I am a novice to Matlab)
My solution is as follow: I have the formula for the displacement from starting position.
I can define a vector using loop for x coordinates until the given beam length. Hence,
x=[0 ... L]
Then I want to define another vector where the difference is calculated (this is where I can't figure out Matlab)
y = [h, h - y(x1), h - y(x2), .... h - y(L)]
where h is the starting height, which I have thought to be defined as (y(x1) - y(L)) + 1, so that the graph then doesn't go into the negative axes. y(x) is the function which will calculate the displacement or fall of the beam.
Once that is done, then I can simply plot(x,y) and that would give me a graph of a shape of deflected beam for the given range from 0 to beam length. I have tested my theory on excel and it works as per the graph is concerned but I can not figure out implementation on Matlab.
My incomplete code
%Firstly we need the inputs
%Length of the beam
l = str2double(input('Insert the length of your beam: ', 's'));
%Now we need a vector for the positions of the load
a = [];
while 1
a(end+1) = input('Input the coordinate for the position of your load: ');
if length(a)>1; break; end
end
%Now we need a vector for the forces of the load
W = [];
while 1
W(end+1) = input('Input the forces of your load: ');
if length(W)>1; break; end
end
%
%
%
%Define the formula
y = ((W * (l - a) * x)/(6*E*I*l)) * (l^2 - x^2 - (l - a)^2);
%Where
E = 200*10^9;
I = 0.001;
%
%
%
%Now we try to plot
%Define a vector with the x values
vectx = [];
for i = 1:l
vectx = [vectx i];
end
%Now I want to calculate displacement for each x value from vectx
vecty = [];
for i=1:l
vecty=[10 - y(x(i)) i];
end
%Now I can plot all the information
plot(vectx, vecty)
hold on
%Now I plot the coordinate of the positions of the load
plot(load)
end
Really need some help/guidance. Would be truly grateful if someone can help me out or give me a hint :)
I have edited the question with further details
There are several things that do not work in your example.
For instance, parameters should be defined BEFORE you use them, so E and I should be defined before the deflection equation. And you should define x.
I do not understand why you put your inputs whithin a while loop, if you stop it at length(a)>1;. You can remove the loop.
You do not need a loop to calculate displacements, you can just use a substraction between vectors, like displacement = 10 - y. However, I do not understand what is H in your example; since your beam is initially at position 0, your displacement is just -y.
Finally, your equation to calculate the deformed shape is wrong; it only accounts for the first part of the beam.
Here, try if this code works:
%Length of the beam
l = input('Insert the length of your beam: ');
%Now we need a vector for the positions of the load
a = input('Input the coordinate for the position of your load: ');
%Now we need a vector for the forces of the load
W = input('Input the forces of your load: ');
%Define the formula
E = 200*10^9;
I = 0.001;
% x Position along the beam
x = linspace(0,l,100);
b = l - a;
% Deflection before the load position
pos = x <= a;
y(pos) = ((W * b .* x(pos))/(6*E*I*l)) .* (l^2 - x(pos).^2 - b^2);
% Cantilever option
% y(pos) = W*x(pos).^2/(6*E*I).*(3*a-x(pos));
% Deflection after the load position
pos = x > a;
y(pos) = ((W * b )/(6*E*I*l)) .* (l/b*(x(pos)-a).^3 + (l^2 - b^2)*x(pos) - x(pos).^3);
% Cantilever option
% y(pos) = W*a^2/(6*E*I).*(3*x(pos)-a);
displacement = 10 - y; % ???
% Plot beam
figure
plot(x , x .* 0 , 'k-')
hold on;
% Plot deflection
plot(x , y , '--')
% Plot load position
% Normalize arrow size as 1/10 of the beam length
quiver(a , 0 , 0 , sign(W) .* max(abs(y))/2)