Molecule#

The Molecule class represents the basic quantum objects of interest in Quantarhei, namely, the molecules. For Quantarhei, molecule is a multilevel quantum system with electronic gaps in the optical region of frequencies. As of version 0.0.67, Quantarhei can reliably handle only molecules with two electronic states, the ground state and one excited state, however, the work on extension to more excited states is well under way.

Multi-level molecule (monomer)

The molecule is defined by the vector of energies of its states and by the transition dipole moments between allowed transitions.

>>> m = Molecule([0.0, 1.0])
>>> print(m.Nel)
2

Information about the molecule can be obtained simply by printing it

>>> print(m)

quantarhei.Molecule object
==========================
name =
position = None
number of electronic states = 2
# State properties
State nr: 0 (ground state)
electronic energy = 0.0 1/fs
number of vibrational modes = 0

State nr: 1
electronic energy = 1.0 1/fs
transition 0 -> 1
transition dipole moment = [0.0, 0.0, 0.0]
number of vibrational modes = 0
>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> print(mol)

quantarhei.Molecule object
==========================
name = two-levels-1-mode
position = None
number of electronic states = 2
# State properties
State nr: 0 (ground state)
electronic energy = 0.0 1/fs
number of vibrational modes = 1
# Mode properties
mode no. = 0
frequency = 1.0 1/fs
shift = 0.0
nmax = 2
State nr: 1
electronic energy = 1.0 1/fs
transition 0 -> 1
transition dipole moment = [0.0, 0.0, 0.0]
number of vibrational modes = 1
# Mode properties
mode no. = 0
frequency = 1.0 1/fs
shift = 0.0
nmax = 2

Class Details#

class quantarhei.builders.molecules.Molecule(elenergies: list | ndarray | None = None, name: str | None = None)[source]#

Bases: UnitsManaged, Saveable, OpenSystem

Multi-level molecule (monomer).

Represents a single chromophore with multiple electronic states, optional vibrational modes, and system-bath coupling. It is the basic building block for constructing molecular aggregates.

Parameters:
  • elenergies (list of float, optional) – Electronic state energies in the current energy units, starting with the ground state (typically 0.0). Default is [0.0, 1.0].

  • name (str, optional) – Human-readable label for the molecule. Default is ''.

property position: ndarray#
property nal: Any#
property nel: Any#
property nmod: Any#
build(mult: int = 1) None[source]#

Building routine for the molecule

Unlike with the Aggregate, it is not compulsory to call build() before we start using the Molecule

get_name() str[source]#

Returns the name of the molecule

Examples

>>> m = Molecule([0.0, 1.0], name="Jane")
>>> m.get_name()
'Jane'
set_name(name: str) None[source]#

Sets the name of the Molecule object

Examples

>>> m = Molecule([0.0, 1.0])
>>> m.set_name("Jane")
>>> print(m.get_name())
Jane
set_electronic_rwa(rwa_indices: list | None) None[source]#

Sets which electronic states belong to different blocks

Setting the indices of blocks should allow the construction of Rotating Wave Approximation for the Hamiltonian. This in turn is used for the calculations of optical spectra.

Examples

>>> with energy_units("1/cm"):
...     mol1 = Molecule([0.0, 10000.0])
>>> mol1.set_electronic_rwa([0, 1])
>>> H = mol1.get_Hamiltonian()
>>> H.has_rwa
True
>>> with energy_units("1/cm"):
...     mol2 = Molecule([0.0, 10000.0, 10500.0, 20000.0])
>>> with energy_units("1/cm"):
...     mod2 = Mode(frequency=200.0)
...     mol2.add_Mode(mod2)
>>> mod2.set_nmax(0, 5)
>>> mod2.set_nmax(1, 4)
>>> mod2.set_nmax(2, 5)
>>> mod2.set_nmax(3, 3)
>>> mol2.set_electronic_rwa([0, 1, 3])
>>> H = mol2.get_Hamiltonian()
>>> H.has_rwa
True
>>> print(H.rwa_indices)
[ 0  5 14]
set_egcf_mapping(transition: tuple, correlation_matrix: object, position: int) None[source]#

Sets a correlation function mapping for a selected transition.

The monomer can either have a correlation function assigned to it, or it can be a part of a correlation matrix. Here the mapping to the correlation matrix is specified.

