Esempio n. 1
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 ]
Esempio n. 2
0
    def _integrate(self, prev, dt, eta0, q, g0=np.eye(4), intermediate=False):
        self.xi[0, :] = np.array([0, 0, 0, 0, 0, 1])
        self.eta[0, :] = eta0

        # integration over the body (don't need the initial point as the initial values are determined already)
        # g_half = g0  # known initial condition
        g_half = expm(dt / 2 * se(prev.eta[0, :]))
        for i in range(self.N - 1):
            # averaging over steps to get half step values
            xi_half = (self.xi[i, :] + prev.xi[i, :]) / 2
            eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2

            # implicit midpoint approximation
            xi_dot = (self.xi[i, :] - prev.xi[i, :]) / dt
            eta_dot = (self.eta[i, :] - prev.eta[i, :]) / dt

            # external loads
            A_bar = 0
            B_bar = 0
            # viscosity
            B_bar += self.V @ xi_dot

            # other loads
            for load in self.loads:
                A, B = load.dist_load(g_half, xi_half, eta_half, xi_dot,
                                      eta_dot, self, q)
                A_bar += A
                B_bar += B

            if intermediate and i == self.N - 2:
                for load in self.loads:
                    W = load.tip_load(g_half, xi_half, eta_half, xi_dot,
                                      eta_dot, self, q)
                    B_bar += W

            # spatial derivatives
            xi_der = np.linalg.inv(self.K - A_bar) @ (
                (self.M @ eta_dot) -
                (adjoint(eta_half).T @ self.M @ eta_half) +
                (adjoint(xi_half).T @ self.K @ (xi_half - self.xi_ref)) +
                B_bar)
            eta_der = xi_dot - (adjoint(xi_half) @ eta_half)

            # explicit Euler step
            xi_half_next = xi_half + self.ds * xi_der
            eta_half_next = eta_half + self.ds * eta_der
            g_half = g_half @ expm(se(self.ds * xi_half))

            # determine next step from half step value
            self.xi[i + 1, :] = 2 * xi_half_next - prev.xi[i + 1, :]
            self.eta[i + 1, :] = 2 * eta_half_next - prev.eta[i + 1, :]

        # midpoint RKMK to step the g values
        for i in range(self.N):
            self.g[i, :] = flatten(
                unflatten(prev.g[i, :]) @ expm(
                    se(dt * (self.eta[i, :] + prev.eta[i, :]) / 2)))

        return g_half
Esempio n. 3
0
def FCI_GS(h, V, Ecore, Norbs, Nele):

    #Subroutine to perform groundstate FCI calculation using pyscf

    if (isinstance(Nele, tuple)):
        Nele = sum(Nele)

    #Define pyscf molecule
    mol = gto.M()
    mol.nelectron = Nele
    mol.incore_anyway = True  #this call is necessary to use user defined hamiltonian in fci step

    #First perform HF calculation
    mf = scf.RHF(mol)
    mf.get_hcore = lambda *args: h
    mf.get_ovlp = lambda *args: np.eye(Norbs)
    mf._eri = ao2mo.restore(8, V, Norbs)
    mf.kernel()

    #Perform FCI calculation using HF MOs
    cisolver = pyscf.fci.FCI(mf, mf.mo_coeff)
    E_FCI, CIcoeffs = cisolver.kernel()

    #Rotate CI coefficients back to site basis used in DMET calculations
    CIcoeffs = pyscf.fci.addons.transform_ci_for_orbital_rotation(
        CIcoeffs, Norbs, Nele, utils.adjoint(mf.mo_coeff))

    return CIcoeffs
