Example #1
0
def loc_orbs(mol: gto.Mole, mo_coeff: Tuple[np.ndarray, np.ndarray], \
             s: np.ndarray, ref: str, variant: str) -> np.ndarray:
    """
        this function returns a set of localized MOs of a specific variant
        """
    # loop over spins
    for i, spin_mo in enumerate((mol.alpha, mol.beta)):

        if variant == 'fb':
            # foster-boys procedure
            loc = lo.Boys(mol, mo_coeff[i][:, spin_mo])
            loc.conv_tol = LOC_CONV
            # FB MOs
            mo_coeff[i][:, spin_mo] = loc.kernel()
        elif variant == 'pm':
            # pipek-mezey procedure
            loc = lo.PM(mol, mo_coeff[i][:, spin_mo])
            loc.conv_tol = LOC_CONV
            # PM MOs
            mo_coeff[i][:, spin_mo] = loc.kernel()
        elif 'ibo' in variant:
            # orthogonalized IAOs
            iao = lo.iao.iao(mol, mo_coeff[i][:, spin_mo])
            iao = lo.vec_lowdin(iao, s)
            # IBOs
            mo_coeff[i][:, spin_mo] = lo.ibo.ibo(mol, mo_coeff[i][:, spin_mo], iaos=iao, \
                                                 grad_tol = LOC_CONV, exponent=int(variant[-1]), verbose=0)
        # closed-shell reference
        if ref == 'restricted' and mol.spin == 0:
            mo_coeff[i + 1][:, spin_mo] = mo_coeff[i][:, spin_mo]
            break

    return mo_coeff
Example #2
0
def make_separate_spin_iaos(cell, mf, mos, iao_basis="minao"):
    """ Make IAOs for up and down MOs separately for all k points. 
  Args:
    cell (PySCF cell): Cell for the calculation.
    mf (PySCF UKS or UHF object): Contains the MOs information.
    mos (array): indices of the MOs to use to make the IAOs.
    basis (basis): IAO basis desired (in PySCF format).
  Returns:
    iaos_all (list): each list entry is np array of IAO orbitals 
                     in the basis of cell for a given k point.
  """
    # print("Making combined spin-up and spin-dw IAOs...")
    ovlp = mf.get_ovlp()
    coefs = np.array(mf.mo_coeff)[:, :, mos]
    iaos_up = lo.iao.iao(cell, coefs[0], minao=iao_basis)
    iaos_up = lo.vec_lowdin(iaos_up, ovlp)
    iaos_down = lo.iao.iao(cell, coefs[1], minao=iao_basis)
    iaos_down = lo.vec_lowdin(iaos_down, ovlp)
    return np.array([iaos_up, iaos_down])
Example #3
0
def localizeValence(mf, mo_coeff, method="iao"):
    if (method == "iao"):
        return iao.iao(mf.mol, mo_coeff)
    elif (method == "ibo"):
        a = iao.iao(mf.mol, mo_coeff)
        a = lo.vec_lowdin(a, mf.get_ovlp())
        return ibo.ibo(mf.mol, mo_coeff, iaos=a)
    elif (method == "boys"):
        return boys.Boys(mf.mol).kernel(mo_coeff)
    elif (method == "er"):
        return edmiston.ER(mf.mol).kernel(mo_coeff)
Example #4
0
def gen_basis(mol, mf, obdm, threshold=1e-2):
    """From an obdm, use IAOs to generate a minimal atomic basis for a given state """
    n = obdm.shape[0]
    obdm *= n
    w, v = np.linalg.eig(obdm)
    keep = np.abs(w) > threshold
    a = lo.orth_ao(mol, 'lowdin')
    basis = np.dot(a, v[:, keep]).real
    iao = lo.iao.iao(mol, basis)
    iao = lo.vec_lowdin(iao, mf.get_ovlp())
    return iao
