tlm_adjoint.interface

This module defines an interface for interaction with backend data types. This is implemented via runtime binding of mixins. The VariableInterface adds methods to ‘variables’ which can be used to interact with backend variables. The SpaceInterface adds methods to ‘spaces’ which define the vector spaces in which those ‘variables’ are defined.

The extra methods are accessed using the callables defined in this module (which also handle some extra details, e.g. related to cache invalidation and space type checking). Typically these are prefixed with space_ for spaces and var_ for variables.

The interface distinguishes between original backend ‘variables’, which both define symbolic variables and store values, and replacement ‘variables’, which define the same variables but which need not store values.

Variables have an associated ‘space type’, which indicates e.g. if the variable is ‘primal’, meaning a member on an originating vector space, or ‘conjugate dual’, meaning a member of the corresponding antidual space of antilinear functionals from the originating vector space. Variables can also be ‘dual’, meaning a member of the dual space of linear functionals, or ‘conjugate’, meaning a member of a space defined by a conjugate operator from the primal space. This conjugate operator is defined by complex conjugation of the vector of degrees of freedom, and could e.g. correspond to complex conjugation of a finite element discretized function.

The space type associated with a variable is defined relative to an originating vector space (e.g. a finite element discrete function space). A ‘relative space type’ is defined relative to one of the ‘primal’, ‘conjugate’, ‘dual’, or ‘conjugate dual’ spaces. For example the primal space associated with the dual space is the dual space, and the dual space associated with the dual space is the primal space.

This module defines a default communicator DEFAULT_COMM.

Module Contents

tlm_adjoint.interface.comm_dup_cached(comm, *, key=None)

Return an internal duplicated communicator with key key.

Parameters:
  • comm – A communicator. Defines the base communicator.

  • key – The key.

Returns:

An internal duplicated communicator. May be comm itself. Freed when the original base communicator is freed.

tlm_adjoint.interface.garbage_cleanup(comm=None)

Call petsc4py.PETSc.garbage_cleanup(comm) for a communicator, and any communicators duplicated from it using comm_dup_cached().

Parameters:

comm – A communicator. Defaults to DEFAULT_COMM.

tlm_adjoint.interface.add_interface(obj, interface_cls, attrs=None)

Attach a mixin interface_cls, defining an interface, to obj.

Parameters:
  • obj – An object to which the mixin should be attached.

  • interface_cls – A subclass of SpaceInterface or VariableInterface defining the interface.

  • attrs – A Mapping defining any attributes. Used to set an attribute _tlm_adjoint__space_interface_attrs (for a SpaceInterface) or _tlm_adjoint__var_interface_attrs (for a VariableInterface).

class tlm_adjoint.interface.SpaceInterface

A mixin defining an interface for spaces. Space types do not inherit from this class – instead an interface is defined by a SpaceInterface subclass, and methods are bound dynamically at runtime using add_interface().

tlm_adjoint.interface.is_space(space)

Return whether space is a space – i.e. has had a SpaceInterface attached.

Parameters:

space – An arbitrary object.

Returns:

True if space is a space, and False otherwise.

tlm_adjoint.interface.space_comm(space)
Parameters:

space – A space.

Returns:

The communicator associated with the space.

tlm_adjoint.interface.space_dtype(space)
Parameters:

space – A space.

Returns:

The data type associated with the space. Typically numpy.double or numpy.cdouble.

tlm_adjoint.interface.space_id(space)

Return a unique int ID associated with a space.

Parameters:

space – The space.

Returns:

The unique int ID.

tlm_adjoint.interface.space_new(space, *, name=None, space_type='primal', static=False, cache=None)

Return a new variable.

Parameters:
  • space – The space.

  • name – A str name for the variable.

  • space_type – The space type for the new variable. ‘primal’, ‘dual’, ‘conjugate’, or ‘conjugate_dual’.

  • static – Defines whether the new variable is static, meaning that it is stored by reference in checkpointing/replay, and an associated tangent-linear variable is zero.

  • cache – Defines whether results involving the new variable may be cached. Default static.

Returns:

The new variable.

tlm_adjoint.interface.relative_space_type(space_type, rel_space_type)

Return a relative space type. For example if space_type is ‘dual’ and rel_space_type is ‘conjugate_dual’, this returns ‘conjugate’.