def calc_Umat( natevals, natorbs, Nsites, Nocc ):

    #Subroutine to calculate the summed U tensor

    #First form matrix given by one over the difference in the global 1RDM natural orbital evals 
    #(ie just the evals of the global 1RDM)
    #This only has to be defined for the occupied - virtual block b/c MF rdm invariant to intra-space rotations
    #chi = np.zeros( [ Nocc, (Nsites-Nocc) ] )
    #for mu in range(Nocc):
    #    for nu in range(Nocc,Nsites):
    #        chi[ mu, nu-Nocc ] = 1.0/(natevals[mu]-natevals[nu])

    #grr##
    chi = np.zeros( [ Nocc, Nsites ] )
    for mu in range(Nocc):
        for nu in range(Nsites):
            if( mu != nu and natevals[mu]-natevals[nu] > 1e-14 ):
                chi[ mu, nu ] = 1.0/(natevals[mu]-natevals[nu])

    #Adjoint of natural orbitals
    adj_natorbs = utils.adjoint( natorbs )

    #Form U tensor by summing over natural orbitals
    #PING can calculate U in this form more quickly using its hermiticity
    #U = np.einsum( 'ij,pj,js,ri,iq -> sqpr', chi, natorbs[:,Nocc:], adj_natorbs[Nocc:,:], natorbs[:,:Nocc], adj_natorbs[:Nocc,:] )
    U = np.einsum( 'ij,pj,js,ri,iq -> sqpr', chi, natorbs[:,:], adj_natorbs[:,:], natorbs[:,:Nocc], adj_natorbs[:Nocc,:] ) #grr

    #Return the total summed U matrix
    return U + np.einsum( 'sqpr -> qsrp', U )
    def one_rk_step_mf(self, nproc):
        #Subroutine to calculate one change in a runge-kutta step of any order
        #Using EOM that integrates CI coefficients and MF 1RDM
        #embedding orbitals obtained by diagonalizing MF 1RDM at each step
        #Prior to calling this routine need to update MF 1RDM and CI coefficients

        #Calculate embedding orbitals maintaining same phase from previous step
        prev_rotmat = []
        for frag in self.tot_system.frag_list:
            prev_rotmat.append(np.copy(frag.rotmat))

        self.tot_system.get_frag_rotmat()

        for cnt, frag in enumerate(self.tot_system.frag_list):
            phase = np.diag(
                np.diag(
                    np.real(
                        np.dot(utils.adjoint(prev_rotmat[cnt]), frag.rotmat))))
            frag.rotmat = np.dot(frag.rotmat, phase)

        #Calculate the rest of the terms needed for time-derivative of MF-1RDM
        self.tot_system.get_frag_corr1RDM()
        self.tot_system.get_glob1RDM()
        self.tot_system.get_nat_orbs()

        print(self.tot_system.NOevals)

        exit()

        #Calculate embedding hamiltonian
        self.tot_system.get_frag_Hemb()

        #Make sure Ecore for each fragment is 0 for dynamics
        for frag in self.tot_system.frag_list:
            frag.Ecore = 0.0

        #Calculate change in mf1RDM
        change_mf1RDM = self.delt * mf1rdm_timedep_mod.get_ddt_mf1rdm_serial(
            self.tot_system, int(self.tot_system.Nele / 2))

        #Calculate change in CI coefficients in parallel
        if (nproc == 1):
            change_CIcoeffs_list = []
            for frag in self.tot_system.frag_list:
                change_CIcoeffs_list.append(
                    -1j * self.delt *
                    applyham_pyscf.apply_ham_pyscf_fully_complex(
                        frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp,
                        frag.Nimp, 2 * frag.Nimp, frag.Ecore))
        else:
            frag_pool = multproc.Pool(nproc)
            change_CIcoeffs_list = frag_pool.starmap(
                applyham_wrapper,
                [(frag, self.delt) for frag in self.tot_system.frag_list])
            frag_pool.close()

        return change_mf1RDM, change_CIcoeffs_list
