#*********************************************************************************
#* Copyright (C) 2019 Xiang Sun, Alexey V. Akimov
#* Copyright (C) 2018 Alexey V. Akimov
#*
#* This file is distributed under the terms of the GNU General Public License
#* as published by the Free Software Foundation, either version 2 of
#* the License, or (at your option) any later version.
#* See the file LICENSE in the root directory of this distribution
#* or <http://www.gnu.org/licenses/>.
#*
#*********************************************************************************/
"""
.. module:: fgr_py
:platform: Unix, Windows
:synopsis:
This module implements the auxiliary Python functions for dealing with
various kinds of FGR calculations (as implemented in C++)
.. moduleauthor:: Alexey V. Akimov
"""
import sys
import cmath
import math
import os
if sys.platform=="cygwin":
from cyglibra_core import *
elif sys.platform=="linux" or sys.platform=="linux2":
from liblibra_core import *
#import common_utils as comn
import util.libutil as comn
from . import units
[docs]def run_NEFGRL_populations(omega_DA, V, omega_nm, gamma_nm, req_nm, shift_NE, params):
"""
Noneq FGR in non-Condon/Condon case (linear coupling) using normal modes
k(t') = 2/(hbar^2) * Re { int_0^t' { dtau * C(tau) } }
Compute the non-equilibrium FGR populations as a function of time
Args:
omega_DA ( double ): energy gap between donor and acceptor states E(donor) - E(acceptor) [units: a.u.]
V ( double ): electronic coupling between the two states [units: a.u.]
omega_nm ( list of doubles ): frequencies of the bath normal modes [units: a.u.]
gamma_nm ( list of doubles ): couplings of the bath modes to the quantum system/primary mode [units: a.u.]
req_nm ( list of doubles ): displacements of the normal modes from their equilibrium positions upon the
charge transfer
shift_NE ( list of doubles ): non-equilibrium displacements of the normal modes
params ( dictionary ): parameters controlling the execution of the calculations
* **params["tmax"]** ( double ): time since the initial photoexcitation [units: a.u. of time; default: 10 fs]
* **params["dt"]** ( double ): integration timestep for the forward propagation [units: a.u. of time, ]
* **params["dtau"]** ( double ): integration timestep for backward propagation,
used to take the integral above (tau = dtau*n < t, where n is integer) [units: a.u.]
* **params["method"]** ( int ): flag that specifies which method to use:
- 0: Exact quantum result [ default ]
- 1: LSC
- 2: CAV
- 3: CD
- 4: W0
- 5: C0
* **params["dyn_type"]** ( int ): flag that selects:
- 0: Condon [ default ]
- 1: non-Condon
* **params["Temperature"]** ( double ): temperature of the bath [ units: K, default: 300.0 ]
* **params["do_output"]** ( Boolean ): whether to print out the results in a file [ default: False ]
* **params["filename"]** ( string ): the name of the file where the results would be
printed out if ```do_output``` is set to True [ default: "FGR.txt" ]
Returns:
tuple: (time, rate, pop), where:
* time ( list of doubles ): time axis [ units: a.u. ]
* rate ( list of doubles ): time-dependent rate constants [ units: a.u.^-1 ]
* pop ( list of doubles ): time-dependent population of the donor state
"""
critical_params = [ ]
default_params = { "method":0, "dyn_type":0,
"Temperature":300.0,
"dtau":0.02 * units.fs2au, "tmax":10.0 * units.fs2au, "dt":0.1 * units.fs2au,
"do_output":False, "filename":"FGR.txt"
}
comn.check_input(params, default_params, critical_params)
method = params["method"]
dyn_type = params["dyn_type"]
T = params["Temperature"]
tmax = params["tmax"]
dt = params["dt"]
dtau = params["dtau"]
do_output = params["do_output"]
filename = params["filename"]
beta = 1.0 / (units.kB * T)
nsteps = int(tmax/dt)+1
summ, P, k = 0.0, 1.0, 0.0 # probability of donor state
time, pop, rate = [], [], []
if do_output:
f = open(filename, "w"); f.close()
for step in range(0,nsteps):
t = step*dt
# k = k(t')
k = NEFGRL_rate(t, omega_DA, V, omega_nm, gamma_nm, req_nm, shift_NE, method, beta, dyn_type, dtau)
summ += k * dt;
P = math.exp(-summ) # exp(- int dt' k(t'))
if do_output:
f = open(filename, "a")
f.write("%8.5f %8.5f %8.5f \n" % (t, k, P))
f.close()
time.append(t)
rate.append(k)
pop.append(P)
return time, rate, pop
[docs]def run_NEFRG_acf(t, omega_DA, V, omega_nm, gamma_nm, req_nm, shift_NE, params):
"""
Noneq FGR in non-Condon/Condon case (linear coupling) using normal modes
Compute the non-equilibrium FGR populations as a function of time
Args:
t ( double ): compute the properties (e.g. rates) for the time t [units: a.u.]
SeeAlso: ```run_NEFGRL_populations``` - the present function takes the same arguments
Returns:
tuple: (_tau, _argg_re, _argg_im, _lin_re, _lin_im, _C_re, _C_im, _int_re, _int_im), where:
* _tau ( list of doubles ): time axis [ units: a.u. ]
* _argg_re ( list of doubles ): real part of the sum over frequencies - sitting in the exponent, at given tau
* _argg_im ( list of doubles ): imaginary part of the sum over frequencies - sitting in the exponent, at given tau
* _lin_re ( list of doubles ): real part of the linear term - in front of the exponent, at given tau
* _lin_im ( list of doubles ): imaginary part of the linear term - in front of the exponent, at given tau
* _C_re ( list of doubles ): real part of the time-correlation function, at given tau
* _C_im ( list of doubles ): real part of the time-correlation function, at given tau
* _int_re ( list of double ): integral of _C_re to this time point, int_0_t { C(t,tau) dtau } for a fixed t
* _int_re ( list of double ): integral of _C_re to this time point, int_0_t { C(t,tau) dtau } for a fixed t
"""
critical_params = [ ]
default_params = { "method":0, "dyn_type":0,
"Temperature":300.0,
"dtau":0.02 * units.fs2au,
"do_output":False, "filename":"FGR.txt"
}
comn.check_input(params, default_params, critical_params)
method = params["method"]
dyn_type = params["dyn_type"]
T = params["Temperature"]
dtau = params["dtau"]
do_output = params["do_output"]
filename = params["filename"]
beta = 1.0 / (units.kB * T)
nsteps = int(t/dtau)
# nsteps = int(tmax/dt)+1
nomega = len(omega_nm)
_tau = []
_argg_re, _argg_im = [], []
_lin_re, _lin_im = [], []
_C_re, _C_im = [], []
_int_re, _int_im = [], []
if do_output==True:
f = open(filename, "w"); f.close()
integ = 0.0+0.0j
for step in range(0,nsteps):
tau = step*dtau
argg, lin = 0.0+0.0j, 0.0+0.0j
for w in range(nomega):
if method==0:
argg = argg + Integrand_NE_exact(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_exact(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
elif method==1:
argg = argg + Integrand_NE_LSC(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_LSC(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
elif method==2:
argg = argg + Integrand_NE_CAV(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_CAV(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
elif method==3:
argg = argg + Integrand_NE_CD(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_CD(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
elif method==4:
argg = argg + Integrand_NE_W0(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_W0(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
elif method==5:
argg = argg + Integrand_NE_C0(t, tau, omega_DA, omega_nm[w], req_nm[w], shift_NE[w], beta)
lin = lin + Linear_NE_C0(t, tau, gamma_nm[w], omega_nm[w], req_nm[w], shift_NE[w], beta)
C = 0.0+0.0j
if dyn_type==0:
C = cmath.exp(argg) * V * V
elif dyn_type==1:
C = cmath.exp(argg) * lin
integ = integ + C*dtau
if do_output==True:
f = open(filename, "a")
f.write("%8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f\n"
% (tau, argg.real, argg.imag, lin.real, lin.imag, C.real, C.imag, integ.real, integ.imag))
f.close()
_tau.append(tau)
_argg_re.append(argg.real)
_argg_im.append(argg.imag)
_lin_re.append(lin.real)
_lin_im.append(lin.imag)
_C_re.append(C.real)
_C_im.append(C.imag)
_int_re.append(integ.real)
_int_im.append(integ.imag)
return _tau, _argg_re, _argg_im, _lin_re, _lin_im, _C_re, _C_im, _int_re, _int_im