def SCF_Hx(x, moFa, moFb, C): """ Compute a hessian vector guess where x is a ov matrix of nonredundant operators. """ Co_a = C[:, :nocc] Co_b = C[:, :ndocc] C_right_a = np.dot(C[:, nocc:], x[:, nsocc:].T) C_right_b = np.dot(C[:, ndocc:], x[:ndocc, :].T) J, K = scf_helper.compute_jk(jk, [Co_a, Co_b], [C_right_a, C_right_b]) J1, J2 = J K1, K2 = K IAJB = (C[:, :nocc].T).dot(J1 - 0.5 * K1 - 0.5 * K1.T).dot(C[:, ndocc:]) IAJB += 0.5 * np.dot(x[:, nsocc:], moFa[nocc:, ndocc:]) IAJB -= 0.5 * np.dot(moFa[:nocc, :nocc], x) IAJB[:, :nsocc] = 0.0 iajb = (C[:, :nocc].T).dot(J2 - 0.5 * K2 - 0.5 * K2.T).dot(C[:, ndocc:]) iajb += 0.5 * np.dot(x, moFb[ndocc:, ndocc:]) iajb -= 0.5 * np.dot(moFb[:nocc, :ndocc], x[:ndocc, :]) iajb[ndocc:, :] = 0.0 IAjb = (C[:, :nocc].T).dot(J2).dot(C[:, ndocc:]) IAjb[ndocc:] += 0.5 * np.dot(x[:, :nsocc].T, moFb[:nocc, ndocc:]) IAjb[:, :nsocc] = 0.0 iaJB = (C[:, :nocc].T).dot(J1).dot(C[:, ndocc:]) iaJB[:, :nsocc] += 0.5 * np.dot(moFb[:nocc, nocc:], x[ndocc:, nsocc:].T) iaJB[ndocc:] = 0.0 ret = 4 * (IAJB + IAjb + iaJB + iajb) return ret
def SCF_Hx(xa, xb, moFa, Co_a, Cv_a, moFb, Co_b, Cv_b): """ Compute the "matrix-vector" product between electronic Hessian (rank-4) and matrix of nonredundant orbital rotations (rank-2). Parameters ---------- x : numpy.array Matrix of nonredundant rotations. moF : numpy.array MO-basis Fock matrix Co : numpy.array Matrix of occupied orbital coefficients. Cv : numpy.array Matrix of virtual orbital coefficients. Returns ------- F : numpy.array Hessian product tensor """ Hx_a = np.dot(moFa[:nalpha, :nalpha], xa) Hx_a -= np.dot(xa, moFa[nalpha:, nalpha:]) Hx_b = np.dot(moFb[:nbeta, :nbeta], xb) Hx_b -= np.dot(xb, moFb[nbeta:, nbeta:]) # Build two electron part, M = -4 (4 G_{mnip} - g_{mpin} - g_{npim}) K_{ip} # From [Helgaker:2000] Eqn. 10.8.65 C_right_a = np.einsum('ia,sa->si', -xa, Cv_a) C_right_b = np.einsum('ia,sa->si', -xb, Cv_b) J, K = scf_helper.compute_jk(jk, [Co_a, Co_b], [C_right_a, C_right_b]) Jab = J[0] + J[1] Hx_a += (Co_a.T).dot(2 * Jab - K[0].T - K[0]).dot(Cv_a) Hx_b += (Co_b.T).dot(2 * Jab - K[1].T - K[1]).dot(Cv_b) Hx_a *= -4 Hx_b *= -4 return (Hx_a, Hx_b)
def SCF_Hx(xa, xb, moFa, Co_a, Cv_a, moFb, Co_b, Cv_b): """ Compute the "matrix-vector" product between electronic Hessian (rank-4) and matrix of nonredundant orbital rotations (rank-2). Parameters ---------- x : numpy.array Matrix of nonredundant rotations. moF : numpy.array MO-basis Fock matrix Co : numpy.array Matrix of occupied orbital coefficients. Cv : numpy.array Matrix of virtual orbital coefficients. Returns ------- F : numpy.array Hessian product tensor """ Hx_a = np.dot(moFa[:nbeta, :nbeta], xa) Hx_a -= np.dot(xa, moFa[nbeta:, nbeta:]) Hx_b = np.dot(moFb[:nalpha, :nalpha], xb) Hx_b -= np.dot(xb, moFb[nalpha:, nalpha:]) # Build two electron part, M = -4 (4 G_{mnip} - g_{mpin} - g_{npim}) K_{ip} # From [Helgaker:2000] Eqn. 10.8.65 C_right_a = np.einsum('ia,sa->si', -xa, Cv_a) C_right_b = np.einsum('ia,sa->si', -xb, Cv_b) J, K = scf_helper.compute_jk(jk, [Co_a, Co_b], [C_right_a, C_right_b]) Jab = J[0] + J[1] Hx_a += (Co_a.T).dot(2 * Jab - K[0].T - K[0]).dot(Cv_a) Hx_b += (Co_b.T).dot(2 * Jab - K[1].T - K[1]).dot(Cv_b) Hx_a *= -4 Hx_b *= -4 return (Hx_a, Hx_b)
def SCF_Hx(xa, xb, moFa, Co_a, Cv_a, moFb, Co_b, Cv_b): """ Compute a hessian vector guess where x is a ov matrix of nonredundant operators. """ Hx_a = np.dot(moFa[:nbeta, :nbeta], xa) Hx_a -= np.dot(xa, moFa[nbeta:, nbeta:]) Hx_b = np.dot(moFb[:nalpha, :nalpha], xb) Hx_b -= np.dot(xb, moFb[nalpha:, nalpha:]) # Build two electron part, M = -4 (4 G_{mnip} - g_{mpin} - g_{npim}) K_{ip} C_right_a = np.einsum('ia,sa->si', -xa, Cv_a) C_right_b = np.einsum('ia,sa->si', -xb, Cv_b) J, K = scf_helper.compute_jk(jk, [Co_a, Co_b], [C_right_a, C_right_b]) Jab = J[0] + J[1] Hx_a += (Co_a.T).dot(2 * Jab - K[0].T - K[0]).dot(Cv_a) Hx_b += (Co_b.T).dot(2 * Jab - K[1].T - K[1]).dot(Cv_b) Hx_a *= -4 Hx_b *= -4 return (Hx_a, Hx_b)
# Initialize the JK object jk = psi4.core.JK.build(wfn.basisset()) jk.initialize() # Build a DIIS helper object diis = scf_helper.DIIS_helper() print('\nTotal time taken for setup: %.3f seconds' % (time.time() - t)) print('\nStart SCF iterations:\n') t = time.time() for SCF_ITER in range(1, maxiter + 1): # Build a and b fock matrices J, K = scf_helper.compute_jk(jk, [C[:, :nocc], C[:, :ndocc]]) J = J[0] + J[1] Fa = H + J - K[0] Fb = H + J - K[1] # Build MO Fock matrix moFa = (C.T).dot(Fa).dot(C) moFb = (C.T).dot(Fb).dot(C) # Special note on the ROHF Fock matrix (taken from psi4) # Fo = open-shell fock matrix = 0.5 Fa # Fc = closed-shell fock matrix = 0.5 (Fa + Fb) # # The effective Fock matrix has the following structure # | closed open virtual # ----------------------------------------
jk = psi4.core.JK.build(wfn.basisset()) jk.initialize() # Build a DIIS helper object diisa = scf_helper.DIIS_helper() diisb = scf_helper.DIIS_helper() print('\nTotal time taken for setup: %.3f seconds' % (time.time() - t)) print('\nStart SCF iterations:\n') t = time.time() for SCF_ITER in range(1, maxiter + 1): # Build Fock matrices J, K = scf_helper.compute_jk(jk, [Ca[:, :nbeta], Cb[:, :nalpha]]) J = J[0] + J[1] Fa = H + J - K[0] Fb = H + J - K[1] # DIIS error build and update diisa_e = Fa.dot(Da).dot(S) - S.dot(Da).dot(Fa) diisa_e = (A.T).dot(diisa_e).dot(A) diisa.add(Fa, diisa_e) diisb_e = Fb.dot(Db).dot(S) - S.dot(Db).dot(Fb) diisb_e = (A.T).dot(diisb_e).dot(A) diisb.add(Fb, diisb_e) # SCF energy and update SCF_E = np.einsum('pq,pq->', Da + Db, H)