11from firedrake import *
2+ import pytest
23import 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
72106def 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