/
test_snes.py
109 lines (99 loc) · 3.98 KB
/
test_snes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
'''
This module test the snes class
'''
from ngsolve import Mesh, VectorH1, BilinearForm, Variation, H1
from ngsolve import GridFunction, CoefficientFunction, Parameter
from ngsolve import InnerProduct, Grad, grad, dx, x,y, Id, Trace, Det, exp, log
from netgen.geom2d import unit_square
import netgen.meshing as ngm
from mpi4py.MPI import COMM_WORLD
import pytest
from ngsPETSc import NonLinearSolver
def test_snes_toy_newtonls():
'''
Testing ngsPETSc SNES wrap for a toy problem, using newtonls
'''
if COMM_WORLD.rank == 0:
mesh = Mesh(unit_square.GenerateMesh(maxh=0.1).Distribute(COMM_WORLD))
else:
mesh = Mesh(ngm.Mesh.Receive(COMM_WORLD))
fes = H1(mesh, order=1, dirichlet="left|right|top|bottom")
u,v = fes.TnT()
a = BilinearForm(fes)
a += (grad(u) * grad(v) + 1/3*u**3*v- 10 * v)*dx
solver = NonLinearSolver(fes, a=a, objective=False,
solverParameters={"snes_type": "newtonls", "snes_monitor": "",
"pc_type": "none"})
gfu0 = GridFunction(fes)
gfu0.Set((x*(1-x))**4*(y*(1-y))**4) # initial guess
solver.solve(gfu0)
assert solver.snes.getConvergedReason() in [4,3,2]
def test_snes_toy_lbfgs():
'''
Testing ngsPETSc SNES wrap for a toy problem, using lbfgs
'''
if COMM_WORLD.rank == 0:
mesh = Mesh(unit_square.GenerateMesh(maxh=0.1).Distribute(COMM_WORLD))
else:
mesh = Mesh(ngm.Mesh.Receive(COMM_WORLD))
fes = H1(mesh, order=3, dirichlet="left|right|top|bottom")
u,v = fes.TnT()
a = BilinearForm(fes)
a += (grad(u) * grad(v) + 1/3*u**3*v- 10 * v)*dx
solver = NonLinearSolver(fes, a=a, objective=False,
solverParameters={"snes_type": "qn", "snes_monitor": "",
"pc_type": "lu"})
gfu0 = GridFunction(fes)
gfu0.Set((x*(1-x))**4*(y*(1-y))**4) # initial guess
solver.solve(gfu0)
assert solver.snes.getConvergedReason() in [4,3,2]
@pytest.mark.mpi_skip()
def test_snes_elastic_beam_newtonls():
'''
Testing ngsPETSc SNES wrap for NeoHook energy minimisation, using newtonls
This test run only in serial becasue variational energy as objective only works
in serial, please use objective=False in parallel.
'''
from netgen.geom2d import SplineGeometry
if COMM_WORLD.rank == 0:
geo = SplineGeometry()
pnums = [ geo.AddPoint (x,y,maxh=0.01) for x,y in [(0,0), (1,0), (1,0.1), (0,0.1)] ]
for p1,p2,bc in [(0,1,"bot"), (1,2,"right"), (2,3,"top"), (3,0,"left")]:
geo.Append(["line", pnums[p1], pnums[p2]], bc=bc)
mesh = Mesh(geo.GenerateMesh(maxh=0.05).Distribute(COMM_WORLD))
else:
mesh = Mesh(ngm.Mesh.Receive(COMM_WORLD))
# E module and poisson number:
E, nu = 210, 0.2
# Lamé constants:
mu = E / 2 / (1+nu)
lam = E * nu / ((1+nu)*(1-2*nu))
fes = VectorH1(mesh, order=2, dirichlet="left")
#gravity:
force = CoefficientFunction( (0,-1) )
u,_ = fes.TnT()
def Pow(a, b):
return exp (log(a)*b)
def NeoHook (C):
return 0.5 * mu * (Trace(C-I) + 2*mu/lam * Pow(Det(C), -lam/2/mu) - 1)
I = Id(mesh.dim)
F = I + Grad(u)
C = F.trans * F
factor = Parameter(0.1)
a = BilinearForm(fes, symmetric=True)
a += Variation(NeoHook (C).Compile() * dx
-factor * (InnerProduct(force,u) ).Compile() * dx)
solver = NonLinearSolver(fes, a=a,
solverParameters={"snes_type": "newtonls",
"snes_max_it": 10,
"snes_monitor": "",
"pc_type": "lu"})
gfu0 = GridFunction(fes)
gfu0.Set((0,0)) # initial guess
solver.solve(gfu0)
assert solver.snes.getConvergedReason() in [4,3,2]
if __name__ == '__main__':
test_snes_toy_lbfgs()
test_snes_toy_newtonls()
if COMM_WORLD.size == 1:
test_snes_elastic_beam_newtonls()