Skip to content

Commit 3fd6452

Browse files
committed
coarsen EquationBC for LVP
1 parent c242479 commit 3fd6452

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

firedrake/bcs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ def __init__(self, *args, bcs=None, J=None, Jp=None, V=None, is_linear=False, Jp
512512
raise ValueError("Provided BC RHS is not a linear form")
513513
F = ufl_expr.action(J, u) - L
514514
self.is_linear = True
515+
self.lhs = J
516+
self.rhs = L
515517
# nonlinear
516518
else:
517519
if eq.rhs != 0:

firedrake/mg/ufl_utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,20 @@ def coarsen_bc(bc, self, coefficient_mapping=None):
129129

130130
@coarsen.register(firedrake.EquationBC)
131131
def coarsen_equation_bc(ebc, self, coefficient_mapping=None):
132-
F = self(ebc._F.f, self, coefficient_mapping=coefficient_mapping)
133132
J = self(ebc._J.f, self, coefficient_mapping=coefficient_mapping)
134133
Jp = self(ebc._Jp.f, self, coefficient_mapping=coefficient_mapping)
135134
u = self(ebc._F.u, self, coefficient_mapping=coefficient_mapping)
136135
sub_domain = ebc._F.sub_domain
137136
bcs = [self(bc, self, coefficient_mapping=coefficient_mapping) for bc in ebc.bcs]
138137
V = self(ebc._F.function_space(), self, coefficient_mapping=coefficient_mapping)
139138

140-
return type(ebc)(F == 0, u, sub_domain, V=V, bcs=bcs, J=J, Jp=Jp)
139+
if ebc.is_linear:
140+
lhs = self(ebc.lhs, self, coefficient_mapping=coefficient_mapping)
141+
rhs = self(ebc.rhs, self, coefficient_mapping=coefficient_mapping)
142+
return type(ebc)(lhs == rhs, u, sub_domain, V=V, bcs=bcs, J=J, Jp=Jp)
143+
else:
144+
F = self(ebc._F.f, self, coefficient_mapping=coefficient_mapping)
145+
return type(ebc)(F == 0, u, sub_domain, V=V, bcs=bcs, J=J, Jp=Jp)
141146

142147

143148
@coarsen.register(firedrake.functionspaceimpl.WithGeometryBase)

tests/firedrake/multigrid/test_equation_bc.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
from firedrake import *
22

33

4-
def test_poisson():
4+
def test_poisson_NLVP():
55
mesh = UnitIntervalMesh(10)
66
mesh_hierarchy = MeshHierarchy(mesh, 1)
77
mesh = mesh_hierarchy[-1]
88

99
x = SpatialCoordinate(mesh)
10-
u_exact = x[0]*(x[0]-1)
10+
u_exact = x[0]**2
1111
f = -div(grad(u_exact))
1212

1313
V = FunctionSpace(mesh, "CG", 1)
1414
u = Function(V)
1515
v = TestFunction(V)
1616

1717
F = inner(grad(u), grad(v))*dx(degree=0) - inner(f, v)*dx
18-
bcs = [EquationBC(inner(u, v) * ds == 0, u, "on_boundary", V=V)]
18+
bcs = [EquationBC(inner(u - u_exact, v) * ds == 0, u, "on_boundary", V=V)]
1919
NLVP = NonlinearVariationalProblem(F, u, bcs=bcs)
2020

2121
sp = {"pc_type": "mg"}
@@ -26,6 +26,32 @@ def test_poisson():
2626
assert errornorm(u_exact, u) < 5e-4
2727

2828

29+
def test_poisson_LVP():
30+
mesh = UnitIntervalMesh(10)
31+
mesh_hierarchy = MeshHierarchy(mesh, 1)
32+
mesh = mesh_hierarchy[-1]
33+
34+
x = SpatialCoordinate(mesh)
35+
u_exact = x[0]**2
36+
f = -div(grad(u_exact))
37+
38+
V = FunctionSpace(mesh, "CG", 1)
39+
u = TrialFunction(V)
40+
u_ = Function(V)
41+
v = TestFunction(V)
42+
43+
a = inner(grad(u), grad(v))*dx(degree=0)
44+
L = inner(f, v)*dx
45+
bcs = [EquationBC(inner(u, v) * ds == inner(u_exact, v) * ds, u_, "on_boundary", V=V)]
46+
LVP = LinearVariationalProblem(a, L, u_, bcs=bcs)
47+
48+
sp = {"pc_type": "mg"}
49+
LVS = LinearVariationalSolver(LVP, solver_parameters=sp)
50+
LVS.solve()
51+
52+
assert errornorm(u_exact, u_) < 5e-4
53+
54+
2955
def test_nested_equation_bc():
3056
mesh = UnitCubeMesh(2, 2, 2)
3157
mesh_hierarchy = MeshHierarchy(mesh, 2)

0 commit comments

Comments
 (0)