Beispiel #1
0
    def get_Xmat( self, mf1RDM, ddt_mf1RDM ):
        #Subroutine to calculate the X-matrix to propagate embedding orbitals

        #Initialize X-matrix
        self.Xmat = np.zeros( [self.Nsites, self.Nsites], dtype=complex )

        #Index of orbitals in the site-basis corresponding to the environment
        envindx = np.setdiff1d( np.arange(self.Nsites), self.impindx)

        #Eigenvalues of environment part of mf1RDM
        self.env1RDM_evals = np.diag( np.real( utils.rot1el( mf1RDM[ envindx[:,None], envindx ], self.rotmat[ envindx, self.Nimp: ] ) ) )

        #Calculate X-matrix setting diagonal, core-core, and virtual virtual terms to zero

        #Matrix of one over the difference in embedding orbital eigenvalues
        #Set redundant terms to zero, ie diagonal, core-core, and virtual-virtual
        eval_dif = np.zeros( [ self.Nsites-self.Nimp, self.Nsites-self.Nimp ] )
        for b in range(self.Nimp,self.Nsites):
            for a in range(self.Nimp,self.Nsites):
                if( a != b and not ( a in self.corerange and b in self.corerange ) and not ( a in self.virtrange and b in self.virtrange ) ):
                    eval_dif[ b-self.Nimp, a-self.Nimp ] = 1.0 / ( self.env1RDM_evals[a-self.Nimp] - self.env1RDM_evals[b-self.Nimp] )

        #Rotate time-derivative of mean-field 1RDM
        self.Xmat[ self.Nimp:, self.Nimp: ] = utils.rot1el( 1j*ddt_mf1RDM[ envindx[:,None], envindx ], self.rotmat[ envindx, self.Nimp: ] )

        #Multiply difference in eigenalues and rotated time-derivative matrix
        self.Xmat[ self.Nimp:, self.Nimp: ] = np.multiply( eval_dif, self.Xmat[ self.Nimp:, self.Nimp: ] )
Beispiel #2
0
    def get_Hemb( self, h_site, V_site, hamtype=0, hubsite_indx=None ):
        #Subroutine to the get the 1 and 2 e- terms of the Hamiltonian in the embedding basis
        #Transformation accounts for interaction with the core
        #Also calculates 1 e- term with only 1/2 interaction with the core - this is used in calculation of DMET energy

        #remove the virtual states from the rotation matrix
        #the rotation matrix is of form ( site basis fcns ) x ( impurities, virtual, bath, core )
        rotmat_small = np.delete( self.rotmat, np.s_[self.Nimp:self.Nimp+self.Nvirt], 1 )

        #rotate the 1 e- terms, h_emb currently ( impurities, bath, core ) x ( impurities, bath, core )
        h_emb = utils.rot1el( h_site, rotmat_small )

        #define 1 e- term of size ( impurities, bath ) x ( impurities, bath ) that will only have 1/2 interaction with the core
        self.h_emb_halfcore = np.copy( h_emb[ :2*self.Nimp, :2*self.Nimp ] )

        #rotate the 2 e- terms
        if( hamtype == 0 ):
            #General hamiltonian, V_emb currently ( impurities, bath, core ) ^ 4
            V_emb = utils.rot2el_chem( V_site, rotmat_small )
        elif( hamtype == 1 ):
            #Hubbard hamiltonian
            rotmat_vsmall = rotmat_small[ hubsite_indx, :2*self.Nimp ] #remove core states from rotation matrix
            self.V_emb = V_site*np.einsum( 'ap,cp,pb,pd->abcd', utils.adjoint( rotmat_vsmall ), utils.adjoint( rotmat_vsmall ), rotmat_vsmall, rotmat_vsmall )

        #augment the impurity/bath 1e- terms from contribution of coulomb and exchange terms btwn impurity/bath and core
        #and augment the 1 e- term with only half the contribution from the core to be used in DMET energy calculation
        if( hamtype == 0 ):
            #General hamiltonian
            for core in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ):
                h_emb[ :2*self.Nimp, :2*self.Nimp ] = h_emb[ :2*self.Nimp, :2*self.Nimp ] + 2*V_emb[ :2*self.Nimp, :2*self.Nimp, core, core ] - V_emb[ :2*self.Nimp, core, core, :2*self.Nimp ]
                self.h_emb_halfcore += V_emb[ :2*self.Nimp, :2*self.Nimp, core, core ] - 0.5*V_emb[ :2*self.Nimp, core, core, :2*self.Nimp ]
        elif( hamtype == 1):
            #Hubbard hamiltonian
            core_int = V_site * np.einsum( 'ap,pb,p->ab', utils.adjoint( rotmat_vsmall ), rotmat_vsmall, np.einsum( 'pe,ep->p',rotmat_small[hubsite_indx,2*self.Nimp:], utils.adjoint( rotmat_small[hubsite_indx,2*self.Nimp:] ) ) )
            h_emb[ :2*self.Nimp, :2*self.Nimp ] += core_int
            self.h_emb_halfcore += 0.5*core_int


        #calculate the energy associated with core-core interactions, setting it numerically to a real number since it always will be
        Ecore = 0
        for core1 in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ):

            Ecore += 2*h_emb[ core1, core1 ]

            if( hamtype == 0 ):
                #General hamiltonian
                for core2 in range( 2*self.Nimp, 2*self.Nimp+self.Ncore ):
                    Ecore += 2*V_emb[ core1, core1, core2, core2 ] - V_emb[ core1, core2, core2, core1 ]
        if( hamtype == 1):
            #Hubbard hamiltonian
            vec = np.einsum( 'pe,ep->p',rotmat_small[hubsite_indx,2*self.Nimp:],utils.adjoint( rotmat_small[hubsite_indx,2*self.Nimp:] ) )
            Ecore += V_site * np.einsum( 'p,p', vec, vec )

        self.Ecore = Ecore.real

        #shrink h_emb and V_emb arrays to only include the impurity and bath
        self.h_emb = h_emb[ :2*self.Nimp, :2*self.Nimp ]
        if( hamtype == 0 ):
            #General hamiltonian
            self.V_emb = V_emb[ :2*self.Nimp, :2*self.Nimp, :2*self.Nimp, :2*self.Nimp ]