Esempio n. 6
0
    def get_ddt_corr1RDM( self ):
        #Subroutine to calculate first time-derivative of correlated 1RDM
        #Only calculated in the necessary impurity-bath space

        Ctil = applyham_pyscf.apply_ham_pyscf_fully_complex( self.CIcoeffs, self.h_emb, self.V_emb, self.Nimp, self.Nimp, 2*self.Nimp, self.Ecore )

        rdmtil = fci_mod.get_trans1RDM( self.CIcoeffs, Ctil, 2*self.Nimp, 2*self.Nimp )

        self.ddt_corr1RDM = -1j*( rdmtil - utils.adjoint( rdmtil ) )
    def print_data(self, current_time):
        #Subroutine to calculate and print-out observables of interest

        fmt_str = '%20.8e'

        ######## CALCULATE OBSERVABLES OF INTEREST #######

        #Calculate DMET energy, which also includes calculation of 1 & 2 RDMs and embedding hamiltonian for each fragment
        self.tot_system.get_DMET_E()

        #Calculate total number of electrons
        self.tot_system.get_DMET_Nele()

        ####msh####
        frag = self.tot_system.frag_list[0]
        #Efci = fci_mod.get_FCI_E( frag.h_emb, frag.V_emb, 0.0, frag.CIcoeffs, 2*frag.Nimp, frag.Nimp, frag.Nimp )
        #print( Efci, file=self.file_test )
        testdata = np.zeros(3 + self.tot_system.Nsites)
        testdata[0] = current_time
        testdata[1] = np.linalg.norm(frag.CIcoeffs)**2
        testdata[2] = np.real(np.sum(np.diag(frag.corr1RDM)))
        testdata[3:] = np.copy(
            np.real(np.diag(np.dot(utils.adjoint(frag.rotmat), frag.rotmat))))
        np.savetxt(self.file_test, testdata.reshape(1, testdata.shape[0]),
                   fmt_str)
        self.file_test.flush()
        ###########

        ######## PRINT OUT EVERYTHING #######

        #Print correlated density in the site basis
        cnt = 0
        corrdens = np.zeros(self.tot_system.Nsites)
        for frag in self.tot_system.frag_list:
            corrdens[cnt:cnt + frag.Nimp] = np.copy(
                np.diag(np.real(frag.corr1RDM[:frag.Nimp])))
            cnt += frag.Nimp
        corrdens = np.insert(corrdens, 0, current_time)
        np.savetxt(self.file_corrdens, corrdens.reshape(1, corrdens.shape[0]),
                   fmt_str)
        self.file_corrdens.flush()

        #Print output data
        output = np.zeros(3)
        output[0] = current_time
        output[1] = self.tot_system.DMET_E
        output[2] = self.tot_system.DMET_Nele
        np.savetxt(self.file_output, output.reshape(1, output.shape[0]),
                   fmt_str)
        self.file_output.flush()

        #Save total system to file for restart purposes using pickle
        file_system = open('restart_system.dat', 'wb')
        pickle.dump(self.tot_system, file_system)
        file_system.close()
def calc_Yvec(Umat, phimat, Nsites):

    #Subroutine to calculate the Y super-vector

    #Contract Umat and phimat
    Yvec = np.einsum('sqpr,sr -> pq', Umat, phimat)

    #Sum up Y vector
    Yvec = Yvec - utils.adjoint(Yvec)

    #Reshape Y vector to be a super-vector
    return -1j * Yvec.reshape(Nsites**2)
Esempio n. 9
0
    def get_ddt_corr1RDM( self ):
        #Subroutine to calculate first time-derivative of correlated 1RDM
        #Only calculated in the necessary impurity-bath space

        t1 = time.time() #grr

        Ctil = applyham_pyscf.apply_ham_pyscf_fully_complex( self.CIcoeffs, self.h_emb, self.V_emb, self.Nimp, self.Nimp, 2*self.Nimp, self.Ecore )

        t2 = time.time() #grr

        rdmtil = fci_mod.get_trans1RDM( self.CIcoeffs, Ctil, 2*self.Nimp, 2*self.Nimp )

        t3 = time.time() #grr

        #print()
        #print( 'Ctil = ',t2-t1 ) #grr
        #print( 'rdm = ',t3-t2 ) #grr
        #print()

        self.ddt_corr1RDM = -1j*( rdmtil - utils.adjoint( rdmtil ) )
def calc_Rmat( system ):

    #Subroutine to calculate the 4-index R tensor

    R = np.zeros( [ system.Nsites, system.Nsites, system.Nsites, system.Nsites ], dtype=complex )
    for r in range( system.Nsites ):

        #Fragment corresponding to site r
        frag = system.frag_list[system.site_to_frag_list[r]]

        #Concatenated list of virtual and core orbitals for fragment
        virtcore = np.concatenate( ( frag.virtrange, frag.corerange ) )

        #First form matrix given by one over the difference in the environment orbital eigenvalues
        #This only has to be defined for the bath - core/virtual space
        #Subtract off terms b/c indexing of embedding orbitals goes as imp,virt,bath,core
        chi = np.zeros( [ frag.Nimp, frag.Ncore+frag.Nvirt ] )
        i = 0
        for a in frag.bathrange:
            j = 0
            for c in virtcore:
                chi[i,j] = 1.0/( frag.env1RDM_evals[a-frag.Nimp] - frag.env1RDM_evals[c-frag.Nimp] )
                j += 1
            i += 1

        #Impurity index within fragment corresponding to site r
        rimp = system.site_to_impindx[r]

        #Adjoint of rotation matrix
        adj_rotmat = utils.adjoint( frag.rotmat )

        #Form portion of R tensor by summing over embedding orbitals
        #a is over bath orbitals and c is over virtual and core orbitals
        R[:,:,:,r] = np.einsum( 'ac,sc,ct,ua,a -> stu', chi, frag.rotmat[:,virtcore], adj_rotmat[virtcore,:], \
                                                 frag.rotmat[:,frag.bathrange], frag.corr1RDM[frag.Nimp:,rimp] )

    return R
