System Initialisation

The core functionality of this library is to provide an easy way to construct arbitrarily complicated systems of spins and electronic levels. Below you find a hands-on introduction on how to initialise an open quantum system in python with SimOS.

System Construction

Arbitrarily complicated systems of spins and electronic levels can be constructed using only two mathematical operations, (i) a tensor product and (ii) a direct sum, to combine the Hilbert spaces of the individual system components. If a tensor product is used, the overall size of the composite Hilbert space is the product of the dimensions of the individual components. If a direct sum is used, the overall Hilbert space size results as the sum of the individual dimensions.

_images/core_basicoperations.png

Composite Hilbert spaces of spins or electronic levels can be combined via tensor products (left) and direct sums (right).

The central part of this library is the class System which is used to define the system structure and which holds a complete set of operators after construction. The class constructor is called with a systemarray that is essentially a recipe on how to build the quantum system. It specifies all members of the system and how their individual Hilbert spaces are combined.

Each member of the spin system is defined as a python dictionary with keys

  1. name: The name of member:

  2. val: Multiplicity of the level, i.e. val = 0.5 for spin 1/2, val = 1 for spin 1 and so on or val = 0.0 for a single electronic level.

These dictionaries are then combined in the systemarray as a series of nested lists and tuples. Lists indicate that Hilbert spaces are combined using tensor products while tuples indicate combination with a direct sum. The system class instance (typically in our examples denoted as s) holds identity operators for all members of the quantum system (e.g., s.Aid for a member with name A) as well as x, y, z, lowering, raising and projection operators for all spins (e.g., s.Ax, s.Ay, s.Az, s.Aplus, s.Aminus, s.Ap[0.5] and s.Ap[-0.5] for a spin 1/2 with name A).

Warning

Names of system members must only contain alphanumerical letters. Special characters are reserved and used internally to distinguish native from non-native system members.

Note

Additional keys can be used to specify further parameters of system members, such as the spin type, isotope, relaxation times, spatial positions etc. Some functions of SimOS require that these parameters are specified. Keys can be read, added, deleted or modified after system construction with the get_properties, set_properties and del_properties functions of the system.

As a first example, we generate a system of two spins S=1/2 (e.g. two electron spins), whose composite Hilbert space size is 2x2 = 4.

_images/core_2spinsystem.png

Constructing a system of two coupled spins.

import simos as sos
S = {'name': 'S', 'val': 0.5}
I = {'name': 'I', 'val': 0.5}
system_array = [S,I]
s = sos.System(system_array)

The spin operators in the joint Hilbert space are stored as class attributes, e.g. the z-operators of the spins are obtained as s.Sz and s.Iz. Another very simple example is a pair of electronic levels, e.g. an electronic ground and an electronic excited state, with no spin. The composite Hilbert space size is 1+1=2.

_images/core_2levelsystem.png

Constructing a system of two electronic levels.

GS= {'name': 'GS', 'val': 0}
ES = {'name': 'ES', 'val': 0}
system_array = (GS,ES)
s = sos.System(system_array)

The identity operators of the levels in the combined Hilbert space are obtained as s.GSid and s.ESid. More complicated examples, e.g. the NV center in diamond and spin-correlated radical pairs are showcased in our examples section.

Basis Transformations

Upon system construction, the spin operators are initialized in the Zeeman basis, spanned by the magnetic quantum numbers of the individual spin members. To include alternative basis sets and transform operators between various bases, the System class provides users with two specific methods.

Coupled Product States of Spins

Coupled product states of pairs or groups of spins are useful representations for systems in which spin-spin interactions dominate the system Hamiltonian. In SimOS, they can be constructed with the add_ghostspin method of the System. The simplest example, the coupled representation of two coupled spin 1/2 particles as a singlet ( \(S_{tot} = \frac{1}{2}-\frac{1}{2} = 0\) ) and triplet ( \(S_{tot} = \frac{1}{2} + \frac{1}{2} = 1\) ) is illustrated below. Here, spins S and I are coupled to obtain the singlet and triplet ghostspins C_1 and C_3.

_images/core_couplespins.png
S  = {"name": "S", "val": 1/2}
I  = {"name": "I", "val": 1/2}
s = sos.System([S,I])
s.add_ghostspin("C", ["S", "I"])

