psi4.driver.p4util.hamiltonian_solver(engine, guess, *, nroot, r_convergence=0.0001, max_ss_size=100, maxiter=60, verbose=1)[source]

Finds the smallest eigenvalues and associated right and left hand eigenvectors of a large real Hamiltonian eigenvalue problem emulated through an engine.

A Hamiltonian eigenvalue problem (EVP) has the following structure:

[A  B][X]  = [1   0](w)[X]
[B  A][Y]    [0  -1](w)[Y]

with A, B of some large dimension N, the problem is of dimension 2Nx2N.

The real, Hamiltonian EVP can be rewritten as the NxN, non-hermitian EVP: \((A+B)(A-B)(X+Y) = w^2(X+Y)\)

With left-hand eigenvectors: \((X-Y)(A-B)(A+B) = w^2(X-Y)\)

if \((A-B)\) is positive definite, we can transform the problem to arrive at the hermitian NxN EVP: \((A-B)^{1/2}(A+B)(A-B)^{1/2} = w^2 T\)

Where \(T = (A-B)^{-1/2}(X+Y)\).

We use a Davidson like iteration where we transform \((A+B)\) (H1) and \((A-B)\) (H2) in to the subspace defined by the trial vectors. The subspace analog of the NxN hermitian EVP is diagonalized and left \((X-Y)\) and right \((X+Y)\) eigenvectors of the NxN non-hermitian EVP are approximated. Residual vectors are formed for both and the guess space is augmented with two correction vectors per iteration. The advantages and properties of this algorithm are described in the literature [stratmann:1998] .

  • engine (Type[SolverEngine]) – The engine drive all operations involving data structures that have at least one “large” dimension. See SolverEngine for requirements

  • guess (List) – list {engine dependent} At least nroot initial expansion vectors

  • nroot (int) – Number of roots desired

  • r_convergence (float) – Convergence tolerance for residual vectors

  • max_ss_size (int) – The maximum number of trial vectors in the iterative subspace that will be stored before a collapse is done.

  • maxiter (int) – The maximum number of iterations

  • verbose (int) – The amount of logging info to print (0 -> none, 1 -> some, >1 -> everything)


  • best_values (numpy.ndarray) – (nroots, ) The best approximation of the eigenvalues of w, computed on the last iteration of the solver

  • best_R (List[vector]) – (nroots) The best approximation of the right hand eigenvectors, \(X+Y\), computed on the last iteration of the solver.

  • best_L (List[vector]) – (nroots) The best approximation of the left hand eigenvectors, \(X-Y\), computed on the last iteration of the solver.

  • stats (List[Dict]) – Statistics collected on each iteration

    • count : int, iteration number

    • res_norm : np.ndarray (nroots, ), the norm of residual vector for each roots

    • val : np.ndarray (nroots, ), the eigenvalue corresponding to each root

    • delta_val : np.ndarray (nroots, ), the change in eigenvalue from the last iteration to this ones

    • collapse : bool, if a subspace collapse was performed

    • product_count : int, the running total of product evaluations that was performed

    • done : bool, if all roots were converged


The solution vector is normalized to 1/2

The solver will return even when maxiter iterations are performed without convergence. The caller must check stats[-1]['done'] for failure and handle each case accordingly.


R. Eric Stratmann, G. E. Scuseria, and M. J. Frisch, “An efficient implementation of time-dependent density-functional theory for the calculation of excitation energies of large molecules.” J. Chem. Phys., 109, 8218 (1998)