Example #5
0
def test_pbc(li_cubic_ccecp):
    from pyqmc import supercell
    import scipy

    mol, mf = li_cubic_ccecp

    # S = np.ones((3, 3)) - np.eye(3)
    S = np.identity(3)
    mol = supercell.get_supercell(mol, S)
    kpts = supercell.get_supercell_kpts(mol)[:2]
    kdiffs = mf.kpts[np.newaxis] - kpts[:, np.newaxis]
    kinds = np.nonzero(np.linalg.norm(kdiffs, axis=-1) < 1e-12)[1]

    # Lowdin orthogonalized AO basis.
    # lowdin = lo.orth_ao(mol, "lowdin")
    loiao = lo.iao.iao(mol.original_cell, mf.mo_coeff, kpts=kpts)
    occs = [mf.mo_occ[k] for k in kinds]
    coefs = [mf.mo_coeff[k] for k in kinds]
    ovlp = mf.get_ovlp()[kinds]
    lowdin = [lo.vec_lowdin(l, o) for l, o in zip(loiao, ovlp)]
    lreps = [np.linalg.multi_dot([l.T, o, c]) for l, o, c in zip(lowdin, ovlp, coefs)]

    # make AO to localized orbital coefficients.
    mfobdm = [np.einsum("ij,j,kj->ik", l.conj(), o, l) for l, o in zip(lreps, occs)]

    ### Test OBDM calculation.
    nconf = 500
    nsteps = 100
    warmup = 6
    wf = Slater(mol, mf)
    configs = initial_guess(mol, nconf)
    obdm_dict = dict(mol=mol, orb_coeff=lowdin, kpts=kpts, nsweeps=4, warmup=10)
    obdm = OBDMAccumulator(**obdm_dict)

    df, coords = vmc(
        wf,
        configs,
        nsteps=nsteps,
        accumulators={"obdm": obdm},  # , "obdm_up": obdm_up, "obdm_down": obdm_down},
        verbose=True,
    )

    obdm_est = {}
    for k in ["obdm"]:  # , "obdm_up", "obdm_down"]:
        avg_norm = np.mean(df[k + "norm"][warmup:], axis=0)
        avg_obdm = np.mean(df[k + "value"][warmup:], axis=0)
        obdm_est[k] = normalize_obdm(avg_obdm, avg_norm)

    mfobdm = scipy.linalg.block_diag(*mfobdm)

    mae = np.mean(np.abs(obdm_est["obdm"] - mfobdm))
    assert mae < 0.05, f"mae {mae}"
Example #6
0
def localizeAllElectron(mf, method="lowdin"):
    if (method == "lowdin"):
        return fractional_matrix_power(mf.get_ovlp(), -0.5).T
    elif (method == "pm"):
        return pipek.PM(mf.mol).kernel(mf.mo_coeff)
    elif (method == "boys"):
        return boys.Boys(mf.mol).kernel(mf.mo_coeff)
    elif (method == "er"):
        return edmiston.ER(mf.mol).kernel(mf.mo_coeff)
    elif (method == "iao"):
        return iao.iao(mf.mol, mf.mo_coeff)
    elif (method == "ibo"):
        a = iao.iao(mf.mol, mf.mo_coeff)
        a = lo.vec_lowdin(a, mf.get_ovlp())
        return ibo.ibo(mf.mol, mf.mo_coeff, iaos=a)
Example #7
0
def calcIAO(cell, mf, basis, occ):
    ''' 
  input: 
  cell and scf (PBC SCF) objects from pyscf and basis
  to calculate IAOs on
  occ is MOs which IAOs should span
  output:
  Calculates 1RDM on orthog atomic orbitals, orthogonalized
  using Lowdin S^1/2
  Returns coefficient matrix for IAOs 
  '''
    s = mf.get_ovlp()[0]

    mo_occ = mf.mo_coeff[0][0][:, occ[0]]
    mo_occ2 = mf.mo_coeff[1][0][:, occ[1]]
    mo_occ = np.concatenate((mo_occ, mo_occ2), axis=1)
    a = lo.iao.iao(cell, mo_occ, minao=basis)
    a = lo.vec_lowdin(a, s)

    return a
Example #8
0
def make_combined_spin_iaos(cell, mf, mos, iao_basis="minao"):
    """ Make IAOs for up and down MOs together for all k points. 
  Args:
    cell (PySCF cell): Cell for the calculation.
    mf (PySCF UKS or UHF object): Contains the MOs information.
    mos (array): indices of the MOs to use to make the IAOs.
    basis (basis): IAO basis desired (in PySCF format).
  Returns:
    iaos_all (list): each list entry is np array of IAO orbitals 
                     in the basis of cell for a given k point.
  """
    # print("Making combined spin-up and spin-dw IAOs...")
    ovlp = mf.get_ovlp()
    # Concatenates the spin-up and the spin-down chosen MOs
    coefs = np.array(mf.mo_coeff)[
        :, :, mos
    ]  # Notice that, unlike the KUHF case, here we do not need to transpose the matrix
    coefs = np.concatenate([coefs[0].T, coefs[1].T]).T
    iaos = lo.iao.iao(cell, coefs, minao=iao_basis)
    iaos = lo.vec_lowdin(iaos, ovlp)
    return np.array([iaos, iaos])
Example #9
0
def make_minao_lo(ks, minao_ref):
    """
    Construct minao local orbitals.
    """
    cell = ks.cell
    nao = cell.nao_nr()
    kpts = ks.kpts
    nkpts = len(kpts)
    ovlp = ks.get_ovlp()
    C_ao_minao, labels = proj_ref_ao(cell, minao=minao_ref, kpts=kpts,
                                     return_labels=True)
    for k in range(nkpts):
        C_ao_minao[k] = lo.vec_lowdin(C_ao_minao[k], ovlp[k])
    labels = np.asarray(labels)

    C_ao_lo = np.zeros((nkpts, nao, nao), dtype=np.complex128)
    for idx, lab in zip(ks.U_idx, ks.U_lab):
        idx_minao = [i for i, l in enumerate(labels) if l in lab]
        assert len(idx_minao) == len(idx)
        C_ao_sub = C_ao_minao[:, :, idx_minao]
        C_ao_lo[:, :, idx] = C_ao_sub
    return C_ao_lo
