Source code for quantarhei.builders.modes

# -*- coding: utf-8 -*-
"""
    Class representing intramolecular vibrations.
       
    The Mode class is a user class through which the user defines an intra
    molecular mode.
        
    The vibrational mode is supposed to be an intramolecular mode of some
    molecule. This class is therefore aware of its Molecule class. Once it
    knows in which Molecule object it lives, it creates instances of the class
    Submode (as many as there are electronic states in the Molecule). Submods 
    hold the parameters of the mode respective to a give electronic state
    of the monomer
    
    These parameters have to be set after the mode is registered in
    the Molecule, and therefore there is an issue of consistency of the class. 
    Currently, the consistency is completely in the hands of the user.
    
    Class Details
    -------------
    
    
"""

import numpy

from ..utils import Integer
from ..utils import Bool

from ..core.managers import UnitsManaged, energy_units
from ..core.wrappers import deprecated

from ..core.saveable import Saveable

from .submodes import SubMode
        
        
# Mode is UnitsManaged with components of different dimensions
# Mode is not BasisManaged
[docs]class Mode(UnitsManaged, Saveable): """ Vibrational mode Parameters ---------- omega : float vibrational frequency Examples -------- >>> import quantarhei as qr >>> mol = qr.Molecule([0.0, 1.0]) >>> md = Mode(frequency=0.2) >>> mol.add_Mode(md) >>> print(md.get_energy(1)) 0.2 This class is units management aware >>> import quantarhei as qr >>> with qr.energy_units("1/cm"): ... md = Mode(250.0) >>> mol.add_Mode(md) >>> print(md.get_energy(0)) 0.047091289182721326 >>> mol.get_number_of_modes() 2 """ # number of electronic states (same as the monomer) nel = Integer('nel') # is the monomer for this mode set? monomer_set = Bool('monomer_set') def __init__(self, frequency=1.0): # this holds a list of submods self.submodes = [] # ground state submode is created (with shift = 0 # and a default no. of states) freq = self.convert_energy_2_internal_u(frequency) with energy_units("int"): self.submodes.append(SubMode(freq)) # monomer is not set at creation self.monomer_set = False # no electronic states set or asigned self.nel = 0 self.has_mode_environment = False
[docs] def set_Molecule(self, monomer): """Assigns this mode to a given monomer. When set, the mode knows on how many electronic states it is supposed to live. This method is called by the Molecule's `add_Mode` method. Parameters ---------- monomer : quantarhei.Molecule Molecule object to which this Mode will be assigned Examples -------- `set_Molecule` should not be called directly, except of some (hard to imagine) special cases. The `add_Mode` method of the Molecule class does some extra work to keep consistent record of the Modes in the Molecule. Here, the difference between `set_Molecule` and `add_Mode` method of the Molecule class is demonstrated. >>> import quantarhei as qr >>> mol1 = qr.Molecule([0.0, 2.0]) >>> mol2 = qr.Molecule([0.0, 2.0]) >>> mod1 = qr.Mode(0.2) >>> mod2 = qr.Mode(0.2) >>> mol1.add_Mode(mod1) >>> mod2.set_Molecule(mol2) The number of modes recorded is consistent >>> print(mol1.get_number_of_modes()) 1 >>> print(len(mod1.submodes)) 2 The number of modes in this case is not consistent. The Mode knows that it has SubModes, but Molecule has no mode recorded. >>> print(mol2.get_number_of_modes()) 0 >>> print(len(mod2.submodes)) 2 """ self.nel = monomer.nel self.monomer = monomer # Must have as many submodes as electronic states in the monomer with energy_units("int"): for k in range(1, self.nel): # submodes are created with the same frequency as # in the groundstate and with zero shift self.submodes.append(SubMode(self.submodes[0].omega)) self.monomer_set = True
# # Setters #
[docs] @deprecated def set_frequency(self, N, omega): """Sets vibrational frequency Usage of this method is deprecated, use `set_energy` instead Parameters ---------- N : int Index of the electronic state omega : float Vibrational frequency Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) This function is deprecated and it throws a warning text when it is run >>> mod.set_frequency(1, 1.3) # doctest: +ELLIPSIS function <function Mode.set_frequency at ...> is deprecated >>> mod.get_energy(1) 1.3 """ #sbm = self.submodes[N] #sbm.omega = omega self.set_energy(N, omega)
[docs] def set_energy(self, N, omega): """Sets energy/frequency of the mode relative to a molecular state Parameters ---------- N : int Index of the electronic state for we set frequency omega : float Energy of the vibrational quantum / frequency of the oscillator Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.set_energy(1, 1.3) >>> mod.get_energy(1) 1.3 >>> with qr.energy_units("1/cm"): ... mod.set_energy(1, 1300.0) >>> mod.get_energy(1) 0.2448747037501509 """ sbm = self.submodes[N] sbm.omega = self.convert_energy_2_internal_u(omega)
[docs] def set_shift(self, N, shift): """Sets the potential energy surface shift with respect to ground state The shift is dimensionless. frequency*(shift^2)/2 is the reorganization energy. Parameters ---------- N : int Index of the electronic state for we set frequency shift : float Shift of the PES with respect to ground state Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.set_shift(1, 0.1) >>> mod.get_shift(1) 0.1 """ sbm = self.submodes[N] sbm.shift = shift
[docs] def set_nmax(self, N, nmax): """Sets maximum quantum number of the mode in an electronic state N Parameters ---------- N : int Index of the electronic state nmax : int Maximum quantum number to be set Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) Hamiltonian of a two-level molecule with one vibrational mode, for which we take 5 levels in each electronic state, has 10 levels >>> mod.set_nmax(0, 5) >>> mod.set_nmax(1, 5) >>> H = mol.get_Hamiltonian() >>> print(H.dim) 10 """ sbm = self.submodes[N] sbm.nmax = nmax
[docs] def set_HR(self, N, hr): """Sets Huang-Rhys factor of the PES on the Nth electronic state Parameters ---------- N : int Index of the state for which we set. Setting for N=0 gives exception hr : float Huang-Rhys factor. Dimensionless quantity (ratio of reorganization energy and vibrational quantum) Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.set_HR(1, 1.0) HR is the shift square devide by 2 >>> freq = mod.get_energy(1) >>> sft = mod.get_shift(1) >>> hr = (sft**2)/2.0 >>> print("{0:.2f}".format(hr)) 1.00 """ #if N==0: # raise Exception("Makes no sense to set HR in the ground state") sh = numpy.sqrt(2.0*hr) self.set_shift(N, sh)
# # Getters #
[docs] @deprecated def get_frequency(self, N): """Returns vibrational frequency Usage of this method is deprecated, use `get_energy` instead Parameters ---------- N : int Index of the electronic state Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.set_energy(1, 1.3) This function is deprecated and it throws a warning text when it is run >>> mod.get_frequency(1) # doctest: +ELLIPSIS function <function Mode.get_frequency at ...> is deprecated 1.3 """ return self.get_energy(N)
[docs] def get_energy(self, N, no_conversion=True): """Returns frequency of the mode corresponding to Nth electronic state Parameters ---------- N : int Index of the electronic state no_conversion : bool If set to True, the function does not react to units management Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.get_energy(1) 1.0 >>> with qr.energy_units("1/cm"): ... mod.get_energy(1) # default is `no_conversion=True` 1.0 >>> with qr.energy_units("1/cm"): ... mod.get_energy(1, no_conversion=False) # default is `no_conversion=True` 5308.837458876145 """ if no_conversion: return self.submodes[N].omega else: return self.convert_energy_2_current_u(self.submodes[N].omega)
[docs] def get_shift(self, N): """Returns the shift of the PES of the mode at Nth electronic state Parameters ---------- N : int Index of the electronic state Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.get_shift(0) 0.0 >>> mod.get_shift(1) 0.0 >>> mod.set_shift(1, 1.0) >>> mod.get_shift(1) 1.0 """ return self.submodes[N].shift
[docs] def get_nmax(self, N): """Returns maximum quantum number of the mode at electronic state N Parameters ---------- N : int Index of the electronic state Examples -------- Default value of `nmax` is 2 >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.get_nmax(0) 2 >>> mod.get_nmax(1) 2 """ return self.submodes[N].nmax
[docs] def get_HR(self, N): """Returns Huang-Rhys factor of vib. mode in Nth electronic state Parameters ---------- N : int Index of the electronic state Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.get_HR(0) 0.0 >>> mod.set_HR(1, 1.0) >>> print("{0:.2f}".format(mod.get_HR(1))) 1.00 >>> mod.get_HR(0) 0.0 """ return (self.submodes[N].shift**2)/2.0
[docs] def set_all(self, N, param): """Sets all the parameters of an intramolecular mode at once Parameters ---------- N : int Index of the electronic states for which we set the mode parameters param : list like List of the mode parameters in the following order corresponding to the properties of the SubMode class, i.e. `omega`, `shift`, `nmax`. The parameters `omega` is units managed. Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> mod.set_all(1, [1.2, 0.8, 3]) >>> print("{0:1.2f}".format(mod.get_HR(1))) 0.32 >>> mod.get_shift(1) 0.8 >>> mod.get_energy(1) 1.2 >>> mod.get_nmax(1) 3 Energy is units management sensitive >>> with qr.energy_units("1/cm"): ... mod.set_all(1, [1200, 0.8, 3]) >>> mod.get_energy(1) 0.22603818807706239 """ sbm = self.submodes[N] sbm.omega = self.convert_energy_2_internal_u(param[0]) sbm.shift = param[1] sbm.nmax = param[2]
[docs] def get_SubMode(self, N): """Returns the SubMode class of a give electronic state of the molecule Parameters ---------- N : int Index of the electronic state Examples -------- >>> import quantarhei as qr >>> mol = qr.TestMolecule("two-levels-1-mode") >>> mod = mol.get_Mode(0) >>> sm = mod.get_SubMode(1) >>> print(sm.omega, sm.shift, sm.nmax) 1.0 0.0 2 """ return self.submodes[N]
[docs] def set_mode_environment(self, corfce): """Set linear interaction with a bosonic environment """ self.egcf = corfce self.has_mode_environment = True
[docs] def get_mode_environment(self): """Returns interaction of this mode with a bosonic bath """ if not self.has_mode_environment: return None return self.egcf