pyadjoint API reference

See also the dolfin-adjoint API reference.

Core classes

class pyadjoint.Tape(blocks=None, package_data=None)

The tape.

The tape consists of blocks, Block instances. Each block represents one operation in the forward model.

add_block(block)

Adds a block to the tape and returns the index.

visualise(output='log', launch_tensorboard=False, open_in_browser=False)

Makes a visualisation of the tape as a graph using TensorFlow or GraphViz. (Default: Tensorflow). If output endswith .dot or .pdf, Graphviz is used.

Parameters:
  • output (str) – Directory where event files for TensorBoard is stored. Default log.

  • launch_tensorboard (bool) – Launch TensorBoard in the background. Default False.

  • open_in_browser (bool) – Opens http://localhost:6006/ in a web browser. Default False.

property progress_bar

Specify a progress bar class to print during tape evaluation.

Setting this attribute to a subclass of progress.bar.Bar will cause every evaluation of a reduced functional, adjoint, TLM or Hessian to print a progress bar.

For example, the following code:

from progress.bar import FillingSquaresBar
tape = get_working_tape()
tape.progress_bar = FillingSquaresBar

will cause tape evaluations to print progress bars similar to the following:

Evaluating functional ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣ 100%
Evaluating adjoint ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣ 100%

For information on available progress bar styles and their configuration, see the progress package documentation.

end_timestep()

Mark the end of a timestep when taping the forward model.

timestepper(iterable)

Return an iterator that advances the tape timestep.

Note

This method facilitates taping timestepping simulations so that recompute checkpointing can be used on the tape. For example, a simulation with 10 timesteps might use a timestepping loop of this form:

tape = get_working_tape()

for timestep in tape.timestepper(range(10)):
    ...

This has the effect of calling tape.end_timestep() after each iteration.

Parameters:

iterable (iterable) – The iterable definining the sequence of timesteps.

Returns:

An iterator that advances the tape timestep.

Return type:

TapeTimeStepper

class pyadjoint.Block(ad_block_tag=None)

Base class for all Tape Block types.

Each instance of a Block type represents an elementary operation in the forward model.

Abstract methods

evaluate_adj()

classmethod pop_kwargs(kwargs)

Takes in a dictionary of keyword arguments, and pops the ones used by the Block-subclass cls

add_dependency(dep, no_duplicates=False)

Adds object to the block dependencies.

Will also save the output if it has not been saved before. Which should only happen if the BlockVariable was not created by a Block (but by the user).

Parameters:
  • dep (OverloadedType) – The object to be added.

  • no_duplicates (bool, optional) – If True, the dependency is only added if it is not already in the list. Default is False.

add_output(obj)

Adds object to the block output list.

Will also save the output.

Parameters:

obj (BlockVariable) – The object to be added.

evaluate_adj(markings=False)

Computes the adjoint action and stores the result in the adj_value attribute of the dependencies.

This method will by default call the evaluate_adj_component method for each dependency.

Parameters:

markings (bool) – If True, then each block_variable will have set marked_in_path attribute indicating whether their adjoint components are relevant for computing the final target adjoint values. Default is False.

prepare_evaluate_adj(inputs, adj_inputs, relevant_dependencies)

Runs preparations before evalute_adj_component is ran.

The return value is supplied to each of the subsequent evaluate_adj_component calls. This method is intended to be overridden for blocks that require such preparations, by default there is none.

Parameters:
  • inputs – The values of the inputs

  • adj_inputs – The adjoint inputs

  • relevant_dependencies – A list of the relevant block variables for evaluate_adj_component.

Returns:

Anything. The returned value is supplied to evaluate_adj_component

evaluate_adj_component(inputs, adj_inputs, block_variable, idx, prepared=None)

This method should be overridden.

The method should implement a routine for evaluating the adjoint of the block that corresponds to one dependency. If one considers the adjoint action a vector right multiplied with the Jacobian matrix, then this method should return one entry in the resulting product, where the entry returned is decided by the argument idx.

Parameters:
  • inputs (list) – A list of the saved input values, determined by the dependencies list.

  • adj_inputs (list) – A list of the adjoint input values, determined by the outputs list.

  • block_variable (BlockVariable) – The block variable of the dependency corresponding to index idx.

  • idx (int) – The index of the component to compute.

  • prepared (object) – Anything returned by the prepare_evaluate_adj method. Default is None.

Returns:

The resulting product.

