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.

roots

List of states in trajectory.

Type

list of Root

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 = 0

  • W (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