Skip to content

Commit 7b6a89a

Browse files
committed
add more tests
1 parent af3b325 commit 7b6a89a

File tree

2 files changed

+39
-24
lines changed

2 files changed

+39
-24
lines changed

firedrake/preconditioners/bddc.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,12 @@ def get_discrete_gradient(V):
157157

158158
Q = FunctionSpace(V.mesh(), curl_to_grad(V.ufl_element()))
159159
gradient = tabulate_exterior_derivative(Q, V)
160-
nsp = VectorSpaceBasis([Function(Q).interpolate(Constant(1))])
160+
basis = Function(Q)
161+
try:
162+
basis.interpolate(Constant(1))
163+
except NotImplementedError:
164+
basis.project(Constant(1))
165+
nsp = VectorSpaceBasis([basis])
161166
nsp.orthonormalize()
162167
gradient.setNullSpace(nsp.nullspace())
163168
if not is_lagrange(Q.finat_element):

tests/firedrake/regression/test_bddc.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ def bddc_params():
2424
return sp
2525

2626

27-
def solver_parameters(static_condensation=False, variant=None):
28-
rtol = 1E-8
29-
atol = 0
27+
def solver_parameters(cellwise=False, condense=False, variant=None, rtol=1E-10, atol=0):
3028
sp_bddc = bddc_params()
31-
if variant != "fdm":
29+
if not cellwise:
30+
assert not condense
3231
sp = sp_bddc
3332

34-
elif static_condensation:
33+
elif condense:
34+
assert variant == "fdm"
3535
sp = {
3636
"pc_type": "python",
3737
"pc_python_type": "firedrake.FacetSplitPC",
@@ -46,10 +46,12 @@ def solver_parameters(static_condensation=False, variant=None):
4646
"facet_fdm_pc_fieldsplit_diag_use_amat": False,
4747
"facet_fdm_pc_fieldsplit_off_diag_use_amat": False,
4848
"facet_fdm_fieldsplit_ksp_type": "preonly",
49-
"facet_fdm_fieldsplit_0_pc_type": "jacobi",
49+
"facet_fdm_fieldsplit_0_pc_type": "bjacobi",
50+
"facet_fdm_fieldsplit_0_pc_type_sub_pc_type": "icc",
5051
"facet_fdm_fieldsplit_1": sp_bddc,
5152
}
5253
else:
54+
assert variant == "fdm"
5355
sp = {
5456
"pc_type": "python",
5557
"pc_python_type": "firedrake.FDMPC",
@@ -62,7 +64,6 @@ def solver_parameters(static_condensation=False, variant=None):
6264
"ksp_type": "cg",
6365
"ksp_norm_type": "natural",
6466
"ksp_converged_reason": None,
65-
"ksp_monitor": None,
6667
"ksp_rtol": rtol,
6768
"ksp_atol": atol,
6869
})
@@ -71,7 +72,9 @@ def solver_parameters(static_condensation=False, variant=None):
7172
return sp
7273

7374

