Skip to content

Commit e8daeb4

Browse files
authored
Test MTW tetrahedron (#4884)
1 parent ec6c302 commit e8daeb4

File tree

1 file changed

+72
-41
lines changed

1 file changed

+72
-41
lines changed

tests/firedrake/regression/test_mtw.py

Lines changed: 72 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
from firedrake import *
2+
import pytest
23
import numpy as np
34

45

5-
convergence_orders = lambda x: np.log2(np.array(x)[:-1] / np.array(x)[1:])
6-
7-
8-
def test_mtw():
6+
@pytest.fixture(params=(2, 3))
7+
def mh(request):
8+
dim = request.param
99
N_base = 2
10-
msh = UnitSquareMesh(N_base, N_base)
11-
mh = MeshHierarchy(msh, 5)
10+
if dim == 2:
11+
refine = 3
12+
msh = UnitSquareMesh(N_base, N_base)
13+
elif dim == 3:
14+
refine = 2
15+
msh = UnitCubeMesh(N_base, N_base, N_base)
16+
else:
17+
raise ValueError("Unexpected dimension")
18+
mh = MeshHierarchy(msh, refine)
1219

1320
V = FunctionSpace(msh, msh.coordinates.ufl_element())
1421
eps = Constant(1 / 2**(N_base-1))
15-
x, y = SpatialCoordinate(msh)
22+
x, y, *z = SpatialCoordinate(msh)
23+
1624
new = Function(V).interpolate(as_vector([x + eps*sin(2*pi*x)*sin(2*pi*y),
17-
y - eps*sin(2*pi*x)*sin(2*pi*y)]))
25+
y - eps*sin(2*pi*x)*sin(2*pi*y), *z]))
1826

1927
# And propagate to refined meshes
2028
coords = [new]
@@ -26,63 +34,86 @@ def test_mtw():
2634

2735
for msh, coord in zip(mh, coords):
2836
msh.coordinates.assign(coord)
29-
30-
params = {"snes_type": "newtonls",
31-
"snes_linesearch_type": "basic",
32-
"snes_monitor": None,
33-
"mat_type": "aij",
34-
"snes_max_it": 10,
35-
"snes_lag_jacobian": -2,
36-
"snes_lag_preconditioner": -2,
37-
"ksp_type": "preonly",
38-
"pc_type": "lu",
39-
"pc_factor_shift_type": "inblocks",
40-
"snes_rtol": 1e-16,
41-
"snes_atol": 1e-25}
42-
37+
return mh
38+
39+
40+
def mesh_sizes(mh):
41+
mesh_size = []
42+
for msh in mh:
43+
DG0 = FunctionSpace(msh, "DG", 0)
44+
h = Function(DG0).interpolate(CellDiameter(msh))
45+
with h.dat.vec as hvec:
46+
_, maxh = hvec.max()
47+
mesh_size.append(maxh)
48+
return mesh_size
49+
50+
51+
def convergence_orders(error, h):
52+
return np.diff(np.log2(error)) / np.diff(np.log2(h))
53+
54+
55+
def test_mtw_darcy_convergence(mh):
56+
sp = {
57+
"ksp_monitor": None,
58+
"mat_type": "matfree",
59+
"pmat_type": "nest",
60+
"ksp_type": "minres",
61+
"ksp_norm_type": "preconditioned",
62+
"pc_type": "fieldsplit",
63+
"pc_fieldsplit_type": "additive",
64+
"fieldsplit_ksp_type": "preonly",
65+
"fieldsplit_0_pc_type": "lu",
66+
"fieldsplit_0_pc_factor_mat_solver_type": "mumps",
67+
"fieldsplit_1_pc_type": "jacobi",
68+
}
69+
gamma = Constant(1E4)
4370
l2_u = []
4471
l2_p = []
4572
for msh in mh[1:]:
46-
x, y = SpatialCoordinate(msh)
73+
x, y, *z = SpatialCoordinate(msh)
4774
pex = sin(pi * x) * sin(2 * pi * y)
75+
if z:
76+
pex *= sin(pi*z[0])
77+
4878
uex = -grad(pex)
4979
f = div(uex)
5080

51-
V = FunctionSpace(msh, "MTW", 3)
52-
W = FunctionSpace(msh, "DG", 0)
53-
Z = V * W
81+
V = FunctionSpace(msh, "MTW", 1)
82+
Q = FunctionSpace(msh, "DG", 0)
83+
Z = V * Q
5484

55-
up = Function(Z)
56-
u, p = split(up)
57-
v, w = TestFunctions(Z)
85+
u, p = TrialFunctions(Z)
86+
v, q = TestFunctions(Z)
87+
88+
a = -inner(u, v) * dx + inner(p, div(v)) * dx + inner(div(u), q) * dx
89+
L = inner(f, q) * dx
90+
91+
Jp = inner(u, v)*dx + inner(div(u), gamma*div(v))*dx + inner(p/gamma, q)*dx
5892

59-
F = (inner(u, v) * dx - inner(p, div(v)) * dx
60-
+ inner(div(u), w) * dx - inner(f, w) * dx)
93+
up = Function(Z)
6194

62-
solve(F == 0, up, solver_parameters=params)
95+
solve(a == L, up, Jp=Jp, solver_parameters=sp)
6396

6497
u, p = up.subfunctions
6598
l2_u.append(errornorm(uex, u))
6699
l2_p.append(errornorm(pex, p))
67100

68-
assert min(convergence_orders(l2_u)) > 1.8
69-
assert min(convergence_orders(l2_p)) > 0.8
101+
h = mesh_sizes(mh[1:])
102+
assert min(convergence_orders(l2_u, h)) > 1.75
103+
assert min(convergence_orders(l2_p, h)) > 0.8
70104

71105

72106
def test_mtw_interior_facet():
73107
mesh = UnitSquareMesh(4, 4)
74-
V = FunctionSpace(mesh, mesh.coordinates.ufl_element())
75108
eps = Constant(0.5 / 2**3)
76109

77110
x, y = SpatialCoordinate(mesh)
78-
new = Function(V).interpolate(as_vector([x + eps*sin(2*pi*x)*sin(2*pi*y),
79-
y - eps*sin(2*pi*x)*sin(2*pi*y)]))
80-
mesh = Mesh(new)
111+
mesh.coordinates.interpolate(as_vector([x + eps*sin(2*pi*x)*sin(2*pi*y),
112+
y - eps*sin(2*pi*x)*sin(2*pi*y)]))
81113

82-
V = FunctionSpace(mesh, 'Mardal-Tai-Winther', 3)
114+
V = FunctionSpace(mesh, 'Mardal-Tai-Winther', 1)
83115

84-
x, y = SpatialCoordinate(mesh)
85-
uh = project(as_vector((x+y, 2*x-y)), V)
116+
uh = Function(V).interpolate(as_vector((x+y, 2*x-y)))
86117

87118
volume = assemble(div(uh)*dx)
88119

0 commit comments

Comments
 (0)