Solve differential equation with infinite boundary condition in Matlab - matlab

I would like to solve the following equation :
f''+tau(x)*f+f^3=0
f'(0)=0
f(inf)=1
Where tau(x) can be any function of x. The problem is to translate the boundary condition f(inf)=1 into matlab. My first solution, by reading different posts on the web was to approximate infinity by a large finite number but it doesn't give satisfying solution. Here is the code that I use :
function f = solve_GL(tau)
options = bvpset('RelTol', 1e-5);
Xstart = 0;
Xend = 1000;
solinit = bvpinit(linspace(Xstart, Xend, 50), [0, 1]);
sol = bvp4c(#twoode, #twobc, solinit, options);
x = linspace(Xstart,Xend);
y = deval(sol,x);
plot(x,y(1,:))
function dydx = twoode(x,y)
dydx = [y(2); (-heaviside(x-2)+1).*y(1)+y(1).^3];
function res = twobc(ya,yb)
res = [ya(2); yb(1)-1];
If somebody has a solution to this problem, I would be glad to hear it !

Related

How to solve a second order non linear ode system with bvp4c?

I'm trying to solve a system of two second order non linear Odes and since it is a boundary valued problem I suppose I need to use the bvp4c function.
The system I'm talking about is the following:
f''(x) = F(f,f',x);
s''(x) = G(f, f',s,s',x)
with the conditions f(0) = pi, f(inf = 35) = s(inf = 35) = 0. The F and G functions are known and I assumed that 35 would be a decent replacement for infinity.
It is separable and I have already solved for f but I don't know how to solve it for s either.
The code that allegedly solves for f is the following:
options = bvpset('RelTol', 1e-5);
Xstart = 0.01;
Xend = 35;
solinit = bvpinit(linspace(Xstart, Xend, 1000), [0, 1]);
sol = bvp4c(#twoode, #twobc, solinit, options);
x = linspace(Xstart,Xend);
y = deval(sol,x);
figure(1)
plot(x,y(1,:))
figure(2)
plot(x,y(2,:))
function dydx = twoode(x,y)
dydx = [y(2); ((-1/(x^2 + 2+sin(y(1))^2))*(2*x*y(2) + sin(2*y(1))*y(2)^2 -
2*sin(2*y(1)) - (sin(y(1)^2)*sin(2*y(1)))/x^2) )];
end
function res = twobc(ya,yb)
res = [ya(1) - pi
yb(2)];
end
So my question is how can I use the results I obtained for f in order to solve the equation for s? I have tried doing the same things I did for f but if I define a function for s that uses y(1,:) and y(2,:) it gives me an error message that says y is not defined.
Since I am quite new to solving dfferential equations with Matlab and to using Matlab in general I am probably making some trivial mistake but I have been looking for answers and couldn't find any. I hope someone with enough patience can help me.
Thanks in advance for any useful advice.

Solving Coupled partial differential equations of stiff nature using MATLAB

I want to solve coupled partial differential equations of first order, which are of stiff nature. I have coded in MATLAB to solve this pde's, I have used Method of line to convert PDE into ODE, and i have used beam and warmings(second order upwind) method to discritize the spatial derivative. The discretization method is total variation diminishing(TVD) to eliminate the oscillation. But rather using TVD and ode15s solver to integrate resultant stiff ode's the resultant plot is oscillatory(not smooth). What should i do to eliminate this oscillation and get correct results.
I have attached my MATLAB code.. please see it and suggest some improvement.
∂y(1)/∂t=-0.1 ∂y(1)/∂x + (0.5*e^(15*(y(2)⁄(1+y(2))))*(1- y(1))
∂y(2)/∂t=-0.1 ∂y(2)/∂x - (0.4*e^(15*(y(2)⁄(1+y(2))))*(1- y(1))-0.4
Initial condition: at t = 0 y(1)= y(2)=0
Boundary condition: y(1)= y(2) = 0 at x=0
I have attached my MATLAB code.. please see it and suggest some improvement.
function brussode(N)
if nargin<1
N = 149;
end
tspan = [0 10];
m = 0.00035
t = (1:N)/(N+1)*m;
y0 = [repmat(0,1,N); repmat(0,1,N)];
p = 0.5
q = 0.4
options = odeset('Vectorized','on','JPattern',jpattern(N));
[t,y] = ode15s(#f,tspan,y0,options);
a = size(y,2)
u = y(:,1:2:end);
x = (1:N)/(N+1);
figure;
%surf(x,t(end,:),u);
plot(x,u(end,:))
xlabel('space');
ylabel('solution');
zlabel('solution u');
%--------------------------------------------------------------
%Nested function -- N is provided by the outer function.
%
function dydt = f(t,y)
%Derivative function
dydt = zeros(2*N,size(y,2)); %preallocate dy/dt
x = (1:N)/(N+1);
% Evaluate the 2 components of the function at one edge of the grid
% (with edge conditions).
i = 1;
%y(1,:) = 0;
%y(2,:) = 0;
dydt(i,:) = -0.1*(N+1)*(y(i+2,:)-0)+ (0.01/2)*m*((N+1).^3)*(y(i+2,:)-0) + p*exp(15*(0/(1+0)))*(1-0);
dydt(i+1,:) = -0.1*(N+1)*(y(i+3,:)-0)+ (0.01/2)*m*((N+1).^3)*(y(i+3,:)-0) - q*exp(15*(0/(1+0)))*(1-0)+0.25;
i = 3;
%y(1,:) = 0;
%y(2,:) = 0;
dydt(i,:) = -0.1*(N+1)*(y(i+2,:)-y(i,:)) + (0.01/2)*m*((N+1).^3)*(y(i+3,:)-y(i,:)) + p*exp(15*(y(i+1,:)/(1+y(i+1,:))))*(1-y(i,:));
dydt(i+1,:) = -0.1*(N+1)*(y(i+3,:)-y(i+1,:)) + (0.01/2)*m*((N+1).^3)*(y(i+3,:)-y(i,:)) - q*exp(15*(y(i+1,:)/(1+y(i+1,:))))*(1-y(i,:))+0.25;
%Evaluate the 2 components of the function at all interior grid
%points.
i = 5:2:2*N;
%y(1,:) = 0;
% y(2,:) = 0;
dydt(i,:) = (-0.1/2)*(N+1)*(3*y(i,:)-4*y(i-2,:)+y(i-4,:)) +(0.01/2)*m*((N+1).^3)*(y(i,:)-2*y(i-2,:)+y(i-4,:))+ p*exp(15*(y(i+1,:)/(1+y(i+1,:))))*(1-y(i,:));
dydt(i+1,:) = (-0.1/2)*(N+1)*(3*y(i+1,:)-4*y(i-1,:)+y(i-3,:))+(0.01/2)*m*((N+1).^3)*(y(i+1,:)-2*y(i-1,:)+y(i-3,:)) - q*exp(15*(y(i+1,:)/(1+y(i+1,:))))*(1-y(i,:))+0.25;
end
%-------------------------------------------------------------
end %brussode
%-------------------------------------------------------------
% Subfunction -- the sparsity pattern
%
function S = jpattern(N)
% Jacobian sparsity patter
B = ones(2*N,5);
B(2:2:2*N,2) = zeros(N,1);
B(1:2:2*N-1,4) = zeros(N,1);
S = spdiags(B,-2:2,2*N,2*N);
end
%-------------------------------------------------------------

Matlab PDE Solver Issue

Im trying to solve the transient heat equation in 1D and comparing the analytical and numerial solutions. The solutions have the same trend but are very different, also the relative error is coming out to be zero, even though its clearly not supposed to be. Im not sure if I have solved the PDE correctly. (the pde is du/dt = d^2u/dx^2) and bcs are u(0,t)=1, u(100,t) = 0, u(x,0)=0. Can someone please take a look at my code?
function he
m = 0;
x = linspace(0,100,500);
t = linspace(0,1000,500);
sol = pdepe(m,#hepde,#heic,#hebc,x,t);
u = sol(:,:,1);
y = erfc(x./(2*(t.^0.5)));
r=(y-u(70,:))/y;
figure;
plot(x,u(50,:),'.',x,u(150,:),'.',x,u(250,:),'.',x,u(end,:),'.',x,y,'.');
title('Numerical Solutions at different times.');
legend('t=100','t=300','t=500','t=700','y ana',0);
xlabel('Distance x');
ylabel('u(x,t)');
figure;
plot(x,r);
title('error in numerical and analytical solution');
legend('error',0);
xlabel('Distance x');
ylabel('error');
% --------------------------------------------------------------------------
function [c,f,s] = hepde(x,t,u,DuDx)
c = 1;
f = DuDx;
s = 0;
% --------------------------------------------------------------------------
function u0 = heic(x)
u0 = 0;
% --------------------------------------------------------------------------
function [pl,ql,pr,qr] = hebc(xl,ul,xr,ur,t)
pl = ul-1;
ql = 0;
pr = ur;
qr = 0;
You actually had the solution all set up correctly, you just used the results incorrectly. I'll go through the errors one by one.
sol = pdepe(m,#hepde,#heic,#hebc,x,t);
u = sol(:,:,1);
You found the right answer, but the line u=sol(:,:,1); is useless as size(sol)=[2 2], so you may as well just do u=pdepe(...);.
Now when you calculated your exact solution you did it very strangely. You want to find it at each x/t combination, but you did it only at some of them. You need to use meshgrid to get all the combinations of x and t then calculate your exact solution at each one.
[X,T]=meshgrid(x,t);
y = erfc(X./(2*(T.^0.5)));
Then you need to calculate the error differently.
r=(y-u)./y;
figure(3);
And plot differently.
plot(x,u(50,:),'b',x,u(150,:),'g',x,u(250,:),'r',x,u(end,:),'c',x,y(50,:),'b--',x,y(150,:),'g--',x,y(250,:),'r--',x,y(end,:),'c--');
Actually your exact solution doesn't satisfy the boundary condition at x=100......

Matlab: 1D Numerical PDEs without Loops

So, currently I am trying to find the numerical solutions for the berger equation, $u_t+u∗u_x=0$. The numerical solution to this equation is:
$u^{n+1}_j=u_n^j−\frac{Δx}{Δt}u^n_j(u^n_j−u^n_{j−1})$
I wrote code on Matlab that computes this. As you can see, there is only one for-loop in the code. However, my u matrix extremely large, the algorithm becomes slow. Is there a way for me to use no loops at all. I was thinking about using the command cumsum, but I am not sure how to integrate that to my program. Please look at my code. Thanks.
dx = 0.9;
dt = 0.9;
tf = 10;
l = 10;
xstep = [-1:dx:l];
tstep = [0:dt:tf];
uinit = zeros(length(tstep),length(xstep));
%%Setting Initial and Boundary Conditions
bc.left = #(t) 2;
bc.right = #(t) -1;
ic = #(x) ...
2*(x<=0) ...
-1*(x>0);
uinit(1, :) = ic(xstep);
uinit(:, 1) = bc.left(tstep);
uinit(:, end) = bc.right(tstep);
%% Numerical method part
for c=1:(length(tstep)-1)
uinit(2:end -1, c+1) = uinit(2:end -1, c) - dx/dt*(uinit(2:end -1, c).*(uinit(2:end-1, c) - uinit(1:end-2, c)));
end
surf(xstep,tstep,uinit)

Matlab code for Gauss-Seidel and Successive over relaxation iterative methods

I need to code the Gauss Seidel and Successive over relaxation iterative methods in Matlab. I have created the below code for each of them, however my final solution vector does not return the correct answers and i'm really struggling to figure out why. Could anyone please help me?
In both cases, x is the final solution vector and i returns the number of iterations.
Thanks in advance
Gauss Seidel Method:
function [x,i] = gaussSeidel(A,b,x0,tol)
x2 = x0;
count = 0;
D = diag(diag(A));
U = triu(A-D);
disp(U);
L = tril(A-D);
disp(L);
C = diag(diag(A));
disp(C);
Inv = inv(C+D);
error = inf;
while error>tol
x1 = x2;
x2 = Inv*(b-(U*x1));
error = max(abs(x2-x1)/abs(x1));
count = count + 1;
end
x = x2;
i = count;
end
SOR Method:
function [x,i] = sor(A,b,x0,tol,omega)
[m,n] = size(A);
D = diag(diag(A));
U = triu(A-D);
L = tril(A-D);
count = 1;
xtable = x0;
w = omega;
if size(b) ~= size(x0)
error('The given approximation vector does not match the x vector size');
elseif m~=n
error('The given coefficient matrix is not a square');
else
xnew = (inv(D+w*L))*(((1-w)*D-w*U)*x0 +w*b);
RelError = (abs(xnew-x0))/(abs(xnew));
RelErrorCol = max(max(RelError));
while RelErrorCol>tol
xnew = (inv(D+w*L))*(((1-w)*D-w*U)*x0 +w*b);
RelError = (abs(xnew-x0))/(abs(xnew));
RelErrorCol = max(max(RelError));
x0 = xnew;
count = count+1;
xtable = [xtable, xnew];
end
disp(xtable);
x = xnew;
i = count;
end
Gauss-Seidel: Your line that describes C is wrong. Actually it shouldn't be there. Also for the Inv line, it should be inv(D+L), not inv(C+D).
As for the SOR method, in hindsight it seems right. To double check, compare with this method:
http://www.netlib.org/templates/matlab/sor.m. This method relies on http://www.netlib.org/templates/matlab/split.m
Edit: April 4, 2014 - Also check: https://www.dropbox.com/s/p9wlzi9x9evqj5k/MTH719W2013_Assn4_Part1.pdf?dl=1 . I taught a course on Applied Linear Algebra and have MATLAB code that implements Gauss-Seidel and SOR. Check slides 12-20 for the theory and how to implement Gauss-Seidel and slides 35-37 for the SOR method.
Let me know how it goes.