Skip to content

Commit 55755b4

Browse files
committed
Momentum balance fixes
* No need to pass velocity to variational form of momentum balance * Add variational form of ice shelf momentum balance
1 parent 661f5a8 commit 55755b4

File tree

2 files changed

+52
-36
lines changed

2 files changed

+52
-36
lines changed

src/icepack2/model/variational.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,28 @@ def calving_terminus(**kwargs):
5959

6060
def momentum_balance(**kwargs):
6161
field_names = (
62-
"velocity",
6362
"membrane_stress",
6463
"basal_stress",
6564
"thickness",
6665
"surface",
6766
"test_function",
6867
)
69-
u, M, τ, h, s, v = map(kwargs.get, field_names)
68+
M, τ, h, s, v = map(kwargs.get, field_names)
7069

7170
ε = sym(grad(v))
7271
cell_balance = (-h * inner(M, ε) + inner(τ - ρ_I * g * h * grad(s), v)) * dx
7372

74-
mesh = ufl.domain.extract_unique_domain(u)
73+
mesh = ufl.domain.extract_unique_domain(v)
7574
ν = FacetNormal(mesh)
7675
facet_balance = ρ_I * g * avg(h) * inner(jump(s, ν), avg(v)) * dS
7776

7877
return cell_balance + facet_balance
7978

8079

80+
def ice_shelf_momentum_balance(**kwargs):
81+
field_names = ("membrane_stress", "thickness", "test_function")
82+
M, h, v = map(kwargs.get, field_names)
83+
ε = sym(grad(v))
84+
85+
ρ = ρ_I * (1 - ρ_I / ρ_W)
86+
return (-h * inner(M, ε) + 0.5 * ρ * g * h**2 * div(v)) * dx

test/momentum_balance_test.py

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import firedrake
44
from firedrake import (
55
as_vector,
6-
max_value,
76
Constant,
87
Function,
98
derivative,
9+
DirichletBC,
1010
NonlinearVariationalProblem,
1111
NonlinearVariationalSolver,
1212
)
@@ -40,8 +40,8 @@ def test_convergence_rate_grounded(degree, form):
4040
s0, ds = Constant(150.0), Constant(90.0)
4141
u_inflow = Constant(100.0)
4242

43-
n = firedrake.Constant(glen_flow_law)
44-
m = firedrake.Constant(glen_flow_law)
43+
n = Constant(glen_flow_law)
44+
m = Constant(glen_flow_law)
4545

4646
τ_c = Constant(0.1)
4747
ε_c = Constant(0.01)
@@ -99,12 +99,12 @@ def friction(x):
9999
outflow_ids = (2,)
100100
side_wall_ids = (3, 4)
101101

102-
inflow_bc = firedrake.DirichletBC(Z.sub(0), Constant((u_inflow, 0)), inflow_ids)
103-
side_wall_bc = firedrake.DirichletBC(Z.sub(0).sub(1), 0, side_wall_ids)
102+
inflow_bc = DirichletBC(Z.sub(0), Constant((u_inflow, 0)), inflow_ids)
103+
side_wall_bc = DirichletBC(Z.sub(0).sub(1), 0, side_wall_ids)
104104
bcs = [inflow_bc, side_wall_bc]
105105

106-
n = firedrake.Constant(1.0)
107-
m = firedrake.Constant(1.0)
106+
n = Constant(1.0)
107+
m = Constant(1.0)
108108

