示例#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
示例#2
0
from pyscf import lo
from pyscf.tools import molden

mol = gto.M(
    atom = '''
C    0.000000000000     1.398696930758     0.000000000000
C    0.000000000000    -1.398696930758     0.000000000000
C    1.211265339156     0.699329968382     0.000000000000
C    1.211265339156    -0.699329968382     0.000000000000
C   -1.211265339156     0.699329968382     0.000000000000
C   -1.211265339156    -0.699329968382     0.000000000000
H    0.000000000000     2.491406946734     0.000000000000
H    0.000000000000    -2.491406946734     0.000000000000
H    2.157597486829     1.245660462400     0.000000000000
H    2.157597486829    -1.245660462400     0.000000000000
H   -2.157597486829     1.245660462400     0.000000000000
H   -2.157597486829    -1.245660462400     0.000000000000''',
    basis = '6-31g')
mf = scf.RHF(mol).run()

pz_idx = numpy.array([17,20,21,22,23,30,36,41,42,47,48,49])-1
loc_orb = lo.Boys(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'boys.molden', loc_orb)

loc_orb = lo.ER(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'edmiston.molden', loc_orb)

loc_orb = lo.PM(mol, mf.mo_coeff[:,pz_idx]).kernel()
molden.from_mo(mol, 'pm.molden', loc_orb)

示例#3
0
#!/usr/bin/env python
'''
PM localization for PBC systems.  It supports gamma point only.
'''

import numpy as np
from pyscf.pbc import gto
from pyscf.pbc import scf
from pyscf import lo

cell = gto.Cell()
cell.atom = '''
 C                  3.17500000    3.17500000    3.17500000
 H                  2.54626556    2.54626556    2.54626556
 H                  3.80373444    3.80373444    2.54626556
 H                  2.54626556    3.80373444    3.80373444
 H                  3.80373444    2.54626556    3.80373444
'''
cell.basis = 'sto3g'
cell.a = np.eye(3) * 6.35
cell.build()

mf = scf.RHF(cell).density_fit().run()
lmo = lo.PM(cell, mf.mo_coeff[:, 1:5]).kernel()

nk = [1, 1, 1]
abs_kpts = cell.make_kpts(nk)
kmf = scf.KRHF(cell, abs_kpts).density_fit().run()
lmo = lo.PM(cell, kmf.mo_coeff[0][:, 1:5]).kernel()
示例#4
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)
示例#5
0
def localize(pyscf_mf, loc_type='pm', verbose=0):
    """ Localize orbitals given a PySCF mean-field object

    Args:
        pyscf_mf:  PySCF mean field object
        loc_type (str): localization type;
            Pipek-Mezey ('pm') or Edmiston-Rudenberg ('er')
        verbose (int): print level during localization

    Returns:
        pyscf_mf:  Updated PySCF mean field object with localized orbitals
    """
    # Note: After loading with `load_casfile_to_pyscf()` you can quiet message
    # by resetting mf.mol, i.e., mf.mol = gto.M(...)
    # but this assumes you have the *exact* molecular specification on hand.
    # I've gotten acceptable results by restoring mf.mol this way (usually
    # followed by calling mf.kernel()). But consistent localization is not a
    # given (not unique) despite restoring data this way, hence the message.
    if len(pyscf_mf.mol.atom) == 0:
        sys.exit("`localize()` requires atom loc. and atomic basis to be" + \
                 " defined.\n  " + \
                 "It also can be sensitive to the initial guess and MO" + \
                 " coefficients.\n  " + \
                 "Best to try re-creating the PySCF molecule and doing the" + \
                 " SCF, rather than\n  " + \
                 "try to load the mean-field object with" + \
                 " `load_casfile_to_pyscf()`. You can \n " + \
                 "try to provide the missing information, but consistency" + \
                 " cannot be guaranteed!")

    # Split-localize (localize DOCC, SOCC, and virtual separately)
    docc_idx = np.where(np.isclose(pyscf_mf.mo_occ, 2.))[0]
    socc_idx = np.where(np.isclose(pyscf_mf.mo_occ, 1.))[0]
    virt_idx = np.where(np.isclose(pyscf_mf.mo_occ, 0.))[0]

    # Pipek-Mezey
    if loc_type.lower() == 'pm':
        print("Localizing doubly occupied ... ", end="")
        loc_docc_mo = lo.PM(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, docc_idx]).kernel(verbose=verbose)
        print("singly occupied ... ", end="")
        loc_socc_mo = lo.PM(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, socc_idx]).kernel(verbose=verbose)
        print("virtual ... ", end="")
        loc_virt_mo = lo.PM(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, virt_idx]).kernel(verbose=verbose)
        print("DONE")

    # Edmiston-Rudenberg
    elif loc_type.lower() == 'er':
        print("Localizing doubly occupied ... ", end="")
        loc_docc_mo = lo.ER(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, docc_idx]).kernel(verbose=verbose)
        print("singly occupied ... ", end="")
        loc_socc_mo = lo.ER(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, socc_idx]).kernel(verbose=verbose)
        print("virtual ... ", end="")
        loc_virt_mo = lo.ER(
            pyscf_mf.mol,
            pyscf_mf.mo_coeff[:, virt_idx]).kernel(verbose=verbose)
        print("DONE")

    # overwrite orbitals with localized orbitals
    pyscf_mf.mo_coeff[:, docc_idx] = loc_docc_mo.copy()
    pyscf_mf.mo_coeff[:, socc_idx] = loc_socc_mo.copy()
    pyscf_mf.mo_coeff[:, virt_idx] = loc_virt_mo.copy()

    return pyscf_mf
