sandbox/easystab/free_surface_mapping_numjac.m
In this code, I test to have the domain mapping as one of the unknown of the nonlinear problem. In this version, I use the numerical Jacobian. To see the use of the analytical Jacobian, please check out free_surface_mapping.m.
clear all; clf;
disp('%%%%%%%%%')
% parameters
Lx=1;
Ly=1;
Nx=15;
Ny=15;
rho=1;
sig=1;
V=Lx*Ly*0.9; % the initial volume
U=2.01; % inflow velocity
method='fd';
delta=0.1; % continuation length
eps=1e-8; % for the numerical Jacobian
% differentiation
[d.x,d.xx,d.wx,x]=dif1D(method,0,Lx,Nx,5);
[d.y,d.yy,d.wy,y]=dif1D(method,0,Ly,Ny,5);
[D,l,X,Y,Z,I,NN]=dif2D(d,x,y);
% useful
l.top=[l.ctl; l.top; l.ctr]; % include the corners to the top
l.bot=[l.cbl; l.bot; l.cbr]; % include the corners to the bot
l.phi=(1:NN)';
l.e=l.phi(end)+(1:Nx)'; % where we store the interface deformation
l.p0=l.e(end)+1; % where we store the reference pressure
n=NN+Nx+1; % numbers of degrees of freedom
ZZ=zeros(n,n); zx=zeros(Nx,Nx);
II=eye(n); ix=eye(Nx);
%initial guess
phi=U*X(:);
e=1+0*x;
p0=0;
q0=[phi; e; p0];
q=q0;
% Newton iterations
quit=0;count=0;
while ~quit
Numerical Jacobian
In most of the codes, I build the analytical Jacobian, building it using the differentiation matrices and the formula that I derived by hand. Here instead I build it numerically by finite differences.
% nonlinear function and numerical Jacobian
A=zeros(n,n);
for gre=0:n
qq=q+((1:n)==(gre))'*eps;
% variables and their derivatives
e=qq(l.e);
ex=d.x*e; exx=d.xx*e;
a=1+ex.^2;
E=ones(Ny,1)*e';E=E(:);
Ex=ones(Ny,1)*ex'; Ex=Ex(:);
Exx=ones(Ny,1)*exx'; Exx=Exx(:);
Dp.x=D.x-diag(Y(:).*E.^-1.*Ex)*D.y;
Dp.y=diag(E.^-1)*D.y;
Dp.lap=D.xx ...
+diag(-2*Y(:).*E.^-1.*Ex)*(D.x*D.y) ...
+diag(Y(:).^2.*E.^-2.*Ex.^2+E.^-2)*D.yy ...
+diag(Y(:).*(2*E.^-2.*Ex.^2-E.^-1.*Exx))*D.y;
% the present solution and its derivatives
Dp.xE=Dp.x(l.top,:);
Dp.yE=Dp.y(l.top,:);
Dp.lapE=Dp.lap(l.top,:);
Dp.xyE=Dp.xE*D.y;
phi=qq(l.phi); phixE=Dp.xE*phi; phiyE=Dp.yE*phi;
p0=qq(l.p0);
Nonlinear function
% nonlinear function
feps=[Dp.lap*phi; ... % potential flow
-sig*(exx.*a.^-1.5)-(p0+rho/2*(U^2-(phixE.^2+phiyE.^2))); ... % pressure at interface
d.wx*Ly*e-V]; % volume
% boundary conditions
loc=[l.top;l.left;l.bot;l.right;l.e([1,Nx])];
C=[D.x([l.left;l.right],:)*II(l.phi,:); ...
D.y(l.bot,:)*II(l.phi,:); ...
ix([1,Nx],:)*II(l.e,:)];
feps(loc)=[C*(qq-q0); ...
phiyE-phixE.*ex];
% store Jacobian
if gre==0; f=feps; else
A(:,gre)=(feps-f)/eps;
end
end
% show solution
Yp=Y.*reshape(E,Ny,Nx); % physical mesh
plot(x,1+0*x,'k--');hold on
u=Dp.x*phi; v=Dp.y*phi;
surf(X,Yp,reshape(p0-rho/2*(u.^2+v.^2),Ny,Nx)-10,'facealpha',0.2); shading interp;
quiver(X(:),Yp(:),u,v,'k');hold off
axis([-0.1,Lx+0.1,-0.1,1.5*Ly]);
title(V);
drawnow
% convergence test
res=norm(f);
disp([num2str(count) ' ' num2str(res)]);
if count>50||res>1e5||isnan(res); disp('no convergence'); quitcon=1; break; end
if res<1e-7; quit=1; disp('converged'); continue; end
% Newton step
q=q-A\f;
count=count+1;
end
% print figure
set(gcf,'paperpositionmode','auto');
print('-dpng','-r80','free_surface_mapping.png')
The figure showing the deformed domain with velocity field and pressure as color map. We are very close to the fold of the bifurcation branch, we see this by the curvature of the interface.
%}