Parameters:
  • space_type – An input space type. One of ‘primal’, ‘conjugate’, ‘dual’, or ‘conjugate_dual’.

  • rel_space_type – The relative space type to return. One of ‘primal’, ‘conjugate’, ‘dual’, or ‘conjugate_dual’.

Returns:

A space type relative to space_type.

tlm_adjoint.interface.conjugate_space_type(space_type)

Defines a map

  • ‘primal’ \(\rightarrow\) ‘conjugate’

  • ‘conjugate’ \(\rightarrow\) ‘primal’

  • ‘dual’ \(\rightarrow\) ‘conjugate_dual’

  • ‘conjugate_dual’ \(\rightarrow\) ‘dual’

Returns:

The space type conjugate to space_type.

tlm_adjoint.interface.dual_space_type(space_type)

Defines a map

  • ‘primal’ \(\rightarrow\) ‘dual’

  • ‘conjugate’ \(\rightarrow\) ‘conjugate_dual’

  • ‘dual’ \(\rightarrow\) ‘primal’

  • ‘conjugate_dual’ \(\rightarrow\) ‘conjugate’

Returns:

The space type dual to space_type.

tlm_adjoint.interface.conjugate_dual_space_type(space_type)

Defines a map

  • ‘primal’ \(\rightarrow\) ‘conjugate_dual’

  • ‘conjugate’ \(\rightarrow\) ‘dual’

  • ‘dual’ \(\rightarrow\) ‘conjugate’

  • ‘conjugate_dual’ \(\rightarrow\) ‘primal’

Returns:

The space type conjugate dual to space_type.

tlm_adjoint.interface.no_space_type_checking(fn)

Decorator to disable space type checking.

Parameters:

fn – A callable for which space type checking should be disabled.

Returns:

A callable for which space type checking is disabled.

tlm_adjoint.interface.paused_space_type_checking()

Construct a context manager which can be used to temporarily disable space type checking.

Returns:

A context manager which can be used to temporarily disable space type checking.

exception tlm_adjoint.interface.SpaceTypeError

Raised when an unexpected space type is encountered with space type checking enabled.

tlm_adjoint.interface.check_space_type(x, space_type)

Check that a variable has a given space type.

Raises a SpaceTypeError if the check fails and space type checking is enabled.

Parameters:
  • x – A variable, whose space type should be checked.

  • space_type – The space type. One of ‘primal’, ‘conjugate’, ‘dual’, or ‘conjugate_dual’.

tlm_adjoint.interface.check_space_types(x, y, *, rel_space_type='primal')

Check that x and y have compatible space types.

Raises a SpaceTypeError if the check fails and space type checking is enabled.

Parameters:
  • x – A variable.

  • y – A variable.

  • rel_space_type – Check that the space type of x is rel_space_type relative to y. For example if rel_space_type=’dual’, and the space type of y is ‘conjugate_dual’, checks that the space type of x is ‘conjugate’.

tlm_adjoint.interface.check_space_types_conjugate(x, y)

Check that x has space type conjugate to the space type for y.

Raises a SpaceTypeError if the check fails and space type checking is enabled.

Parameters:
  • x – A variable.

  • y – A variable.

tlm_adjoint.interface.check_space_types_dual(x, y)

Check that x has space type dual to the space type for y.

Raises a SpaceTypeError if the check fails and space type checking is enabled.

Parameters:
  • x – A variable.

  • y – A variable.

tlm_adjoint.interface.check_space_types_conjugate_dual(x, y)

Check that x has space type conjugate dual to the space type for y.

Raises a SpaceTypeError if the check fails and space type checking is enabled.

Parameters:
  • x – A variable.

  • y – A variable.

class tlm_adjoint.interface.VariableInterface

A mixin defining an interface for variables. Variables types do not inherit from this class – instead an interface is defined by a VariableInterface subclass, and methods are bound dynamically at runtime using add_interface().

tlm_adjoint.interface.is_var(x)

Return whether x is a variable – i.e. has had a VariableInterface added.

Parameters:

x – An arbitrary object.

Returns:

True if x is a variable, and False otherwise.

tlm_adjoint.interface.var_comm(x)
Parameters:

x – A variable.