Esempio n. 11
0
def one_rk_step(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp, delt,
                rotmat_old):

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

    rotmat, evals = get_rotmat(mf1RDM, Nsites, Nimp)

    phase = np.diag(
        np.round(np.diag(np.real(np.dot(utils.adjoint(rotmat_old), rotmat)))))
    rotmat = np.dot(rotmat, phase)

    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)

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

    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, rotmat
Esempio n. 12
0
def integrate(mf1RDM, CIcoeffs, Nsites, Nele, h_site, delt, Nimp, rotmat):

    l1, k1, rotmat = one_rk_step(mf1RDM, CIcoeffs, Nsites, Nele, h_site, Nimp,
                                 delt, rotmat)

    l2, k2, rotmat = one_rk_step(mf1RDM + 0.5 * l1, CIcoeffs + 0.5 * k1,
                                 Nsites, Nele, h_site, Nimp, delt, rotmat)

    l3, k3, rotmat = one_rk_step(mf1RDM + 0.5 * l2, CIcoeffs + 0.5 * k2,
                                 Nsites, Nele, h_site, Nimp, delt, rotmat)

    l4, k4, rotmat = one_rk_step(mf1RDM + 1.0 * l3, CIcoeffs + 1.0 * k3,
                                 Nsites, Nele, h_site, Nimp, delt, rotmat)

    mf1RDM = mf1RDM + 1.0 / 6.0 * (l1 + 2.0 * l2 + 2.0 * l3 + l4)
    CIcoeffs = CIcoeffs + 1.0 / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4)

    rotmat_old = np.copy(rotmat)
    rotmat, evals = get_rotmat(mf1RDM, Nsites, Nimp)
    phase = np.diag(
        np.round(np.diag(np.real(np.dot(utils.adjoint(rotmat_old), rotmat)))))
    rotmat = np.dot(rotmat, phase)

    return mf1RDM, CIcoeffs, rotmat