Parameters:
  • transition (tuple) – A tuple describing a transition in the molecule, e.g. (0,1) is a transition from the ground state to the first excited state.

  • correlation_matrix (CorrelationFunctionMatrix) – An instance of CorrelationFunctionMatrix

  • position (int) – Position in the CorrelationFunctionMatrix corresponding to the monomer.

Examples

A set of three monomers

>>> en1 = [0.0,12100, 13000] #*cm2int]
>>> en2 = [0.0,12000] #*cm2int]
>>> with energy_units("1/cm"):
...     m1 = Molecule(en1)
...     m2 = Molecule(en1)
...     m3 = Molecule(en2)

Bath correlation functions to describe molecular environment

>>> from .. import TimeAxis
>>> from .. import CorrelationFunction
>>> time = TimeAxis(0.0, 2000, 1.0) # in fs
>>> temperature = 300.0 # in Kelvins
>>> cfce_params1 = dict(ftype="OverdampedBrownian",
...           reorg=30.0,
...           cortime=60.0,
...           T=temperature)
>>> cfce_params2 = dict(ftype="OverdampedBrownian",
...           reorg=30.0,
...           cortime=60.0,
...           T=temperature)
>>> with energy_units("1/cm"):
...    cf1 = CorrelationFunction(time,cfce_params1)
...    cf2 = CorrelationFunction(time,cfce_params2)

Environment of the molecules is collected to a matrix. A smaller number of correlation functions can be assigned to a large number of “sites”.

>>> cm = CorrelationFunctionMatrix(time,3)
>>> ic1 = cm.set_correlation_function(cf1,[(0,0),(2,2)])
>>> ic2 = cm.set_correlation_function(cf2,[(1,1)])

The sites of the in the matrix are assigned to molecules.

>>> m1.set_egcf_mapping((0,1), cm, 0)
>>> m2.set_egcf_mapping((0,1), cm, 1)
>>> m3.set_egcf_mapping((0,1), cm, 2)

The environment cannot be set twice

>>> m1.set_egcf_mapping((0,1), cm, 2)
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: Monomer has a correlation function already
>>> m1.set_egcf_mapping((0,2), cm, 2)
>>> m1.set_egcf_mapping((0,2), cm, 2)
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: Monomer has a correlation function already
set_transition_environment(transition: tuple, egcf: object) None[source]#

Sets a correlation function for a transition on this monomer

Parameters:
  • transition (tuple) – A tuple describing a transition in the molecule, e.g. (0,1) is a transition from the ground state to the first excited state.

  • egcf (CorrelationFunction) – CorrelationFunction object

Example

>>> from ..qm.corfunctions import CorrelationFunction
>>> from .. import TimeAxis
>>> ta = TimeAxis(0.0,1000,1.0)
>>> params = dict(ftype="OverdampedBrownian",reorg=20,cortime=100,T=300)
>>> with energy_units("1/cm"):
...     cf = CorrelationFunction(ta, params)
>>> m = Molecule([0.0, 1.0])
>>> m.set_transition_environment((0,1), cf)
>>> print(m._has_system_bath_coupling)
True

When the environment is already set, the next attempt is refused

>>> m.set_transition_environment((0,1), cf)
Traceback (most recent call last):
...
quantarhei.exceptions.QuantarheiError: Correlation function already speficied for this monomer

The environment cannot be set when the molecule is mapped on a correlation function matrix

>>> with energy_units("1/cm"):
...     cf1 = CorrelationFunction(ta, params)
>>> cm = CorrelationFunctionMatrix(ta,1)
>>> ic1 = cm.set_correlation_function(cf1,[(0,0)])
>>> m1 = Molecule([0.0, 1.0])
>>> m1.set_egcf_mapping((0,1), cm, 0)
>>> m1.set_transition_environment((0,1), cf1)
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: This monomer is mapped on a CorrelationFunctionMatrix
unset_transition_environment(transition: tuple) None[source]#

Unsets correlation function from a transition on this monomer

This is needed if the environment is to be replaced

Parameters:

transition (tuple) – A tuple describing a transition in the molecule, e.g. (0,1) is a transition from the ground state to the first excited state.

Example

>>> from ..qm.corfunctions import CorrelationFunction
>>> from .. import TimeAxis
>>> ta = TimeAxis(0.0,1000,1.0)
>>> params = dict(ftype="OverdampedBrownian",reorg=20,cortime=100,T=300)
>>> with energy_units("1/cm"):
...     cf = CorrelationFunction(ta, params)
>>> m = Molecule([0.0, 1.0])
>>> m.set_transition_environment((0,1), cf)
>>> print(m._has_system_bath_coupling)
True
>>> m.unset_transition_environment((0,1))
>>> print(m._has_system_bath_coupling)
False

