1616 glen_flow_law ,
1717 weertman_sliding_law ,
1818)
19- from icepack2 import model
19+ from icepack2 .model .minimization import viscous_power , ice_shelf_momentum_balance
20+
21+
22+ sparams = {
23+ "solver_parameters" : {
24+ "snes_type" : "newtonls" ,
25+ "snes_max_it" : 200 ,
26+ "snes_linesearch_type" : "nleqerr" ,
27+ "ksp_type" : "gmres" ,
28+ "pc_type" : "lu" ,
29+ "pc_factor_mat_solver_type" : "mumps" ,
30+ },
31+ }
2032
2133
2234def test_composite_rheology_floating ():
@@ -29,13 +41,13 @@ def test_composite_rheology_floating():
2941
3042 τ_c = Constant (0.1 )
3143 ε_c = Constant (0.01 )
32- A1 = ε_c / τ_c
33- A3 = ε_c / τ_c ** n
44+ A1 = ε_c / τ_c ** n1
45+ A3 = ε_c / τ_c ** n3
3446
3547 # This is an exact solution for the velocity of a floating ice shelf with
3648 # constant temperature and linearly decreasing thickness. See Greve and
3749 # Blatter for the derivation.
38- def exact_u (x , n , A ):
50+ def exact_δu (x , n , A ):
3951 ρ = ρ_I * (1 - ρ_I / ρ_W )
4052 h = h0 - dh * x / Lx
4153 P = ρ * g * h / 4
@@ -49,6 +61,7 @@ def perturb_u(x, y):
4961 q = 16 * px * (1 - px ) * py * (1 - py )
5062 return 60 * q * (px - 0.5 )
5163
64+ degree = 1
5265 errors , mesh_sizes = [], []
5366 k_min , k_max , num_steps = 5 - degree , 8 - degree , 9
5467 for nx in np .logspace (k_min , k_max , num_steps , base = 2 , dtype = int ):
@@ -65,7 +78,7 @@ def perturb_u(x, y):
6578 z .sub (0 ).assign (Constant (u_inflow , 0 ))
6679
6780 expr = u_inflow + exact_δu (x , n1 , A1 ) + exact_δu (x , n3 , A3 )
68- u_exact = Function (V ).interpolate (as_vector ((exact_u ( x ) , 0 )))
81+ u_exact = Function (V ).interpolate (as_vector ((expr , 0 )))
6982
7083 h = Function (Q ).interpolate (h0 - dh * x / Lx )
7184 inflow_ids = (1 ,)
@@ -76,4 +89,36 @@ def perturb_u(x, y):
7689 side_wall_bc = firedrake .DirichletBC (Z .sub (0 ).sub (1 ), 0 , side_wall_ids )
7790 bcs = [inflow_bc , side_wall_bc ]
7891
79- # Miracle occurs...
92+ u , M = firedrake .split (z )
93+ fields = {"velocity" : u , "membrane_stress" : M , "thickness" : h }
94+ boundary_ids = {"outflow_ids" : outflow_ids }
95+
96+ L = (
97+ viscous_power (** fields , flow_law_exponent = n1 , flow_law_coefficient = A1 ) +
98+ viscous_power (** fields , flow_law_exponent = n3 , flow_law_coefficient = A3 ) +
99+ ice_shelf_momentum_balance (** fields , ** boundary_ids )
100+ )
101+
102+ F = derivative (L , z )
103+ qdegree = max (8 , degree ** glen_flow_law )
104+ pparams = {"form_compiler_parameters" : {"quadrature_degree" : qdegree }}
105+ problem = NonlinearVariationalProblem (F , z , bcs , ** pparams )
106+ solver = NonlinearVariationalSolver (problem , ** sparams )
107+
108+ num_continuation_steps = 5
109+ for exponent in np .linspace (1.0 , glen_flow_law , num_continuation_steps ):
110+ n3 .assign (exponent )
111+ solver .solve ()
112+
113+ u , M = z .subfunctions
114+ error = firedrake .norm (u - u_exact ) / firedrake .norm (u_exact )
115+ δx = mesh .cell_sizes .dat .data_ro .min ()
116+ mesh_sizes .append (δx )
117+ errors .append (error )
118+ print ("." , end = "" , flush = True )
119+
120+ log_mesh_sizes = np .log2 (np .array (mesh_sizes ))
121+ log_errors = np .log2 (np .array (errors ))
122+ slope , intercept = np .polyfit (log_mesh_sizes , log_errors , 1 )
123+ print (f"degree { degree } : log(error) ~= { slope :g} * log(dx) { intercept :+g} " )
124+ assert slope > degree + 0.9
0 commit comments