parameters: (engine, guess: List, *, nroot: int, r_convergence: float = 1.0E-4, max_ss_size: int = 100, maxiter: int = 60, verbose: int = 1)
return_statement: return {"eigvals": best_eigvals, "eigvecs": list(zip(best_eigvecs, best_eigvecs)), "stats": stats}
docstring: Solves for the lowest few eigenvalues and eigenvectors of a large problem emulated through an engine.
  
  
      If the large matrix `A` has dimension `{NxN}` and N is very large, and only
      a small number of roots, `k` are desired this algorithm is preferable to
      standard methods as uses on the order of `N * k` memory. One only needs to
      have the ability to compute the product of a times a vector.
  
      For non-hermitan `A` the basis of the algorithm breaks down. However in
      practice, for strongly diagonally-dominant `A` such as the
      similarity-transformed Hamiltonian in EOM-CC this algorithm is commonly still
      used.
  
      Parameters
      -----------
      engine : object (subclass of :class:`SolverEngine`)
         The engine drive all operations involving data structures that have at
         least one "large" dimension. See :class:`SolverEngine` for requirements
      guess
         list {engine dependent}
         At least `nroot` initial expansion vectors
      nroot
          Number of roots desired
      r_convergence
          Convergence tolerance for residual vectors
      max_ss_size:
         The maximum number of trial vectors in the iterative subspace that will
         be stored before a collapse is done.
      maxiter
          The maximum number of iterations
      verbose
          The amount of logging info to print (0 -> none, 1 -> some, >1 -> everything)
  
      Returns
      -------
      best_values : numpy.ndarray (nroots, )
         The best approximation of the eigenvalues of A, computed on the last iteration of the solver
      best_vectors: list of `vector` (nroots)
         The best approximation of the eigenvectors of A, 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
  
      Notes
      -----
      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.
