EigenvalueTrajectory
This section briefly describes how to use the EigenvalueTrajectory object to analyze eigenvalue trajectories.
Initialization
EigenvalueTrajectory
objects are generated by the track_state()
function of the CAPHamiltonian
class. The state index i starts from 0, and the
first state in the trajectory is the ith eigen pair generated by the first diagonalization at \(\eta=0\).
State Tracking
At each diagonalization of the CAP Hamiltonian, left and right \(\eta\)-dependent eigenpairs
are computed and bi-orthogonalized. States are tracked using using one of two criterion: overlap and energy, which
is controlled by the tracking keyword argument of track_state()
.
When overlap tracking is used (the default), at each step, the state with maximum overlap with the previous state is chosen as the next point on the trajectory. The overlap is simply calculated as the absolute value of the dot product between the right eigenvectors.
When energy tracking is used, at each step, the state with the minimum difference in energy from the previous state is chosen. Since the energies are complex, the difference is computed as the modulus of the difference of the two complex energies.
Each state in the trajectory is stored as a Root
object stored in the
states attribute. Lists of uncorrected energies and \(\eta\) values (in order of
smallest to largest \(\eta\) value) are also stored in the uncorrected_energies
and etas class attributes for convenience.
Corrected Trajectories
Raw uncorrected energies obtained from diagonalizaiton of the CAP Hamiltonian can be sensitive to CAP onset and basis set quality. Practitioners of CAP theory often report so called corrected energies, the exact form of which may vary from publication to publication.
We implement two forms of 1st-order corrections: density and derivative, which is controlled by the correction
keyword argument of track_state()
.
The default is the first-order correction of [Cederbaum2002], which has the form:
\(U(\eta)=E(\eta)-\eta\frac{\partial E(\eta) }{\partial \eta}\).
One can also use the density matrix correction of [Jagau2014] :
\(U(\eta)=E(\eta)+ i \eta Tr [\gamma(\eta) W]\),
where the trace expression is evaluated using the matrix elements of the CAP in the correlated basis:
\(Tr [\gamma(\eta) W] = \sum_{kl} c^L_k(\eta)c^R_l(\eta)W_{kl}^{CB}\),
and \(c^L\) and \(c^R\) xrefer to the components of the bi-orthogonalized left and right eigenvectors respectively. Note that this option should only
be used when biorthogonalize=True is passed to run_trajectory()
.
The two approaches can be related to one another by the Hellman-Feynman theoreom, and in our experience yield nearly identical results.
Corrected trajectories are automatically computed when one obtains an EigenvalueTrajectory
object generated by the track_state()
function, and
are stored in the class attribute corrected_energies.
# the various options for state tracking and corrections
traj = CAPH.track_state(1,tracking="energy",correction="density")
traj = CAPH.track_state(1,tracking="overlap",correction="derivative")
\(\eta_{opt}\)
As briefly outlined in the theory, the key to any CAP calculation is to
find the optimal value of the CAP strength parameter \(\eta_{opt}\). The EigenvalueTrajectory
class has a function find_eta_opt
for
exactly that purpose. For uncorrected trajectories, \(\eta_{opt}\) is calculated as
\(min |\eta\frac{dE}{d\eta}|\)
For corrected trajectories, \(\eta_{opt}\) is calculated as
\(min |\eta\frac{dU}{d\eta}|\)
The derivative is calculated numerically by means of finite differences.
uc_energy,uc_eta_opt = traj.find_eta_opt()
corr_energy,corr_eta_opt = traj.find_eta_opt(corrected=True)
The presence of nonphysical stationary points can sometimes result in this function returning smaller values of \(\eta_{opt}\) than desired. One can specify the start_idx keyword argument to begin the search starting from a specified index along the trajectory.
uc_energy,uc_eta_opt = traj.find_eta_opt(start_idx=20)
Visualization
It can often be helpful to visualize trajectories graphically. In addition to access to the class attributes uncorrected_energies and corrected_energies, we also provide some helper functions which process the data in useful ways for visualization.
For instance, energies_ev()
returns
the excitation energies in eV with respect to specified reference energy.
import matplotlib.pyplot as plt
UC_ev = traj.energies_ev(ref_energy)
Corr_ev = traj.energies_ev(ref_energy,corrected=True)
plt.plot(np.real(UC_ev),np.imag(UC_ev),'ro', label='Uncorrected')
plt.plot(np.real(Corr_ev),np.imag(Corr_ev),'ro', label='Corrected')
plt.show()
get_logarithmic_velocities()
returns the value of
\(\eta\frac{\partial E(\eta) }{\partial \eta}\) (or
\(|\eta\frac{dU}{d\eta}|\rightarrow min\) if the corrected keyword argument is set to True)
for each point along the trajectory.
derivs = traj.get_logarithmic_velocities()
plt.plot(traj.etas,derivs)
plt.show()
References
- Cederbaum2002
Santra, R.; Cederbaum, L. S. Non-Hermitian Electronic Theory and Applications to Clusters. Phys. Rep. 2002, 368 (1), 1–117.
- Jagau2014
Jagau TC, Zuev D, Bravaya KB, Epifanovsky E, Krylov AI. A Fresh Look at Resonances and Complex Absorbing Potentials: Density Matrix-Based Approach. J Phys Chem Lett. 2014 5, 2, 310–315
- class pyopencap.analysis.EigenvalueTrajectory(state_idx, init_roots, W, tracking='overlap', correction='derivative', biorthogonalized=False)[source]
Eigenvalue trajectory generated by repeated diagonalizations of CAP Hamiltonian over range of eta values.
States are tracked using either eigenvector overlap or energy criterion. Corrected energies are obtained using density matrix or first order correction.
- uncorrected_energies
List of uncorrected energies in trajectory.
- Type
list of float
- corrected_energies
List of corrected energies in trajectory.
- Type
list of float
- W
CAP matrix in state basis. -1 prefactor is assumed.
- Type
np.ndarray of float: default=None
- etas
List of CAP strengths in trajectory.
- Type
list of float
- tracking
Method to use to track the state
- Type
str, default=”overlap”
- correction
Choice of correction scheme. Either “density” or “derivative”. Density matrix correction should only be used when the eigenvectors have been biorthogonalized. See
run_trajectory()
.- Type
str, default=”derivative”
- __init__(state_idx, init_roots, W, tracking='overlap', correction='derivative', biorthogonalized=False)[source]
Initializes EigenvalueTrajectory object, which tracks a state starting from the first diagonalization at eta = 0.
- Parameters
state_idx (int) – Index of state to track
init_roots (list of
Root
) – Initial set of roots generated by diagonalization at eta = 0W (np.ndarray of float: default=None) – CAP matrix in state basis. -1 prefactor is assumed.
tracking (str, default="overlap") – Method to use to track the state
correction (str, default="derivative") – Choice of correction scheme. Either “density” or “derivative”.
biorthogonalized (bool default=False) – Whether eigenvectors have been biorthogonalized
- energies_ev(ref_energy, corrected=False)[source]
Returns excitation energies of all states in trajectory in eV with respect to specified reference energy.
- Parameters
ref_energy (float) – Reference energy
corrected (bool, default=False) – Set to true if analyzing corrected trajectory
- Returns
E_eV – Excitation energies in eV with respect to specified reference energy.
- Return type
list of floats
- find_eta_opt(corrected=False, start_idx=1, end_idx=-1, ref_energy=0.0, units='au', return_root=False)[source]
Finds optimal cap strength parameter for eigenvalue trajectory, as defined by eta_opt = min|eta*dE/deta|.
The range of self.etas[start_idx:end_idx] (in python slice notation) is searched for the optimal value of CAP strength parameter.
- Parameters
corrected (bool, default=False) – Set to true if searching for stationary point on corrected trajectory
start_idx (int, default=1) – Starting slice index
end_idx (int, default=1) – Ending slice index
ref_energy (float, default=0.0) – Reference energy to define excitation energy.
units (str, default="au") – Options are “au” or “eV”
return_root (bool, default=False) – Whether to return
Root
object associated with optimal value of eta
- Returns
E_res (complex float) – Complex energy at optimal value of eta
eta_opt (float) – Optimal value of eta
root (
Root
) – Only returned when return_root is set to true
- get_energy(eta, corrected=False, ref_energy=0.0, units='au', return_root=False)[source]
Returns total energy at given value of eta.
Note that if the eta provided is not in self.etas, the nearest value will be used.
- Parameters
eta (float) – Value of CAP strength parameter
corrected (bool, default=False) – Set to true if analyzing corrected trajectory
ref_energy (float, default=0.0) – Reference energy to define excitation energy.
units (str, default="au") – Options are “au” or “eV”
return_root (bool, default=False) – Whether to return
Root
object associated with optimal value of eta
- Returns
E (float) – Energy at given value of eta
root (
Root
) – Only returned when return_root is set to true
- get_logarithmic_velocities(corrected=False)[source]
Returns eta*dE/deta for each point on eigenvalue trajectory.
Useful for plotting when dealing with multiple potential stationary points.
- Parameters
corrected (bool, default=False) – Set to true if analyzing corrected trajectory
- Returns
derivs – eta*dE/deta for each point on eigenvalue trajectory
- Return type
np.array of float