When the environment is unset, the next attempt to set is succesful

>>> m.set_transition_environment((0,1), cf)
>>> print(m._has_system_bath_coupling)
True

The environment cannot be unset when the molecule is mapped on a correlation function matrix

>>> with energy_units("1/cm"):
...     cf1 = CorrelationFunction(ta, params)
>>> cm = CorrelationFunctionMatrix(ta,1)
>>> ic1 = cm.set_correlation_function(cf1,[(0,0)])
>>> m1 = Molecule([0.0, 1.0])
>>> m1.set_egcf_mapping((0,1), cm, 0)
>>> m1.unset_transition_environment((0,1))
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: This monomer is mapped on a CorrelationFunctionMatrix
set_egcf(transition: tuple, egcf: object) None[source]#
get_transition_environment(transition: Any) Any[source]#

Returns energy gap correlation function of a monomer

Parameters:

transition (tuple) – A tuple describing a transition in the molecule, e.g. (0,1) is a transition from the ground state to the first excited state.

Example

>>> m = Molecule([0.0, 1.0])

Environment of the transition has to be set first

>>> cc = m.get_transition_environment((0,1))
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: No environment set for the transition

Environment is characterized by the bath correlation function

>>> from ..qm.corfunctions import CorrelationFunction
>>> from .. import TimeAxis
>>> ta = TimeAxis(0.0,1000,1.0)
>>> params = dict(ftype="OverdampedBrownian",reorg=20,cortime=100,T=300)
>>> with energy_units("1/cm"):
...     cf = CorrelationFunction(ta, params)
>>> m.set_transition_environment((0,1), cf)
>>> cc = m.get_transition_environment((0,1))
>>> cc == cf
True

When non-existent transition is tried, exception is raised

>>> cc = m.get_transition_environment((0,2))
Traceback (most recent call last):
    ...
quantarhei.exceptions.QuantarheiError: Index out of range
get_egcf(transition: tuple) object[source]#
add_Mode(mod: object) None[source]#

Adds a vibrational mode to the monomer

Parameters:

mod (quantarhei.Mode) – Intramolecular vibrational mode

Examples

>>> mode = Mode()
>>> mol = Molecule([0.0, 2.0])
>>> print(mol.get_number_of_modes())
0
>>> mol.add_Mode(mode)
>>> print(mol.get_number_of_modes())
1
get_Mode(N: int) object[source]#

Returns the Nth mode of the Molecule object

Parameters:

N (int) – Index of the mode to be returned

Examples

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> mod = mol.get_Mode(1)
Traceback (most recent call last):
    ...
IndexError: list index out of range
>>> mod = mol.get_Mode(0)
>>> mod.get_energy(1)
1.0
get_number_of_modes() int[source]#

Retruns the number of modes in this molecule

Examples

>>> m = Molecule([0.0, 1.0])
>>> m.get_number_of_modes()
0
>>> import quantarhei as qr
>>> m = qr.TestMolecule("two-levels-1-mode")
>>> m.get_number_of_modes()
1
get_dipole(N: int, M: int) ndarray[source]#

Returns the dipole vector for a given electronic transition

There are two ways how to use this function:

  1. recommended

    get_dipole((0,1),[1.0, 0.0, 0.0])

    here N represents a transition by a tuple, M is the dipole

  2. deprecated (used in earlier versions of quantarhei)

    get_dipole(0,1,[1.0, 0.0, 0.0])

    here the transition is characterized by two integers and the last arguments is the vector

Examples

>>> m = OpenSystem([0.0, 1.0])
>>> m.set_dipole((0,1),[1.0, 0.0, 0.0])
>>> m.get_dipole((0,1))
array([ 1.,  0.,  0.])
get_velocity_dipole(N: int, M: int) ndarray[source]#
get_magnetic_dipole(N: int, M: int) ndarray[source]#
set_dipole(N: Any, M: Any = None, vec: Any = None) None[source]#

Sets transition dipole moment for an electronic transition

There are two ways how to use this function:

  1. recommended

    set_dipole((0,1),[1.0, 0.0, 0.0])

    here N represents a transition by a tuple, M is the dipole

  2. deprecated (used in earlier versions of quantarhei)

    set_dipole(0,1,[1.0, 0.0, 0.0])

    here the transition is characterized by two integers and the last arguments is the vector

Examples