109109
# Make the material parameters and input fields
110110
rheology = {
@@ -127,6 +127,7 @@ def friction(x):
127127

128128
qdegree = max(8, degree ** glen_flow_law)
129129
pparams = {"form_compiler_parameters": {"quadrature_degree": qdegree}}
130+
130131
if form == "minimization":
131132
fns = [
132133
model.minimization.viscous_power,
@@ -138,9 +139,7 @@ def friction(x):
138139
def form_problem(rheology):
139140
L = sum(fn(**fields, **rheology, **boundary_ids) for fn in fns)
140141
F = derivative(L, z)
141-
J = derivative(F, z)
142-
problem = NonlinearVariationalProblem(F, z, bcs, J=J, **pparams)
143-
return problem
142+
return NonlinearVariationalProblem(F, z, bcs, **pparams)
144143
elif form == "variational":
145144
v, N, σ = firedrake.TestFunctions(Z)
146145
fns = [
@@ -155,17 +154,15 @@ def form_problem(rheology):
155154
fn(**fields, **rheology, **boundary_ids, test_function=φ)
156155
for fn, φ in fns
157156
)
158-
J = derivative(F, z)
159-
problem = NonlinearVariationalProblem(F, z, bcs, J=J, **pparams)
160-
return problem
157+
return NonlinearVariationalProblem(F, z, bcs, **pparams)
161158

159+
problem = form_problem(rheology)
160+
solver = NonlinearVariationalSolver(problem, **sparams)
162161
num_continuation_steps = 5
163162
λs = np.linspace(0.0, 1.0, num_continuation_steps)
164163
for λ in λs:
165164
n.assign((1 - λ) + λ * glen_flow_law)
166165
m.assign((1 - λ) + λ * weertman_sliding_law)
167-
problem = form_problem(rheology)
168-
solver = NonlinearVariationalSolver(problem, **sparams)
169166
solver.solve()
170167

171168
u, M, τ = z.subfunctions
@@ -183,12 +180,13 @@ def form_problem(rheology):
183180

184181

185182
@pytest.mark.parametrize("degree", [1, 2])
186-
def test_convergence_rate_floating(degree):
183+
@pytest.mark.parametrize("form", ("minimization", "variational"))
184+
def test_convergence_rate_floating(degree, form):
187185
Lx, Ly = Constant(20e3), Constant(20e3)
188186
h0, dh = Constant(500.0), Constant(100.0)
189187
u_inflow = Constant(100.0)
190188

191-
n = firedrake.Constant(glen_flow_law)
189+
n = Constant(glen_flow_law)
192190

193191
τ_c = Constant(0.1)
194192
ε_c = Constant(0.01)
@@ -230,18 +228,37 @@ def perturb_u(x, y):
230228

231229
h = Function(Q).interpolate(h0 - dh * x / Lx)
232230
inflow_ids = (1,)
233-
outflow_ids = (2,)
234231
side_wall_ids = (3, 4)
235232

236-
inflow_bc = firedrake.DirichletBC(Z.sub(0), Constant((u_inflow, 0)), inflow_ids)
237-
side_wall_bc = firedrake.DirichletBC(Z.sub(0).sub(1), 0, side_wall_ids)
233+
inflow_bc = DirichletBC(Z.sub(0), Constant((u_inflow, 0)), inflow_ids)
234+
side_wall_bc = DirichletBC(Z.sub(0).sub(1), 0, side_wall_ids)
238235
bcs = [inflow_bc, side_wall_bc]
239236

240-
fns = [
241-
model.minimization.viscous_power,
242-
#model.minimization.calving_terminus,
243-
model.minimization.ice_shelf_momentum_balance,
244-
]
237+
qdegree = max(8, degree ** glen_flow_law)
238+
pparams = {"form_compiler_parameters": {"quadrature_degree": qdegree}}
239+
240+
if form == "minimization":
241+
fns = [
242+
model.minimization.viscous_power,
243+
model.minimization.ice_shelf_momentum_balance,
244+
]
245+
246+
def form_problem(rheology):
247+
L = sum(fn(**fields, **rheology) for fn in fns)
248+
F = derivative(L, z)
249+
return NonlinearVariationalProblem(F, z, bcs, **pparams)
250+
else:
251+
v, N = firedrake.TestFunctions(Z)
252+
fns = [
253+
(model.variational.flow_law, N),
254+
(model.variational.ice_shelf_momentum_balance, v),
255+
]
256+
257+
def form_problem(rheology):
258+
F = sum(
259+
fn(**fields, **rheology, test_function=φ) for fn, φ in fns
260+
)
261+
return NonlinearVariationalProblem(F, z, bcs, **pparams)
245262

246263
rheology = {
247264
"flow_law_exponent": n,
@@ -250,14 +267,7 @@ def perturb_u(x, y):
250267

251268
u, M = firedrake.split(z)
252269
fields = {"velocity": u, "membrane_stress": M, "thickness": h}
253-
254-
boundary_ids = {"outflow_ids": outflow_ids}
255-
L = sum(fn(**fields, **rheology, **boundary_ids) for fn in fns)
256-
F = derivative(L, z)
257-
258-
qdegree = max(8, degree ** glen_flow_law)
259-
pparams = {"form_compiler_parameters": {"quadrature_degree": qdegree}}
260-
problem = NonlinearVariationalProblem(F, z, bcs, **pparams)
270+
problem = form_problem(rheology)
261271
solver = NonlinearVariationalSolver(problem, **sparams)
262272

263273
num_continuation_steps = 5

0 commit comments

Comments
 (0)