newtonprop.interface module

Recommended interface for a stateful Newton propagator

Typically, an efficient propagator will rely on low-level data structures. Since conversion between high- and low-level structures in every call of newtonprop.propagator.step() would be wasteful, it is better to use a stateful propagator that only does the conversion once, holds the required state, and converts back only on demand.

While a stateful propagator could be achieved through a wrapper function and closures, a more straightforward implementation holds the necessary state in a class. To encourage a consistent interface, you should subclass NewtonPropagatorBase for this purpose.

Summary

Classes:

NewtonPropagatorBase Abstract base class for a stateful interface for using the Newton propagator

__all__: NewtonPropagatorBase

Reference

class newtonprop.interface.NewtonPropagatorBase(data, func='exp', m_max=10, maxrestart=100, tol=1e-12)[source]

Bases: object

Abstract base class for a stateful interface for using the Newton propagator

This must be sub-classed before it can be used.

Parameters:
  • data – data that underlies the abstract operator \(A\). The propagator will use this together with a time parameter t to construct the argument A for newtonprop.propagator.step().
  • func (callable or str) – The scalar version of the operator-function \(f\). Must take one complex argument and return a complex value. If given as a string, the corresponding callable will be looked up in funcs.
  • m_max (int) – Maximal Krylov dimension. Initializes the corresponding attribute.
  • maxrestart (int) – Maximum number of Newton restarts. Initializes the corresponding attribute.
  • tol (float) – Desired precision of the result. Initializes the corresponding attribute.

Subclasses will customize the behavior mostly by overriding a number of private methods, outlined below. These methods may act on the following (private) attributes:

_data

Internal data that may be used to calculate \(A\). Obtained from data via _convert_data_to_internal().

_v0

The state set by set_initial_state(), in its original format

_v

The current state, in an internal format. The internal format is determined by _convert_state_to_internal().

Private methods:

_check()[source]

Check completeness and consistency of attributes

After set_initial_state(), check that all attributes are defined and are consistent. If not, raise an AttributeError.

_convert_state_to_internal(v)[source]

Convert the initial state v into a more efficient internal format.

This is used when setting _v from the v given in set_initial_state(). By default, the state is passed on unchanged.

_convert_state_from_internal(v)[source]

Convert v in internal format of _v to original format

If _v uses an internal format different from the v in set_initial_state(), this method must be overridden to convert _v back to the original format. It is used by state for this purpose. By default, the internal state is passed on unchanged.

static _convert_data_to_internal(data)[source]

Convert data to _data

Optional conversion of the data passed to the initializer to a more efficient internal format. By default, the data is stored unchanged.

_inner(a, b)[source]

Inner product between two states a, b in the format of _v

Must return a complex number. This is an abstract method, and thus must be implemented by any subclass of NewtonPropagatorBase.

An example implementation is:

def _inner(self, a, b):
    return numpy.vdot(a, b)
_norm(a)[source]

Norm of a state a in the format of _v

Must return a complex number. This is an abstract method, and thus must be implemented by any subclass of NewtonPropagatorBase.

An example implementation is:

def _norm(self, a):
    return numpy.linalg.norm(a)
_zero(a)[source]

A new zero-state compatible with the format of _v

Must allocate and return a new state in the same internal format as _v, but containing zeros, so that the state can set in-place. This is an abstract method, and thus must be implemented by any subclass of NewtonPropagatorBase.

An example implementation is:

def _zero(self, a):
    return numpy.zeros(shape=a.shape, dtype=a.dtype)
_A(t)[source]

Callable A(v) encoding the abstract operator \(A(t)\).

Must return a callable A(v) that takes a state v in the internal format of _v and returns a state in the same format. This is an abstract method, and thus must be implemented by any subclass of NewtonPropagatorBase.

Assuming self._data contains a nested list [L0, [L1, eps]] where L0 and L1 are numpy matrices containing a superoperator, and eps is a callable with argument t for a time-dependent control, an example implementation is:

def _A(self, t):
    Lmatrix = (
        self._data[0] + self._data[1][0] + self._data[1][1](t))

    def L(v):
        return Lmatrix @ v

    return L

Note

This method does not calculate A(v) directly, but returns a callable that does. This is to take into account time-dependent operators, which newtonprop.propagator.step() does not know anything about.

Public methods, attributes, and properties:

func

The scalar version of the operator-function \(f\), as a callable

m_max

Maximal Krylov dimension (int)

maxrestart

Maximum number of Newton restarts (int)

tol

Desired precision of the result (float)

funcs = {'exp': <function _exp>, 'expi': <function _expi>, 'expmi': <function _expmi>}

Registry of func names (class attribute)

Cf. the func argument of newtonprop.propagator.step(). You may extend this with your own function names.

set_initial_state(v)[source]

Set the initial state for the propagation.

state

The current state (read-only)

After a call to set_initial_state(), this is the state set by that call. After a call to step(), it is the result of that propagation step.

step(t, dt)[source]

Perform a single propagation step

Parameters:
  • t (float) – time value at which to evaluate the abstract operator \(A(t)\)
  • dt (float) – length of the time step

Construct an abstract operator \(A(t)\) based on the data the propagator was initialized with, and calculate

\[v_\text{out} = f(A(t)\,dt) \, v_\text{in}\]

where \(v_\text{in}\) is the current state, and \(f\) is the function specified by func during initialization.

The state \(v_\text{out}\) becomes \(v_\text{in}\) for the next call to step(). The time parameter t should generally be the midpoint of the interval covered by \(dt\).

The results of the propagation step may be read from state. The step() method does not return anything.