Return type:

An object of a type consistent with the adj_value type of block_variable

evaluate_tlm(markings=False)

Computes the tangent linear action and stores the result in the tlm_value attribute of the outputs.

This method will by default call the evaluate_tlm_component method for each output.

Parameters:

markings (bool) – If True, then each block_variable will have set marked_in_path attribute indicating whether their tlm components are relevant for computing the final target tlm values. Default is False.

prepare_evaluate_tlm(inputs, tlm_inputs, relevant_outputs)

Runs preparations before evalute_tlm_component is ran.

The return value is supplied to each of the subsequent evaluate_tlm_component calls. This method is intended to be overridden for blocks that require such preparations, by default there is none.

Parameters:
  • inputs – The values of the inputs

  • tlm_inputs – The tlm inputs

  • relevant_outputs – A list of the relevant block variables for evaluate_tlm_component.

Returns:

Anything. The returned value is supplied to evaluate_tlm_component

evaluate_tlm_component(inputs, tlm_inputs, block_variable, idx, prepared=None)

This method should be overridden.

The method should implement a routine for computing the tangent linear model of the block that corresponds to one output. If one considers the tangent linear action as a Jacobian matrix multiplied with a vector, then this method should return one entry in the resulting product, where the entry returned is decided by the argument idx.

Parameters:
  • inputs (list) – A list of the saved input values, determined by the dependencies list.

  • tlm_inputs (list) – A list of the tlm input values, determined by the dependencies list.

  • block_variable (BlockVariable) – The block variable of the output corresponding to index idx.

  • idx (int) – The index of the component to compute.

  • prepared (object) – Anything returned by the prepare_evaluate_tlm method. Default is None.

Returns:

The resulting product.

Return type:

An object of the same type as block_variable.saved_output

evaluate_hessian(markings=False)
prepare_evaluate_hessian(inputs, hessian_inputs, adj_inputs, relevant_dependencies)

Runs preparations before evalute_hessian_component is ran for each relevant dependency.

The return value is supplied to each of the subsequent evaluate_hessian_component calls. This method is intended to be overridden for blocks that require such preparations, by default there is none.

Parameters:
  • inputs – The values of the inputs

  • hessian_inputs – The hessian inputs

  • adj_inputs – The adjoint inputs

  • relevant_dependencies – A list of the relevant block variables for evaluate_hessian_component.

Returns:

Anything. The returned value is supplied to evaluate_hessian_component

evaluate_hessian_component(inputs, hessian_inputs, adj_inputs, block_variable, idx, relevant_dependencies, prepared=None)

This method must be overridden.

The method should implement a routine for evaluating the hessian of the block. It is preferable that a “Forward-over-Reverse” scheme is used. Thus the hessians are evaluated in reverse (starting with the last block on the tape).

recompute(markings=False)
Recomputes the overloaded function with new inputs

and stores the results in the checkpoint attribute of the outputs.

This method will by default call the recompute_component method for each output.

Parameters:

markings (bool) – If True, then each block_variable will have set marked_in_path attribute indicating whether their checkpoints need to be recomputed for recomputing the final target function value. Default is False.

prepare_recompute_component(inputs, relevant_outputs)

Runs preparations before recompute_component is ran.

The return value is supplied to each of the subsequent recompute_component calls. This method is intended to be overridden for blocks that require such preparations, by default there is none.

Parameters:
  • inputs – The values of the inputs

  • relevant_outputs – A list of the relevant block variables for recompute_component.

Returns:

Anything. The returned value is supplied to recompute_component

recompute_component(inputs, block_variable, idx, prepared)

This method must be overridden.

The method should implement a routine for recomputing one output of the block in the forward computations. The output to recompute is determined by the idx argument, which corresponds to the index of the output in the outputs list. If the block only has a single output, then idx will always be 0.

Parameters:
  • inputs (list) – A list of the saved input values, determined by the dependencies list.

  • block_variable (BlockVariable) – The block variable of the output corresponding to index idx.

  • idx (int) – The index of the output to compute.

  • prepared (object) – Anything returned by the prepare_recompute_component method. Default is None.

Returns:

An object of the same type as block_variable.checkpoint which is determined by OverloadedType._ad_create_checkpoint (often the same as block_variable.saved_output): The new output.

class pyadjoint.block_variable.BlockVariable(output)

References a block output variable.

class pyadjoint.OverloadedType(*args, **kwargs)