Beispiel #3
0
def get_Hemb(h_site, rotmat, Nimp, Nsites, Nele):

    Ncore = round(Nele / 2) - Nimp
    Nvirt = Nsites - 2 * Nimp - Ncore

    rotmat_small = np.delete(rotmat, np.s_[Nimp:Nimp + Nvirt], 1)

    h_emb = utils.rot1el(h_site, rotmat_small)

    Ecore = 0.0
    for core in range(2 * Nimp, 2 * Nimp + Ncore):
        Ecore += h_emb[core, core]

    h_emb = h_emb[:2 * Nimp, :2 * Nimp]

    return h_emb, core
Beispiel #4
0
def one_rk_step2(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp, delt, rotmat):

    iddt_mf1RDM = utils.commutator(h_site, mf1RDM)
    change_mf1RDM = -1j * delt * iddt_mf1RDM

    evals = np.copy(
        np.real(
            np.diag(utils.rot1el(mf1RDM[Nimp:, Nimp:], rotmat[Nimp:, Nimp:]))))

    #####grr####
    #chk1, chk2 = get_rotmat( mf1RDM, Nsites, Nimp )
    #print(rotmat[Nimp:,Nimp:])
    #print()
    #print(chk1[Nimp:,Nimp:])
    #print()
    #print(evals)
    #print()
    #print(chk2)
    #print()
    #print('------------------')
    #print()
    ############

    Xmat, Xmat_sml = get_Xmat(mf1RDM, iddt_mf1RDM, rotmat, evals, Nsites, Nele,
                              Nimp)

    change_rotmat = -1j * delt * np.dot(rotmat, Xmat)

    h_emb, Ecore = get_Hemb(h_site, rotmat, Nimp, Nsites, Nele)

    V_emb = np.zeros([2 * Nimp, 2 * Nimp, 2 * Nimp, 2 * Nimp], dtype=complex)

    Ecore = 0.0
    change_CIcoeffs = -1j * delt * applyham_pyscf.apply_ham_pyscf_fully_complex(
        CIcoeffs, h_emb - Xmat_sml, V_emb, Nimp, Nimp, 2 * Nimp, Ecore)

    return change_mf1RDM, change_CIcoeffs, change_rotmat