Returns:

The communicator associated with the variable.

tlm_adjoint.interface.var_space(x)
Parameters:

x – A variable.

Returns:

The space associated with the variable.

tlm_adjoint.interface.var_space_type(x, *, rel_space_type='primal')

Return the space type of a variable.

Parameters:
  • x – The variable.

  • rel_space_type – If supplied then return a space type relative to the variable space type. One of ‘primal’, ‘conjugate’, ‘dual’, or ‘conjugate_dual’.

Returns:

The space type.

tlm_adjoint.interface.var_dtype(x)
Parameters:

x – A variable.

Returns:

The data type associated with the variable. Typically numpy.double or numpy.cdouble.

tlm_adjoint.interface.var_id(x)

Return a unique int ID associated with a variable.

Note that two variables share the same ID if they represent the same symbolic variable – for example if one variable represents both a variable and stores a value, and a second the same variable with no value (i.e. is a ‘replacement’), then the two variables share the same ID.

Parameters:

x – The variable.

Returns:

The int ID.

tlm_adjoint.interface.var_name(x)
Parameters:

x – A variable.

Returns:

The str name of the variable.

tlm_adjoint.interface.var_state(x)

Return the value of the state counter for a variable. Updated when the value of the variable changes.

Parameters:

x – The variable.

Returns:

The int state value.

tlm_adjoint.interface.var_lock_state(x)

Lock the state of a variable.

Parameters:

x – The variable.

class tlm_adjoint.interface.VariableStateLockDictionary(*args, **kwargs)

A dictionary-like class. If a value is a variable and not a replacement then the variable state is ‘locked’ so that a state update, with the lock active, will raise an exception.

State locks are automatically released when the VariableStateLockDictionary is destroyed. Consequently objects of this type should be used with caution. In particular object destruction via the garbage collector may lead to non-deterministic release of the state lock.

tlm_adjoint.interface.var_locked(*X)

Construct a context manager which can be used to temporarily lock the state of one or more variables.

Parameters:

X – A tuple of variables.

Returns:

A context manager which can be used to temporarily lock the state of the variables in X.

tlm_adjoint.interface.var_update_state(*X)

Ensure that variable state is updated, and check for cache invalidation. May delegate updating of the state to a backend library.

Parameters:

X – A tuple of variables.

tlm_adjoint.interface.var_is_static(x)

Return whether a variable is flagged as ‘static’. A static variable is stored by reference in checkpointing/replay, and the associated tangent-linear variable is zero.

Parameters:

x – The variable.

Returns:

Whether the variable is flagged as static.

tlm_adjoint.interface.var_is_cached(x)

Return whether results involving this variable may be cached.

Parameters:

x – The variable.

Returns:

Whether results involving the variable may be cached.

tlm_adjoint.interface.var_caches(x)

Return the Caches associated with a variable.

Parameters:

x – The variable.

Returns:

The Caches associated with the variable.

tlm_adjoint.interface.var_update_caches(*X, value=None)

Check for cache invalidation associated with a possible change in value.

Parameters:
  • X – A tuple of variables whose value may have changed.

  • value – A variable or a Sequence of variables defining the possible new values. X is used if not supplied.

tlm_adjoint.interface.var_zero(x)

Zero a variable.

Parameters:

x – The variable.

tlm_adjoint.interface.var_assign(x, y)

Perform an assignment x = y.

Parameters:
  • x – A variable.

  • y – A variable.

tlm_adjoint.interface.var_axpy(y, alpha, x, /)

Perform an in-place addition y += alpha * x.

Parameters:
  • y – A variable.

  • alpha – A scalar.

  • x – A variable.

tlm_adjoint.interface.var_inner(x, y)

Compute the \(l_2\) inner product of the degrees of freedom vectors associated with x and y. By convention if y is in the conjugate dual space associated with x, this returns the complex conjugate of the functional associated with y evaluated at x.

Parameters:
  • x – A variable.

  • y – A variable.

Returns:

The result of the inner product.

tlm_adjoint.interface.var_linf_norm(x)

Compute the \(l_\infty\) norm of the degrees of freedom vector associated with a variable.

Parameters:

x – The variable.

Returns:

The \(l_\infty\) norm of the degrees of freedom vector.