>>> m = OpenSystem([0.0, 1.0])
>>> m.set_dipole((0,1),[1.0, 0.0, 0.0])
>>> m.get_dipole((0,1))
array([ 1.,  0.,  0.])
set_velocity_dipole(N: Any, M: Any = None, vec: Any = None) None[source]#
set_velocity_dipole_from_dipole() None[source]#
set_magnetic_dipole(N: Any, M: Any = None, vec: Any = None) None[source]#
set_magnetic_dipoleR(N: Any, M: Any, vec: Any, RR: Any = None) None[source]#
set_transition_width(transition: tuple, width: float) None[source]#

Sets the width of a given transition

Parameters:
  • transition ({tuple, list}) – Quantum numbers of the states between which the transition occurs

  • width (float) – The full width at half maximum (FWHM) of a Gaussian lineshape, or half width at half maximum (HWHM) of a Lorentzian lineshape

get_transition_width(transition: tuple) float[source]#

Returns the transition width

Returns the full width at half maximum (FWHM) of a Gaussian lineshape, or half width at half maximum (HWHM) of a Lorentzian lineshape

Parameters:

transition ({tuple, list}) – Quantum numbers of the states between which the transition occurs

set_transition_dephasing(transition: tuple, deph: float) None[source]#

Sets the dephasing rate of a given transition

Parameters:
  • transition ({tuple, list}) – Quantum numbers of the states between which the transition occurs

  • deph (float) – Dephasing rate of the transition

get_transition_dephasing(transition: tuple) float[source]#

Returns the dephasing rate of a given transition

Parameters:

transition ({tuple, list}) – Quantum numbers of the states between which the transition occurs

get_energy(N: int) float | ndarray[source]#

Returns energy of the Nth state of the molecule

Parameters:

N (int) – Index of the state

Examples

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> mol.get_energy(1)
1.0

This methods reacts to the energy_units context manager

>>> with qr.energy_units("1/cm"):
...     print("{0:.8f}".format(mol.get_energy(1)))
5308.83745888
set_energy(N: int, en: float) None[source]#

Sets the energy of the Nth state of the molecule

Parameters:
  • N (int) – Index of the state

  • en (float) – Energy to be assigned to the Nth state.

Examples

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> mol.set_energy(1, 1.5)
>>> mol.get_energy(1)
1.5

This method reacts to the energy_units context manager

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> with qr.energy_units("1/cm"):
...     mol.set_energy(1, 5308.8374588761453)
>>> mol.get_energy(1)
1.0
get_temperature() float[source]#

Returns temperature of the molecule

Checks if the setting of environments is consistent and than takes the temperature from one of the energy gaps. If no environment (correlation function) is assigned to this molecule, we assume zero temperature.

Examples

Default temperature is 0 K

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> mol.get_temperature()
0.0

Molecule gets its temperature from the environment

>>> from ..qm.corfunctions import CorrelationFunction
>>> from .. import TimeAxis
>>> ta = TimeAxis(0.0,1000,1.0)
>>> params = dict(ftype="OverdampedBrownian",reorg=20,cortime=100,T=300)
>>> with energy_units("1/cm"):
...     cf = CorrelationFunction(ta, params)
>>> m = Molecule([0.0, 1.0])
>>> m.set_transition_environment((0,1), cf)
>>> print(m.get_temperature())
300
check_temperature_consistent() bool[source]#

Checks that the temperature is the same for all components

Examples

Isolated molecule has always consistent temperature

>>> m = Molecule([0.0, 1.0, 1.2])
>>> print(m.check_temperature_consistent())
True
>>> from ..qm.corfunctions import CorrelationFunction
>>> from .. import TimeAxis
>>> ta = TimeAxis(0.0,1000,1.0)
>>> params1 = dict(ftype="OverdampedBrownian",
...                reorg=20,cortime=100,T=300)
>>> params2 = dict(ftype="OverdampedBrownian",
...                reorg=20,cortime=100,T=200)
>>> with energy_units("1/cm"):
...     cf1 = CorrelationFunction(ta, params1)
...     cf2 = CorrelationFunction(ta, params2)
>>> m.set_transition_environment((0,1), cf1)
>>> m.set_transition_environment((0,2), cf2)
>>> print(m.get_temperature())
Traceback (most recent call last):
...
quantarhei.exceptions.QuantarheiError: Molecular environment has an inconsisten temperature
set_diabatic_coupling(element: tuple, factor: list, shifts: list | None = None) None[source]#