Base class for OverloadedType types.

The purpose of each OverloadedType is to extend a type such that it can be referenced by blocks as well as overload basic mathematical operations such as __mul__, __add__, where they are needed.

classmethod _ad_init_object(obj)

This method will often need to be overridden.

The method should implement a way to reconstruct a new overloaded instance from a (possibly) not-overloaded instance.

Parameters:

obj – An instance of the original type

Returns:

An overloaded instance which is considered the same as obj.

Return type:

OverloadedType

_ad_convert_type(value, options={})

This method must be overridden.

Should implement a way to convert the result of an adjoint computation, value, into the same type as self.

Parameters:
  • value (Any) – The value to convert. Should be a result of an adjoint computation.

  • options (dict) – A dictionary with options that may be supplied by the user. If the convert type functionality offers some options on how to convert, this is the dictionary that should be used. For an example see fenics_adjoint.types.Function

Returns:

An instance of the same type as self.

Return type:

OverloadedType

_ad_create_checkpoint()

This method must be overridden.

Should implement a way to create a checkpoint for the overloaded object. The checkpoint should be returned and possible to restore from in the corresponding _ad_restore_at_checkpoint method.

Returns:

A checkpoint. Could be of any type, but must be possible

to restore an object from that point.

Return type:

object

_ad_restore_at_checkpoint(checkpoint)

This method must be overridden.

Should implement a way to restore the object at supplied checkpoint. The checkpoint is created from the _ad_create_checkpoint method.

Returns:

The object with same state as at the supplied checkpoint.

Return type:

OverloadedType

_ad_mul(other)

This method must be overridden.

The method should implement a routine for multiplying the overloaded object with another object, and return an object of the same type as self.

Parameters:

other (object) – The object to be multiplied with this. Should at the very least accept float and integer objects.

Returns:

The product of the two objects represented as

an instance of the same subclass of OverloadedType as the type of self.

Return type:

OverloadedType

_ad_imul(other)

In-place multiplies self with other.

This method should be overridden if the default behaviour is not compatible with this OverloadedType.

Parameters:

other (object) – The object to multiply self with. Should at the very least accept float objects.

Returns:

None

_ad_add(other)

This method must be overridden.

The method should implement a routine for adding the overloaded object with another object, and return an object of the same type as self.

Parameters:

other (object) – The object to be added with this. Should at the very least accept objects of the same type as self.

Returns:

The sum of the two objects represented as

an instance of the same subclass of OverloadedType as the type of self.

Return type:

OverloadedType

_ad_iadd(other)

In-place adds other to self.

This method should be overridden if the default behaviour is not compatible with this OverloadedType.

Parameters:

other (object) – The object to multiply self with. Should at the very least accept objects of the same type as self.

Returns:

None

_ad_dot(other)

This method must be overridden.

The method should implement a routine for computing the dot product of the overloaded object with another object of the same type, and return a float.

Parameters:

other (OverloadedType) – The object to compute the dot product with. Should be of the same type as self.

Returns:

The dot product of the two objects.

Return type:

float

static _ad_assign_numpy(dst, src, offset)

This method must be overridden.

The method should implement a routine for assigning the values from a numpy array src to the checkpoint dst. dst should be an instance of the implementing class.

Parameters:
  • dst (obj) – The object which should be assigned new values. The type will most likely be an OverloadedType or similar.

  • src (numpy.ndarray) – The numpy array to use as a source for the assignment. src should have the same underlying dimensions as dst.

  • offset (int) – Start reading dst from offset.

Returns:

obj: The dst object. If dst is mutable it is preferred to be the same

instance as supplied to the function call. Otherwise a new instance must be initialized and returned with the correct src values.

int: The new offset.

Return type:

tuple

static _ad_to_list(m)

This method must be overridden.

The method should implement a routine for converting m into a list type. m should be an instance of the same type as the class this method is implemented in. Although maybe the backend version of this class, meaning it is not necessarily an OverloadedType.

Parameters:

m (obj) – The object to be converted into a list.

Returns:

A list representation of the data structure of m.

Return type:

list

_ad_copy()

This method must be overridden.

The method should implement a routine for copying itself.

Returns:

A (deep) copy of self.

Return type:

OverloadedType

_ad_dim()

This method must be overridden.

The method should implement a routine for computing the number of components of self.

Returns:

The number of components of self.

Return type:

int

Core utility functions

