Taking Derivatives

In FEniCS there is a concept of scalar, vector and tensors (of order 2).
i.e.
Consider a functional, \int_\Omega c u^2 \mathrm{d}x where u and c is a function.
If we want to compute the derivative (Gateaux derivative, Integrating a functional, followed by differentiation - #2 by kamensky)
we call

from dolfin import *
mesh = UnitSquareMesh(10, 10)
V = FunctionSpace(mesh, "CG", 1)
u = Function(V)
J = c * inner(u, u) * dx
dJdu = derivative(J, u)
v = TestFunction(V)
dJdu_v = derivative(J, u, v)
assert(dJdu == dJdu_v)

assembling dJdu will assemble into a vector:

print(type(assemble(dJdu)))
<class 'dolfin.cpp.la.Vector'>

If you again differentiate dJdu, which is equal to \int_\Omega2 c u\cdot v ~\mathrm{d} x you obtain \int_\Omega 2c \cdot du \cdot v ~\mathrm{d} x which assembles into a matrix:


dJdudv = derivative(dJdu, u)
du = TrialFunction(V)
dJdu_vdu = derivative(dJdu_v, u, du)
assert(dJdudv == dJdu_vdu)
print(type(assemble(dJdudv)))
<class 'dolfin.cpp.la.Matrix'>

In dolfin, we do not have a concept of tensors with higher order than two, and thus you cannot differentiate this form with respect to a TrialFunction or TestFunction, as it would increase the dimensionality of the object.

However, you can differentiate it with respect to a Function, i.e derivative(dJdudv, c, Function(V)) will give you a resulting matrix, and you can create the tensor by looping over all dofs, inserting a one for each dof and zero for all the others if you want to emulate differentiating with respect to a trial or test function.

2 Likes