@@ -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" ))
134142def 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" ))
171180def 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 )])
181190def 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