Esempio n. 13
0
    def one_rk_step_mf(self, nproc):
        #Subroutine to calculate one change in a runge-kutta step of any order
        #Using EOM that integrates CI coefficients and MF 1RDM
        #embedding orbitals obtained by diagonalizing MF 1RDM at each step
        #Prior to calling this routine need to update MF 1RDM and CI coefficients

        #calculate embedding orbitals maintaining same phase from previous step
        prev_rotmat = []
        for frag in self.tot_system.frag_list:
            prev_rotmat.append(np.copy(frag.rotmat))

        self.tot_system.get_frag_rotmat()

        for cnt, frag in enumerate(self.tot_system.frag_list):
            phase = np.diag(
                np.round(
                    np.diag(
                        np.real(
                            np.dot(utils.adjoint(prev_rotmat[cnt]),
                                   frag.rotmat)))))
            frag.rotmat = np.dot(frag.rotmat, phase)

        #calculate the rest of the terms needed for time-derivative of mf-1rdm
        self.tot_system.get_frag_corr1RDM()
        self.tot_system.get_glob1RDM()
        self.tot_system.get_nat_orbs()

        #calculate embedding hamiltonian
        self.tot_system.get_frag_Hemb()

        #Make sure Ecore for each fragment is 0 for dynamics
        for frag in self.tot_system.frag_list:
            frag.Ecore = 0.0

        #Calculate change in mf1RDM
        change_mf1RDM = self.delt * mf1rdm_timedep_mod.get_ddt_mf1rdm_serial(
            self.tot_system, round(self.tot_system.Nele / 2))

        ############
        #print( np.allclose( mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, round(self.tot_system.Nele/2) ), -1j*utils.commutator( self.tot_system.h_site, self.tot_system.mf1RDM ), rtol=0.0, atol=1e-12 ) )
        #print()
        #print( mf1rdm_timedep_mod.get_ddt_mf1rdm_serial( self.tot_system, round(self.tot_system.Nele/2) ) )
        #print()
        #print( -1j*utils.commutator( self.tot_system.h_site, self.tot_system.mf1RDM ) )
        #print()
        #print('--------------------------------------')
        #print()
        #exit() #msh

        #Calculate bath-bath terms of X-matrix necessary for CI propagation
        Xmat_list = []
        for frag in self.tot_system.frag_list:
            X_small = np.zeros([frag.Nimp, frag.Nimp], dtype=complex)

            for b in frag.bathrange:
                for a in frag.bathrange:
                    if (b != a):
                        ib = b - frag.Nimp - frag.Nvirt
                        ia = a - frag.Nimp - frag.Nvirt
                        X_small[ib, ia] = 1.0 / (
                            frag.env1RDM_evals[a - frag.Nimp] -
                            frag.env1RDM_evals[b - frag.Nimp]) * utils.matprod(
                                utils.adjoint(frag.rotmat)[b, :], 1j *
                                change_mf1RDM / self.delt, frag.rotmat[:, a])

            X = np.zeros([2 * frag.Nimp, 2 * frag.Nimp], dtype=complex)
            X[frag.Nimp:, frag.Nimp:] = np.copy(X_small)

            Xmat_list.append(X)

        #Calculate change in CI coefficients in parallel
        if (nproc == 1):
            change_CIcoeffs_list = []
            for ifrag, frag in enumerate(self.tot_system.frag_list):
                #change_CIcoeffs_list.append( -1j * self.delt * applyham_pyscf.apply_ham_pyscf_fully_complex( frag.CIcoeffs, frag.h_emb, frag.V_emb, frag.Nimp, frag.Nimp, 2*frag.Nimp, frag.Ecore ) )
                change_CIcoeffs_list.append(
                    -1j * self.delt *
                    applyham_pyscf.apply_ham_pyscf_fully_complex(
                        frag.CIcoeffs, frag.h_emb - Xmat_list[ifrag],
                        frag.V_emb, frag.Nimp, frag.Nimp, 2 * frag.Nimp,
                        frag.Ecore))  #grr

        else:
            frag_pool = multproc.Pool(nproc)
            change_CIcoeffs_list = frag_pool.starmap(
                applyham_wrapper,
                [(frag, self.delt) for frag in self.tot_system.frag_list])
            frag_pool.close()

        return change_mf1RDM, change_CIcoeffs_list