Example #10
0
File: cdft.py Project: MSwenne/BEP
    cell.build()
    cell.rcut *= 2

    print("running intial DFT calc to generate IAOs")
    mf = dft.RKS(cell)
    mf.chkfile = 'graphene.chk'
    mf.init_guess = 'chkfile'
    mf.xc = 'pbe,pbe'
    mf.kernel()

    #we need to makVe the IAOs out of a converged calculation
    print("generating IAOs")
    mo_occ = mf.mo_coeff[:, mf.mo_occ > 0]
    a = lo.iao.iao(cell, mo_occ)
    # Orthogonalize IAO
    a = lo.vec_lowdin(a, mf.get_ovlp())

    #arbitrary parameters
    offset = 0.0001
    orbital = 4

    print("running constrained dft")

    mf = cdft(mf, mf.cell, offset, orbital, basis=a)
    population = fast_iao_mullikan_pop(mf, a=a)
    result = numpy.zeros(3)

    result[0] = offset
    result[1] = mf.e_tot
    result[2] = population[0][4]
    scaled_kpts = cell.get_scaled_kpts(abs_kpts)

    kmf = pscf.KRHF(cell, abs_kpts).density_fit()
    gdf = df.GDF(cell, abs_kpts)
    kmf.with_df = gdf
    kmf.checkfile = './ch4.chk'
    kmf.verbose = 5
    #kmf = pscf.KRHF(cell, abs_kpts)
    #kmf.__dict__.update(scf.chkfile.load('ch4.chk', 'scf')) # test
    ekpt = kmf.run()

    kmf_sc = k2gamma(kmf, abs_kpts, kmesh, realize = False, tol_deg = 5e-5, real_split = False)
    c_g_ao = kmf_sc.mo_coeff[0] 
    print "Supercell gamma MO in AO basis from conversion:"
    print c_g_ao
    
    mo_coeff_occ = kmf_sc.mo_coeff[0][:,kmf_sc.mo_occ[0]>0]
    lo_iao = lo.iao.iao(kmf_sc.cell, mo_coeff_occ)

    # Orthogonalize IAO
    lo_iao = lo.vec_lowdin(lo_iao, kmf_sc.get_ovlp()[0])

    # transform mo_occ to IAO representation. Note the AO dimension is reduced
    mo_coeff_occ = reduce(np.dot, (lo_iao.conj().T, kmf_sc.get_ovlp()[0], mo_coeff_occ))

    dm = np.dot(mo_coeff_occ, mo_coeff_occ.conj().T) * 2
    
    pmol = kmf_sc.cell.copy()
    pmol.build(False, False, basis='minao')
    kmf_sc.mulliken_pop(pmol, dm, s=np.eye(pmol.nao_nr()))
Example #12
0
    cell.build()
    cell.rcut*=2

    print("running intial DFT calc to generate IAOs")
    mf = dft.RKS(cell)
    mf.chkfile = 'graphene.chk'
    mf.init_guess = 'chkfile'
    mf.xc = 'pbe,pbe'
    mf.kernel()

    #we need to makVe the IAOs out of a converged calculation
    print("generating IAOs")
    mo_occ = mf.mo_coeff[:,mf.mo_occ>0]
    a = lo.iao.iao(cell, mo_occ)
    # Orthogonalize IAO
    a = lo.vec_lowdin(a, mf.get_ovlp())

    #arbitrary parameters
    offset = 0.0001
    orbital =4

    print("running constrained dft")

    mf  = cdft(mf,mf.cell,offset,orbital,basis=a)
    population = fast_iao_mullikan_pop(mf,a=a)
    result = numpy.zeros(3)

    result[0] = offset
    result[1] = mf.e_tot
    result[2] = population[0][4]
