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.