Esempio n. 14
0
    def integrate(self, nproc):
        #Subroutine to integrate equations of motion

        if (self.integ == 'rk1_orb'):
            #Use 1st order runge-kutta (ie euler's method) to integrate EOMs
            #Using EOM that explicitly integrate embedding orbitals and CI coefficients using X-matrix

            #Calculate appropriate changes in rotation matrices and CI coeffients
            #Note that l and k terms are for the rotation matrices and CI coefficients respectively
            l1_list, k1_list = self.one_rk_step_orb(nproc)

            #Update rotation matrices and CI coefficients by full time step
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.rotmat += l1_list[cnt]
                frag.CIcoeffs += k1_list[cnt]

        elif (self.integ == 'rk4_orb'):
            #Use 4th order runge-kutta to integrate EOMs
            #Using EOM that explicitly integrate embedding orbitals and CI coefficients using X-matrix

            #Copy rotation matrices (ie orbitals) and CI coefficients at time t
            init_rotmat_list = []
            init_CIcoeffs_list = []
            for frag in self.tot_system.frag_list:
                init_rotmat_list.append(np.copy(frag.rotmat))
                init_CIcoeffs_list.append(np.copy(frag.CIcoeffs))

            #Calculate appropriate changes in rotation matrices and CI coeffients
            #Note that l and k terms are for the rotation matrices and CI coefficients respectively
            l1_list, k1_list = self.one_rk_step_orb(nproc)

            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.rotmat = init_rotmat_list[cnt] + 0.5 * l1_list[cnt]
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k1_list[cnt]

            l2_list, k2_list = self.one_rk_step_orb(nproc)

            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.rotmat = init_rotmat_list[cnt] + 0.5 * l2_list[cnt]
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k2_list[cnt]

            l3_list, k3_list = self.one_rk_step_orb(nproc)

            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.rotmat = init_rotmat_list[cnt] + 1.0 * l3_list[cnt]
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 * k3_list[cnt]

            l4_list, k4_list = self.one_rk_step_orb(nproc)

            #Update rotation matrices and CI coefficients by full time-step
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.rotmat = init_rotmat_list[cnt] + 1.0 / 6.0 * (
                    l1_list[cnt] + 2.0 * l2_list[cnt] + 2.0 * l3_list[cnt] +
                    l4_list[cnt])
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 / 6.0 * (
                    k1_list[cnt] + 2.0 * k2_list[cnt] + 2.0 * k3_list[cnt] +
                    k4_list[cnt])

        elif (self.integ == 'rk4_mf'):
            #Use 4th order runge-kutta to integrate EOMs
            #Using EOM that integrates CI coefficients and MF 1RDM
            #embedding orbitals obtained by diagonalizing MF 1RDM at each step

            #Copy MF 1RDM and CI coefficients at time t
            init_mf1RDM = np.copy(self.tot_system.mf1RDM)
            init_CIcoeffs_list = []
            for frag in self.tot_system.frag_list:
                init_CIcoeffs_list.append(np.copy(frag.CIcoeffs))

            #Calculate appropriate changes in MF 1RDM and CI coefficients
            #Note that l and k terms are for MF 1 RDM and CI coefficients respectively
            l1, k1_list = self.one_rk_step_mf(nproc)

            self.tot_system.mf1RDM = init_mf1RDM + 0.5 * l1
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k1_list[cnt]

            ###msh##
            #print()
            #print('****************************')
            #print()
            #print( self.tot_system.mf1RDM )
            #print()
            #prev_rotmat = []
            #for frag in self.tot_system.frag_list:
            #    prev_rotmat.append( np.copy(frag.rotmat) )

            #self.tot_system.get_frag_rotmat()

            #for cnt, frag in enumerate(self.tot_system.frag_list):
            #    phase = np.diag( np.round( np.diag( np.real( np.dot( utils.adjoint( prev_rotmat[cnt] ), frag.rotmat ) ) ) ) )
            #    frag.rotmat = np.dot( frag.rotmat, phase )

            #self.tot_system.get_frag_corr1RDM()
            #self.tot_system.get_glob1RDM()
            #self.tot_system.get_nat_orbs()
            #self.tot_system.get_new_mf1RDM( int(self.tot_system.Nele/2) )
            #print( self.tot_system.mf1RDM)
            #exit()
            #######

            l2, k2_list = self.one_rk_step_mf(nproc)

            self.tot_system.mf1RDM = init_mf1RDM + 0.5 * l2
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 0.5 * k2_list[cnt]

            l3, k3_list = self.one_rk_step_mf(nproc)

            self.tot_system.mf1RDM = init_mf1RDM + 1.0 * l3
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 * k3_list[cnt]

            l4, k4_list = self.one_rk_step_mf(nproc)

            #Update MF 1RDM and CI coefficients by full time-step
            self.tot_system.mf1RDM = init_mf1RDM + 1.0 / 6.0 * (l1 + 2.0 * l2 +
                                                                2.0 * l3 + l4)
            for cnt, frag in enumerate(self.tot_system.frag_list):
                frag.CIcoeffs = init_CIcoeffs_list[cnt] + 1.0 / 6.0 * (
                    k1_list[cnt] + 2.0 * k2_list[cnt] + 2.0 * k3_list[cnt] +
                    k4_list[cnt])

            #Update rotation matrix at new time-step by diagonalizing MF 1RDM maintaing same phase from previous step
            #Technically maintaining phase amongst each partial step along RK algorithm
            prev_rotmat = []
            for frag in self.tot_system.frag_list:
                prev_rotmat.append(np.copy(frag.rotmat))

            self.tot_system.get_frag_rotmat()

            for cnt, frag in enumerate(self.tot_system.frag_list):
                phase = np.diag(
                    np.round(
                        np.diag(
                            np.real(
                                np.dot(utils.adjoint(prev_rotmat[cnt]),
                                       frag.rotmat)))))
                frag.rotmat = np.dot(frag.rotmat, phase)

        elif (self.integ == 'exact'):
            #Exactly propagate CI coefficients
            #Only works if have 2 fragments, each spanning full space since then embedding hamiltonian is time-independent
            #and embedding orbitals are time-independent
            #Embedding hamiltonian must also be real

            #Calculate embedding hamiltonian (isnt technically needed since it doesnt change)
            self.tot_system.get_frag_Hemb()

            #Form FCI hamiltonian (technically only need to do this at time zero since doesnt change)
            for frag in self.tot_system.frag_list:
                dim1 = frag.CIcoeffs.shape[0]
                dim2 = frag.CIcoeffs.shape[1]
                Ndet = dim1 * dim2
                H_fci = np.zeros([Ndet, Ndet])
                for i1 in range(dim1):
                    for i2 in range(dim2):
                        vec1 = np.zeros([dim1, dim2])
                        vec1[i1, i2] = 1.0
                        i = i2 + i1 * dim2
                        for j1 in range(dim1):
                            for j2 in range(dim2):
                                j = j2 + j1 * dim2
                                vec2 = np.zeros([dim1, dim2])
                                vec2[j1, j2] = 1.0

                                H_fci[i, j] = pyscf.fci.addons.overlap(
                                    vec1,
                                    np.real(
                                        applyham_pyscf.
                                        apply_ham_pyscf_fully_complex(
                                            vec2, frag.h_emb, frag.V_emb,
                                            frag.Nimp, frag.Nimp,
                                            2 * frag.Nimp, frag.Ecore)),
                                    2 * frag.Nimp, (frag.Nimp, frag.Nimp))

                #Convert matrix of CI coeffs to a vector
                CIvec = frag.CIcoeffs.flatten('F')

                #Exactly integrate the CI coefficients using the FCI hamiltonian
                frag.CIcoeffs = integrators.exact_timeindep_coeff_matrix(
                    CIvec, H_fci, self.delt).reshape((dim1, dim2), order='F')

        else:
            print('ERROR: A proper integrator was not specified')
            print()
            exit()