74-
def solve_riesz_map(rg, mesh, family, degree, variant, bcs, condense=False, vector=False):
75+
def solve_riesz_map(rg, mesh, family, degree, variant, bcs, cellwise=False, condense=False, vector=False):
76+
"""Solve the riesz map for a random manufactured solution and return the
77+
square root of the estimated condition number."""
7578
dirichlet_ids = []
7679
if bcs:
7780
dirichlet_ids = ["on_boundary"]
@@ -120,20 +123,25 @@ def solve_riesz_map(rg, mesh, family, degree, variant, bcs, condense=False, vect
120123
uh = Function(V, name="solution")
121124
problem = LinearVariationalProblem(a, L, uh, bcs=bcs)
122125

123-
sp = solver_parameters(condense, variant=variant)
126+
rtol = 1E-8
127+
sp = solver_parameters(cellwise=cellwise, condense=condense, variant=variant, rtol=rtol)
128+
sp.setdefault("ksp_view_singularvalues", None)
124129
solver = LinearVariationalSolver(problem, near_nullspace=nsp,
125130
solver_parameters=sp)
126131
solver.solve()
127-
rtol = sp.get("ksp_rtol", 1E-8)
128132
uerr = Function(V).assign(uh - u_exact)
129133
assert (assemble(a(uerr, uerr)) / assemble(a(u_exact, u_exact))) ** 0.5 < rtol
130-
return solver.snes.getLinearSolveIterations()
134+
135+
ew = solver.snes.ksp.computeEigenvalues()
136+
assert min(ew) >= 1.0
137+
kappa = max(abs(ew)) / min(abs(ew))
138+
return kappa ** 0.5
131139

132140

133141
@pytest.fixture(params=(2, 3), ids=("square", "cube"))
134142
def mh(request):
135143
dim = request.param
136-
nx = 3
144+
nx = 4
137145
base = UnitSquareMesh(nx, nx, quadrilateral=True)
138146
mh = MeshHierarchy(base, 1)
139147
if dim == 3:
@@ -155,33 +163,35 @@ def test_vertex_dofs(mh, variant, degree):
155163

156164

157165
@pytest.mark.parallel
158-
@pytest.mark.parametrize("family,degree", [("Q", 4)])
166+
@pytest.mark.parametrize("family,degree", [("Q", 4), ("E", 3), ("F", 3)])
159167
@pytest.mark.parametrize("condense", (False, True))
160-
def test_bddc_fdm(rg, mh, family, degree, condense):
168+
def test_bddc_cellwise_fdm(rg, mh, family, degree, condense):
161169
"""Test h-independence of condition number by measuring iteration counts"""
162170
variant = "fdm"
163171
bcs = True
164-
its = [solve_riesz_map(rg, m, family, degree, variant, bcs, condense=condense) for m in mh]
165-
assert (np.diff(its) <= 2).all()
172+
sqrt_kappa = [solve_riesz_map(rg, m, family, degree, variant, bcs, cellwise=True, condense=condense) for m in mh]
173+
print(sqrt_kappa)
174+
assert (np.diff(sqrt_kappa) <= 0.1).all(), str(sqrt_kappa)
166175

167176

168177
@pytest.mark.parallel
169178
@pytest.mark.parametrize("family,degree", [("Q", 4)])
170179
@pytest.mark.parametrize("vector", (False, True), ids=("scalar", "vector"))
171180
def test_bddc_aij_quad(rg, mh, family, degree, vector):
172-
"""Test h-independence of condition number by measuring iteration counts"""
181+
"""Test h-dependence of condition number by measuring iteration counts"""
173182
variant = None
174183
bcs = True
175-
its = [solve_riesz_map(rg, m, family, degree, variant, bcs, vector=vector) for m in mh]
176-
assert (np.diff(its) <= 2).all()
184+
sqrt_kappa = [solve_riesz_map(rg, m, family, degree, variant, bcs, vector=vector) for m in mh]
185+
assert (np.diff(sqrt_kappa) <= 0.5).all(), str(sqrt_kappa)
177186

178187

179188
@pytest.mark.parallel
180189
@pytest.mark.parametrize("family,degree", [("CG", 3), ("N1curl", 3), ("N1div", 3)])
181190
def test_bddc_aij_simplex(rg, family, degree):
182-
"""Test h-independence of condition number by measuring iteration counts"""
191+
"""Test h-dependence of condition number by measuring iteration counts"""
183192
variant = None
184193
bcs = True
185-
meshes = [UnitCubeMesh(nx, nx, nx) for nx in (3, 6)]
186-
its = [solve_riesz_map(rg, m, family, degree, variant, bcs) for m in meshes]
187-
assert (np.diff(its) <= 2).all()
194+
base = UnitCubeMesh(2, 2, 2)
195+
meshes = MeshHierarchy(base, 2)
196+
sqrt_kappa = [solve_riesz_map(rg, m, family, degree, variant, bcs) for m in meshes]
197+
assert (np.diff(sqrt_kappa) <= 0.5).all(), str(sqrt_kappa)

0 commit comments

Comments
 (0)