BUG: Adjoint inconsistency with self-assignment via projection
Closed this issue · 1 comments
jrmaddison commented
Describe the bug
An adjoint inconsistency when adding an extra calculation which should not change the derivative.
Steps to Reproduce
from firedrake import *
from firedrake.adjoint import *
import numpy as np
mesh = UnitIntervalMesh(10)
X = SpatialCoordinate(mesh)
space = FunctionSpace(mesh, "Lagrange", 1)
test = TestFunction(space)
continue_annotation()
u = Function(space, name="u").interpolate(X[0] - 0.5)
u_ref = u.copy(deepcopy=True)
v = Function(space).assign(u)
u.project(u)
J = assemble(v * v * dx)
pause_annotation()
_ = compute_gradient(J, Control(u))
adj_value = u.block_variable.adj_value
assert np.allclose(adj_value.dat.data_ro,
assemble(2 * inner(u_ref, test) * dx).dat.data_ro)
leads to
WARNING:root:Adjoint value is None, is the functional independent of the control variable?
Traceback (most recent call last):
File "/home/maddison/build/tlm_adjoint/firedrake_bugs/adjoint_self_assignment.py", line 22, in <module>
assert np.allclose(adj_value.dat.data_ro,
AttributeError: 'NoneType' object has no attribute 'dat'
Commenting out the u.project(u)
line leads to a correct derivative.
Expected behavior
The derivative should be unaffected.
Environment:
Ubuntu 22.04, recent Firedrake build.
Additional Info
Changing to an Expr
, u.project(2 * u)
, leads to the same error.
jrmaddison commented
This looks I've misunderstood the behaviour. Here Control(u)
refers to the last version, which is the result of the project
, and not the first version, which is the input to project. The derivative with respect to the last version is, correctly, zero.