33from firedrake .petsc import DEFAULT_DIRECT_SOLVER
44
55
6- def bddc_params (static_condensation ):
6+ def bddc_params ():
77 chol = {
88 "pc_type" : "cholesky" ,
99 "pc_factor_mat_solver_type" : "petsc" ,
1010 "pc_factor_mat_ordering_type" : "natural" ,
1111 }
1212 sp = {
13+ "mat_type" : "is" ,
1314 "pc_type" : "python" ,
1415 "pc_python_type" : "firedrake.BDDCPC" ,
1516 "bddc_pc_bddc_neumann" : chol ,
@@ -19,12 +20,14 @@ def bddc_params(static_condensation):
1920 return sp
2021
2122
22- def solver_parameters (static_condensation = True ):
23+ def solver_parameters (static_condensation = False , variant = None ):
2324 rtol = 1E-8
2425 atol = 1E-12
25- sp_bddc = bddc_params (static_condensation )
26- repeated = True
27- if static_condensation :
26+ sp_bddc = bddc_params ()
27+ if variant != "fdm" :
28+ sp = sp_bddc
29+
30+ elif static_condensation :
2831 sp = {
2932 "pc_type" : "python" ,
3033 "pc_python_type" : "firedrake.FacetSplitPC" ,
@@ -33,7 +36,7 @@ def solver_parameters(static_condensation=True):
3336 "facet_fdm_static_condensation" : True ,
3437 "facet_fdm_pc_use_amat" : False ,
3538 "facet_fdm_mat_type" : "is" ,
36- "facet_fdm_mat_is_allow_repeated" : repeated ,
39+ "facet_fdm_mat_is_allow_repeated" : True ,
3740 "facet_fdm_pc_type" : "fieldsplit" ,
3841 "facet_fdm_pc_fieldsplit_type" : "symmetric_multiplicative" ,
3942 "facet_fdm_pc_fieldsplit_diag_use_amat" : False ,
@@ -47,22 +50,23 @@ def solver_parameters(static_condensation=True):
4750 "pc_type" : "python" ,
4851 "pc_python_type" : "firedrake.FDMPC" ,
4952 "fdm_pc_use_amat" : False ,
50- "fdm_mat_type" : "is" ,
51- "fdm_mat_is_allow_repeated" : repeated ,
53+ "fdm_mat_is_allow_repeated" : True ,
5254 "fdm" : sp_bddc ,
5355 }
56+
5457 sp .update ({
55- "mat_type" : "matfree" ,
5658 "ksp_type" : "cg" ,
5759 "ksp_norm_type" : "natural" ,
5860 "ksp_monitor" : None ,
5961 "ksp_rtol" : rtol ,
6062 "ksp_atol" : atol ,
6163 })
64+ if variant == "fdm" :
65+ sp ["mat_type" ] = "matfree"
6266 return sp
6367
6468
65- def solve_riesz_map (mesh , family , degree , bcs , condense ):
69+ def solve_riesz_map (mesh , family , degree , variant , bcs , condense = False , vector = False ):
6670 dirichlet_ids = []
6771 if bcs :
6872 dirichlet_ids = ["on_boundary" ]
@@ -74,7 +78,10 @@ def solve_riesz_map(mesh, family, degree, bcs, condense):
7478 family = "RTCE" if tdim == 2 else "NCE"
7579 if family .endswith ("F" ):
7680 family = "RTCF" if tdim == 2 else "NCF"
77- V = FunctionSpace (mesh , family , degree , variant = "fdm" )
81+
82+ fs = VectorFunctionSpace if vector else FunctionSpace
83+
84+ V = fs (mesh , family , degree , variant = variant )
7885 v = TestFunction (V )
7986 u = TrialFunction (V )
8087 d = {
@@ -95,13 +102,21 @@ def solve_riesz_map(mesh, family, degree, bcs, condense):
95102 bcs = [DirichletBC (V , u_exact , sub ) for sub in dirichlet_ids ]
96103 nsp = None
97104 if formdegree == 0 :
98- nsp = VectorSpaceBasis ([Function (V ).interpolate (Constant (1 ))])
105+ b = np .zeros (V .value_shape )
106+ expr = Constant (b )
107+ basis = []
108+ for i in np .ndindex (V .value_shape ):
109+ b [...] = 0
110+ b [i ] = 1
111+ expr .assign (b )
112+ basis .append (Function (V ).interpolate (expr ))
113+ nsp = VectorSpaceBasis (basis )
99114 nsp .orthonormalize ()
100115
101116 uh = Function (V , name = "solution" )
102117 problem = LinearVariationalProblem (a , L , uh , bcs = bcs )
103118
104- sp = solver_parameters (condense )
119+ sp = solver_parameters (condense , variant = variant )
105120 solver = LinearVariationalSolver (problem , near_nullspace = nsp ,
106121 solver_parameters = sp ,
107122 options_prefix = "" )
@@ -120,11 +135,24 @@ def mesh(request):
120135
121136
122137@pytest .mark .parallel
123- @pytest .mark .parametrize ("family" , "Q" )
124138@pytest .mark .parametrize ("degree" , (4 ,))
125- @pytest .mark .parametrize ("condense" , (False , True ))
139+ @pytest .mark .parametrize ("family" , "Q" )
140+ @pytest .mark .parametrize ("condense" , (False , True ), ids = ("full" , "condense" ))
126141def test_bddc_fdm (mesh , family , degree , condense ):
142+ variant = "fdm"
127143 bcs = True
128144 tdim = mesh .topological_dimension ()
129145 expected = 6 if tdim == 2 else 11
130- assert solve_riesz_map (mesh , family , degree , bcs , condense ) <= expected
146+ assert solve_riesz_map (mesh , family , degree , variant , bcs , condense = condense ) <= expected
147+
148+
149+ @pytest .mark .parallel
150+ @pytest .mark .parametrize ("degree" , (4 ,))
151+ @pytest .mark .parametrize ("family" , "Q" )
152+ @pytest .mark .parametrize ("vector" , (False , True ), ids = ("scalar" , "vector" ))
153+ def test_bddc_aij (mesh , family , degree , vector ):
154+ variant = None
155+ bcs = True
156+ tdim = mesh .topological_dimension ()
157+ expected = 7 if tdim == 2 else 11
158+ assert solve_riesz_map (mesh , family , degree , variant , bcs , vector = vector ) <= expected
0 commit comments