Poisson Boltzmann eq. with an infinite boundary condition
Show older comments
Hi everybody!
I've written a code that solves the following PB problem

This is a 2nd order ode and the dependant variable here is psi (tilde) and the independant variable is x (tilde). The boundary conditions are:

The code includes an optimizer based on the secant method. I'm trying to guess the solution that will ''land'' on the 2nd boundary condition via the shooting method:
function [x2,p2]=optimumup(y21,y22,bc2,l)
%optimizing the choice of y2 for the shooting method, using the Newton
%method (secant) by solving the equation p(length(p(:,1))-bc2=0
[x1,p1] = BP(y21,l);
[x2,p2] = BP(y22,l)
size(p2)
for i=1:10
dp=((p2(length(p2(:,1)),1)-bc2)-(p1(length(p1(:,1)),1)-bc2))/(y22-y21);
y23=y22-(p2(length(p2(:,1)),1)-bc2)/dp;%recurrence relation
p1=p2;
[x2,p2] = BP(y23,l);
if abs(p2(length(p2(:,1)))-bc2)<0.001;
disp(p2(length(p2(:,1)),1));
disp(p2(length(p2(:,1)),1)-bc2);
plot(x2,p2(:,1),x2,p2(:,2))
return
end
y21=p1(1,2);
y22=p2(1,2);
end
disp('No success')
end
function [x,p] = BP(y2,l)
%Shooting method for the BP eq
options = odeset('RelTol',1e-4,'AbsTol',1e-4);
[x,p] = ode45(@eqs,[0 l],[90/24 y2],options);
%n=size(p);p(n(1),1)
%plot(x,p(:,1),x,p(:,2))
end
function [dy] = eqs(x,y)
%PB equation
dy = zeros(2,1); % a column vector
dy(1) = y(2);
dy(2) = sinh(y(1));
end
y21 and y22 are the initial x guesses for the secant method. bc2 is the boundary condition at x goes to inifinity. l is the interval size.
I have two main problems:
- I don't know how to incorperate the inifinite boundary condition.
- For some reason my solution does not converge. I'm working dimensionless.
I would appreciate some help guys.
Thanks,
Roi
Accepted Answer
More Answers (3)
David Goodmanson
on 24 Oct 2020
Edited: David Goodmanson
on 24 Oct 2020
Hi Roi
For convenience I will use u in place of psi. An exact solution is
tanh(u/4) = A*exp(-x) where A = tanh(1/4) [1]
so
u = 4*atanh(A*exp(-x))
which meets both of the boundary conditons. For du/dx at the origin, it turns out that
du/dx = -2*sinh(1/2) = -1.042190610987495
which disagrees slightly from what Alan has, for reasons not known to me.
===========derivation=============
start with
u'' = sinh(u)
multiply by integrating factor u' and integrate
u'^2/2 = cosh(u) (+ constant)
u'^2 = 2*cosh(u) + constant
as x --> inf you want u --> 0 which also means that u' --> 0, so the constant = -2
u'^2 = 2*(cosh(u)-1) = 4*sinh(u/2)^2
u' = -2*sinh(u/2) % pick the negatatve root
du/(2*sinh(u/2)) = -dx
% integrate
log(tanh(u/4)) = -x + constant
tanh(u/4) = A*exp(-x)
you want u = 1 at x = 0 so
A = tanh(1/4)
For the derivative at the origin, take the derivative of both sides of [1] at the top
( (1/4) / cosh^2(u/4) ) du/dx = -A*exp(-x)
% evaluate this at x = 0 and u(0) = 1
( (1/4) / cosh^2(1/4) ) du/dx = -A
du/dx = -tanh(1/4)*4*cosh^2(1/4) = -4*sinh(1/4)*cosh(1/4) = -2*sinh(1/2)
2 Comments
Alan Stevens
on 24 Oct 2020
Nicely done David!
David Goodmanson
on 24 Oct 2020
Hi Alan,
Thanks, it did work in this special case but I think your comments about a finite boundary and/or an asymptotic approach are going to be more useful in general. In this case out at infinity the answer has to be u = A*exp(-x), so both u and u' are known there. Then starting at large x, integrating to the origin and using the shooting method for various A should also work, I think. I have not tried it.
Roi Bar-On
on 24 Oct 2020
0 votes
2 Comments
Alan Stevens
on 24 Oct 2020
No, but I'll have a look later today.
Roi Bar-On
on 24 Oct 2020
Roi Bar-On
on 25 Oct 2020
0 votes
8 Comments
Alan Stevens
on 25 Oct 2020
The single point secant method only requires one guess together with an initial increment. I've modified your code to use this (its "cleaner" than the two point secant method), and compared the result with the analytical solution:
tolerance = 10^-8; % Set as desired
xspan = [0 5]; % inf = 5 here!
% Initial guess for gradients dpsidx(x=0)
dp1 = -1;
delta = -10^-10;
flag = 1; % Repeat indicator
itmax = 100; % Maximum allowable number of iterations
its = 0;
while (flag==1) && its<itmax
% Call ode solver twice with different guesses for initial gradient
% and get values of psi at boundary in return psi(x=inf)
[~, p1] = BP([1 dp1],xspan);
P1 = p1(end);
[x, p2] = BP([1 (dp1+delta)],xspan);
P2 = p2(end);
if abs(P2)<tolerance % then we are finished
flag = 0;
else % we need another iteration
% Secant improvement
dP = P2 - P1; % Difference between end values of psi
dp1 = dp1 - delta*P1/dP;
end
its = its + 1;
end
% Display data
format long
disp('psi(x=inf) and dpsidx(x=0)')
disp([P2 dp1])
disp(['number of iterations = ' num2str(its)])
% Analytical solution
A = tanh(1/4);
psi = 4*atanh(A*exp(-x));
% Plot numerical and analytical comparison
plot(x,p2(:,1),x,psi),grid
xlabel('x'),ylabel('\psi')
legend('numerical','analytical')
function [x,p] = BP(y0,xspan)
%Shooting method for the BP eq
options = odeset('RelTol',1e-10,'AbsTol',1e-10);
[x,p] = ode45(@eqs, xspan, y0 ,options);
%n=size(p);p(n(1),1)
%plot(x,p(:,1),x,p(:,2)),grid
%legend('\psi','d\psi dx')
end
function dy = eqs(~,y) % x not used within the function so replaced by ~
%PB equation
dy = zeros(2,1); % a column vector
dy(1) = y(2);
dy(2) = sinh(y(1));
end
This gives the following graph:

(Interestingly, if you just plot exp(-x), you get a curve extremely close to the analytical solution also!)
Roi Bar-On
on 30 Oct 2020
Alan Stevens
on 30 Oct 2020
Derived as follows
(P2-P1)/(dp2-dp1) = (P1-0)/(dp1-dpnew)
dp1 - dpnew = P1*(dp2-dp1)/(P2-P1)
dpnew = dp1 - P1*(dp2-dp1)/(P2-P1)
Now, dp2 = dp1 + delta, so
dpnew = dp1 - P1*delta/(P2-P1)
Roi Bar-On
on 30 Oct 2020
Alan Stevens
on 30 Oct 2020
Think of the curve of P vs dp. Use similar triangles to extrapolate from P1 and P2 to zero. You then repeat the process until the new value P (corresponding to dpnew) is close enough to zero.

Roi Bar-On
on 30 Oct 2020
Alan Stevens
on 30 Oct 2020
Yes, one of your boundary conditions is that psi(x=infinity) = 0. So we try a value of dpsi/dx(x=0) and see what value of psi(x = infinity) we get. If the latter isn't zero, we try another value of dpsi/dx(x=0) and keep repeating this process until we hit on a value that makes psi(x=infintiy) zero. Instead of trying random guesses for dpsi/dx(x=0), the secant method provides a way of improving subsequent guesses (though the method isn't infallible!).
Roi Bar-On
on 3 Nov 2020
Categories
Find more on Matrix Computations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!