Esempio n. 15
0
    A = st.Psitf
    xhat = tf.constant(0,dtype=tf.float32)
    MUL = tf.matmul
    NoverM = tf.constant(float(N)/M,dtype=tf.float32)
    OneOverM = tf.constant(float(1)/M,dtype=tf.float32)

    for t in range(st.T):  # layers 0 thru T-1
        if t==0:
            # xhat is zero, vt is zero
            vt = y_ph
        else:
            bt = dxdr * NoverM
            vt = y_ph - MUL( A , xhat ) + bt * vt
        rvar = tf.reduce_sum(tf.square(vt),0) * OneOverM
        if t==0 or not st.tieS:
            Bt = MUL(ut.adjoint(A) ,S[t] )
        (xhat,dxdr) = shrink_func( xhat + MUL(Bt,vt),rvar , theta[t] )

    # in the case of T==1, at least some of the shrinkage functions  (e.g. "soft")
    # are overparameterized for only a loss on xhat.
    # To mitigate this, we add an extremely weak penalty on the norm of the next v
    if st.T == 1 and st.T1weight > 0:
        bt = dxdr * NoverM
        vt = y_ph - MUL( A , xhat ) + bt * vt
        rvar = tf.reduce_sum(tf.square(vt),0) * OneOverM
        st.add_penalty(st.T1weight * rvar )

st.set_output_node(xhat)

