C++QEDCore  2.100.2 (v2 Milestone 10 Development branch)
a framework for simulating open quantum dynamics – core
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages

Table of Contents

Analogously to slicing state vectors, it is also necessary to slice LazyDensityOperator objects because for calculating quantum expectation values of subsystem-observables (e.g. in Composite objects), the partial-trace density operator is needed.

For the partial trace, however, only such elements of the full density operator are needed as are diagonal in the indices not belonging to the given subsystem (dummy indices). This is the reason why the tool performing the iteration is called DiagonalIterator.

Slicing is fully recursive, a sliced LazyDensityOperator (usually obtained by dereferencing a DiagonalIterator) can be further sliced.

Notes on implementation

Difficulty: LazyDensityOperator is an abstract interface, and the organization of its data (and hence the actual procedure of slicing) varies along implementations.

ldoDiagonalIterator.png

Implemented using a classical inheritance-based strategy idiom, together with both compile-time and run-time implementation selection (similarly to blitzplusplus::basi::Iterator, a special implementation (DiagonalIterator::DI_ImplSpecial) is needed when the size of the compile-time vector V equals RANK).

The run-time polymorphy of LazyDensityOperator necessitates run-time implementation selection. This happens when the actual implementation (DI_SV_Impl or DI_DO_Impl, or their non-orthogonal counterparts) is chosen depending on whether the given LazyDensityOperator is a StateVector or a DensityOperator (or their non-orthogonal counterparts).