docstring_summary: Solves for the lowest few eigenvalues and eigenvectors of a large problem emulated through an engine.
docstring_tokens: Solves for the lowest few eigenvalues and eigenvectors of a large problem emulated through an engine .
function: def davidson_solver(engine, guess: List, *, nroot: int, r_convergence: float = 1.0E-4, max_ss_size: int = 100, maxiter: int = 60, verbose: int = 1):
      """Solves for the lowest few eigenvalues and eigenvectors of a large problem emulated through an engine.
  
  
      If the large matrix `A` has dimension `{NxN}` and N is very large, and only
      a small number of roots, `k` are desired this algorithm is preferable to
      standard methods as uses on the order of `N * k` memory. One only needs to
      have the ability to compute the product of a times a vector.
  
      For non-hermitan `A` the basis of the algorithm breaks down. However in
      practice, for strongly diagonally-dominant `A` such as the
      similarity-transformed Hamiltonian in EOM-CC this algorithm is commonly still
      used.
  
      Parameters
      -----------
      engine : object (subclass of :class:`SolverEngine`)
         The engine drive all operations involving data structures that have at
         least one "large" dimension. See :class:`SolverEngine` for requirements
      guess
         list {engine dependent}
         At least `nroot` initial expansion vectors
      nroot
          Number of roots desired
      r_convergence
          Convergence tolerance for residual vectors
      max_ss_size:
         The maximum number of trial vectors in the iterative subspace that will
         be stored before a collapse is done.
      maxiter
          The maximum number of iterations
      verbose
          The amount of logging info to print (0 -> none, 1 -> some, >1 -> everything)
  
      Returns
      -------
      best_values : numpy.ndarray (nroots, )
         The best approximation of the eigenvalues of A, computed on the last iteration of the solver
      best_vectors: list of `vector` (nroots)
         The best approximation of the eigenvectors of A, 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
  
      Notes
      -----
      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.
      """
      nk = nroot
  
      iter_info = {
          "count": 0,
          "res_norm": np.zeros((nk)),
          "val": np.zeros((nk)),
          "delta_val": np.zeros((nk)),
  
          # conv defaults to true, and will be flipped when a non-conv root is hit
          "done": True,
          "nvec": 0,
          "collapse": False,
          "product_count": 0,
      }
  
      print_name = "DavidsonSolver"
      title_lines = ["Generalized Davidson Solver", "By Ruhee Dcunha"]
  
      _diag_print_heading(title_lines, print_name, max_ss_size, nroot, r_convergence, maxiter, verbose)
  
      vecs = guess
      stats = []
      best_eigvecs = []
      best_eigvals = []
      while iter_info['count'] < maxiter:
  
          # increment iteration/ save old vals
          iter_info['count'] += 1
          old_vals = iter_info['val'].copy()
  
          # reset flags
          iter_info['collapse'] = False
          iter_info['done'] = True
  
          # get subspace dimension
          l = len(vecs)
          iter_info['nvec'] = l
  
          # check if ss dimension has exceeded limits
          if l >= max_ss_size:
              iter_info['collapse'] = True
  
          # compute A times trial vector products
          Ax, nprod = engine.compute_products(vecs)
          iter_info['product_count'] += nprod
  
          # Build Subspace matrix
          G = np.zeros((l, l))
          for i in range(l):
              for j in range(i):
                  G[i, j] = G[j, i] = engine.vector_dot(vecs[i], Ax[j])
              G[i, i] = engine.vector_dot(vecs[i], Ax[i])
  
          _print_array("SS transformed A", G, verbose)
  
          # diagonalize subspace matrix
          lam, alpha = np.linalg.eigh(G)
  
          _print_array("SS eigenvectors", alpha, verbose)
          _print_array("SS eigenvalues", lam, verbose)
  
          # remove zeros/negatives
          alpha = alpha[:, lam > 1.0e-10]
          lam = lam[lam > 1.0e-10]
  
          # sort/truncate to nroot
          idx = np.argsort(lam)
          lam = lam[idx]
          alpha = alpha[:, idx]
  
          # update best_solution
          best_eigvecs = _best_vectors(engine, alpha[:, :nk], vecs)
          best_eigvals = lam[:nk]
  
          # check convergence of each solution
          new_vecs = []
          for k in range(nk):
  
              # residual vector
              Rk = engine.new_vector()
              lam_k = lam[k]
              for i in range(l):
                  Axi = Ax[i]
                  Rk = engine.vector_axpy(alpha[i, k], Axi, Rk)
  
              Rk = engine.vector_axpy(-1.0 * lam_k, best_eigvecs[k], Rk)
  
              iter_info['val'][k] = lam_k
              iter_info['delta_val'][k] = abs(old_vals[k] - lam_k)
              iter_info['res_norm'][k] = np.sqrt((engine.vector_dot(Rk, Rk)))
  
              # augment guess vector for non-converged roots
              if (iter_info["res_norm"][k] > r_convergence):
                  iter_info['done'] = False
                  Qk = engine.precondition(Rk, lam_k)
                  new_vecs.append(Qk)
  
          # print iteration info to output
          _diag_print_info(print_name, iter_info, verbose)
  
          # save stats for this iteration
          stats.append(iter_info.copy())
  
          if iter_info['done']:
  
              # finished
              _diag_print_converged(print_name, stats, best_eigvals, verbose)
              break
          elif iter_info['collapse']:
  
              # restart needed
              vecs = best_eigvecs
          else:
  
              # Regular subspace update, orthonormalize preconditioned residuals and add to the trial set
              vecs = _gs_orth(engine, vecs, new_vecs)
  
      # always return, the caller should check ret["stats"][-1]['done'] == True for convergence
      return {"eigvals": best_eigvals, "eigvecs": list(zip(best_eigvecs, best_eigvecs)), "stats": stats}