tlm_adjoint.interface.var_local_size(x)

Return the process local number of degrees of freedom associated with a variable. This is the number of ‘owned’ degrees of freedom.

Parameters:

x – The variable.

Returns:

The process local number of degrees of freedom for the variable.

tlm_adjoint.interface.var_global_size(x)

Return the global number of degrees of freedom associated with a variable. This is the total number of ‘owned’ degrees of freedom, summed across all processes.

Parameters:

x – The variable.

Returns:

The global number of degrees of freedom for the variable.

tlm_adjoint.interface.var_local_indices(x)

Return the indices of process local degrees of freedom associated with a variable.

Parameters:

x – The variable.

Returns:

An Iterable, yielding the indices of the process local elements.

tlm_adjoint.interface.var_get_values(x)

Return a copy of the process local degrees of freedom vector associated with a variable.

Parameters:

x – The variable.

Returns:

A numpy.ndarray containing a copy of the degrees of freedom.

tlm_adjoint.interface.var_set_values(x, values)

Set the process local degrees of freedom vector associated with a variable.

Parameters:
  • x – The variable.

  • values – A numpy.ndarray containing the degrees of freedom values.

tlm_adjoint.interface.var_new(x, *, name=None, static=False, cache=None, checkpoint=None, rel_space_type='primal')

Return a new variable defined using the same space as x.

Parameters:
  • x – A variable.

  • name – A str name for the new variable.

  • static – Defines whether the new variable is static, meaning that it is stored by reference in checkpointing/replay, and an associated tangent-linear variable is zero.

  • cache – Defines whether results involving the new variable may be cached. Default static.

  • checkpoint – Deprecated.

  • rel_space_type – Defines the space type of the new variable, relative to the space type of x.

Returns:

The new variable.

tlm_adjoint.interface.var_new_conjugate(x, *, name=None, static=False, cache=None)

Return a new conjugate variable. See var_new().

Returns:

A new variable defined using the same space as x, with space type conjugate to the space type for x.

tlm_adjoint.interface.var_new_dual(x, *, name=None, static=False, cache=None)

Return a new dual variable. See var_new().

Returns:

A new variable defined using the same space as x, with space type dual to the space type for x.

tlm_adjoint.interface.var_new_conjugate_dual(x, *, name=None, static=False, cache=None)

Return a new conjugate dual variable. See var_new().

Returns:

A new variable defined using the same space as x, with space type conjugate dual to the space type for x.

tlm_adjoint.interface.var_copy(x, *, name=None, static=False, cache=None)

Copy a variable. See var_new().

Returns:

The copied variable.

tlm_adjoint.interface.var_replacement(x)

Return a variable, associated with the same variable as x, but possibly without a value.

Parameters:

x – The variable.

Returns:

A variable which symbolically represents the same variable as x, but which may not store a value. May return x itself.

tlm_adjoint.interface.var_is_replacement(x)

Return whether a variable is a ‘replacement’, meaning that it has no associated value.

Parameters:

x – The variable.

Returns:

Whether x is a replacement.

tlm_adjoint.interface.var_is_scalar(x)

Return whether a variable defines a scalar variable.

Parameters:

x – The variable.

Returns:

Whether x defines a scalar variable.

tlm_adjoint.interface.var_scalar_value(x)

If x defines a scalar variable, returns its value.

Parameters:

x – The variable, defining a scalar variable.

Returns:

The scalar value.

tlm_adjoint.interface.var_is_alias(x)

Return whether a variable is an ‘alias’, meaning part or all of the degree of freedom vector associated with the variable is shared with some different aliased variable. A variable may not appear as an equation dependency if it is an alias.

Parameters:

x – The variable.

Returns:

Whether the variable is an alias.

tlm_adjoint.interface.subtract_adjoint_derivative_action(x, y)

Subtract an adjoint right-hand-side contribution defined by y from the right-hand-side defined by x.

Parameters:
  • x – A variable storing the adjoint right-hand-side.

  • y – A contribution to subtract from the adjoint right-hand-side. An Equation.adjoint_derivative_action() return value. Valid types depend upon the variable type. Typically this will be a variable, or a two element tuple (alpha, F), where alpha is a numbers.Complex and F a variable, with the value to subtract defined by the product of alpha and F.