I'm computing the Jacobian of a form using derivative()
and I'd like to double-check the result using simple finite differences. Here's my setup:
mesh = UnitSquareMesh(2, 2)
U = FunctionSpace(mesh, "Lagrange", degree=1)
V = U * U
uf = Function(V)
u, f = split(uf)
v, w = split(TestFunction(V))
a = dot(grad(v), grad(u)) * dx - v * f * dx
da = derivative(a, uf)
The values obtained by assembling da
are consistent in the sense that they're close to values obtained by applying simple finite differences to a
.
Now if I introduce boundary conditions
u0 = interpolate(Constant(0), U)
bc = DirichletBC(U, u0, lambda x, on_boundary: on_boundary)
and check da
at a point where I apply the boundary conditions, the values aren't consistent any more. For example:
import numpy as np
x = np.ones_like(uf.vector().array())
uf.vector()[:] = x
bc.apply(uf.vector()) # Apply bc to uf
cx = assemble(a).array()
Jx = assemble(da).array()
e = np.zeros_like(x); e[0] = 1
h = 1.0e-6
uf.vector()[:] = x + h * e
bc.apply(uf.vector())
cxph = assemble(a).array()
uf.vector()[:] = x - h * e
bc.apply(uf.vector())
cxmh = assemble(a).array()
diff = (cxph - cxmh) / (2 * h)
print diff[0]
print Jx[0, 0]
This code outputs:
0.0
1.0
How can I ensure that I only evaluate a
and da
at values satisfying the boundary conditions and have consistent derivatives?
Thanks!