The operators of the ghostspins are generated in full analogy to the native spins of the system. For example, the projector onto the the \(m_S=0\) level of the triplet is obtained as C_3p[0]. The matrix representations of these operators are still formulated in the Zeeman basis. However, the add_ghostspin method also constructs the transformation matrices to transform operators to or from the coupled basis and stores them as attributes of the System. In our simple example, the transformation matrices can be assessed as s.toC and s.fromC and allow to transform any system operator to or from the Zeeman to the coupled Singlet-Triplet basis.

# Transform z Operators of Singlet and Triplet from
# Zeeman to  Singlet-Triplet Basis
C1z_st = s.C_1z.transform(s.toC)
C3z_st = s.C_3z.transform(s.toC)

The spin operators of the ghost-spins are named according to the following conventions:

  1. The name that the user has specified, e.g. in our case C.

  2. An underscore.

  3. An integer or a series of integers specifying the spin multiplicity. If more than two spins are coupled, the same multiplicity occurs multiple times for the coupled spin. To distinguish them, the multiplicities of their coupling history are included in their name.

  4. The actual name of the operator, e.g. z for a z operator, id for the identity.

If add_ghostspin is called with the option return_names = True the names of the ghost spins (i.e. parts 1-3 of the above list) are returned. This can be helpful if larger groups of spins are coupled.

Generic Basis Transformations

A completely user-defined basis may be defined using a second method, add_basis, by providing (i) a transformation matrix from the Zeeman basis to the new basis and (ii) a name for the basis and a list of names for all basis states. Here, we illustrate this method for the example of a pair of electronic levels. The method stores identity operators of all new basis states as well as transformation matrices for back and forth conversion between the Zeeman and the alternate basis.

_images/core_couplelevels.png
GS= {'name': 'GS', 'val': 0}
ES = {'name': 'ES', 'val': 0}
system_array = (GS,ES)
s = sos.System(system_array)
T= _np.array([[0.5, 0.5], [0.5, -0.5]])
s.add_basis(T,  "A", ["g", "e"])

# Transform one of these states to the new basis.
gid = s.A_gid.transform(s.toA)

The nomenclature of the alternate basis levels has the following convention:

  1. The name that the user has specified for the alternate basis.

  2. An underscore.

  3. The name that the user has specified for the new basis state.

Subspaces

The extraction of sub-parts of a multipartite quantum system is an essential task during simulation routines and is supported in SimOS. For composite systems whose combined Hilbert space was spanned with a tensor product, the subsystem is extracted with a partial trace. If a composite system was obtained with a direct sum, subsystems are directly obtained as subsets of the full system operator by the means of projection. For more complicated multipartite systems, our algorithm extracts the desired subsystem with up to three steps in a top-down approach. This routine does not remove members unless they are fully separable from the desired subsystem.

Let us first consider the simple system of two spins S=1/2 that we have already encountered before. The combined Hilbert space is separable into the individual Hilbert spaces since it was constructed with a tensor product.

_images/core_extractptrace.png
op = s.Sz
op_subS, op_subI, reverse = sos.subsystem(s, op, "S")

Next, we consider our system of two electronic levels. Here the extraction is performed with a projection operation since the two members were combined with a direct sum.

_images/core_extractproject.png
op = s.GSid
op_subGS, op_subES, reverse = sos.subsystem(s, op, "A")

In addition to the operator in the desired subspace (e.g. op_subS and op_subGS), the subsystem routine also returns the subspace for the remaining system (e.g. op_subI and op_subES). If the extraction was performed in multiple steps, a list of operators is returned for the remaining system. Each entry of the list is the subspace which was traced out in a single step of the exctraction procedure. Further, the routine returns a third argument which is essentially an instruction that can be used to again construct the full system from density matrices of the individual components. Users may utilize the reverse_subsystem for this purpose.

Syntax Reference

class System(system_array: list | tuple, method='qutip')[source]

A class for representing composite quantum systems of spins and electronic levels. Stores all operators of the system.

method

Backend that was used for system construction.

Type:

str

system

A list of dictionaries for all members of the system.

Type:

list

structure

A list/tuple of lists/tuples holding the members’ names which indicates how the multipartite quantum system was constructed.

Type:

list/tuple

dim

Hilbert space size of the system.

Type:

int

dims