Example #13
0
    def init(self,molecule,charge,spin,basis_set,orb_basis='scf',cas=False,cas_nstart=None,cas_nstop=None,cas_nel=None,loc_nstart=None,loc_nstop=None,
            scf_conv_tol=1e-14):
    # {{{
        import pyscf
        from pyscf import gto, scf, ao2mo, molden, lo
        pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
        #PYSCF inputs
        print(" ---------------------------------------------------------")
        print("                      Using Pyscf:")
        print(" ---------------------------------------------------------")
        print("                                                          ")

        mol = gto.Mole()
        mol.atom = molecule

        mol.max_memory = 1000 # MB
        mol.symmetry = True
        mol.charge = charge
        mol.spin = spin
        mol.basis = basis_set
        mol.build()
        print("symmertry")
        print(mol.topgroup)

        #SCF 

        #mf = scf.RHF(mol).run(init_guess='atom')
        mf = scf.RHF(mol).run(conv_tol=scf_conv_tol)
        #C = mf.mo_coeff #MO coeffs
        enu = mf.energy_nuc()
        
        print(" SCF Total energy: %12.8f" %mf.e_tot) 
        print(" SCF Elec  energy: %12.8f" %(mf.e_tot-enu))
        print(mf.get_fock())
        print(np.linalg.eig(mf.get_fock())[0])
        
        if mol.symmetry == True:
            from pyscf import symm
            mo = symm.symmetrize_orb(mol, mf.mo_coeff)
            osym = symm.label_orb_symm(mol, mol.irrep_name, mol.symm_orb, mo)
            #symm.addons.symmetrize_space(mol, mo, s=None, check=True, tol=1e-07)
            for i in range(len(osym)):
                print("%4d %8s %16.8f"%(i+1,osym[i],mf.mo_energy[i]))

        #orbitals and lectrons
        n_orb = mol.nao_nr()
        n_b , n_a = mol.nelec 
        nel = n_a + n_b
        self.n_orb = mol.nao_nr()


        if cas == True:
            cas_norb = cas_nstop - cas_nstart
            from pyscf import mcscf
            assert(cas_nstart != None)
            assert(cas_nstop != None)
            assert(cas_nel != None)
        else:
            cas_nstart = 0
            cas_nstop = n_orb
            cas_nel = nel

        ##AO 2 MO Transformation: orb_basis or scf
        if orb_basis == 'scf':
            print("\nUsing Canonical Hartree Fock orbitals...\n")
            C = cp.deepcopy(mf.mo_coeff)
            print("C shape")
            print(C.shape)

        elif orb_basis == 'lowdin':
            assert(cas == False)
            S = mol.intor('int1e_ovlp_sph')
            print("Using lowdin orthogonalized orbitals")

            C = lowdin(S)
            #end

        elif orb_basis == 'boys':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :cas_nstart]
            cl_a = lo.Boys(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, cas_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'boys2':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :loc_nstart]
            cl_a = lo.Boys(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, loc_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'PM':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :cas_nstart]
            cl_a = lo.PM(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, cas_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'PM2':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :loc_nstart]
            cl_a = lo.PM(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, loc_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'ER':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :cas_nstart]
            cl_a = lo.PM(mol, mf.mo_coeff[:, cas_nstart:cas_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, cas_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'ER2':
            pyscf.lib.num_threads(1)  #with degenerate states and multiple processors there can be issues
            cl_c = mf.mo_coeff[:, :loc_nstart]
            cl_a = lo.ER(mol, mf.mo_coeff[:, loc_nstart:loc_nstop]).kernel(verbose=4)
            cl_v = mf.mo_coeff[:, loc_nstop:]
            C = np.column_stack((cl_c, cl_a, cl_v))

        elif orb_basis == 'ibmo':
            loc_vstop =  loc_nstop - n_a
            print(loc_vstop)

            mo_occ = mf.mo_coeff[:,mf.mo_occ>0]
            mo_vir = mf.mo_coeff[:,mf.mo_occ==0]
            c_core = mo_occ[:,:loc_nstart]
            iao_occ = lo.iao.iao(mol, mo_occ[:,loc_nstart:])
            iao_vir = lo.iao.iao(mol, mo_vir[:,:loc_vstop])
            c_out  = mo_vir[:,loc_vstop:]

            # Orthogonalize IAO
            iao_occ = lo.vec_lowdin(iao_occ, mf.get_ovlp())
            iao_vir = lo.vec_lowdin(iao_vir, mf.get_ovlp())

            #
            # Method 1, using Knizia's alogrithm to localize IAO orbitals
            #
            '''
            Generate IBOS from orthogonal IAOs
            '''
            ibo_occ = lo.ibo.ibo(mol, mo_occ[:,loc_nstart:], iaos = iao_occ)
            ibo_vir = lo.ibo.ibo(mol, mo_vir[:,:loc_vstop], iaos = iao_vir)

            C = np.column_stack((c_core,ibo_occ,ibo_vir,c_out))

        else: 
            print("Error:NO orbital basis defined")

        molden.from_mo(mol, 'orbitals.molden', C)

        if cas == True:
            print(C.shape)
            print(cas_norb)
            print(cas_nel)
            mycas = mcscf.CASSCF(mf, cas_norb, cas_nel)
            h1e_cas, ecore = mycas.get_h1eff(mo_coeff = C)  #core core orbs to form ecore and eff
            h2e_cas = ao2mo.kernel(mol, C[:,cas_nstart:cas_nstop], aosym='s4',compact=False).reshape(4 * ((cas_norb), )) 
            print(h1e_cas)
            print(h1e_cas.shape)
            #return h1e_cas,h2e_cas,ecore,C,mol,mf
            self.h = h1e_cas
            self.g = h2e_cas
            self.ecore = ecore
            self.mf = mf
            self.mol = mol
            self.C = cp.deepcopy(C[:,cas_nstart:cas_nstop])
            J,K = mf.get_jk()
            self.J = self.C.T @ J @ self.C
            self.K = self.C.T @ J @ self.C

            #HF density
            if orb_basis == 'scf':
                #C = C[:,cas_nstart:cas_nstop]
                D = mf.make_rdm1(mo_coeff=C)
                S = mf.get_ovlp()
                sal, svec = np.linalg.eigh(S)
                idx = sal.argsort()[::-1]
                sal = sal[idx]
                svec = svec[:, idx]
                sal = sal**-0.5
                sal = np.diagflat(sal)
                X = svec @ sal @ svec.T
                C_ao2mo = np.linalg.inv(X) @ C
                Cocc = C_ao2mo[:, :n_a]
                D = Cocc @ Cocc.T
                DMO = C_ao2mo.T   @ D @ C_ao2mo
                
                #only for cas space 
                DMO = DMO[cas_nstart:cas_nstop,cas_nstart:cas_nstop]
                self.dm_aa = DMO
                self.dm_bb = DMO
                print("DENSITY")
                print(self.dm_aa.shape)

            if 0:
                h = C.T.dot(mf.get_hcore()).dot(C)
                g = ao2mo.kernel(mol,C,aosym='s4',compact=False).reshape(4*((n_orb),))
                const,heff = get_eff_for_casci(cas_nstart,cas_nstop,h,g)
                print(heff)
                print("const",const)
                print("ecore",ecore)
                
                idx = range(cas_nstart,cas_nstop)
                h = h[:,idx] 
                h = h[idx,:] 
                g = g[:,:,:,idx] 
                g = g[:,:,idx,:] 
                g = g[:,idx,:,:] 
                g = g[idx,:,:,:] 

                self.ecore = const
                self.h = h + heff
                self.g = g 


        elif cas==False:
            h = C.T.dot(mf.get_hcore()).dot(C)
            g = ao2mo.kernel(mol,C,aosym='s4',compact=False).reshape(4*((n_orb),))
            print(h)
            #return h, g, enu, C,mol,mf
            self.h = h
            self.g = g
            self.ecore = enu
            self.mf = mf
            self.mol = mol
            self.C = C
            J,K = mf.get_jk()
            self.J = self.C.T @ J @ self.C
            self.K = self.C.T @ J @ self.C

            #HF density
            if orb_basis == 'scf':
                D = mf.make_rdm1(mo_coeff=None)
                S = mf.get_ovlp()
                sal, svec = np.linalg.eigh(S)
                idx = sal.argsort()[::-1]
                sal = sal[idx]
                svec = svec[:, idx]
                sal = sal**-0.5
                sal = np.diagflat(sal)
                X = svec @ sal @ svec.T
                C_ao2mo = np.linalg.inv(X) @ C
                Cocc = C_ao2mo[:, :n_a]
                D = Cocc @ Cocc.T
                DMO = C_ao2mo.T   @ D @ C_ao2mo
                self.dm_aa = DMO
                self.dm_bb = DMO
                print("DENSITY")
                print(self.dm_aa)
Example #14
0
def assign_rdm1s(mol: gto.Mole, s: np.ndarray, mo_coeff: Tuple[np.ndarray, np.ndarray], \
                 mo_occ: np.ndarray, ref: str, pop: str, part: str, multiproc: bool, verbose: int, \
                 **kwargs: float) -> Tuple[Union[List[np.ndarray], List[List[np.ndarray]]], Union[None, np.ndarray]]:
    """
        this function returns a list of population weights of each spin-orbital on the individual atoms
        """
    # declare nested kernel function in global scope
    global get_weights

    # max number of occupied spin-orbs
    n_spin = max(mol.alpha.size, mol.beta.size)

    # mol object projected into minao basis
    if pop == 'iao':
        pmol = lo.iao.reference_mol(mol)
    else:
        pmol = mol

    # number of atoms
    natm = pmol.natm

    # AO labels
    ao_labels = pmol.ao_labels(fmt=None)

    # overlap matrix
    if pop == 'mulliken':
        ovlp = s
    else:
        ovlp = np.eye(pmol.nao_nr())

    def get_weights(orb_idx: int):
        """
            this function computes the full set of population weights
            """
        # get orbital
        orb = mo[:, orb_idx].reshape(mo.shape[0], 1)
        # orbital-specific rdm1
        rdm1_orb = make_rdm1(orb, mocc[orb_idx])
        # population weights of rdm1_orb
        return _population(natm, ao_labels, ovlp, rdm1_orb)

    # init population weights array
    weights = [
        np.zeros([n_spin, pmol.natm], dtype=np.float64),
        np.zeros([n_spin, pmol.natm], dtype=np.float64)
    ]

    # loop over spin
    for i, spin_mo in enumerate((mol.alpha, mol.beta)):

        # get mo coefficients and occupation
        if pop == 'mulliken':
            mo = mo_coeff[i][:, spin_mo]
        elif pop == 'iao':
            iao = lo.iao.iao(mol, mo_coeff[i][:, spin_mo])
            iao = lo.vec_lowdin(iao, s)
            mo = contract('ki,kl,lj->ij', iao, s, mo_coeff[i][:, spin_mo])
        mocc = mo_occ[i][spin_mo]

        # domain
        domain = np.arange(spin_mo.size)
        # execute kernel
        if multiproc:
            n_threads = min(domain.size, lib.num_threads())
            with mp.Pool(processes=n_threads) as pool:
                weights[i] = pool.map(get_weights, domain)  # type:ignore
        else:
            weights[i] = list(map(get_weights, domain))  # type:ignore

        # closed-shell reference
        if ref == 'restricted' and mol.spin == 0:
            weights[i + 1] = weights[i]
            break

    # verbose print
    if 0 < verbose:
        symbols = [pmol.atom_pure_symbol(i) for i in range(pmol.natm)]
        print('\n *** partial population weights: ***')
        print(' spin  ' + 'MO       ' +
              '      '.join(['{:}'.format(i) for i in symbols]))
        for i, spin_mo in enumerate((mol.alpha, mol.beta)):
            for j in domain:
                with np.printoptions(suppress=True,
                                     linewidth=200,
                                     formatter={'float': '{:6.3f}'.format}):
                    print('  {:s}    {:>2d}   {:}'.format(
                        'a' if i == 0 else 'b', spin_mo[j], weights[i][j]))

    # bond-wise partitioning
    if part == 'bonds':
        # init population centres array and get threshold
        centres = [
            np.zeros([mol.alpha.size, 2], dtype=np.int),
            np.zeros([mol.beta.size, 2], dtype=np.int)
        ]
        thres = kwargs['thres']
        # loop over spin
        for i, spin_mo in enumerate((mol.alpha, mol.beta)):
            # loop over orbitals
            for j in domain:
                # get sorted indices
                max_idx = np.argsort(weights[i][j])[::-1]
                # compute population centres
                if np.abs(weights[i][j][max_idx[0]]) > thres:
                    # core orbital or lone pair
                    centres[i][j] = np.array([max_idx[0], max_idx[0]],
                                             dtype=np.int)
                else:
                    # valence orbitals
                    centres[i][j] = np.sort(
                        np.array([max_idx[0], max_idx[1]], dtype=np.int))
            # closed-shell reference
            if ref == 'restricted' and mol.spin == 0:
                centres[i + 1] = centres[i]
                break
        # unique and repetitive centres
        centres_unique = np.array(
            [np.unique(centres[i], axis=0) for i in range(2)])
        rep_idx = [[
            np.where((centres[i] == j).all(axis=1))[0]
            for j in centres_unique[i]
        ] for i in range(2)]

    if part in ['atoms', 'eda']:
        return weights, None
    else:
        return rep_idx, centres_unique
Example #15
0
File: cdft.py Project: sapatha2/cuo
def get_localized_orbitals(mf, lo_method, mo=None):
    if mo is None:
        mo = mf.mo_coeff

    if not isinstance(mf, khf.KSCF):
        mol = mf.mol
        s1e = mf.get_ovlp()

        if lo_method.lower() == 'lowdin' or lo_method.lower() == 'meta_lowdin':
            C = lo.orth_ao(mf, 'meta_lowdin', s=s1e)
            C_inv = np.dot(C.conj().T, s1e)
            if isinstance(mf, scf.hf.RHF):
                C_inv_spin = C_inv
            else:
                C_inv_spin = np.array([C_inv] * 2)

        elif lo_method == 'iao':
            s1e = mf.get_ovlp()
            pmol = mf.mol.copy()
            pmol.build(False, False, basis='minao')
            if isinstance(mf, scf.hf.RHF):
                mo_coeff_occ = mf.mo_coeff[:, mf.mo_occ > 0]
                C = lo.iao.iao(mf.mol, mo_coeff_occ)
                # Orthogonalize IAO
                C = lo.vec_lowdin(C, s1e)
                C_inv = np.dot(C.conj().T, s1e)
                C_inv_spin = C_inv
            else:
                mo_coeff_occ_a = mf.mo_coeff[0][:, mf.mo_occ[0] > 0]
                mo_coeff_occ_b = mf.mo_coeff[1][:, mf.mo_occ[1] > 0]
                C_a = lo.iao.iao(mf.mol, mo_coeff_occ_a)
                C_b = lo.iao.iao(mf.mol, mo_coeff_occ_b)
                C_a = lo.vec_lowdin(C_a, s1e)
                C_b = lo.vec_lowdin(C_b, s1e)
                C_inv_a = np.dot(C_a.T, s1e)
                C_inv_b = np.dot(C_b.T, s1e)
                C_inv_spin = np.array([C_inv_a, C_inv_b])

        elif lo_method == 'nao':
            C = lo.orth_ao(mf, 'nao')
            C_inv = np.dot(C.conj().T, s1e)
            if isinstance(mf, scf.hf.RHF):
                C_inv_spin = C_inv
            else:
                C_inv_spin = np.array([C_inv] * 2)

        else:
            raise NotImplementedError("UNDEFINED LOCAL ORBITAL TYPE, EXIT...")

        mo_lo = np.einsum('...jk,...kl->...jl', C_inv_spin, mo)
        return C_inv_spin, mo_lo

    else:
        cell = mf.cell
        s1e = mf.get_ovlp()

        if lo_method.lower() == 'lowdin' or lo_method.lower() == 'meta_lowdin':
            nkpt = len(mf.kpts)
            C_arr = []
            C_inv_arr = []
            for i in range(nkpt):
                C_curr = lo.orth_ao(mf, 'meta_lowdin', s=s1e[i])
                C_inv_arr.append(np.dot(C_curr.conj().T, s1e[i]))
            C_inv_arr = np.array(C_inv_arr)
            if isinstance(mf, scf.hf.RHF):
                C_inv_spin = C_inv_arr
            else:
                C_inv_spin = np.array([C_inv_arr] * 2)
        else:
            raise NotImplementedError("CONSTRUCTING...EXIT")

        mo_lo = np.einsum('...jk,...kl->...jl', C_inv_spin, mo)
        return C_inv_spin, mo_lo
Example #16
0
def setuph2(r, obdm_steps=5):
    from pyscf import gto, scf, lo
    from pyqmc.accumulators import LinearTransform, EnergyAccumulator
    from pyqmc.obdm import OBDMAccumulator
    from pyqmc.cvmc import DescriptorFromOBDM, PGradDescriptor

    import itertools

    # ccECP from A. Annaberdiyev et al. Journal of Chemical Physics 149, 134108 (2018)
    basis = {
        "H":
        gto.basis.parse("""
    H S
23.843185 0.00411490
10.212443 0.01046440
4.374164 0.02801110
1.873529 0.07588620
0.802465 0.18210620
0.343709 0.34852140
0.147217 0.37823130
0.063055 0.11642410
""")
    }
    """
H S
0.040680 1.00000000
H S
0.139013 1.00000000
H P
0.166430 1.00000000
H P
0.740212 1.00000000
"""
    ecp = {
        "H":
        gto.basis.parse_ecp("""
    H nelec 0
H ul
1 21.24359508259891 1.00000000000000
3 21.24359508259891 21.24359508259891
2 21.77696655044365 -10.85192405303825
""")
    }

    mol = gto.M(atom=f"H 0. 0. 0.; H 0. 0. {r}",
                unit="bohr",
                basis=basis,
                ecp=ecp,
                verbose=5)
    mf = scf.RHF(mol).run()
    mo_occ = mf.mo_coeff[:, mf.mo_occ > 0]
    a = lo.iao.iao(mol, mo_occ)
    a = lo.vec_lowdin(a, mf.get_ovlp())

    obdm_up = OBDMAccumulator(mol=mol, orb_coeff=a, nstep=obdm_steps, spin=0)
    obdm_down = OBDMAccumulator(mol=mol, orb_coeff=a, nstep=obdm_steps, spin=1)

    wf = pyqmc.slater_jastrow(mol, mf)

    freeze = {}
    for k in wf.parameters:
        freeze[k] = np.zeros(wf.parameters[k].shape, dtype='bool')
    print(freeze.keys())
    print(wf.parameters['wf1mo_coeff_alpha'])
    #this freezing allows us to easily go between bonding and
    # AFM configurations.
    freeze['wf1mo_coeff_alpha'][0, 0] = True
    freeze['wf1mo_coeff_beta'][1, 0] = True

    descriptors = {
        "t": [[(1.0, (0, 1)), (1.0, (1, 0))], [(1.0, (0, 1)), (1.0, (1, 0))]],
        "trace": [[(1.0, (0, 0)), (1.0, (1, 1))], [(1.0, (0, 0)),
                                                   (1.0, (1, 1))]],
    }
    for i in [0, 1]:
        descriptors[f"nup{i}"] = [[(1.0, (i, i))], []]
        descriptors[f"ndown{i}"] = [[], [(1.0, (i, i))]]

    acc = PGradDescriptor(
        EnergyAccumulator(mol),
        LinearTransform(wf.parameters, freeze=freeze),
        [obdm_up, obdm_down],
        DescriptorFromOBDM(descriptors, norm=2.0),
    )

    return {
        "wf": wf,
        "acc": acc,
        "mol": mol,
        "mf": mf,
        "descriptors": descriptors
    }
Example #17
0
m.__dict__.update(lib.chkfile.load('rohf/Cuvtz_r1.725_s1_ROHF_0.chk', 'scf'))

for i in (mol.basis["Cu"]):
    if (len(cu_basis) < 2):
        if (i[0] == 0): cu_basis.append(i)
    elif (len(cu_basis) == 2):
        if (i[0] == 1): cu_basis.append(i)
    elif (len(cu_basis) == 3):
        if (i[0] == 2): cu_basis.append(i)
    else:
        pass
o_basis = []
for i in (mol.basis["O"]):
    if (len(o_basis) == 0):
        if (i[0] == 0): o_basis.append(i)
    elif (len(o_basis) == 1):
        if (i[0] == 1): o_basis.append(i)
    else:
        pass
minbasis = {'Cu': cu_basis, 'O': o_basis}

#Build IAOs
s = m.get_ovlp()
a = lo.iao.iao(mol, mo_coeff, minao=minbasis)
a = lo.vec_lowdin(a, s)
a.dump('b3lyp_iao_b.pickle')

#Plot IAOs
m.mo_coeff[:, :a.shape[1]] = a
print_qwalk_mol(mol, m, method='scf', basename='qwalk/b3lyp_iao_b')
Example #18
0
def test_pbc():
    from pyscf.pbc import gto, scf
    from pyqmc import PySCFSlaterUHF, PySCFSlaterPBC
    from pyqmc import slaterpbc
    import scipy

    lvecs = (np.ones((3, 3)) - np.eye(3)) * 2.0
    mol = gto.M(
        atom="H 0. 0. -{0}; H 0. 0. {0}".format(0.7),
        basis="sto-3g",
        unit="bohr",
        verbose=0,
        a=lvecs,
    )
    mf = scf.KRHF(mol, kpts=mol.make_kpts((2, 2, 2)))
    mf = mf.run()

    S = np.ones((3, 3)) - 2 * np.eye(3)
    mol = slaterpbc.get_supercell(mol, S)
    kpts = slaterpbc.get_supercell_kpts(mol)[:2]
    kdiffs = mf.kpts[np.newaxis] - kpts[:, np.newaxis]
    kinds = np.nonzero(np.linalg.norm(kdiffs, axis=-1) < 1e-12)[1]

    # Lowdin orthogonalized AO basis.
    # lowdin = lo.orth_ao(mol, "lowdin")
    loiao = lo.iao.iao(mol.original_cell, mf.mo_coeff, kpts=kpts)
    occs = [mf.mo_occ[k] for k in kinds]
    coefs = [mf.mo_coeff[k] for k in kinds]
    ovlp = mf.get_ovlp()[kinds]
    lowdin = [lo.vec_lowdin(l, o) for l, o in zip(loiao, ovlp)]
    lreps = [np.linalg.multi_dot([l.T, o, c]) for l, o, c in zip(lowdin, ovlp, coefs)]

    # make AO to localized orbital coefficients.
    mfobdm = [np.einsum("ij,j,kj->ik", l.conj(), o, l) for l, o in zip(lreps, occs)]

    ### Test OBDM calculation.
    nconf = 800
    nsteps = 50
    warmup = 6
    wf = PySCFSlaterPBC(mol, mf)
    configs = initial_guess(mol, nconf)
    obdm_dict = dict(mol=mol, orb_coeff=lowdin, kpts=kpts, nsweeps=4, warmup=10)
    obdm = OBDMAccumulator(**obdm_dict)
    obdm_up = OBDMAccumulator(**obdm_dict, spin=0)
    obdm_down = OBDMAccumulator(**obdm_dict, spin=1)

    df, coords = vmc(
        wf,
        configs,
        nsteps=nsteps,
        accumulators={"obdm": obdm, "obdm_up": obdm_up, "obdm_down": obdm_down},
        verbose=True,
    )
    df = DataFrame(df)

    obdm_est = {}
    for k in ["obdm", "obdm_up", "obdm_down"]:
        avg_norm = np.array(df.loc[warmup:, k + "norm"].values.tolist()).mean(axis=0)
        avg_obdm = np.array(df.loc[warmup:, k + "value"].values.tolist()).mean(axis=0)
        obdm_est[k] = normalize_obdm(avg_obdm, avg_norm)

    print("Average OBDM(orb,orb)", obdm_est["obdm"].round(3))
    mfobdm = scipy.linalg.block_diag(*mfobdm)
    print("mf obdm", mfobdm.round(3))
    max_abs_err = np.max(np.abs(obdm_est["obdm"] - mfobdm))
    assert max_abs_err < 0.05, "max abs err {0}".format(max_abs_err)
    print(obdm_est["obdm_up"].diagonal().round(3))
    print(obdm_est["obdm_down"].diagonal().round(3))
    mae = np.mean(np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm))
    maup = np.mean(np.abs(obdm_est["obdm_up"]))
    madn = np.mean(np.abs(obdm_est["obdm_down"]))
    mamf = np.mean(np.abs(mfobdm))
    assert mae < 0.05, "mae {0}\n maup {1}\n madn {2}\n mamf {3}".format(
        mae, maup, madn, mamf
    )