From e664dcb537761710dfdec50ee129680faf0717ee Mon Sep 17 00:00:00 2001 From: Iglesia Dolci Date: Thu, 26 Jun 2025 14:55:47 +0100 Subject: [PATCH 1/4] Update bcs with checkpoints for adjs --- firedrake/bcs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firedrake/bcs.py b/firedrake/bcs.py index 6cd6f3d5d7..58d95d581a 100644 --- a/firedrake/bcs.py +++ b/firedrake/bcs.py @@ -452,6 +452,8 @@ def apply(self, r, u=None): u = u.sub(idx) if u: r.assign(u - self.function_arg, subset=self.node_set) + elif self.block_variable.checkpoint is not None: + r.assign(self.block_variable.checkpoint.checkpoint, subset=self.node_set) else: r.assign(self.function_arg, subset=self.node_set) From bbec24bc6aae39ee58d4cc87abd0c6777d913f7b Mon Sep 17 00:00:00 2001 From: Iglesia Dolci Date: Thu, 26 Jun 2025 15:16:02 +0100 Subject: [PATCH 2/4] testing --- tests/firedrake/regression/test_adjoint_operators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/firedrake/regression/test_adjoint_operators.py b/tests/firedrake/regression/test_adjoint_operators.py index b7ecdd6ed0..96fadd9eb0 100644 --- a/tests/firedrake/regression/test_adjoint_operators.py +++ b/tests/firedrake/regression/test_adjoint_operators.py @@ -1050,3 +1050,5 @@ def u_analytical(x, a, b): # tape._blocks[1] is the DirichletBC block for the right boundary assert isinstance(tape._blocks[1], DirichletBCBlock) and \ tape._blocks[1]._outputs[0].checkpoint.checkpoint is not bc_right._original_arg + # taylor test + taylor_test(J_hat, [a, b], [Function(R, val=0.1), Function(R, val=0.2)]) From 2db7c9799dbe71c3a36ecea0fba37aac38b171bb Mon Sep 17 00:00:00 2001 From: Iglesia Dolci Date: Thu, 26 Jun 2025 15:43:56 +0100 Subject: [PATCH 3/4] Right test / cleaner code --- firedrake/bcs.py | 11 ++++++---- .../regression/test_adjoint_operators.py | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/firedrake/bcs.py b/firedrake/bcs.py index 58d95d581a..6ec838a425 100644 --- a/firedrake/bcs.py +++ b/firedrake/bcs.py @@ -450,12 +450,15 @@ def apply(self, r, u=None): r = r.sub(idx) if u: u = u.sub(idx) + + bc_checkpointed = self.block_variable.checkpoint + bc = bc_checkpointed.checkpoint \ + if bc_checkpointed is not None else self.function_arg + if u: - r.assign(u - self.function_arg, subset=self.node_set) - elif self.block_variable.checkpoint is not None: - r.assign(self.block_variable.checkpoint.checkpoint, subset=self.node_set) + r.assign(u - bc, subset=self.node_set) else: - r.assign(self.function_arg, subset=self.node_set) + r.assign(bc, subset=self.node_set) def integrals(self): return [] diff --git a/tests/firedrake/regression/test_adjoint_operators.py b/tests/firedrake/regression/test_adjoint_operators.py index 96fadd9eb0..f9ea9d3d74 100644 --- a/tests/firedrake/regression/test_adjoint_operators.py +++ b/tests/firedrake/regression/test_adjoint_operators.py @@ -1052,3 +1052,24 @@ def u_analytical(x, a, b): tape._blocks[1]._outputs[0].checkpoint.checkpoint is not bc_right._original_arg # taylor test taylor_test(J_hat, [a, b], [Function(R, val=0.1), Function(R, val=0.2)]) + +@pytest.mark.skipcomplex # Taping for complex-valued 0-forms not yet done +def test_bdy_update(): + # Fix the issue https://github.com/firedrakeproject/firedrake/issues/4387 + mesh = UnitSquareMesh(5, 5) + V = FunctionSpace(mesh, "CG", 1) + R = FunctionSpace(mesh, "R", 0) + + bc_func = Function(R, val=2.0) + bc = DirichletBC(V, bc_func, 1) + u_ = Function(V) + + v = TestFunction(V) + problem = NonlinearVariationalProblem( + inner(grad(u_), grad(v)) * dx - v * dx, u_, bcs=bc) + solver = NonlinearVariationalSolver(problem) + solver.solve() + J = assemble(u_**2 * dx) + c = Control(bc_func) + Jhat = ReducedFunctional(J, c) + assert taylor_test(Jhat, bc_func, Function(R, val=0.1)) > 1.9 From 5ead7173eb77db036698a1cb48250b13dad54311 Mon Sep 17 00:00:00 2001 From: Iglesia Dolci Date: Thu, 26 Jun 2025 15:47:13 +0100 Subject: [PATCH 4/4] Remove unecessary test --- tests/firedrake/regression/test_adjoint_operators.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/firedrake/regression/test_adjoint_operators.py b/tests/firedrake/regression/test_adjoint_operators.py index f9ea9d3d74..5b4ccd6933 100644 --- a/tests/firedrake/regression/test_adjoint_operators.py +++ b/tests/firedrake/regression/test_adjoint_operators.py @@ -1050,8 +1050,7 @@ def u_analytical(x, a, b): # tape._blocks[1] is the DirichletBC block for the right boundary assert isinstance(tape._blocks[1], DirichletBCBlock) and \ tape._blocks[1]._outputs[0].checkpoint.checkpoint is not bc_right._original_arg - # taylor test - taylor_test(J_hat, [a, b], [Function(R, val=0.1), Function(R, val=0.2)]) + @pytest.mark.skipcomplex # Taping for complex-valued 0-forms not yet done def test_bdy_update():