function_tokens: def davidson_solver ( engine , guess : List , * , nroot : int , r_convergence : float = 1.0E-4 , max_ss_size : int = 100 , maxiter : int = 60 , verbose : int = 1 ) : nk = nroot iter_info = { "count" : 0 , "res_norm" : np . zeros ( ( nk ) ) , "val" : np . zeros ( ( nk ) ) , "delta_val" : np . zeros ( ( nk ) ) , # conv defaults to true, and will be flipped when a non-conv root is hit "done" : True , "nvec" : 0 , "collapse" : False , "product_count" : 0 , } print_name = "DavidsonSolver" title_lines = [ "Generalized Davidson Solver" , "By Ruhee Dcunha" ] _diag_print_heading ( title_lines , print_name , max_ss_size , nroot , r_convergence , maxiter , verbose ) vecs = guess stats = [ ] best_eigvecs = [ ] best_eigvals = [ ] while iter_info [ 'count' ] < maxiter : # increment iteration/ save old vals iter_info [ 'count' ] += 1 old_vals = iter_info [ 'val' ] . copy ( ) # reset flags iter_info [ 'collapse' ] = False iter_info [ 'done' ] = True # get subspace dimension l = len ( vecs ) iter_info [ 'nvec' ] = l # check if ss dimension has exceeded limits if l >= max_ss_size : iter_info [ 'collapse' ] = True # compute A times trial vector products Ax , nprod = engine . compute_products ( vecs ) iter_info [ 'product_count' ] += nprod # Build Subspace matrix G = np . zeros ( ( l , l ) ) for i in range ( l ) : for j in range ( i ) : G [ i , j ] = G [ j , i ] = engine . vector_dot ( vecs [ i ] , Ax [ j ] ) G [ i , i ] = engine . vector_dot ( vecs [ i ] , Ax [ i ] ) _print_array ( "SS transformed A" , G , verbose ) # diagonalize subspace matrix lam , alpha = np . linalg . eigh ( G ) _print_array ( "SS eigenvectors" , alpha , verbose ) _print_array ( "SS eigenvalues" , lam , verbose ) # remove zeros/negatives alpha = alpha [ : , lam > 1.0e-10 ] lam = lam [ lam > 1.0e-10 ] # sort/truncate to nroot idx = np . argsort ( lam ) lam = lam [ idx ] alpha = alpha [ : , idx ] # update best_solution best_eigvecs = _best_vectors ( engine , alpha [ : , : nk ] , vecs ) best_eigvals = lam [ : nk ] # check convergence of each solution new_vecs = [ ] for k in range ( nk ) : # residual vector Rk = engine . new_vector ( ) lam_k = lam [ k ] for i in range ( l ) : Axi = Ax [ i ] Rk = engine . vector_axpy ( alpha [ i , k ] , Axi , Rk ) Rk = engine . vector_axpy ( - 1.0 * lam_k , best_eigvecs [ k ] , Rk ) iter_info [ 'val' ] [ k ] = lam_k iter_info [ 'delta_val' ] [ k ] = abs ( old_vals [ k ] - lam_k ) iter_info [ 'res_norm' ] [ k ] = np . sqrt ( ( engine . vector_dot ( Rk , Rk ) ) ) # augment guess vector for non-converged roots if ( iter_info [ "res_norm" ] [ k ] > r_convergence ) : iter_info [ 'done' ] = False Qk = engine . precondition ( Rk , lam_k ) new_vecs . append ( Qk ) # print iteration info to output _diag_print_info ( print_name , iter_info , verbose ) # save stats for this iteration stats . append ( iter_info . copy ( ) ) if iter_info [ 'done' ] : # finished _diag_print_converged ( print_name , stats , best_eigvals , verbose ) break elif iter_info [ 'collapse' ] : # restart needed vecs = best_eigvecs else : # Regular subspace update, orthonormalize preconditioned residuals and add to the trial set vecs = _gs_orth ( engine , vecs , new_vecs ) # always return, the caller should check ret["stats"][-1]['done'] == True for convergence return { "eigvals" : best_eigvals , "eigvecs" : list ( zip ( best_eigvecs , best_eigvecs ) ) , "stats" : stats }