Sets off-diagobal elements of the diabatic potential matrix

get_potential_1D(mode: int, points: ndarray, other_modes: list | None = None) tuple[source]#

Returns the one dimensional diabatic potentials

get_potential_2D(modes: list, points: list, other_modes: list | None = None) tuple[source]#

Returns the two dimensional diabatic potentials

plot_potential_1D(mode: int, points: ndarray, other_modes: list | None = None, nonint: bool = True, states: list | None = None, energies: bool = True, show: bool = True, ylims: list | None = None) None[source]#

Plots the potentials

plot_stick_spectrum(xlims: list | None = None, ylims: list | None = None, show_zero_coupling: bool = False, show: bool = True) None[source]#

Plots the stick spectrum of the molecule

plot_dressed_sticks(dfce: Any = None, xlims: list | None = None, nsteps: int = 1000, show_zero_coupling: bool = False, show: bool = True) None[source]#

Plots a stick spectrum dessed by a supplied function

get_diabatic_coupling(element: tuple) list[source]#

Returns list of coupling descriptors

get_diabatic_shifts(order: int = 1) None[source]#
set_adiabatic_coupling(state1: int, state2: int, coupl: float) None[source]#

Sets adiabatic coupling between two states

get_adiabatic_coupling(state1: int, state2: int) float[source]#

Returns adiabatic coupling between two states

get_electronic_natural_linewidth(N: int) float[source]#

Returns natural linewidth of a given electronic state

get_Hamiltonian(multi: bool = True, recalculate: bool = False) Any[source]#

Returns the Hamiltonian of the Molecule object

Examples

After the molecule is created, its Hamiltonian can be obtained

>>> import quantarhei as qr
>>> mol = qr.TestMolecule("two-levels-1-mode")
>>> H = mol.get_Hamiltonian()
>>> print(H.dim)
4
>>> print(H.data)
[[ 0.  0.  0.  0.]
 [ 0.  1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0.  2.]]

The Hamiltonian is stored, and next time it is retrieved we obtain the same object.

>>> print(H.has_rwa)
False

We can manipulate with the Hamiltonian in between retrievals >>> H.set_rwa([0,1]) >>> print(H.has_rwa) True

The Hamiltonian the obtain the second time is affected by the changes performed outside the Molecule class

>>> H1 = mol.get_Hamiltonian()
>>> print(H1.has_rwa)
True

The newly obtained Hamiltonina IS the Hamiltonian obtained earlier.

>>> H1 is H
True
get_TransitionDipoleMoment(multi: bool = True) Any[source]#

Returns the transition dipole moment operator

get_SystemBathInteraction() object[source]#

Returns a SystemBathInteraction object of the molecule

get_RelaxationTensor(*args: Any, **kwargs: Any) Any[source]#

Returns relaxation tensor, building the molecule if necessary.

set_mode_environment(mode: int = 0, elstate: int | str = 0, corfunc: object = None) None[source]#

Sets mode environment

Sets the environment (bath correlation function) interacting with a a given mode in a given electronic state.

Parameters:
  • mode (int) – index of the mode

  • elstate (int) – index of the electronic state

  • corfunc (quantarhei.CorrelationFunction) – CorrelationFunction object

get_mode_environment(mode: int, elstate: int) object[source]#

Returns mode environment

Returns the environment (bath correlation function) interacting with a a given mode in a given electronic state.

Parameters:
  • mode (int) – index of the mode

  • elstate (int) – index of the electronic state

liouville_pathways_1(eUt: object = None, ham: object = None, dtol: float = 0.01, ptol: float = 0.001, etol: float = 1e-06, verbose: int = 0, lab: object = None) list[source]#

Generator of the first order Liouville pathways

Generator of the pathways for an absorption spectrum calculation.

Parameters:

eUt (EvolutionSuperOperator) – Evolution superoperator representing the evolution of optical coherence in the system

dtolfloat

Minimum acceptable strength of the transition from ground to excited state, relative to the maximum dipole strength available in the system

ptolfloat

Minimum acceptable population of the ground state (e.g. states not thermally populated are excluded)

labLaboratorySetup

Object representing laboratory setup - number of pulses, polarization etc.

Returns:

lst (list) – List of LiouvillePathway objects

quantarhei.builders.molecules.generate_1orderP_sec(self: Any, lst: list, pop_tol: float, dip_tol: float, verbose: int) None[source]#
quantarhei.builders.molecules.PiMolecule(Molecule: Any) None[source]#