def calculate_update(self, h, a): """ Calculate new amplitudes """ names_abij = ['x1', 'x2', 'x3', 'x4'] xs = [a.t2[key] for key in names_abij] # symmetrize t2 before feeding into res xs_sym = cpd_symmetrize(xs, {(1, 0, 3, 2): ('ident', )}) r = self.calc_residuals( h, Tensors(t1=a.t1, t2=Tensors(zip(names_abij, xs_sym)))) # Solve T1 t1 = a.t1 - r.t1 * (cc_denom(h.f, 2, 'dir', 'full')) # Symmetrize T2 residuals r2 = 1 / 2 * (r.t2 + r.t2.transpose([1, 0, 3, 2])) # Solve T2 r2_d = -r2 * cc_denom(h.f, 4, 'dir', 'full') t2 = [f for f in xs] for idx in range(len(t2)): g = (als_contract_dense(t2, r2_d, idx, tensor_format='cpd') + als_contract_cpd(t2, xs_sym, idx, tensor_format='cpd')) s = als_pseudo_inverse(t2, t2, idx) f = np.dot(g, s) t2[idx] = f return Tensors(t1=t1, t2=Tensors(zip(names_abij, t2)))
def __init__(self, mf, frozen=[], mo_energy=None, mo_coeff=None, mo_occ=None, rankt=None): """ Initialize RCCSDT """ # Simply copy some parameters from RHF calculation super().__init__(mf) # Initialize molecular orbitals if mo_energy is None: mo_energy = mf.mo_energy if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ from tcc.mos import SPINLESS_MOS self._mos = SPINLESS_MOS(mo_coeff, mo_energy, mo_occ, frozen) # initialize ranks if rankt is None: n = np.min((self._mos.nocc, self._mos.nvir)) self.rankt = Tensors(t2=n, t3=n) else: self.rankt = Tensors(rankt)
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_ai = cc_denom(ham.f, 2, 'dir', 'full') e_abij = cc_denom(ham.f, 4, 'dir', 'full') nocc = self.mos.nocc nvir = self.mos.nvir t1 = ham.f.ov.transpose().conj() * (- e_ai) v_vovo = einsum("pia,pjb->aibj", ham.l.pov, ham.l.pov).conj() t2_full = v_vovo.transpose([0, 2, 1, 3]) * (- e_abij) t2names = ['x1', 'x2', 'x3', 'x4'] t3names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6'] t2x = cpd_initialize(t2_full.shape, self.rankt.t2) t2x = als_dense(t2x, t2_full, max_cycle=100, tensor_format='cpd') t3x = cpd_initialize((nvir,) * 3 + (nocc,) * 3, self.rankt.t3, init_function=np.zeros) return Tensors(t1=t1, t2=Tensors(zip(t2names, t2x)), t3=Tensors(zip(t3names, t3x)))
def solve_amps(self, h, a, g): """ Solving for new T amlitudes using RHS and denominator tensor """ # g2_aa = (+ g.t2.aa # + g.t2.aa.transpose([1, 0, 3, 2]) # - g.t2.aa.transpose([0, 1, 3, 2]) # - g.t2.aa.transpose([1, 0, 2, 3])) / 4 # g2_bb = (+ g.t2.bb # + g.t2.bb.transpose([1, 0, 3, 2]) # - g.t2.bb.transpose([0, 1, 3, 2]) # - g.t2.bb.transpose([1, 0, 2, 3])) / 4 g2_ab = (g.t2.ab + g.t2.ab.transpose([1, 0, 3, 2])) / 2 g2_aa = g.t2.aa g2_bb = g.t2.aa # g2_ab = g.t2.ab return Tensors( t1=Tensors(a=g.t1.a * (-cc_denom_spin(h.f.a, h.f.b, 1, 2, 'dir', 'full')), b=g.t1.b * (-cc_denom_spin(h.f.a, h.f.b, 0, 2, 'dir', 'full'))), t2=Tensors( aa=g2_aa * (-cc_denom_spin(h.f.a, h.f.b, 2, 4, 'dir', 'full')), bb=g2_bb * (-cc_denom_spin(h.f.a, h.f.b, 0, 4, 'dir', 'full')), ab=g2_ab * (-cc_denom_spin(h.f.a, h.f.b, 1, 4, 'dir', 'full')), ))
def calc_residuals(self, h, a): """ Calculates CC residuals for CC equations """ # Symmetrize T2 before feeding into res names = ['x1', 'x2', 'x3', 'x4'] xs_sym = cpd_symmetrize([a.t2.x1, a.t2.x2, a.t2.x3, a.t2.x4], {(1, 0, 3, 2): ('ident', )}) return _rccsd_cpd_ls_t_calc_residuals( h, Tensors(t1=a.t1, t2=Tensors(zip(names, xs_sym))))
def solve_amps(self, h, a, g): """ Solving for new T amlitudes using RHS and denominator It is assumed that the order of fields in the RHS is consistent with the order in amplitudes """ # Symmetrize T3 RHS - see RCCSDT code g3 = (+g.t3 + g.t3.transpose([1, 2, 0, 4, 5, 3]) + g.t3.transpose( [2, 0, 1, 5, 3, 4]) + g.t3.transpose([0, 2, 1, 3, 5, 4]) + g.t3.transpose([2, 1, 0, 5, 4, 3]) + g.t3.transpose([1, 0, 2, 4, 3, 5])) / 6 # Solve T3 t3 = g3 * (-cc_denom(h.f, g.t3.ndim, 'dir', 'full')) # Symmetrize t3 = (+t3 + t3.transpose([1, 2, 0, 4, 5, 3]) + t3.transpose( [2, 0, 1, 5, 3, 4]) + t3.transpose([0, 2, 1, 3, 5, 4]) + t3.transpose([2, 1, 0, 5, 4, 3]) + t3.transpose([1, 0, 2, 4, 3, 5])) / 6 # Symmetrize T2 RHS g2 = 1 / 2 * (g.t2 + g.t2.transpose([1, 0, 3, 2])) # Solve T2 t2 = g2 * (-cc_denom(h.f, g.t2.ndim, 'dir', 'full')) # Symmetrize t2 = 1 / 2 * (t2 + t2.transpose([1, 0, 3, 2])) # Solve for factors t2x = als_dense([a.t2.xlam, a.t2.x1, a.t2.x2, a.t2.x3, a.t2.x4], t2, max_cycle=1, tensor_format='ncpd') t3x = als_dense( [a.t3.xlam, a.t3.x1, a.t3.x2, a.t3.x3, a.t3.x4, a.t3.x5, a.t3.x6], t3, max_cycle=1, tensor_format='ncpd') return Tensors( t1=g.t1 * (-cc_denom(h.f, g.t1.ndim, 'dir', 'full')), t2=Tensors(xlam=t2x[0], x1=t2x[1], x2=t2x[2], x3=t2x[3], x4=t2x[4]), t3=Tensors(xlam=t3x[0], x1=t3x[1], x2=t3x[2], x3=t3x[3], x4=t3x[4], x5=t3x[5], x6=t3x[6]), )
def calculate_update(self, h, a): """ Calculate new amplitudes """ names_abij = sorted(a.t2.keys()) xs = [elem for elem in a.t2.to_generator()] # symmetrize t2 before feeding into res xs_sym = cpd_symmetrize(xs, {(1, 0, 3, 2): ('ident', )}) a_sym = Tensors(t1=a.t1, t2=Tensors(zip(names_abij, xs_sym))) # Calculate residuals r1 = _rccsd_cpd_ls_t_true_calc_r1(h, a_sym) # Solve T1 t1 = a.t1 - r1 * (cc_denom(h.f, 2, 'dir', 'full')) namesd_abij = ['d1', 'd2', 'd3', 'd4'] d = Tensors( t2=Tensors(zip(namesd_abij, cc_denom(h.f, 4, 'dir', 'cpd')))) new_a = Tensors(t1=t1, t2=Tensors(zip(names_abij, xs))) for idx, name in enumerate(sorted(a_sym.t2.keys())): g = (-self._calculate_r2d_projection(name, h, a_sym, new_a, d) + als_contract_cpd(new_a.t2.to_list(), a_sym.t2.to_list(), idx, tensor_format='cpd')) s = als_pseudo_inverse(new_a.t2.to_list(), new_a.t2.to_list(), idx) f = np.dot(g, s) new_a.t2[name] = f return new_a
def solve_amps(self, h, a, g): """ Solving for new T amlitudes using RHS and denominator It is assumed that the order of fields in the RHS is consistent with the order in amplitudes """ # Symmetrize T3 RHS g3 = ((+g.t3 + g.t3.transpose([1, 2, 0, 4, 5, 3]) + g.t3.transpose( [2, 0, 1, 5, 3, 4]) + g.t3.transpose([0, 2, 1, 3, 5, 4]) + g.t3.transpose([2, 1, 0, 5, 4, 3]) + g.t3.transpose([1, 0, 2, 4, 3, 5])) / 12) # Symmetrize T2 RHS g2 = 1 / 2 * (g.t2 + g.t2.transpose([1, 0, 3, 2])) # Solve t2 = g2 * (-cc_denom(h.f, g.t2.ndim, 'dir', 'full')) t3 = g3 * (-cc_denom(h.f, g.t3.ndim, 'dir', 'full')) # Symmetrize amplitudes t2 = 1 / 2 * (t2 + t2.transpose([1, 0, 3, 2])) t3 = ((+t3 + t3.transpose([1, 2, 0, 4, 5, 3]) + t3.transpose( [2, 0, 1, 5, 3, 4]) + t3.transpose([0, 2, 1, 3, 5, 4]) + t3.transpose([2, 1, 0, 5, 4, 3]) + t3.transpose([1, 0, 2, 4, 3, 5])) / 6) return Tensors(t1=g.t1 * (-cc_denom(h.f, g.t1.ndim, 'dir', 'full')), t2=t2, t3=t3)
def solve_amps(self, h, a, g): """ Solving for new T amlitudes using RHS and denominator It is assumed that the order of fields in the RHS is consistent with the order in amplitudes """ # Apply n_body symmetry, which builds all # other spin parts of the unitary group residual g3s = (+g.t3 - g.t3.transpose([0, 1, 2, 3, 5, 4]) + g.t3.transpose([0, 1, 2, 4, 5, 3])) g3 = ((+g.t3 + g.t3.transpose([1, 2, 0, 4, 5, 3]) + g.t3.transpose( [2, 0, 1, 5, 3, 4]) + g.t3.transpose([0, 2, 1, 3, 5, 4]) + g.t3.transpose([2, 1, 0, 5, 4, 3]) + g.t3.transpose([1, 0, 2, 4, 3, 5]) + 2 * g3s) / 12) g2 = 1 / 2 * (g.t2 + g.t2.transpose([1, 0, 3, 2])) t2 = g2 * (-cc_denom(h.f, g.t2.ndim, 'dir', 'full')) t3 = g3 * (-cc_denom(h.f, g.t3.ndim, 'dir', 'full')) # Symmetrize t2 = 1 / 2 * (t2 + t2.transpose([1, 0, 3, 2])) t3 = ((+t3 + t3.transpose([1, 2, 0, 4, 5, 3]) + t3.transpose( [2, 0, 1, 5, 3, 4]) + t3.transpose([0, 2, 1, 3, 5, 4]) + t3.transpose([2, 1, 0, 5, 4, 3]) + t3.transpose([1, 0, 2, 4, 3, 5])) / 6) return Tensors(t1=g.t1 * (-cc_denom(h.f, g.t1.ndim, 'dir', 'full')), t2=t2, t3=t3)
def calc_residuals(self, h, a): """ Updates right hand side of the CC equations, commonly referred as G """ t2names = ['xlam', 'x1', 'x2', 'x3', 'x4'] t2x = [a.t2[key] for key in t2names] t3names = ['xlam', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6'] t3x = [a.t3[key] for key in t3names] # symmetrize t2 before feeding into res t2x_sym = ncpd_symmetrize(t2x, {(1, 0, 3, 2): ('ident',)}) # symmetrize t3 before feeding into res t3x_sym = ncpd_symmetrize(t3x, {(1, 2, 0, 4, 5, 3): ('ident',), (2, 0, 1, 5, 3, 4): ('ident',), (0, 2, 1, 3, 5, 4): ('ident',), (2, 1, 0, 5, 4, 3): ('ident',), (1, 0, 2, 4, 3, 5): ('ident',)}) # return _rccsdt_ncpd_ls_t_calc_residuals(h, a) return _rccsdt_mul_ri_calc_residuals( h, Tensors(t1=a.t1, t2=ncpd_rebuild(t2x_sym), t3=ncpd_rebuild(t3x_sym)) )
def __init__(self, cc, mos=None): cput0 = (time.clock(), time.time()) log = logger.Logger(cc.stdout, cc.verbose) # Get mos if mos is None: self.mos = cc.mos else: self.mos = mos # Add Fock matrix self.f = _assemble_fock(cc, mos) if (cc._scf._eri is not None): self.v = Tensors(aaaa=_assemble_moeri_full_core(cc._scf, self.mos.a, order='dir'), bbbb=_assemble_moeri_full_core(cc._scf, self.mos.b, order='dir'), abab=_assemble_moeri_full_core(cc._scf, self.mos.a, self.mos.b, order='dir')) else: raise ValueError('SCF object did not supply AO integrals') log.timer('CCSD integral transformation', *cput0)
def __init__(self, cc, filename='init_ints.mat'): cput0 = (time.clock(), time.time()) log = logger.Logger(cc.stdout, cc.verbose) # Get sizes self.mos = cc.mos nocc = self.mos.nocc from scipy.io import loadmat from os.path import isfile # Add Fock matrix if (isfile(filename)): fock = loadmat(filename, variable_names=('Fmo'), matlab_compatible=True)['Fmo'] self.f = Tensors(oo=fock[:nocc, :nocc], ov=fock[:nocc, nocc:], vv=fock[nocc:, nocc:]) if (isfile(filename)): eri1 = loadmat(filename, variable_names=('Imo'), matlab_compatible=True)['Imo'] self.v = _extract_blocks_dir(eri1, nocc, nocc) else: raise ValueError('File not found: {}'.format(filename)) log.timer('CCSD integral transformation', *cput0)
def solve_amps(self, h, a, g): """ Solving for new T amlitudes using RHS and denominator It is assumed that the order of fields in the RHS is consistent with the order in amplitudes """ # Solve T2 (see RCCSD_UNIT) t2 = ((2 * g.t2 + g.t2.transpose([0, 1, 3, 2])) / (-6) * cc_denom(h.f, 4, 'dir', 'full')) # Symmetrize t2 = (+t2 + t2.transpose([1, 0, 3, 2])) / 2 # Solve T3 t3 = (g.t3 / 12 * (-cc_denom(h.f, g.t3.ndim, 'dir', 'full'))) # Symmetrize t3 = ((+t3 + t3.transpose([1, 2, 0, 4, 5, 3]) + t3.transpose( [2, 0, 1, 5, 3, 4]) + t3.transpose([0, 2, 1, 3, 5, 4]) + t3.transpose([2, 1, 0, 5, 4, 3]) + t3.transpose([1, 0, 2, 4, 3, 5])) / 6) return Tensors(t1=g.t1 * (-cc_denom(h.f, g.t1.ndim, 'dir', 'full')), t2=t2, t3=t3)
def _assemble_moeri_ri_core_hub(scf, mosa, mosb=None): """ Builds RI decomposed Hubbard interaction, transforms it to MO basis and returns relevant blocks """ nocc = mosa.nocc nmo = mosa.nmo from tcc.utils import khatrirao from math import sqrt # Build RI integrals analytically u = scf._hubbard_interaction if u < 0: u12 = 1j * sqrt(-u) else: u12 = sqrt(u) Lpnn = u12 * np.reshape( np.transpose(khatrirao((np.conj((mosa.mo_coeff).T), mosa.mo_coeff.T))), (nmo, nmo, nmo)) return Tensors(poo=ref_ndarray(Lpnn[:, :nocc, :nocc]), pov=ref_ndarray(Lpnn[:, :nocc, nocc:]), pvv=ref_ndarray(Lpnn[:, nocc:, nocc:]), pvo=ref_ndarray(Lpnn[:, nocc:, :nocc]))
def _assemble_moeri_ri_core(scf, mos): """ Gets RI decomposed eris from scf, transforms them to MO basis and takes relevant blocks """ nocc = mos.nocc nmo = mos.nmo naux = scf.with_df.get_naoaux() Lpnn = np.empty((naux, nmo, nmo)) mof = np.asarray(mos.mo_coeff, order='F') ijslice = (0, nmo, 0, nmo) Lpq = None pq = 0 for eri1 in scf.with_df.loop(): Lpq = ao2mo._ao2mo.nr_e2(eri1, mof, ijslice, aosym='s2', out=Lpq).reshape(-1, nmo, nmo) npbatch = Lpq.shape[0] Lpnn[pq:pq + npbatch, :, :] = Lpq pq += npbatch return Tensors(poo=ref_ndarray(Lpnn[:, :nocc, :nocc]), pov=ref_ndarray(Lpnn[:, :nocc, nocc:]), pvv=ref_ndarray(Lpnn[:, nocc:, nocc:]), pvo=ref_ndarray(Lpnn[:, nocc:, :nocc]))
def _extract_blocks_dir(eri, nocc1, nocc2): """ Extracts only symmetrically unique blocks blocks from Dirac ordered integrals """ # FIXME: need to clean up interaction to having only 7 partitions. # FIXME: this will involve fixing rccsd.py return Tensors( oooo=eri[:nocc1, :nocc2, :nocc1, :nocc2], ooov=eri[:nocc1, :nocc2, :nocc1, nocc2:], oovv=eri[:nocc1, :nocc2, nocc1:, nocc2:], ovov=eri[:nocc1, nocc2:, :nocc1, nocc2:], voov=eri[nocc1:, :nocc2, :nocc1, nocc2:], ovvv=eri[:nocc1, nocc2:, nocc1:, nocc2:], vvvv=eri[nocc1:, nocc2:, nocc1:, nocc2:], ovvo=eri[:nocc1, nocc2:, nocc1:, :nocc2], vvov=eri[nocc1:, nocc2:, :nocc1, nocc2:], vvoo=eri[nocc1:, nocc2:, :nocc1, :nocc2], ovoo=eri[:nocc1, nocc2:, :nocc1, :nocc2], oovo=eri[:nocc1, :nocc2, nocc1:, :nocc2], vvvo=eri[nocc1:, nocc2:, nocc1:, :nocc2], vovv=eri[nocc1:, :nocc2, nocc1:, nocc2:], # added for uccsd vovo=eri[nocc1:, :nocc2, nocc1:, :nocc2], # | vooo=eri[nocc1:, :nocc2, :nocc1, :nocc2] # | )
def update_rhs(self, h, a, r): """ Calculates right hand side of CC equations """ return Tensors(t1=r.t1 - a.t1 / cc_denom(h.f, 2, 'dir', 'full'), t2=r.t2 - a.t2 / cc_denom(h.f, 4, 'dir', 'full'), t3=r.t3 - (a.t3 - a.t3.transpose([0, 1, 2, 4, 3, 5])) / cc_denom(h.f, 6, 'dir', 'full'))
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_ai = cc_denom(ham.f, 2, 'dir', 'full') e_abij = cc_denom(ham.f, 4, 'dir', 'full') t1 = 2 * ham.f.ov.transpose().conj() * (-e_ai) v_vovo = einsum("pia,pjb->aibj", ham.l.pov, ham.l.pov).conj() t2_full = 2 * v_vovo.transpose([0, 2, 1, 3]) * (-e_abij) xs = cpd_initialize(t2_full.shape, self.rankt.t2) xs = als_dense(xs, t2_full, max_cycle=100) names = ['x1', 'x2', 'x3', 'x4'] return Tensors(t1=t1, t2=Tensors(zip(names, xs)))
def update_rhs(self, h, a, r): """ Updates right hand side of the CC equations, commonly referred as G """ return Tensors(t1=r.t1 - a.t1 / cc_denom(h.f, 2, 'dir', 'full'), t2=r.t2 - cpd_rebuild( (a.t2.x1, a.t2.x2, a.t2.x3, a.t2.x4)) / cc_denom(h.f, 4, 'dir', 'full'))
def update_rhs(self, h, a, r): """ Calculates RHS of the fixed point iteration of CC equations """ return Tensors(t1=r.t1 - 2 * a.t1 / cc_denom(h.f, 2, 'dir', 'full'), t2=r.t2 - 2 * (2 * a.t2 - a.t2.transpose([0, 1, 3, 2])) / cc_denom(h.f, 4, 'dir', 'full'))
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_ai = cc_denom(ham.f, 2, 'dir', 'full') e_abij = cc_denom(ham.f, 4, 'dir', 'full') t1 = ham.f.ov.transpose().conj() * (-e_ai) v_vovo = einsum("pia,pjb->aibj", ham.l.pov, ham.l.pov).conj() t2_full = v_vovo.transpose([0, 2, 1, 3]) * (-e_abij) xs = ncpd_initialize(t2_full.shape, self.rankt.t2) xs = als_dense(xs, t2_full, max_cycle=100, tensor_format='ncpd') # xs_sym = cpd_symmetrize(xs, {(1, 0, 3, 2): ('ident',)}) names = ['xlam', 'x1', 'x2', 'x3', 'x4'] return Tensors(t1=t1, t2=Tensors(zip(names, xs)))
def _assemble_moeri_thc_core_hub(scf, mosa, mosb=None): """ Builds THC integrals analytically, transfroms them to MO basis, returns blocked structure """ nocc = mosa.nocc nao = mosa.mo_coeff.shape[0] # Build THC integrals analytically u = scf._hubbard_interaction CT = (mosa.mo_coeff) # Why was it done this way? return Tensors(x1=Tensors(CT[:nocc, :], CT[nocc:, :]), x2=Tensors(CT[:nocc, :], CT[nocc:, :]), x3=Tensors(CT[:nocc, :], CT[nocc:, :]), x4=Tensors(CT[:nocc, :], CT[nocc:, :]), x5=u * np.eye(nao))
def compare_to_aq(): # pragma: nocover from pyscf import gto from pyscf import scf mol = gto.Mole() mol.atom = [[8, (0., 0., 0.)], [1, (0., -0.757, 0.587)], [1, (0., 0.757, 0.587)]] mol.basis = { 'H': '3-21g', 'O': '3-21g', } mol.build() rhf = scf.RHF(mol) rhf.scf() # -76.0267656731 # load reference arrays import h5py import numpy as np f1 = h5py.File('data/test_references/aq_ccsd_amps.h5', 'r') # use amplitudes from the last iteration num_steps = int(len(f1.keys()) / 2) t1 = f1['t1_' + str(num_steps)][()].T t2 = f1['t2_' + str(num_steps)][()].T f1.close() f1 = h5py.File('data/test_references/aq_ccsd_mos.h5', 'r') CA = np.hstack((f1['cI'][()].T, f1['cA'][()].T)) CB = np.hstack((f1['ci'][()].T, f1['ca'][()].T)) f1.close() # permute AO indices to match pyscf order perm = [0, 1, 2, 4, 5, 3, 7, 8, 6, 9, 10, 11, 12] from tcc.utils import perm_matrix m = perm_matrix(perm) CA_perm = m.dot(CA) from tcc.cc_solvers import residual_diis_solver from tcc.cc_solvers import step_solver, classic_solver from tcc.rccsd import RCCSD cc = RCCSD(rhf, mo_coeff=CA_perm) converged, energy, amps = classic_solver(cc, conv_tol_energy=1e-14, conv_tol_res=1e-10, max_cycle=200) print('dt1: {}'.format(np.max(t1 - amps.t1))) print('dt2: {}'.format(np.max(t2 - amps.t2))) from tcc.tensors import Tensors test_amps = Tensors(t1=t1, t2=t2) h = cc.create_ham() r = cc.calc_residuals(h, test_amps) print('max r1: {}'.format(np.max(r.t1))) print('max r2: {}'.format(np.max(r.t2)))
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_a_ai = cc_denom_spin(ham.f.a, ham.f.b, 1, 2, 'dir', 'full') e_b_ai = cc_denom_spin(ham.f.a, ham.f.b, 0, 2, 'dir', 'full') t1_a = ham.f.a.ov.transpose().conj() * (-e_a_ai) t1_b = ham.f.b.ov.transpose().conj() * (-e_b_ai) e_a_abij = cc_denom_spin(ham.f.a, ham.f.b, 2, 4, 'dir', 'full') e_b_abij = cc_denom_spin(ham.f.a, ham.f.b, 0, 4, 'dir', 'full') t2_aa = ham.v.aaaa.oovv.transpose([2, 3, 0, 1]).conj() * (-e_a_abij) t2_bb = ham.v.aaaa.oovv.transpose([2, 3, 0, 1]).conj() * (-e_b_abij) e_ab_abij = cc_denom_spin(ham.f.a, ham.f.b, 1, 4, 'dir', 'full') t2_ab = ham.v.abab.oovv.transpose([2, 3, 0, 1]).conj() * (-e_ab_abij) return Tensors(t1=Tensors(a=t1_a, b=t1_b), t2=Tensors(aa=t2_aa, bb=t2_bb, ab=t2_ab))
def solve_amps(self, h, a, g): """ Solve for new amplitudes using RHS and denominator """ t1 = g.t1 * (-cc_denom(h.f, 2, 'dir', 'full')) # Symmetrize T2 HS g2 = 1 / 2 * (g.t2 + g.t2.transpose([1, 0, 3, 2])) # Solve T2 t2_full = g2 * (-cc_denom(h.f, 4, 'dir', 'full')) xs = als_dense([a.t2.x1, a.t2.x2, a.t2.x3, a.t2.x4], t2_full, max_cycle=1, tensor_format='cpd') return Tensors(t1=t1, t2=Tensors(x1=xs[0], x2=xs[1], x3=xs[2], x4=xs[3]))
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_ai = cc_denom(ham.f, 2, 'dir', 'full') e_abij = cc_denom(ham.f, 4, 'dir', 'full') t1 = ham.f.ov.transpose().conj() * (-e_ai) t2 = ham.v.oovv.transpose([2, 3, 0, 1]).conj() * (-e_abij) return Tensors(t1=t1, t2=t2)
def _assemble_uhf_fock(cc, mos=None): """Assembles UHF fock matrix""" if mos is None: # Assume canonical orbitals mos = cc.mos fock = np.array( [np.diag(cc.mos.a.mo_energies), np.diag(cc.mos.b.mo_energies)]) else: # If mo_coeff is not canonical orbitals fock = _calculate_noncanonical_fock( cc._scf, np.array((mos.a.mo_coeff, mos.b.mo_coeff)), np.array((mos.a.mo_occ, mos.b.mos_occ))) nocca = mos.a.nocc noccb = mos.b.nocc return Tensors( a=Tensors(oo=ref_ndarray(fock[0][:nocca, :nocca]), ov=ref_ndarray(fock[0][:nocca, nocca:]), vv=ref_ndarray(fock[0][nocca:, nocca:])), b=Tensors(oo=ref_ndarray(fock[1][:noccb, :noccb]), ov=ref_ndarray(fock[1][:noccb, noccb:]), vv=ref_ndarray(fock[1][noccb:, noccb:])), )
def _extract_blocks_mul(eri, nocc1, nocc2): """ Extracts only symmetrically unique blocks blocks from Mulliken ordered integrals """ return Tensors(oooo=ref_ndarray(eri[:nocc1, :nocc1, :nocc2, :nocc2]), ooov=ref_ndarray(eri[:nocc1, :nocc1, :nocc2, nocc2:]), oovv=ref_ndarray(eri[:nocc1, :nocc1, nocc2:, nocc2:]), ovov=ref_ndarray(eri[:nocc1, nocc1:, :nocc2, nocc2:]), voov=ref_ndarray(eri[nocc1:, :nocc1, :nocc2, nocc2:]), ovvv=ref_ndarray(eri[:nocc1, nocc1:, nocc2:, nocc2:]), vvvv=ref_ndarray(eri[nocc1:, nocc1:, nocc2:, nocc2:]))
def init_amplitudes(self, ham): """ Initialize amplitudes from interaction """ e_ai = cc_denom(ham.f, 2, 'dir', 'full') e_abij = cc_denom(ham.f, 4, 'dir', 'full') nocc = self.mos.nocc nvir = self.mos.nvir t1 = ham.f.ov.transpose().conj() * (-e_ai) v_vovo = einsum("pia,pjb->aibj", ham.l.pov, ham.l.pov).conj() t2_full = v_vovo.transpose([0, 2, 1, 3]) * (-e_abij) t3names = ['xlam', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6'] t3x = ncpd_initialize( (nvir, ) * 3 + (nocc, ) * 3, self.rankt.t3, init_function=(lambda x: 0.001 * np.random.rand(*x))) return Tensors(t1=t1, t2=t2_full, t3=Tensors(zip(t3names, t3x)))
def update_rhs(self, h, a, r): """ Calculates right hand side of CC equations """ return Tensors( t1=r.t1 - a.t1 / cc_denom(h.f, 2, 'dir', 'full'), t2=r.t2 - a.t2 / cc_denom(h.f, 4, 'dir', 'full'), t3=r.t3 - (ncpd_rebuild( (a.t3.xlam, a.t3.x1, a.t3.x2, a.t3.x3, a.t3.x4, a.t3.x5, a.t3.x6)) - ncpd_rebuild( (a.t3.xlam, a.t3.x1, a.t3.x2, a.t3.x3, a.t3.x5, a.t3.x4, a.t3.x6))) / cc_denom(h.f, 6, 'dir', 'full'))