Contents
function [UserVar,rh,kv,Tv,Lv,Pv,Qx,Qy,Rv]=LevelSetEquationAssemblyNR2consistentST(UserVar,CtrlVar,MUA,f0,c0,u0,v0,f1,c1,u1,v1,qx0,qy0,qx1,qy1)
Level Set Equation with a source term

narginchk(15,53) ndim=2; dof=1; neq=dof*MUA.Nnodes; theta=CtrlVar.LevelSetTheta; dt=CtrlVar.dt; CtrlVar.Tracer.SUPG.tau=CtrlVar.LevelSetSUPGtau; isL=CtrlVar.LSF.L ; isP=CtrlVar.LSF.P ; isT=CtrlVar.LSF.T ; f0nod=reshape(f0(MUA.connectivity,1),MUA.Nele,MUA.nod); f1nod=reshape(f1(MUA.connectivity,1),MUA.Nele,MUA.nod); u0nod=reshape(u0(MUA.connectivity,1),MUA.Nele,MUA.nod); % MUA.Nele x nod v0nod=reshape(v0(MUA.connectivity,1),MUA.Nele,MUA.nod); % MUA.Nele x nod u1nod=reshape(u1(MUA.connectivity,1),MUA.Nele,MUA.nod); % MUA.Nele x nod v1nod=reshape(v1(MUA.connectivity,1),MUA.Nele,MUA.nod); % MUA.Nele x nod c0nod=reshape(c0(MUA.connectivity,1),MUA.Nele,MUA.nod); c1nod=reshape(c1(MUA.connectivity,1),MUA.Nele,MUA.nod); qx0nod=reshape(qx0(MUA.connectivity,1),MUA.Nele,MUA.nod); qy0nod=reshape(qy0(MUA.connectivity,1),MUA.Nele,MUA.nod); qx1nod=reshape(qx1(MUA.connectivity,1),MUA.Nele,MUA.nod); qy1nod=reshape(qy1(MUA.connectivity,1),MUA.Nele,MUA.nod); d1d1=zeros(MUA.Nele,MUA.nod,MUA.nod); %b1=zeros(MUA.Nele,MUA.nod); TG=zeros(MUA.Nele,MUA.nod); PG=zeros(MUA.Nele,MUA.nod); LG=zeros(MUA.Nele,MUA.nod); R=zeros(MUA.Nele,MUA.nod); RSUPG=zeros(MUA.Nele,MUA.nod); qx=zeros(MUA.Nele,MUA.nod); qy=zeros(MUA.Nele,MUA.nod); if CtrlVar.LevelSetSolutionMethod=="Newton Raphson" NR=1; else NR=0; end % vector over all elements for each integration point for Iint=1:MUA.nip %Integration points
fun=shape_fun(Iint,ndim,MUA.nod,MUA.points) ; % nod x 1 : [N1 ; N2 ; N3] values of form functions at integration points Deriv=MUA.Deriv(:,:,:,Iint); detJ=MUA.DetJ(:,Iint); f0int=f0nod*fun; f1int=f1nod*fun; u0int=u0nod*fun; v0int=v0nod*fun; u1int=u1nod*fun; v1int=v1nod*fun; c0int=c0nod*fun; c1int=c1nod*fun; % derivatives at one integration point for all elements df0dx=zeros(MUA.Nele,1); df0dy=zeros(MUA.Nele,1); df1dx=zeros(MUA.Nele,1); df1dy=zeros(MUA.Nele,1); dqx0dx=zeros(MUA.Nele,1); dqy0dy=zeros(MUA.Nele,1); dqx1dx=zeros(MUA.Nele,1); dqy1dy=zeros(MUA.Nele,1); for Inod=1:MUA.nod df0dx=df0dx+Deriv(:,1,Inod).*f0nod(:,Inod); df0dy=df0dy+Deriv(:,2,Inod).*f0nod(:,Inod); df1dx=df1dx+Deriv(:,1,Inod).*f1nod(:,Inod); df1dy=df1dy+Deriv(:,2,Inod).*f1nod(:,Inod); dqx0dx=dqx1dx+Deriv(:,1,Inod).*qx0nod(:,Inod); dqy0dy=dqy1dy+Deriv(:,2,Inod).*qy0nod(:,Inod); dqx1dx=dqx1dx+Deriv(:,1,Inod).*qx1nod(:,Inod); dqy1dy=dqy1dy+Deriv(:,2,Inod).*qy1nod(:,Inod); end % Norm of gradient (NG) NG0=sqrt(df0dx.*df0dx+df0dy.*df0dy); % at each integration point for all elements NG1=sqrt(df1dx.*df1dx+df1dy.*df1dy); % at each integration point for all elements n1x=-df1dx./NG1; n1y=-df1dy./NG1; n0x=-df0dx./NG0; n0y=-df0dy./NG0; % if gradient is very small, set normal to zero, and with it the cx and cy components I0=NG0< eps^2 ; I1=NG1< eps^2 ; n1x(I1)=0 ; n1y(I1)=0; n0x(I0)=0 ; n0y(I0)=0; cx1int=-c1int.*n1x ; cy1int=-c1int.*n1y; cx0int=-c0int.*n0x ; cy0int=-c0int.*n0y;
limit cx-u and cy-v where it is suffiently far away from the zero level
tauSUPGint=CalcSUPGtau(CtrlVar,MUA.EleAreas,u0int-cx0int,v0int-cy0int,dt);
%tauSUPGint=CalcSUPGtau(CtrlVar,MUA,u0int,v0int,dt);
% I need to think about a good def for mu
%
% Idea : sqrt( (u0int-cx0int).^2+(v0int-cy0int).^2)) .*sqrt(2*MUA.EleAreas) ;
%
switch lower(CtrlVar.LevelSetFABmu.Scale)
case "constant"
Scale=1 ;
case "ucl"
Scale = sqrt( (u0int-cx0int).^2+(v0int-cy0int).^2) .*sqrt(2*MUA.EleAreas) ;
otherwise
error("Ua:CaseNotFound","CtrlVar.LevelSetFABmu.Scale has an invalid value.")
end
mu=Scale*CtrlVar.LevelSetFABmu.Value; % This has the dimention l^2/t
[kappaint0]=LevelSetEquationFAB(CtrlVar,NG0,mu);
[kappaint1,dkappa]=LevelSetEquationFAB(CtrlVar,NG1,mu);
detJw=detJ*MUA.weights(Iint);
if any(~isfinite(n0x)) ||any(~isfinite(n1x)) || any(~isfinite(kappaint1)) || any(~isfinite(dkappa))
save TestSaveLSFnotFinite
error("LevelSetEquationAssemblyNR2:notfinite","n0x, n1x kappa not finite")
end
isPG=isL ;
for Inod=1:MUA.nod
SUPG=CtrlVar.Tracer.SUPG.Use*tauSUPGint.*((u0int-cx0int).*Deriv(:,1,Inod)+(v0int-cy0int).*Deriv(:,2,Inod));
SUPGdetJw=SUPG.*detJw ; % if there is no advection term, set to zero, ie use Galerkin weighting
if nargout>2
for Jnod=1:MUA.nod
Tlhs=fun(Jnod).*fun(Inod).*detJw;
% (advection term)
Llhs=...
+dt*theta*(...
(u1int-cx1int).*Deriv(:,1,Jnod) + (v1int-cy1int).*Deriv(:,2,Jnod))...
.*fun(Inod).*detJw;
% It might appear one has forgotten to linearize cx, but it turns out this linearisation term is equal to zero. So the only
% contribution of the (u1int-cx1int).*df1dx term stems from the linearisation of df1dx, giving just the usual
% u1int-cx1int).*Deriv(:,1,Jnod) + (v1int-cy1int).*Deriv(:,2,Jnod))...
% Pertubation term (diffusion)
Plhs=dt*theta*...
+(kappaint1.*(Deriv(:,1,Jnod).*Deriv(:,1,Inod)+Deriv(:,2,Jnod).*Deriv(:,2,Inod)) ...
-NR*dkappa.*(n1x.*Deriv(:,1,Jnod)+n1y.*Deriv(:,2,Jnod)).*(df1dx.*Deriv(:,1,Inod)+df1dy.*Deriv(:,2,Inod))) ...
.*detJw;
PGlhs = isT*fun(Jnod) + ...
+isL*dt*theta*((u1int-cx1int).*Deriv(:,1,Jnod) + (v1int-cy1int).*Deriv(:,2,Jnod));
PGlhs=SUPGdetJw.*PGlhs;
% The dqx1dx and dqy1dy terms are calculated from the
% previous interative solution, and therefore do not
% depend on phi at this iteration step
d1d1(:,Inod,Jnod)=d1d1(:,Inod,Jnod)+isL*Llhs+isP*Plhs+isT*Tlhs+isPG*PGlhs;
end
end
% Note, I solve: LSH \phi = - RHS
Galerkin
(time derivative)
Trhs=(f1int-f0int).*fun(Inod).*detJw ;
% (advection)
Lrhs= ...
+ dt*theta* ((u1int-cx1int).*df1dx +(v1int-cy1int).*df1dy).*fun(Inod).*detJw ...
+ dt*(1-theta)*((u0int-cx0int).*df0dx +(v0int-cy0int).*df0dy).*fun(Inod).*detJw ;
% Pertubation term (diffusion)
Prhs=...
dt*theta*kappaint1.*(df1dx.*Deriv(:,1,Inod)+df1dy.*Deriv(:,2,Inod)).*detJw ...
+ dt*(1-theta)*kappaint0.*(df0dx.*Deriv(:,1,Inod)+df0dy.*Deriv(:,2,Inod)).*detJw;
Petrov
ResidualStrong=isT*(f1int-f0int)+... + isL*dt* theta * ((u1int-cx1int).*df1dx +(v1int-cy1int).*df1dy).... + isL*dt*(1-theta) * ((u0int-cx0int).*df0dx +(v0int-cy0int).*df0dy)... - isP*dt* theta * (dqx1dx+ dqy1dy)... - isP*dt*(1-theta) * (dqx0dx+ dqy0dy) ; ResidualStrongSUPGweighted=ResidualStrong.*SUPGdetJw;
% qx= kappaint0.*df0dx ; % qu= kappaint0.*df0dy) ; qx(:,Inod)=qx(:,Inod)+kappaint1.*df1dx ; qy(:,Inod)=qy(:,Inod)+kappaint1.*df1dy ; PG(:,Inod)=PG(:,Inod)+Prhs; LG(:,Inod)=LG(:,Inod)+Lrhs; TG(:,Inod)=TG(:,Inod)+Trhs; R(:,Inod)=R(:,Inod)+ResidualStrong; RSUPG(:,Inod)=RSUPG(:,Inod)+ResidualStrongSUPGweighted;
end
end Pv=sparseUA(neq,1); Lv=sparseUA(neq,1); Tv=sparseUA(neq,1); Qx=sparseUA(neq,1); Qy=sparseUA(neq,1); Rv=sparseUA(neq,1); RSUPGv=sparseUA(neq,1); for Inod=1:MUA.nod Pv=Pv+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),PG(:,Inod),neq,1); Lv=Lv+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),LG(:,Inod),neq,1); Tv=Tv+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),TG(:,Inod),neq,1); Rv=Rv+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),R(:,Inod),neq,1); RSUPGv=RSUPGv+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),RSUPG(:,Inod),neq,1); Qx=Qx+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),qx(:,Inod),neq,1); Qy=Qy+sparseUA(MUA.connectivity(:,Inod),ones(MUA.Nele,1),qy(:,Inod),neq,1); end rh=isL*Lv+isP*Pv+isT*Tv+isPG*RSUPGv; if nargout>2 Iind=zeros(MUA.nod*MUA.nod*MUA.Nele,1); Jind=zeros(MUA.nod*MUA.nod*MUA.Nele,1);Xval=zeros(MUA.nod*MUA.nod*MUA.Nele,1); istak=0; for Inod=1:MUA.nod for Jnod=1:MUA.nod Iind(istak+1:istak+MUA.Nele)=MUA.connectivity(:,Inod); Jind(istak+1:istak+MUA.Nele)=MUA.connectivity(:,Jnod); Xval(istak+1:istak+MUA.Nele)=d1d1(:,Inod,Jnod); istak=istak+MUA.Nele; end end kv=sparseUA(Iind,Jind,Xval,neq,neq); end
end