Expressing functionals

In the example presented in the tutorial, the quantity of interest was evaluated at the end of the simulation. However, it is very common to want to compute integrals over time, or evaluated at certain points in time that are not the end. The syntax of the Functional class is intended to be very general, and to express all of these needs naturally.

The core abstraction for functionals in dolfin-adjoint is that a functional is either

  1. an integral of a form over a certain time window, or
  2. a pointwise evaluation in time of a certain form, or
  3. a sum of terms like (a) and (b).

Examples

To see how it works, consider some examples:

  • Integration over all time:
J = Functional(inner(u, u)*dx*dt)
  • Integration over a certain time window:
J = Functional(inner(u, u)*dx*dt[0:1])
  • Integration from a certain point until the end:
J = Functional(inner(u, u)*dx*dt[0.5:])
  • Pointwise evaluation in time (does not need to line up with timesteps):
J = Functional(inner(u, u)*dx*dt[0.5])
  • Pointwise evaluation at the start (e.g. for regularisation terms):
J = Functional(inner(u, u)*dx*dt[START_TIME])
  • Pointwise evaluation at the end:
J = Functional(inner(u, u)*dx*dt[FINISH_TIME])
  • And sums of these work too:
J = Functional(inner(u, u)*dx*dt + inner(u, u)*dx*dt[FINISH_TIME])

The object to express these evaluations in time is the TimeMeasure object. By default, dolfin-adjoint creates a TimeMeasure called dt. If your code redefines dt, you will need to instantiate a new TimeMeasure class under a different name:

# Can't use dt, because it's been set to be the timestep
dtm = TimeMeasure()
J = Functional(inner(u, u)*dx*dtm + inner(u, u)*dx*dtm[FINISH_TIME])

Limitations

If you use a complicated functional, you should be aware of some points.

  1. In order for anything other than evaluation at the end of time to work, you need to call adj_start_timestep before your time loop, and adj_inc_timestep function as the last instruction in your time loop. This is to make dolfin-adjoint aware that a timestep has ended, and the start and end times of that timestep.
  2. Evaluation of expressions at times other than timesteps is currently performed using linear interpolation, which may not be the correct thing to do if you are using a higher-order scheme in time.