print 'nmse_check : %.1fdB' % (10*math.log10(st.current_value(st.nmse_check)) )
st.run()
Esempio n. 16
0
    def _integrate(self, prev, dt, xi0, q, g0=np.eye(4), eta0=np.array([0, 0, 0, 0, 0, 0]), intermediate=False):
        self.xi[0, :] = xi0
        self.eta[0, :] = eta0

        # integration over the body (don't need the initial point as the initial values are determined already)
        g_half = g0  # known initial condition
        for i in range(self.N - 1):
            s = i * self.ds
            # averaging over steps to get half step values
            xi_half = (self.xi[i, :] + prev.xi[i, :]) / 2
            eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2

            # implicit midpoint approximation
            xi_dot = (self.xi[i, :] - prev.xi[i, :]) / dt
            eta_dot = (self.eta[i, :] - prev.eta[i, :]) / dt

            # external loads
            A_bar = 0
            B_bar = 0
            # viscosity
            B_bar += self.body.viscosity(xi_dot, s)

            # other loads
            for load in self.loads:
                A, B = load.dist_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q, s)
                A_bar += A
                B_bar += B

            if intermediate and i == self.N - 2:
                for load in self.loads:
                    W = load.tip_load(g_half, xi_half, eta_half, xi_dot, eta_dot, self, q)
                    B_bar += W

            # spatial derivatives
            xi_der = np.linalg.inv(self.body.Psi_der(xi_half, s) - A_bar) @ (
                    (self.body.M(s) @ eta_dot) - (adjoint(eta_half).T @ self.body.M(s) @ eta_half) + (
                    adjoint(xi_half).T @ self.body.Psi(xi_half, s)) + B_bar - self.body.Psi_prime(xi_half, s))
            eta_der = xi_dot - (adjoint(xi_half) @ eta_half)

            # explicit Euler step
            xi_half_next = xi_half + self.ds * xi_der
            eta_half_next = eta_half + self.ds * eta_der
            R = g_half[:3, :3]
            p = g_half[:3, 3]
            p = p + self.ds * R @ xi_half[3:]
            q = toQuaternion(R)
            q = q + self.ds / 2 * np.array(
                [[0, -xi_half[0], -xi_half[1], -xi_half[2]], [xi_half[0], 0, xi_half[2], -xi_half[1]],
                 [xi_half[1], -xi_half[2], 0, xi_half[0]], [xi_half[2], xi_half[1], -xi_half[0], 0]]) @ q
            g_half = unflatten(np.concatenate([q, p]))

            # determine next step from half step value
            self.xi[i + 1, :] = 2 * xi_half_next - prev.xi[i + 1, :]
            self.eta[i + 1, :] = 2 * eta_half_next - prev.eta[i + 1, :]

        # midpoint RKMK to step the g values
        for i in range(self.N):
            eta_half = (self.eta[i, :] + prev.eta[i, :]) / 2
            q = prev.g[i, :4]
            p = prev.g[i, 4:]
            q = q + dt / 2 * np.array(
                [[0, -eta_half[0], -eta_half[1], -eta_half[2]], [eta_half[0], 0, eta_half[2], -eta_half[1]],
                 [eta_half[1], -eta_half[2], 0, eta_half[0]], [eta_half[2], eta_half[1], -eta_half[0], 0]]) @ q
            p = p + dt * toMatrix((q + prev.g[i, :4]) / 2) @ eta_half[3:]
            self.g[i, :] = np.concatenate([q, p])

        return g_half
Esempio n. 17
0
    ({}, 'problem_Giid'),
    ({
        'kappa': 15.
    }, 'problem_k15'),
)

for kw, base in configurations:
    # set up the inverse problem basic structure with the configuration-specific kw
    st = ut.Setup(**kw)
    y_ph = st.get_input_node()

    # the structure inside of Setup doesn't create all the fields until `set_output_node`
    # so set a dummy value ( not really used )
    st.set_output_node(
        tf.Variable(1.0, name='junk', dtype=tf.float32) *
        tf.matmul(ut.adjoint(st.Psitf), y_ph))

    # a dictionary with the problem setup
    prob = st.get_problem_vars()

    # save as a numpy archive
    np.savez(base + '.npz', **prob)
    print 'saved numpy archive %s.npz' % base

    try:
        from scipy.io import savemat
        savemat(base + '.mat', prob, oned_as='column')
        print 'saved matlab file %s.mat' % base
    except ImportError:
        pass
Esempio n. 18
0
    def contract_natorb_rotmat(self, NOevecs):
        #Subroutine to contract the rotation matrix of the given fragment with
        #the natural orbitals of the total system global 1RDM

        self.NO_rot = utils.matprod(utils.adjoint(NOevecs), self.rotmat)
Esempio n. 19
0
st.flag('setup', False, 'initialize the last layer greedily')

##### create LISTA graph
# start with the input (to the LISTA inference algorithm)
y_ph = st.get_input_node()
print st

if st.setup:
    import lista_setup
    lista_setup.Setup(st)

Wd = st.noisy_Psi()

L = 1.1 * LA.norm(Wd, 2)**2

We_ = ut.adjoint(Wd / L)
We = st.variable('We', We_)
We_ = st.loaded_state.get('We', We_)


def checkS(lS, dS):
    ls = lS.shape
    ds = dS.shape
    if ls == ds:
        return lS
    res = lS[:]
    if ls[0] < ds[0]:
        # expand with I-We_*Wd
        Snew = np.identity(st.n, dtype=Wd.dtype) - np.matmul(We_, Wd)
        ngrow = ds[0] - ls[0]
        tiledims = (ngrow, 1, 1)