示例#6
0
def init_pyscf(molecule, charge, spin, basis, orbitals):
    # {{{
    #PYSCF inputs
    print(" ---------------------------------------------------------")
    print("                                                          ")
    print("                      Using Pyscf:")
    print("                                                          ")
    print(" ---------------------------------------------------------")
    print("                                                          ")
    mol = gto.Mole()
    mol.atom = molecule

    # this is needed to prevent openblas - openmp clash for some reason
    # todo: take out
    lib.num_threads(1)

    mol.max_memory = 1000  # MB
    mol.charge = charge
    mol.spin = spin
    mol.basis = basis
    mol.build()

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

    #SCF
    mf = scf.RHF(mol).run()
    #mf = scf.ROHF(mol).run()
    C = mf.mo_coeff  #MO coeffs
    S = mf.get_ovlp()

    print(" Orbs1:")
    print(C)
    Cl = cp.deepcopy(C)
    if orbitals == "boys":
        print("\nUsing Boys localised orbitals:\n")
        cl_o = lo.Boys(mol, mf.mo_coeff[:, :n_a]).kernel(verbose=4)
        cl_v = lo.Boys(mol, mf.mo_coeff[:, n_a:]).kernel(verbose=4)
        Cl = np.column_stack((cl_o, cl_v))

    elif orbitals == "pipek":
        print("\nUsing Pipek-Mezey localised orbitals:\n")
        cl_o = lo.PM(mol, mf.mo_coeff[:, :n_a]).kernel(verbose=4)
        cl_v = lo.PM(mol, mf.mo_coeff[:, n_a:]).kernel(verbose=4)
        Cl = np.column_stack((cl_o, cl_v))
    elif orbitals == "edmiston":
        print("\nUsing Edmiston-Ruedenberg localised orbitals:\n")
        cl_o = lo.ER(mol, mf.mo_coeff[:, :n_a]).kernel(verbose=4)
        cl_v = lo.ER(mol, mf.mo_coeff[:, n_a:]).kernel(verbose=4)
        Cl = np.column_stack((cl_o, cl_v))
#    elif orbitals == "svd":
#        print("\nUsing SVD localised orbitals:\n")
#        cl_o = cp.deepcopy(mf.mo_coeff[:,:n_a])
#        cl_v = cp.deepcopy(mf.mo_coeff[:,n_a:])
#
#        [U,s,V] = np.linalg.svd(cl_o)
#        cl_o = cl_o.dot(V.T)
#        Cl = np.column_stack((cl_o,cl_v))
    elif orbitals == "canonical":
        print("\nUsing Canonical orbitals:\n")
        pass
    else:
        print("Error: Wrong orbital specification:")
        exit()

    print(" Overlap:")
    print(C.T.dot(S).dot(Cl))

    # sort by cluster
    blocks = [[0, 1, 2, 3], [4, 5, 6, 7]]
    O = Cl[:, :n_a]
    V = Cl[:, n_a:]
    [sorted_order, cluster_sizes] = mulliken_clustering(blocks, mol, O)
    O = O[:, sorted_order]
    [sorted_order, cluster_sizes] = mulliken_clustering(blocks, mol, V)
    V = V[:, sorted_order]
    Cl = np.column_stack((O, V))

    C = cp.deepcopy(Cl)
    # dump orbitals for viewing
    molden.from_mo(mol, 'orbitals_canon.molden', C)
    molden.from_mo(mol, 'orbitals_local.molden', Cl)

    ##READING INTEGRALS FROM PYSCF
    E_nu = gto.Mole.energy_nuc(mol)
    T = mol.intor('int1e_kin_sph')
    V = mol.intor('int1e_nuc_sph')
    hcore = T + V
    S = mol.intor('int1e_ovlp_sph')
    g = mol.intor('int2e_sph')

    print("\nSystem and Method:")
    print(mol.atom)

    print("Basis set                                      :%12s" % (mol.basis))
    print("Number of Orbitals                             :%10i" % (n_orb))
    print("Number of electrons                            :%10i" % (nel))
    print("Nuclear Repulsion                              :%16.10f " % E_nu)
    print("Electronic SCF energy                          :%16.10f " %
          (mf.e_tot - E_nu))
    print("SCF Energy                                     :%16.10f" %
          (mf.e_tot))

    print(" AO->MO")
    g = np.einsum("pqrs,pl->lqrs", g, C)
    g = np.einsum("lqrs,qm->lmrs", g, C)
    g = np.einsum("lmrs,rn->lmns", g, C)
    g = np.einsum("lmns,so->lmno", g, C)

    h = reduce(np.dot, (C.conj().T, hcore, C))

    #    #mf = mf.density_fit(auxbasis='weigend')
    #    #mf._eri = None
    #    mcc = cc.UCCSD(mf)
    #    eris = mcc.ao2mo()
    #    eris.g = g
    #    eris.focka = h
    #    eris.fockb = h
    #
    #    emp2, t1, t2 = mcc.init_amps(eris)
    #    exit()
    #    print(abs(t2).sum() - 4.9318753386922278)
    #    print(emp2 - -0.20401737899811551)
    #    t1, t2 = update_amps(mcc, t1, t2, eris)
    #    print(abs(t1).sum() - 0.046961325647584914)
    #    print(abs(t2).sum() - 5.378260578551683   )
    #
    #
    #    exit()

    return (n_orb, n_a, n_b, h, g, mol, E_nu, mf.e_tot, C, S)
