23.7. Cooke’s membrane benchmark#
compare Hybrid TDNNS to standard fem
from ngsolve import *
from ngsolve.webgui import Draw
from netgen.occ import *
shape = MoveTo(0,0).Line(48,44).Line(0,16,name="right").Line(-48,-16).Close(name="fix").Face()
shape.vertices.hpref=1
mesh = shape.GenerateMesh(dim=2, maxh=10)
# mesh.RefineHP(4, 0.4)
Draw (mesh);
E,nu = 1, 1/3
# plane stress:
def Strain(stress, E,nu):
return (1+nu)/E * stress - nu/E*Trace(stress)*Id(2)
def Stress(strain, E, nu):
return E/(1+nu) * strain + (E*nu)/(1-nu**2) * Trace(strain)*Id(2)
traction = CF((0,20))
def SolveTDNNS(order=1):
fesu = HCurl(mesh, order=order, type1=True, dirichlet="fix")
if order == 1:
fesuhat = NormalFacetFESpace(mesh, order=1, dirichlet="fix")
fessigma = HDivDiv(mesh, order=1, orderinner=0)
else:
fesuhat = NormalFacetFESpace(mesh, order=order-1, dirichlet="fix")
fessigma = HDivDiv(mesh, order=order-1, plus=True)
fessigma = Discontinuous(fessigma)
# fessigma = PrivateSpace(Discontinuous(fessigma))
fes = fesu*fesuhat*fessigma
(u,uhat, sigma), (du,duhat, dsigma) = fes.TnT()
n = specialcf.normal(2)
def Div(sigma,v, vhat):
return InnerProduct(-Grad(v),sigma)*dx + InnerProduct( (v-vhat)*n,sigma[n,n])*dx(element_boundary=True)
term = InnerProduct(-Strain(sigma,E,nu),dsigma)*dx - Div(dsigma,u,uhat) - Div(sigma,du,duhat)
a = BilinearForm(term, condense=True).Assemble()
f = LinearForm(traction*du.Trace()*ds("right")).Assemble()
gf = GridFunction(fes)
# print (a.mat.nze)
Solve (a*gf==f)
return gf
def SolveStd (order=1):
fes = VectorH1(mesh, order=order, dirichlet="fix")
u,v = fes.TnT()
a = BilinearForm(InnerProduct(Stress(Sym(Grad(u)), E,nu), Grad(v))*dx, condense=True).Assemble()
# print (a.mat.nze)
f = LinearForm(traction*v*ds("right")).Assemble()
gf = GridFunction(fes)
Solve (a*gf==f)
return gf
gf = SolveTDNNS(order=3)
gfu, gfuhat, gfsigma = gf.components
Draw (gfu[1],mesh, deformation=0.001*gfu, order=5);
Draw (gfsigma[0,0], mesh, min=-50, max=50, order=5); # min=-20e6, max=20e6);
gfu = SolveStd(order=3)
Draw (gfu[1],mesh, deformation=0.001*gfu, order=5);
Draw (Stress(Sym(Grad(gfu)),E,nu)[0,0], mesh, min=-50, max=50, order=5);
orders = []
uy_std = []
uy_TDNNS = []
for order in range(1, 10):
orders.append(order)
gfstd = SolveStd(order=order)
uy_std.append (gfstd[1] (mesh(48, 60)))
gfu, gfuhat, gfsigma = SolveTDNNS(order=order).components
uy_TDNNS.append (gfu[1] (mesh(48, 60)))
# print (orders, uy_std, uy_TDNNS)