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,OpenSystemMulti-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
- 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
- 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:
recommended
get_dipole((0,1),[1.0, 0.0, 0.0])
here N represents a transition by a tuple, M is the dipole
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.])
- 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:
recommended
set_dipole((0,1),[1.0, 0.0, 0.0])
here N represents a transition by a tuple, M is the dipole
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_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
- 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_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