pyadjoint.get_working_tape()
pyadjoint.set_working_tape(tape=None, **tape_kwargs)

A context manager whithin which a new tape is set as the working tape. This context manager can also be used in an imperative manner.

Example usage:

  1. Set a new tape as the working tape:

    set_working_tape(Tape())
    
  2. Set a local tape within a context manager:

    with set_working_tape() as tape:
        ...
    
pyadjoint.tape.no_annotations(function)

Decorator to turn off annotation for the decorated function.

class pyadjoint.stop_annotating(modifies=None)

A context manager within which annotation is stopped.

Parameters:

modifies (OverloadedType or list[OverloadedType]) – One or more variables which appear in the tape and whose values are to be changed inside the context manager.

The modifies argument is intended to be used by user code which changes the value of inputs to the adjoint calculation such as time varying forcings. Its effect is to create a new block variable for each of the modified variables at the end of the context manager.

pyadjoint.annotate_tape(kwargs=None)

Return True if annotation flag is on, and False if not.

If kwargs is given, the function will try to extract the annotate keyword. If the annotate keyword is not present it defaults to True. If annotation has been paused, then it will always return False.

Parameters:

kwargs (dict) – A dictionary of keyword arguments to extract from. Note that this should be passed as a dictionary and not actual keyword arguments.

Returns: bool

pyadjoint.overloaded_type.create_overloaded_object(obj, suppress_warning=False)

Creates an OverloadedType instance corresponding obj.

If an OverloadedType corresponding to obj has not been registered through register_overloaded_type, a RuntimeWarning will be issued.

Parameters:
  • obj (object) – The object to create an overloaded instance from.

  • suppress_warning (bool, optional) – When set to True, suppresses warning message when a suitable overloaded class is not found. Default False.

Returns:

OverloadedType

pyadjoint.overloaded_type.register_overloaded_type(overloaded_type, classes=None)

Register an overloaded type for use in create_overloaded_object

Overloaded types used with this function should have implemented a classmethod _ad_create_object. For usage as a decorator, OverloadedType should be the first base of overloaded_type, and classes the second base.

Parameters:
  • overloaded_type (type) – The OverloadedType subclass to register.

  • classes (type, tuple, optional) – The original class/classes that this OverloadedType subclass

  • overloads.

Returns:

returns only overloaded_type such that it can be used as a decorator.

Return type:

type

User interface

class pyadjoint.Control(control)

Defines a control variable from an OverloadedType.

The control object references a specific node on the Tape. For mutable OverloadedType instances the Control only represents the value at the time of initialization.

Example

Given a mutable OverloadedType instance u.

>>> u = MutableFloat(1.0)
>>> float(u)
1.0
>>> c1 = Control(u)
>>> u.add_in_place(2.0)
>>> c2 = Control(u)
>>> float(u)
3.0
>>> c1.data()
1.0
>>> c2.data()
3.0

Now c1 represents the node prior to the add_in_place Block, while c2 represents the node after the add_in_place Block. Creating a ReducedFunctional with c2 as Control results in a reduced problem without the add_in_place Block, while a ReducedFunctional with c1 as Control results in a forward model including the add_in_place.

Parameters:

control (OverloadedType) – The OverloadedType instance to define this control from.

pyadjoint.compute_gradient(J, m, options=None, tape=None, adj_value=1.0)

Compute the gradient of J with respect to the initialisation value of m, that is the value of m at its creation.

Parameters:
  • J (AdjFloat) – The objective functional.

  • m (list or instance of Control) – The (list of) controls.

  • options (dict) – A dictionary of options. To find a list of available options have a look at the specific control type.

  • tape – The tape to use. Default is the current tape.

Returns:

The derivative with respect to the control. Should be an instance of the same type as

the control.

Return type:

OverloadedType

pyadjoint.compute_hessian(J, m, m_dot, options=None, tape=None)

Compute the Hessian of J in a direction m_dot at the current value of m

Parameters:
  • J (AdjFloat) – The objective functional.

  • m (list or instance of Control) – The (list of) controls.

  • m_dot (list or instance of the control type) – The direction in which to compute the Hessian.

  • options (dict) – A dictionary of options. To find a list of available options have a look at the specific control type.

  • tape – The tape to use. Default is the current tape.

Returns:

The second derivative with respect to the control in direction m_dot. Should be an instance of

the same type as the control.

Return type:

OverloadedType