示例#7
0
mol = gto.M(
    atom=open('Ru_ph_ph_ph.xyz').read(),
    unit='ang',
    basis='STO3G',
    charge=2,
    verbose=3,
    symmetry='C1',
    max_memory=13000,
)

mf = mol.HF().run()

# split localizing by Pipek-Mezey
if len(sys.argv) == 2 and sys.argv[1] == 'localized':
    print("Using PM localized orbitals")
    C = np.hstack((lo.PM(mol, mf.mo_coeff[:, mf.mo_occ > 0]).kernel(),
                   lo.PM(mol, mf.mo_coeff[:, mf.mo_occ == 0]).kernel()))
else:
    print("Using RHF orbitals")
    C = mf.mo_coeff

tree = t3ns.T3NS(mol, c=C, network='T3NS')

tree.kernel(D=50, doci=True, max_sweeps=10, verbosity=2)
tree.disentangle()
tree.kernel(D=50, doci=True, max_sweeps=10, verbosity=2)

E = tree.kernel(D=100,
                doci=True,
                max_sweeps=100,
                energy_conv=1e-5,
示例#8
0
cell.pseudo = 'gth-pade'
cell.verbose = 5
cell.build(unit='Angstrom')
mf = scf.RHF(cell)
mf.kernel()
'''
generates IAOs
'''
mo_occ = mf.mo_coeff[:, mf.mo_occ > 0]
#a = lo.iao.iao(cell, mo_occ, minao='minao')
#a = lo.iao.iao(cell, mo_occ, minao='gth-szv')
a = iao.iao(cell, mo_occ, minao='gth-szv', scf_basis=True,
            ref_basis='gth-szv')  # scf basis
print "IAO shape: ", a.shape
molden.from_mo(cell, 'diamondiao_szv.molden', a)

# Orthogonalize IAO
a = lo.vec_lowdin(a, mf.get_ovlp())
molden.from_mo(cell, 'diamondiao_szv_ortho.molden', a)

loc_obj = lo.PM(cell, a)
cost_before = loc_obj.cost_function()
print "cost function before localization: ", cost_before
loc_orb = loc_obj.kernel()
molden.from_mo(cell, 'diamondiao_szv_PM.molden', loc_orb)

#ibo must take the orthonormalized IAOs
#ibo = lo.ibo.ibo(cell, mo_occ, a)
#print "IBO shape: ", ibo.shape
#molden.from_mo(cell, 'diamondibo_szv_ibo.molden', ibo)
mycas = mcscf.CASSCF(mf, 6, 6)
# Be careful with the keyword argument "base". By default sort_mo function takes
# the 1-based indices. The return indices of .argsort() method above are 0-based
cas_orbs = mycas.sort_mo(cas_list, mf.mo_coeff, base=0)
mycas.kernel(cas_orbs)

#
# Localized orbitals are often used as the initial guess of CASSCF method.
# When localizing SCF orbitals, it's better to call the localization twice to
# obtain the localized orbitals for occupied space and virtual space
# separately. This split localization scheme can ensure that the initial core
# determinant sits inside the HF occupied space.
#
nocc = mol.nelectron // 2
loc1 = lo.PM(mol, mf.mo_coeff[:, :nocc]).kernel()
loc2 = lo.PM(mol, mf.mo_coeff[:, nocc:]).kernel()
loc_orbs = numpy.hstack((loc1, loc2))
pz_pop = mo_mapping.mo_comps('C 2pz', mol, loc_orbs)
cas_list = pz_pop.argsort()[-6:]
print('cas_list', cas_list)
print('pz population for active space orbitals', pz_pop[cas_list])

#
# Symmetry was enabled in this molecule. By default, symmetry-adapted CASSCF
# algorithm will be called for molecule with symmetry. However, the orbital
# localization above breaks the orbital spatial symmetry. If proceeding the
# symmetry-adapted CASSCF calculation, the program may complain that the
# CASSCF initial guess is not symmetrized after certain attempts of orbital
# symmetrization. The simplest operation for this problem is to mute the
# spatial symmetry of the molecule.