This Code Has Been Developed Based On An AIAA Conference Paper (2009-3650) Towards Accurate Flow Predictions Using Unstructured
This Code Has Been Developed Based On An AIAA Conference Paper (2009-3650) Towards Accurate Flow Predictions Using Unstructured
> restart;with(LinearAlgebra):
> Lapl_Err:=Matrix(51,15):
> gradx_Err:=Matrix(51,15):
> grady_Err:=Matrix(51,15):
Symbolic names so I won't have to remember what's stored with which index.
Calculate refrence points and all moments of each triangle about its centroid. These
expressions are exact, based on using high-order quadrature and drastically simplifying
the results for centroidal coordinates.
> calcMoments:=proc(tri)
local dx1, dx2, dx3, dy1, dy2, dy3, x1, x2, x3, y1, y2,
y3, vert1, vert2, vert3;
refLoc[tri, 1] := (1/3)*x1+(1/3)*x2+(1/3)*x3;
refLoc[tri, 2] := (1/3)*y1+(1/3)*y2+(1/3)*y3;
dx1 := (2/3)*x1-(1/3)*x2-(1/3)*x3;
dx2 := (2/3)*x2-(1/3)*x1-(1/3)*x3;
dx3 := (2/3)*x3-(1/3)*x1-(1/3)*x2;
dy1 := (2/3)*y1-(1/3)*y2-(1/3)*y3;
dy2 := (2/3)*y2-(1/3)*y1-(1/3)*y3;
dy3 := (2/3)*y3-(1/3)*y1-(1/3)*y2;
moments[tri, eXX] :=
(1/12)*dx1^2+(1/12)*dx2^2+(1/12)*dx3^2;
moments[tri, eXY] :=
(1/12)*dx1*dy1+(1/12)*dx2*dy2+(1/12)*dx3*dy3;
moments[tri, eYY] :=
(1/12)*dy1^2+(1/12)*dy2^2+(1/12)*dy3^2;
moments[tri, eXXY] :=
(1/30)*dx1*dx2*dy3+(1/30)*dx2*dx3*dy1+(1/30)*dx3*dx1*dy2;
moments[tri, eXYY] :=
(1/30)*dx1*dy2*dy3+(1/30)*dx2*dy3*dy1+(1/30)*dx3*dy1*dy2;
return
end proc:
Retrieve a moment based on the exponents of x and y used in it. Great when applying
parallel axis thm.
> Moment:=proc(tri, i, j)
local index;
index:=-1;
if (i+j = 0) then
return 1;
end if;
end if;
end if;
end if;
end if;
end proc:
total := 0;
dx := refLoc[tri1,1] - refLoc[triBase,1];
dy := refLoc[tri1,2] - refLoc[triBase,2];
for k from 0 to n do
for l from 0 to m do
end do ;
end do;
return simplify(expand(total)) ;
end proc:
> computeCVaverage:=proc(i,j)
local sum;
sum:=F+F_x*xyhat(i,j,1,0) + F_y*xyhat(i,j,0,1) +
F_xx/2*xyhat(i,j,2,0)
+ F_xy*xyhat(i,j,1,1) + F_yy/2*xyhat(i,j,0,2)
+ F_xxx*xyhat(i,j,3,0)/6 + F_xxy*xyhat(i,j,2,1)/2
+ F_xyy*xyhat(i,j,1,2)/2 + F_yyy*xyhat(i,j,0,3)/6
+ F_xxxx*xyhat(i,j,4,0)/24 + F_xxxy*xyhat(i,j,3,1)/6
+ F_xxyy*xyhat(i,j,2,2)/4 + F_xyyy*xyhat(i,j,1,3)/6
+ F_yyyy*xyhat(i,j,0,4)/24;
end proc:
> ComputeCvVec:=proc(i,j)
local CvVec;
CvVec:=Vector([1,xyhat(i,j,1,0),xyhat(i,j,0,1),xyhat(i,j,2,
0)/2,xyhat(i,j,1,1),xyhat(i,j,0,2)/2,xyhat(i,j,3,0)/6,xyhat
(i,j,2,1)/2,xyhat(i,j,1,2)/2,xyhat(i,j,0,3)/6,xyhat(i,j,4,0
)/24,xyhat(i,j,3,1)/6,xyhat(i,j,2,2)/4,xyhat(i,j,1,3)/6,xyh
at(i,j,0,4)/24]);
return CvVec;
end proc:
> CA:=proc(tri)
local grad,P,N,F,vert1,vert2,nx,ny,neigh,q_i,i;
P[1]:=refLoc[tri,1]; P[2]:=refLoc[tri,2];
for i from 1 to 3 do
neigh:=NeighCell[tri,i];
N[1]:=refLoc[neigh,1]; N[2]:=refLoc[neigh,2];
vert1:=tri2Vert[tri,i]; vert2:=tri2Vert[tri,i+1];
F[1]:=(coords[vert1,1]+coords[vert2,1])/2;
F[2]:=(coords[vert1,2]+coords[vert2,2])/2;
nx:=-coords[vert1,2]+coords[vert2,2];
ny:=-coords[vert2,1]+coords[vert1,1];
q_i:=(Norm(N-F,2)*CVave[tri]+Norm(P-F,2)*CVave[neigh])/
(Norm(N-F,2)+Norm(P-F,2));
grad[1]:=grad[1]+q_i*nx;
grad[2]:=grad[2]+q_i*ny;
end do;
end proc:
> LS:=proc(tri)
local grad,w,P,N,neigh,i,RHS,LHS;
RHS:=Vector(3);
LHS:=Matrix(3,2);
grad:=Vector(2); P:=Vector(2);
N:=Vector(2);
P[1]:=refLoc[tri,1]; P[2]:=refLoc[tri,2];
for i from 1 to 3 do
neigh:=NeighCell[tri,i];
N[1]:=refLoc[neigh,1]; N[2]:=refLoc[neigh,2];
LHS[i,1]:=simplify((N[1]-P[1])*w);
LHS[i,2]:=simplify((N[2]-P[2])*w);
RHS[i]:=w*(CVave[neigh]-CVave[tri]);
end do;
grad:=LeastSquares(LHS,RHS);
end proc:
This matrix contains the number of neighboring cells for each cell,cells=1...10
> NeighCell:=Matrix(10,3,[[2,4,3],[1,6,5],[1,8,7],[1,10,9],
[2,19,18],[2,12,11],[3,13,12],[3,15,14],[4,16,15],
[4,18,17]]):
This matrix contains the number of vertices that make a cell, note that the sequence of
numbers for each cell obey the sequence of NeighCell Matrix so that fiding location of
face centers become easy!!
> tri2Vert:=Matrix(19,4,[[7,11,12,7],[11,7,6,11],
[7,12,8,7],[12,11,15,12],[11,6,10,11],[6,7,2,6],[7,8,3,7],
[8,12,13,8],[12,15,16,12],[15,11,14,15],[1,6,2,1],
[2,7,3,2],[3,8,4,3],[8,13,9,8],[12,16,13,12],[15,18,16,15],
[14,17,15,14],[10,14,11,10],[5,10,6,5]]):
> AA:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
return((grad1+grad2)/2);
end proc:
> VW:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
local w1,w2;
w1:=moments[tri1,eSize]/(moments[tri1,eSize]
+moments[tri2,eSize]);
w2:=1-w1;
return (simplify(w1*grad1+w2*grad2));
end proc:
> LI:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
F[1]:= (coords[vert1,1]+coords[vert2,1])/2;
F[2]:= (coords[vert1,2]+coords[vert2,2])/2;
N[1]:=refLoc[tri2,1];
N[2]:=refLoc[tri2,2];
P[1]:=refLoc[tri1,1];
P[2]:=refLoc[tri1,2];
w1:=(Norm(F-N,2))/(Norm(F-N,2)+Norm(F-P,2));
w2:=1-w1;
end proc:
> Disconti:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
F[1]:= (coords[vert1,1]+coords[vert2,1])/2;
F[2]:= (coords[vert1,2]+coords[vert2,2])/2;
N[1]:=refLoc[tri2,1];
N[2]:=refLoc[tri2,2];
P[1]:=refLoc[tri1,1];
P[2]:=refLoc[tri1,2];
Fminus:=CVave[tri1]+grad1[1]*(F[1]-P[1])+grad1[2]*(F[2]P[2]);
Fplus:=CVave[tri2]+grad2[1]*(F[1]-N[1])+grad2[2]*(F[2]N[2]);
L:=sqrt((coords[vert1,1]-coords[vert2,1])^2+
(coords[vert1,2]-coords[vert2,2])^2);
nx:=-(coords[vert1,2]-coords[vert2,2])/L;
ny:=-(coords[vert2,1]-coords[vert1,1])/L;
Jump[1]:=((Fplus-Fminus))*nx;#*L*nx)/(moments[tri1,eSize]
+moments[tri2,eSize]);
Jump[2]:=((Fplus-Fminus))*ny;#*L*ny)/(moments[tri1,eSize]
+moments[tri2,eSize]);
return(Jump);
end proc:
> CCED:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
N[1]:=refLoc[tri2,1];
N[2]:=refLoc[tri2,2];
P[1]:=refLoc[tri1,1];
P[2]:=refLoc[tri1,2];
PN2:=(N[1]-P[1])^2+(N[2]-P[2])^2;
FD[1]:=(CVave[tri2]-CVave[tri1])*(N[1]-P[1])/PN2;
FD[2]:=(CVave[tri2]-CVave[tri1])*(N[2]-P[2])/PN2;
return (simplify(FD));
end proc:
> FND:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
N[1]:=refLoc[tri2,1];
N[2]:=refLoc[tri2,2];
P[1]:=refLoc[tri1,1];
P[2]:=refLoc[tri1,2];
PN:=N-P;
L:=sqrt((coords[vert1,1]-coords[vert2,1])^2+
(coords[vert1,2]-coords[vert2,2])^2);
nx:=(coords[vert1,2]-coords[vert2,2])/L;
ny:=(coords[vert2,1]-coords[vert1,1])/L;
FD[1]:=(CVave[tri2]-CVave[tri1])*nx/(nx*PN[1]+ny*PN[2]);
FD[2]:=(CVave[tri2]-CVave[tri1])*ny/(nx*PN[1]+ny*PN[2]);
return (simplify(FD));
end proc:
> CND:=proc(tri1,tri2,vert1,vert2,grad1,grad2)
F[1]:= (coords[vert1,1]+coords[vert2,1])/2;
F[2]:= (coords[vert1,2]+coords[vert2,2])/2;
N[1]:=refLoc[tri2,1];
N[2]:=refLoc[tri2,2];
P[1]:=refLoc[tri1,1];
P[2]:=refLoc[tri1,2];
L:=sqrt((coords[vert1,1]-coords[vert2,1])^2+
(coords[vert1,2]-coords[vert2,2])^2);
n[1]:=(coords[vert1,2]-coords[vert2,2])/L;
n[2]:=(coords[vert2,1]-coords[vert1,1])/L;
t[1]:=(coords[vert1,1]-coords[vert2,1])/L;
t[2]:=(coords[vert1,2]-coords[vert2,2])/L;
FD[1]:=(CVave[tri2]-CVave[tri1]+
(grad2[1]*t[1]+grad2[2]*t[2])*(NF[1]*t[1]+NF[2]*t[2])(grad1[1]*t[1]+grad1[2]*t[2])*(PF[1]*t[1]+PF[2]*t[2]))*n[1]
/(n[1]*PN[1]+n[2]*PN[2]);
FD[2]:=(CVave[tri2]-CVave[tri1]+
(grad2[1]*t[1]+grad2[2]*t[2])*(NF[1]*t[1]+NF[2]*t[2])(grad1[1]*t[1]+grad1[2]*t[2])*(PF[1]*t[1]+PF[2]*t[2]))*n[2]
/(n[1]*PN[1]+n[2]*PN[2]);
end proc:
Flux integral calculation based on cell gradient method, cell gradient averaging and
different types of corrections
> FluxIntegral:=proc(tri,CG,CGA,Jump,FDC,alpha)
flux:=0;
grad1:=CG(tri);
for i from 1 to 3 do
neigh:=NeighCell[tri,i];
vert1:=tri2Vert[tri,i]; vert2:=tri2Vert[tri,i+1];
grad2:=CG(neigh);
else CellAveraging:=CGA(tri,neigh,vert1,vert2,grad1,grad2);
end if;
else Discontinuity:=Jump(tri,neigh,vert1,vert2,grad1,grad2);
end if;
nx:=-coords[vert1,2]+coords[vert2,2];
ny:=-coords[vert2,1]+coords[vert1,1];
n_mag:=sqrt(nx*nx+ny*ny);
Lr:=0.5*abs((refLoc[neigh,1]-refLoc[tri,1])*nx+
(refLoc[neigh,2]-refLoc[tri,2])*ny)/n_mag;
JC:=(0.5*alpha[i])/Lr;
FG:=JC*Discontinuity+CellAveraging;
elif(FDC=CCED) then
FiniteDiff:=CCED(tri,neigh,vert1,vert2,grad1,grad2);
PN_per:=Vector(2,[(refLoc[neigh,2]-refLoc[tri,2]),
(refLoc[tri,1]-refLoc[neigh,1])]);
FG:=((CellAveraging[1]*PN_per[1]+CellAveraging[2]*PN_per[2]
)/
(PN_per[1]*PN_per[1]+PN_per[2]*PN_per[2]))*PN_per+JC*Discon
tinuity+FiniteDiff;
elif(FDC=CCED_n) then
L_face:=sqrt((coords[vert1,1]-coords[vert2,1])^2+
(coords[vert1,2]-coords[vert2,2])^2);
e_face:=Vector(2,[(coords[vert1,1]-coords[vert2,1])/L_face,
(coords[vert1,2]-coords[vert2,2])/L_face]);
L_edge:=sqrt((refLoc[neigh,1]-refLoc[tri,1])^2+
(refLoc[neigh,2]-refLoc[tri,2])^2);
e_edge:=Vector(2,[(refLoc[neigh,1]-refLoc[tri,1])/L_edge,
(refLoc[neigh,2]-refLoc[tri,2])/L_edge]);
Grad_face:=CellAveraging[1]*e_face[1]+CellAveraging[2]*e_fa
ce[2];
FiniteDiff:=(CVave[neigh]-CVave[tri])/L_edge;
LHS:=Matrix(2,2,[e_face[1], e_face[2],
e_edge[1],e_edge[2]]);
RHS:=Vector(2,[Grad_face, FiniteDiff]);
FG:=LinearSolve(LHS,RHS);
else
FiniteDiff:=FDC(tri,neigh,vert1,vert2,grad1,grad2);
t:=Vector(2,[(coords[vert1,1]-coords[vert2,1]),
(coords[vert1,2]-coords[vert2,2])]);
FG:=((CellAveraging[1]*t[1]+CellAveraging[2]*t[2])/
(t[1]*t[1]+t[2]*t[2]))*t+JC*Discontinuity+FiniteDiff;
end if;
flux:=flux+(nx*FG[1]+ny*FG[2]);
end do;
return (simplify(flux))
end proc:
coordsRand:=Matrix(18,2):
testcase1:=subs(R=1.15,a=0.5,CC=sqrt(1-0.25*(0.5)^2),
coordsCurve2):
testcase2:=subs(b=0.2, coordsShear):
coordsRand[i,1]:=coordsPerf[i,1]+h*randneg1to1();
coordsRand[i,2]:=coordsPerf[i,2]+h*randneg1to1();
end do:
#coordsRand[7,1]:=-(coordsRand[11,1]+coordsRand[12,1]);
#coordsRand[7,2]:=-(coordsRand[11,2]+coordsRand[12,2]);
> evalf(subs(h=1,coordsRand));
> Lapl_Err_curve:=Matrix(100,15):
> coordsRand2:=Matrix(18,2);
for i from 1 to 18 do
coordsRand2[i,1]:=coordsRand[i,1]((coordsRand[7,1]+coordsRand[11,1]+coordsRand[12,1])/3);
coordsRand2[i,2]:=coordsRand[i,2]((coordsRand[7,2]+coordsRand[11,2]+coordsRand[12,2])/3);
end do:
> evalf(subs(h=1,coordsRand2));
for i from 1 to 1 do
ia:=(0.01*i);
iCC:=sqrt(1-0.25*(ia)^2);
coords:=subs(R=1.15,a=ia,CC=iCC, coordsCurve2):
calcAllMoments():
exactLapl_Vec:=Vector([0,0,0,1,0,1,0,0,0,0,moments[1,eXX]/2
,moments[1,eXY],(moments[1,eXX]
+moments[1,eYY])/2,moments[1,eXY],moments[1,eYY]/2]):
for j from 1 to 19 do
bleh_Vec[j]:=ComputeCvVec(j,1):
end do:
for r from 1 to 15 do
Lapl_Err_curve[i,r]:=eval(err_Lapl_Vec[r],h=1);
end do:
end do:
> Curved_data:=Matrix(100,2):
Curved_data[i,1]:=i*0.01;
Curved_data[i,2]:=sqrt(Lapl_Err_curve[i,4]^2+Lapl_Err_curve
[i,5]^2+Lapl_Err_curve[i,6]^2);
end do:
> Curved_data;
Lapl_Err_curve;
> coords:=coordsRand:
calcAllMoments():
Lapl_Err_JC:=Matrix(9,15):
Quality:=Matrix(51,9):
exactLapl_Vec:=Vector([0,0,0,1,0,1,0,0,0,0,moments[1,eXX]/2
,moments[1,eXY],(moments[1,eXX]
+moments[1,eYY])/2,moments[1,eXY],moments[1,eYY]/2]):
for j from 1 to 19 do
bleh_Vec[j]:=ComputeCvVec(j,2):
end do:
for i from -4 to 4 do
JJ:=0.3333*i;
discLapl:=FluxIntegral(2,LS,LI,Disconti,0,JJ)/moments[1,eSi
ze]: expand(simplify(%)) assuming h>0;
for r from 1 to 15 do
Lapl_Err_JC[i+5,r]:=eval(err_Lapl_Vec[r],h=1);
for j from 1 to 51 do
Lapl_Err[j,r]:=eval(Lapl_Err_JC[i+5,r],[b=(j-1)/100,h=1]);
Lapl_Err[j,r]:=evalf(%);
Quality[j,i+5]:=sqrt(Lapl_Err[j,7]^2+Lapl_Err[j,8]^2+Lapl_E
rr[j,9]^2+Lapl_Err[j,10]^2);
end do:
end do:
end do:
> Quality;
coord_data:=evalf(subs(h=1,coordsPerf));#Matrix(12,2,
[[coords[2,1],coords[2,2]],[coords[3,1],coords[3,2]],
[coords[6,1],coords[6,2]],[coords[7,1],coords[7,2]],
[coords[8,1],coords[8,2]],[coords[10,1],coords[10,2]],
[coords[11,1],coords[11,2]],[coords[12,1],coords[12,2]],
[coords[13,1],coords[13,2]],[coords[14,1],coords[14,2]],
[coords[15,1],coords[15,2]],[coords[16,1],coords[16,2]]]);
mesh_vertex:=evalf(subs(h=1,s=0.75,coord_data));
> coords:=coordsPerf;
calcAllMoments():
refLoc[1,1];
> grad:=LS(1)+LS(3);
>
exactLapl:=(F_xx+F_yy+F_xxxx*moments[1,eXX]/2+F_xxxy*moment
s[1,eXY]+F_xxyy*(moments[1,eXX]
+moments[1,eYY])/2+F_xyyy*moments[1,eXY]
+F_yyyy*moments[1,eYY]/2);
exactgradx:=(F_x+F_xxx*moments[1,eXX]/2+F_xyy*moments[1,eYY
]/2+F_xxxx*moments[1,eXXX]/6+F_xxxy*moments[1,eXXY]/2+F_xxy
y*moments[1,eXYY]/2+F_xyyy*moments[1,eYYY]/6):
exactgrady:=(F_y+F_xxy*moments[1,eXX]/2+F_yyy*moments[1,eYY
]/2+F_xxxy*moments[1,eXXX]/6+F_xxyy*moments[1,eXXY]/2+F_xyy
y*moments[1,eXYY]/2+F_yyyy*moments[1,eYYY]/6):
exactLapl_Vec:=Vector([0,0,0,1,0,1,0,0,0,0,moments[1,eXX]/2
,moments[1,eXY],(moments[1,eXX]
+moments[1,eYY])/2,moments[1,eXY],moments[1,eYY]/2]):
exactgradx_Vec:=Vector([0,1,0,0,0,0,moments[1,eXX]/2,0,mome
nts[1,eYY]/2,0,moments[1,eXXX]/6,moments[1,eXXY]/2,moments[
1,eXYY]/2,moments[1,eYYY]/6,0]):
exactgrady_Vec:=Vector([0,0,1,0,0,0,0,moments[1,eXX]/2,0,0,
0,0,0,0,0]):
>
bleh_Vec[i]:=ComputeCvVec(i,1):
bleh[i]:=computeCVaverage(i,1):
end do:
> bleh[4];
#discLapl:=FluxIntegral(1,LS,0,0,CCED,JC)/moments[1,eSize]:
expand(simplify(%)) assuming s>0, h>0;
discLapl:=3*CVave[1]-(CVave[2]+CVave[3]+CVave[4]);
> collect(err_grad_x,h);
> collect(err_grad_y,h);
> subs(CVave=bleh,discLapl-exactLapl):
errLapl2:=(simplify(%) assuming h>0):
evalf(collect(%,h));
>
for r from 1 to 15 do
Lapl_Err[j,r]:=eval(err_Lapl_Vec[r],[k=(100-j+1)/100,h=1]);
Lapl_Err[j,r]:=evalf(%);
gradx_Err[j,r]:=eval(err_grad_x_Vec[r],[b=(100j+1)/100,h=1]);
gradx_Err[j,r]:=evalf(%);
grady_Err[j,r]:=eval(err_grad_y_Vec[r],[b=(100j+1)/100,h=1]);
grady_Err[j,r]:=evalf(%);
end do:
end do:
> Lapl_Err;
> gradx_Err;
> grady_Err;
>
>