class pyadjoint.placeholder.Placeholder(obj)

A class that functions as a placeholder for block variables (for dependencies).

This means that you can replace the dependency of a Block with another block variable on the fly. Do note that Block outputs can not be placeholders.

The placeholders are useful when you require earlier values in the computational graph to be values computed later in the computational graph from the previous recomputation. This can be the case for the initial guess for iterative solvers. If the recomputations are expected to only slightly change the solution, then using the previously found solution as initial guess can significantly speed up the recomputation.

Usage:
>>> u = OverloadedType()
>>> p = Placeholder(u)
>>> v = annotated_operator(u)
>>> p.set_value(v)

Each recomputation will now use the previously computed v as input to annotated_operator.

class pyadjoint.ReducedFunctional(functional, controls, derivative_components=None, scale=1.0, tape=None, eval_cb_pre=<function ReducedFunctional.<lambda>>, eval_cb_post=<function ReducedFunctional.<lambda>>, derivative_cb_pre=<function ReducedFunctional.<lambda>>, derivative_cb_post=<function ReducedFunctional.<lambda>>, hessian_cb_pre=<function ReducedFunctional.<lambda>>, hessian_cb_post=<function ReducedFunctional.<lambda>>)

Class representing the reduced functional.

A reduced functional maps a control value to the provided functional. It may also be used to compute the derivative of the functional with respect to the control.

Parameters:
  • functional (OverloadedType) – An instance of an OverloadedType, usually AdjFloat. This should be the return value of the functional you want to reduce.

  • controls (list[Control]) – A list of Control instances, which you want to map to the functional. It is also possible to supply a single Control instance instead of a list.

  • derivative_components (tuple of int) – The indices of the controls with respect to which to take the derivative. By default, the derivative is taken with respect to all controls. If present, it overwrites derivative_cb_pre and derivative_cb_post.

  • derivative_cb_pre (function) – Callback function before evaluating derivatives. Input is a list of Controls. Should return a list of Controls (usually the same list as the input) to be passed to compute_gradient.

  • derivative_cb_post (function) – Callback function after evaluating derivatives. Inputs are: functional.block_variable.checkpoint, list of functional derivatives, list of functional values. Should return a list of derivatives (usually the same list as the input) to be returned from self.derivative.

__call__(values)

Computes the reduced functional with supplied control value.

Parameters:

values ([OverloadedType]) – If you have multiple controls this should be a list of new values for each control in the order you listed the controls to the constructor. If you have a single control it can either be a list or a single object. Each new value should have the same type as the corresponding control.

Returns:

The computed value. Typically of instance

of AdjFloat.

Return type:

OverloadedType

derivative(adj_input=1.0, options={})

Returns the derivative of the functional w.r.t. the control. Using the adjoint method, the derivative of the functional with respect to the control, around the last supplied value of the control, is computed and returned.

Parameters:

options (dict) – A dictionary of options. To find a list of available options have a look at the specific control type.

Returns:

The derivative with respect to the control.

Should be an instance of the same type as the control.

Return type:

OverloadedType

hessian(m_dot, options={})

Returns the action of the Hessian of the functional w.r.t. the control on a vector m_dot.

Using the second-order adjoint method, the action of the Hessian of the functional with respect to the control, around the last supplied value of the control, is computed and returned.

Parameters:
  • m_dot ([OverloadedType]) – The direction in which to compute the action of the Hessian.

  • options (dict) – A dictionary of options. To find a list of available options have a look at the specific control type.

Returns:

The action of the Hessian in the direction m_dot.

Should be an instance of the same type as the control.

Return type:

OverloadedType

optimize_tape()
class pyadjoint.reduced_functional_numpy.ReducedFunctionalNumPy(functional, controls=None, tape=None)

This class implements the reduced functional for given functional and controls based on numpy data structures.

This “NumPy version” of the pyadjoint.ReducedFunctional is created from an existing ReducedFunctional object: rf_np = ReducedFunctionalNumPy(rf = rf)

pyadjoint.taylor_test(J, m, h, dJdm=None, Hm=0)

Run a taylor test on the functional J around point m in direction h.

Given a functional J, a point in control space m, and a direction in control space h, the function computes the taylor remainders and returns the convergence rate.

Parameters:
Returns:

The smallest computed convergence rate of the tested perturbations.

Return type:

float

Overloaded objects

class pyadjoint.AdjFloat(*args, **kwargs)