Substructure of the Hilbert space (i.e. list of Hilbert space sizes of “separable” subsystems that were combined with a tensor product, in analogy to qutips dims attribute)

Type:

list

id

Identity operator of the system.

add_basis(T: ndarray, basis_name: str, state_names: list | tuple | ndarray)[source]

Constructs a complete alternate basis for the system using a user-defined transformation matrix. The identity operators of the new basis states and transformation matrices for conversion between the original and the new basis are stored as attributes of the system.

Parameters:
  • T (numpy.ndarray) – Transformation matrix, describing the transformation from the native system basis (Zeeman basis) to the new basis.

  • basis_name (str) – Name of the basis.

  • state_names (list, tuple, numpy.ndarray) – Series of names for the states of the new basis. A name must be provided for each individual state.

add_ghostspin(newname: str, spinnames: list, returnnames=False)[source]

Couples N spins of the systems with spin values j1, j2 … to N spins with values |j1-j2-...|, |j1-j2-...+1|, …, |j1+j2+...| and stores the spin operators of the new, coupled spins as attributes of the system class.

Parameters:
  • newname (str) – Will be used as a prefix for the spin operators of the new spins.

  • spinnames (list) – List of the names of all spins that will be coupled.

Keyword Arguments:

  • returnnames (bool) – If True, a list with the names of all new spins is returned.

del_property(level_name: str, property_name: str)[source]

Deletes a property of a spin or an electronic level of the system.

Parameters:
  • level_name (str) – Name of the spin or electronic level.

  • property_name (str) – Name of the property.

get_index(level_name: str)[source]

Returns the position of a spin or an electronic level in the system-list.

Parameters:

level_name (str) – Name of the spin or electronic level.

Returns:

Position index.

get_property(level_name: str, property_name: str)[source]

Returns a property of a spin or an electronic level of the system.

Parameters:
  • level_name (str) – Name of the spin or electronic level.

  • property_name (str) – Name of the property.

Returns:

The property.

set_property(level_name: str, property_name: str, value)[source]

Sets a property of a spin or an electronic level of the system to a desired value.

Parameters:
  • level_name (str) – Name of the spin or electronic level.

  • property_name (str) – Name of the property.

  • value – New value of the property.

reverse_subsystem(op, rop, reverse)[source]

Projects an operator formulated in the Hilbert space of a subsystem back into the Hilbert space of the full system. This function is intended as a counterpart to the subsystem method and difficult to use as a standalone method.

Parameters:
  • system (System) – Instance of the System-class.

  • op – Operator of the subsystem.

  • reverse_instruction (dict) – A dictionary with instructions on how to project operators of this subsystem back into the full system. Such a dictionary is automatically generated by the subsystem method.

Returns:

The operator in the Hilbert space of the full system.

spinops(spindef, method='qutip', prefix='')[source]

Returns single-spin operators.

Parameters:

spindef (dict) – Definition of the spin for which operators should be build. Must contain a key ‘val’ that specifies the spin value. Can further contain a key ‘type’ to specify the spin type and a key ‘name’ for the spin name. If spin type is ‘NV’, ‘NV-‘or ‘NV+’ a series of additional operators are constructed.

Keyword Arguments:

  • method (str) – Backend. Default is qutip.

  • prefix (str) – A prefix that is added to the keys of the return dictionary.

Returns:

Dictionary that holds the single spin operators, keys are ‘id’,’x’,’y’,’z’,’+’,’-‘,’p’ for ‘default’ spin type with spin > 0 and ‘id’ if spin = 0.

subsystem(system, op, selection, keep=True)[source]

Extracts a subsystem from a system. Whenever possible, the extraction is done with a partial trace. Otherwise, the subsystem is extracted by simply dropping all non-member dimensions.

Parameters:
  • system (System) – Instance of the System-class.

  • op – Operator of the system.

  • selection (dict, list, str) – Specifies the subsystem. Members can be specified with their names or their entire definition, mutiple members can be provided in a list.

Keyword Arguments:

  • keep (bool) – If True, selection specifies the system remaining after partial trace. If False, selection specifies the subsystem that is removed.

Returns:

  • The operator of the selected subsytem.

  • The operator(s) of the remaining subsystem(s).

  • list Instructions on how to project operators of this subsystem back into the full system.