11import pytest
22import numpy as np
33import firedrake
4- from firedrake import as_vector , max_value , Constant , Function , derivative
4+ from firedrake import (
5+ as_vector ,
6+ max_value ,
7+ Constant ,
8+ Function ,
9+ derivative ,
10+ NonlinearVariationalProblem ,
11+ NonlinearVariationalSolver ,
12+ )
513from icepack2 .constants import (
614 ice_density as ρ_I ,
715 water_density as ρ_W ,
816 gravity as g ,
9- glen_flow_law as n ,
10- weertman_sliding_law as m ,
17+ glen_flow_law ,
18+ weertman_sliding_law ,
1119)
1220from icepack2 .model import VariationalForm , MinimizationForm
1321
@@ -19,6 +27,9 @@ def test_convergence_rate_grounded(degree, form):
1927 h0 , dh = Constant (500.0 ), Constant (100.0 )
2028 u_inflow = Constant (100.0 )
2129
30+ n = firedrake .Constant (glen_flow_law )
31+ m = firedrake .Constant (glen_flow_law )
32+
2233 τ_c = Constant (0.1 )
2334 ε_c = Constant (0.01 )
2435 A = ε_c / τ_c ** n
@@ -81,6 +92,9 @@ def friction(x):
8192 side_wall_bc = firedrake .DirichletBC (Z .sub (0 ).sub (1 ), 0 , side_wall_ids )
8293 bcs = [inflow_bc , side_wall_bc ]
8394
95+ n = firedrake .Constant (1.0 )
96+ m = firedrake .Constant (1.0 )
97+
8498 # Make the material parameters and input fields
8599 rheology = {
86100 "flow_law_exponent" : n ,
@@ -89,14 +103,6 @@ def friction(x):
89103 "sliding_coefficient" : u_c / τ_c ** m ,
90104 }
91105
92- λ = firedrake .Constant (1e-3 )
93- regularized_rheology = {
94- "flow_law_exponent" : 1 ,
95- "flow_law_coefficient" : λ * ε_c / τ_c ,
96- "sliding_exponent" : 1 ,
97- "sliding_coefficient" : λ * u_c / τ_c ,
98- }
99-
100106 u , M , τ = firedrake .split (z )
101107 fields = {
102108 "velocity" : u ,
@@ -108,6 +114,8 @@ def friction(x):
108114
109115 boundary_ids = {"outflow_ids" : outflow_ids }
110116
117+ qdegree = max (8 , degree ** glen_flow_law )
118+ pparams = {"form_compiler_parameters" : {"quadrature_degree" : qdegree }}
111119 if form == "minimization" :
112120 fns = [
113121 MinimizationForm .viscous_power ,
@@ -116,49 +124,49 @@ def friction(x):
116124 MinimizationForm .momentum_balance ,
117125 ]
118126
119- L = sum (fn (** fields , ** rheology , ** boundary_ids ) for fn in fns )
120- F = derivative (L , z )
121-
122- K = sum (
123- fn (** fields , ** regularized_rheology )
124- for fn in [
125- MinimizationForm .viscous_power , MinimizationForm .friction_power
126- ]
127- )
128- J = derivative (derivative (L + K , z ), z )
127+ def form_problem (rheology ):
128+ L = sum (fn (** fields , ** rheology , ** boundary_ids ) for fn in fns )
129+ F = derivative (L , z )
130+ J = derivative (F , z )
131+ problem = NonlinearVariationalProblem (F , z , bcs , J = J , ** pparams )
132+ return problem
129133 elif form == "variational" :
130134 v , N , σ = firedrake .TestFunctions (Z )
131- kfns = [
135+ fns = [
132136 (VariationalForm .flow_law , N ),
133137 (VariationalForm .friction_law , σ ),
134- ]
135- fns = kfns + [
136138 (VariationalForm .calving_terminus , v ),
137139 (VariationalForm .momentum_balance , v ),
138140 ]
139141
140- F = sum (fn (** fields , ** rheology , ** boundary_ids , test_function = φ ) for fn , φ in fns )
141- G = sum (fn (** fields , ** regularized_rheology , test_function = φ ) for fn , φ in kfns )
142- J = derivative (F + G , z )
142+ def form_problem (rheology ):
143+ F = sum (
144+ fn (** fields , ** rheology , ** boundary_ids , test_function = φ )
145+ for fn , φ in fns
146+ )
147+ J = derivative (F , z )
148+ problem = NonlinearVariationalProblem (F , z , bcs , J = J , ** pparams )
149+ return problem
143150
144- qdegree = max (8 , degree ** n )
145- pparams = {"form_compiler_parameters" : {"quadrature_degree" : qdegree }}
146- problem = firedrake .NonlinearVariationalProblem (F , z , bcs , J = J , ** pparams )
147151 sparams = {
148152 "solver_parameters" : {
149153 "snes_type" : "newtonls" ,
150154 "snes_max_it" : 200 ,
151155 "snes_linesearch_type" : "nleqerr" ,
152156 "ksp_type" : "gmres" ,
153157 "pc_type" : "lu" ,
154- "pc_factor_mat_solver_type" : "umfpack " ,
158+ "pc_factor_mat_solver_type" : "mumps " ,
155159 }
156160 }
157- solver = firedrake .NonlinearVariationalSolver (problem , ** sparams )
158161
159- solver .solve ()
160- λ .assign (0.0 )
161- solver .solve ()
162+ num_continuation_steps = 5
163+ λs = np .linspace (0.0 , 1.0 , num_continuation_steps )
164+ for λ in λs :
165+ n .assign ((1 - λ ) + λ * glen_flow_law )
166+ m .assign ((1 - λ ) + λ * weertman_sliding_law )
167+ problem = form_problem (rheology )
168+ solver = NonlinearVariationalSolver (problem , ** sparams )
169+ solver .solve ()
162170
163171 u , M , τ = z .subfunctions
164172 error = firedrake .norm (u - u_exact ) / firedrake .norm (u_exact )
@@ -180,6 +188,8 @@ def test_convergence_rate_floating(degree):
180188 h0 , dh = Constant (500.0 ), Constant (100.0 )
181189 u_inflow = Constant (100.0 )
182190
191+ n = firedrake .Constant (glen_flow_law )
192+
183193 τ_c = Constant (0.1 )
184194 ε_c = Constant (0.01 )
185195 A = ε_c / τ_c ** n
@@ -255,10 +265,10 @@ def perturb_u(x, y):
255265 K = MinimizationForm .viscous_power (** fields , ** regularized_rheology )
256266 J = derivative (derivative (L + K , z ), z )
257267
258- qdegree = max (8 , degree ** n )
268+ qdegree = max (8 , degree ** glen_flow_law )
259269 pparams = {"form_compiler_parameters" : {"quadrature_degree" : qdegree }}
260- problem = firedrake . NonlinearVariationalProblem (F , z , bcs , J = J , ** pparams )
261- solver = firedrake . NonlinearVariationalSolver (problem )
270+ problem = NonlinearVariationalProblem (F , z , bcs , J = J , ** pparams )
271+ solver = NonlinearVariationalSolver (problem )
262272
263273 solver .solve ()
264274 λ .assign (0.0 )
0 commit comments