Exemplo n.º 1
0
def calc_localized_orbitals(mf,mol,method='ER',jmol=False):
    # mf 		...	pyscf calculation object 
    # mol           ...     pyscf geometry object 
        # method 	...	localization method: ER, FB, PM 
        # jmol          ...     debug option to check furher 3d information files 
    
    # Localization. 
    
    # Spin 1. 
    # only occupied orbitals 
    mo_occ = mf.mo_coeff[0][:,mf.mo_occ[0]>0]
    if method == 'ER':
        loc1 = edmiston.Edmiston(mol, mo_occ)
    if method == 'FB':
        loc1 = boys.Boys(mol, mo_occ)
    if method == 'PM':
        loc1 = pipek.PipekMezey(mol, mo_occ)
    orb1 = loc1.kernel()
    
    # Spin 2 
    # only occupied orbitals 
    mo_occ = mf.mo_coeff[1][:,mf.mo_occ[1]>0]
    if method == 'ER':
        loc2 = edmiston.Edmiston(mol, mo_occ) 
    if method == 'FB':
        loc2 = boys.Boys(mol, mo_occ)
    if method == 'PM':
        loc2 = pipek.PipekMezey(mol, mo_occ) 
    orb2 = loc2.kernel()
    
    # Write orbitals for jmol format. 
    if jmol == True: 
        # Spin 1.
        tools.molden.from_mo(mol, 'orb1.molden', orb1)
        with open('orb1.spt', 'w') as f:
            f.write('load orb1.molden; isoSurface MO 001;\n')
    	
    	# Spin 2.
        tools.molden.from_mo(mol, 'orb2.molden', orb2)
        with open('orb2.spt', 'w') as f:
            f.write('load orb2.molden; isoSurface MO 001;\n')
    	
    # Write orbitals in cube format.
    
    # Spin 1. 
    occ = len(mf.mo_coeff[0][mf.mo_occ[0] == 1])
    for i in range(occ):
        orbital(mol, str(method)+'_orb_'+str(i)+'spin1.cube', orb1[:,i], nx=80, ny=80, nz=80)


    # Spin 2.
    occ = len(mf.mo_coeff[1][mf.mo_occ[1] == 1])
    for i in range(occ):
        orbital(mol, str(method)+'_orb_'+str(i)+'spin2.cube', orb2[:,i], nx=80, ny=80, nz=80)
Exemplo n.º 2
0
    def relocalize_states (self, loc2bas, fragments, oneRDM_loc, natorb=False, canonicalize=False):
        '''Do Boys localization on a subspace and assign resulting states to the various fragments using projection operators.
           Optionally diagonalize either the fock or the density matrix inside each subspace. Canonicalize overrides natorb'''

        fock_loc = self.loc_rhf_fock_bis (oneRDM_loc)
        ao2bas = boys.Boys (self.mol, np.dot (self.ao2loc, loc2bas)).kernel ()
        loc2bas = reduce (np.dot, [self.ao2loc.conjugate ().T, self.ao_ovlp, ao2bas])
        
        weights = np.asarray ([np.einsum ('ip,ip->p', loc2bas[f.frag_orb_list,:].conjugate (), loc2bas[f.frag_orb_list,:]) for f in fragments])
        frag_assignments = np.argmax (weights, axis=0)

        loc2bas_assigned = []        
        for idx, frag in enumerate (fragments):
            pick_orbs = (frag_assignments == idx)
            norbs = np.count_nonzero (pick_orbs)
            print ("{} states found for fragment {}".format (norbs, frag.frag_name))
            loc2pick = loc2bas[:,pick_orbs]
            if canonicalize and norbs:
                f = represent_operator_in_basis (fock_loc, loc2pick)
                evals, evecs = matrix_eigen_control_options (f, sort_vecs=1, only_nonzero_vals=False)
                loc2pick = np.dot (loc2pick, evecs)
            elif natorb and norbs:
                f = represent_operator_in_basis (oneRDM_loc, loc2pick)
                evals, evecs = matrix_eigen_control_options (f, sort_vecs=-1, only_nonzero_vals=False)
                loc2pick = np.dot (loc2pick, evecs)
            loc2bas_assigned.append (loc2pick)
        return loc2bas_assigned
Exemplo n.º 3
0
def examine_wmcs (dmet_obj):
    loc2wmas = np.concatenate ([f.loc2amo for f in dmet_obj.fragments], axis=1)
    loc2wmcs = get_complementary_states (loc2wmas)

    print ("Examining whole-molecule active space:")
    loc2wmas = dmet_obj.ints.compare_basis_to_loc (loc2wmas, dmet_obj.fragments, quiet=False)[0]
    norbs_wmas = np.array ([f.norbs_as for f in dmet_obj.fragments])

    print ("Examining whole-molecule core space:")
    norbs_wmcs_before = dmet_obj.ints.compare_basis_to_loc (loc2wmcs, dmet_obj.fragments, quiet=True)[1]
    norbs_before = norbs_wmas + norbs_wmcs_before
    ao2loc = dmet_obj.ints.ao2loc
    loc2ao = ao2loc.conjugate ().T
    ao2wmcs = np.dot (ao2loc, loc2wmcs)
    ao2wmcs_new = boys.Boys (dmet_obj.ints.mol, ao2wmcs).kernel ()
    aoOao_inv = np.linalg.inv (np.dot (ao2loc, loc2ao))
    loc2wmcs_new = reduce (np.dot, [loc2ao, aoOao_inv, ao2wmcs_new])
    loc2wmcs_new, norbs_wmcs_after = dmet_obj.ints.compare_basis_to_loc (loc2wmcs_new, dmet_obj.fragments, quiet=False)
    norbs_after = norbs_wmas + norbs_wmcs_after

    loc2new = np.append (loc2wmas, loc2wmcs_new, axis=1)
    active_flag = np.append (np.ones (loc2wmas.shape[1]), np.zeros (loc2wmcs_new.shape[1]))
    print ("Is the new basis orthonormal and complete? {0}".format (is_basis_orthonormal_and_complete (loc2new)))
    print ("Fragment-orbital assignment breakdown:")
    print ("Frag Before After")
    for frag, bef, aft in zip (dmet_obj.fragments, norbs_before, norbs_after):
        print ('{:>4s} {:6d} {:5d}'.format (frag.frag_name, int (bef), int (aft)))

    filename = 'relocalized_basis.molden'
    mol = dmet_obj.ints.mol.copy ()
    ao2new = np.dot (dmet_obj.ints.ao2loc, loc2new)
    molden.from_mo (mol, filename, ao2new, occ=active_flag)
    '''
Exemplo n.º 4
0
 def test_boys(self):
     idx = numpy.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1
     loc = boys.Boys(mol, mf.mo_coeff[:, idx])
     loc.max_cycle = 100
     mo = loc.kernel()
     dip = boys.dipole_integral(mol, mo)
     z = numpy.einsum('xii,xii->', dip, dip)
     self.assertAlmostEqual(z, 98.670988758151907, 4)
Exemplo n.º 5
0
def localize(mol, mf, method):
  if (method == "lowdin"):
    return fractional_matrix_power(mf.get_ovlp(mol), -0.5).T
  elif (method == "pm"):
    return pipek.PM(mol).kernel(mf.mo_coeff)
  elif (method == "pmLowdin"):
    lowdin = fractional_matrix_power(mf.get_ovlp(mol), -0.5).T
    return pipek.PM(mol).kernel(lowdin)
  elif (method == "boys"):
    return boys.Boys(mol).kernel(mf.mo_coeff)
Exemplo n.º 6
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)
Exemplo n.º 7
0
 def test_pipek(self):
     idx = numpy.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1
     # Initial guess from Boys localization. Otherwise uncertainty between
     # two solutions found in PM kernel
     mo = boys.Boys(mol, mf.mo_coeff[:, idx]).kernel()
     loc = pipek.PipekMezey(mol, mo)
     loc.max_cycle = 100
     mo = loc.kernel()
     pop = pipek.atomic_pops(mol, mo)
     z = numpy.einsum('xii,xii->', pop, pop)
     self.assertAlmostEqual(z, 12, 4)
Exemplo n.º 8
0
    def test_boys(self):
        idx = numpy.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1
        loc = boys.Boys(mol)
        mo = loc.kernel(mf.mo_coeff[:, idx])
        dip = boys.dipole_integral(mol, mo)
        z = numpy.einsum('xii,xii->', dip, dip)
        self.assertAlmostEqual(z, 98.670988758151907, 9)

        mo = loc.kernel(mf.mo_coeff[:, idx + 1])
        dip = boys.dipole_integral(mol, mo)
        z = numpy.einsum('xii,xii->', dip, dip)
        self.assertAlmostEqual(z, 27.481320331665497, 9)
Exemplo n.º 9
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)
Exemplo n.º 10
0
    def __init__( self, the_mf, active_orbs, localizationtype, ao_rotation=None, use_full_hessian=True, localization_threshold=1e-6 ):

        assert (( localizationtype == 'meta_lowdin' ) or ( localizationtype == 'boys' ) or ( localizationtype == 'lowdin' ) or ( localizationtype == 'iao' ))
        self.num_mf_stab_checks = 0
        
        # Information on the full HF problem
        self.mol         = the_mf.mol
        self._scf        = the_mf
        self.max_memory  = the_mf.max_memory
        self.get_jk_ao   = partial (the_mf.get_jk, self.mol)
        self.get_veff_ao = partial (the_mf.get_veff, self.mol)
        self.get_k_ao    = partial (the_mf.get_k, self.mol)
        self.fullovlpao  = the_mf.get_ovlp
        self.fullEhf     = the_mf.e_tot
        self.fullRDM_ao  = np.asarray (the_mf.make_rdm1 ())
        if self.fullRDM_ao.ndim == 3:
            self.fullSDM_ao = self.fullRDM_ao[0] - self.fullRDM_ao[1]
            self.fullRDM_ao = self.fullRDM_ao[0] + self.fullRDM_ao[1]
        else:
            self.fullSDM_ao = np.zeros_like (self.fullRDM_ao)
        self.fullJK_ao    = self.get_veff_ao (dm=self.fullRDM_ao, dm_last=0, vhf_last=0, hermi=1) #Last 3 numbers: dm_last, vhf_last, hermi
        if self.fullJK_ao.ndim == 3:
            self.fullJK_ao = self.fullJK_ao[0] 
            # Because I gave it a spin-summed 1-RDM, the two spins for JK will necessarily be identical
        self.fullFOCK_ao = the_mf.get_hcore () + self.fullJK_ao
        self.e_tot       = the_mf.e_tot
        self.x2c         = isinstance (the_mf, x2c._X2C_SCF)

        # Active space information
        self._which    = localizationtype
        self.active    = np.zeros( [ self.mol.nao_nr() ], dtype=int )
        self.active[ active_orbs ] = 1
        self.norbs_tot = np.sum( self.active ) # Number of active space orbitals
        self.nelec_tot = int(np.rint( self.mol.nelectron - np.sum( the_mf.mo_occ[ self.active==0 ] ))) # Total number of electrons minus frozen part

        # Localize the orbitals
        if (( self._which == 'meta_lowdin' ) or ( self._which == 'boys' )):
            if ( self._which == 'meta_lowdin' ):
                assert( self.norbs_tot == self.mol.nao_nr() ) # Full active space required
            if ( self._which == 'boys' ):
                self.ao2loc = the_mf.mo_coeff[ : , self.active==1 ]
            if ( self.norbs_tot == self.mol.nao_nr() ): # If you want the full active, do meta-Lowdin
                nao.AOSHELL[4] = ['1s0p0d0f', '2s1p0d0f'] # redefine the valence shell for Be
                self.ao2loc = orth.orth_ao( self.mol, 'meta_lowdin' )
                if ( ao_rotation != None ):
                    self.ao2loc = np.dot( self.ao2loc, ao_rotation.T )
            if ( self._which == 'boys' ):
                old_verbose = self.mol.verbose
                self.mol.verbose = 5
                loc = boys.Boys (self.mol, self.ao2loc)
#                loc = localizer.localizer( self.mol, self.ao2loc, self._which, use_full_hessian )
                self.mol.verbose = old_verbose
#                self.ao2loc = loc.optimize( threshold=localization_threshold )
                self.ao2loc = loc.kernel ()
            self.TI_OK = False # Check yourself if OK, then overwrite
        if ( self._which == 'lowdin' ):
            assert( self.norbs_tot == self.mol.nao_nr() ) # Full active space required
            ovlp = self.mol.intor('cint1e_ovlp_sph')
            ovlp_eigs, ovlp_vecs = np.linalg.eigh( ovlp )
            assert ( np.linalg.norm( np.dot( np.dot( ovlp_vecs, np.diag( ovlp_eigs ) ), ovlp_vecs.T ) - ovlp ) < 1e-10 )
            self.ao2loc = np.dot( np.dot( ovlp_vecs, np.diag( np.power( ovlp_eigs, -0.5 ) ) ), ovlp_vecs.T )
            self.TI_OK  = False # Check yourself if OK, then overwrite
        if ( self._which == 'iao' ):
            assert( self.norbs_tot == self.mol.nao_nr() ) # Full active space assumed
            self.ao2loc = iao_helper.localize_iao( self.mol, the_mf )
            if ( ao_rotation != None ):
                self.ao2loc = np.dot( self.ao2loc, ao_rotation.T )
            self.TI_OK = False # Check yourself if OK, then overwrite
            #self.molden( 'dump.molden' ) # Debugging mode
        assert( self.loc_ortho() < 1e-8 )

        # Stored inverse overlap matrix
        self.ao_ovlp_inv = np.dot (self.ao2loc, self.ao2loc.conjugate ().T)
        self.ao_ovlp     = the_mf.get_ovlp ()
        assert (is_matrix_eye (np.dot (self.ao_ovlp, self.ao_ovlp_inv)))


        # Effective Hamiltonian due to frozen part
        self.frozenDM_mo  = np.array( the_mf.mo_occ, copy=True )
        self.frozenDM_mo[ self.active==1 ] = 0 # Only the frozen MO occupancies nonzero
        self.frozenDM_ao  = np.dot(np.dot( the_mf.mo_coeff, np.diag( self.frozenDM_mo )), the_mf.mo_coeff.T )
        self.frozenJK_ao  = self.get_veff_ao (self.frozenDM_ao, 0, 0, 1 ) #Last 3 numbers: dm_last, vhf_last, hermi
        if self.frozenJK_ao.ndim == 3:
            self.frozenJK_ao = self.frozenJK_ao[0]
            # Because I gave it a spin-summed 1-RDM, the two spins for JK will necessarily be identical
        self.frozenOEI_ao = self.fullFOCK_ao - self.fullJK_ao + self.frozenJK_ao

        # Localized OEI and ERI
        self.activeCONST    = self.mol.energy_nuc() + np.einsum( 'ij,ij->', self.frozenOEI_ao - 0.5*self.frozenJK_ao, self.frozenDM_ao )
        self.activeOEI      = represent_operator_in_basis (self.frozenOEI_ao, self.ao2loc )
        self.activeFOCK     = represent_operator_in_basis (self.fullFOCK_ao,  self.ao2loc )
        self.activeVSPIN    = np.zeros_like (self.activeFOCK) # FIXME: correct behavior for ROHF init!
        self.activeJKidem   = self.activeFOCK - self.activeOEI
        self.activeJKcorr   = np.zeros ((self.norbs_tot, self.norbs_tot), dtype=self.activeOEI.dtype)
        self.oneRDM_loc     = self.ao2loc.conjugate ().T @ self.ao_ovlp @ self.fullRDM_ao @ self.ao_ovlp @ self.ao2loc
        self.oneSDM_loc     = self.ao2loc.conjugate ().T @ self.ao_ovlp @ self.fullSDM_ao @ self.ao_ovlp @ self.ao2loc
        self.oneRDMcorr_loc = np.zeros ((self.norbs_tot, self.norbs_tot), dtype=self.activeOEI.dtype)
        self.loc2idem       = np.eye (self.norbs_tot, dtype=self.activeOEI.dtype)
        self.nelec_idem     = self.nelec_tot
        self._eri           = None
        self.with_df        = None
        assert (abs (np.trace (self.oneRDM_loc) - self.nelec_tot) < 1e-8), '{} {}'.format (np.trace (self.oneRDM_loc), self.nelec_tot)
        sys.stdout.flush ()
        def _is_mem_enough ():
            return 2*(self.norbs_tot**4)/1e6 + current_memory ()[0] < self.max_memory*0.95
        # Unfortunately, there is currently no way to do the integral transformation directly on the antisymmetrized two-electron
        # integrals, at least none already implemented in PySCF. Therefore the smallest possible memory footprint involves 
        # two arrays of fourfold symmetry, which works out to roughly one half of an array with no symmetry
        if hasattr (the_mf, 'with_df') and hasattr (the_mf.with_df, '_cderi') and the_mf.with_df._cderi is not None:
            print ("Found density-fitting three-center integrals scf object")
            loc2ao = self.ao2loc.conjugate ().T
            locOao = np.dot (loc2ao, self.ao_ovlp)
            self.with_df = the_mf.with_df
            self.with_df.loc2eri_bas = lambda x: np.dot (self.ao2loc, x)
            self.with_df.loc2eri_op = lambda x: reduce (np.dot, (self.ao2loc, x, loc2ao))
            self.with_df.eri2loc_bas = lambda x: np.dot (locOao, x)
            self.with_df.eri2loc_op = lambda x: reduce (np.dot, (loc2ao, x, self.ao2loc))
        elif the_mf._eri is not None:
            print ("Found eris on scf object")
            loc2ao = self.ao2loc.conjugate ().T
            locOao = np.dot (loc2ao, self.ao_ovlp)
            self._eri = the_mf._eri
            self._eri = tag_array (self._eri, loc2eri_bas = lambda x: np.dot (self.ao2loc, x))
            self._eri = tag_array (self._eri, loc2eri_op = lambda x: reduce (np.dot, (self.ao2loc, x, loc2ao)))
            self._eri = tag_array (self._eri, eri2loc_bas = lambda x: np.dot (locOao, x))
            self._eri = tag_array (self._eri, eri2loc_op = lambda x: reduce (np.dot, (loc2ao, x, self.ao2loc)))
        elif _is_mem_enough ():
            print ("Storing eris in memory")
            self._eri = ao2mo.restore (8, ao2mo.outcore.full_iofree (self.mol, self.ao2loc, compact=True), self.norbs_tot)
            self._eri = tag_array (self._eri, loc2eri_bas = lambda x: x)
            self._eri = tag_array (self._eri, loc2eri_op = lambda x: x)
            self._eri = tag_array (self._eri, eri2loc_bas = lambda x: x)
            self._eri = tag_array (self._eri, eri2loc_op = lambda x: x)
        else:
            print ("Direct calculation")
        sys.stdout.flush ()

        # Symmetry information
        try:
            self.loc2symm = [orthonormalize_a_basis (scipy.linalg.solve (self.ao2loc, ao2ir)) for ao2ir in self.mol.symm_orb]
            self.symmetry = self.mol.groupname
            self.wfnsym = the_mf.wfnsym
            self.ir_names = self.mol.irrep_name
            self.ir_ids = self.mol.irrep_id
            self.enforce_symmetry = True
        except (AttributeError, TypeError) as e:
            if self.mol.symmetry: raise (e)
            self.loc2symm = [np.eye (self.norbs_tot)]
            self.symmetry = False
            self.wfnsym = 'A'
            self.ir_names = ['A']
            self.ir_ids = [0]
            self.enforce_symmetry = False
        print ("Initial loc2symm nonorthonormality: {}".format (measure_basis_nonorthonormality (np.concatenate (self.loc2symm, axis=1))))
        for loc2ir1, loc2ir2 in itertools.combinations (self.loc2symm, 2):
            proj = loc2ir1 @ loc2ir1.conjugate ().T
            loc2ir2[:,:] -= proj @ loc2ir2
        for loc2ir in self.loc2symm:
            loc2ir[:,:] = orthonormalize_a_basis (loc2ir)
        print ("Final loc2symm nonorthonormality: {}".format (measure_basis_nonorthonormality (np.concatenate (self.loc2symm, axis=1))))
Exemplo n.º 11
0
    def test_1orbital(self):
        lmo = boys.Boys(mol, mf.mo_coeff[:, :1]).kernel()
        self.assertTrue(numpy.all(mf.mo_coeff[:, :1] == lmo))

        lmo = boys.Boys(mol, mf.mo_coeff[:, :0]).kernel()
        self.assertTrue(lmo.size == 0)
Exemplo n.º 12
0
mol.basis = '6-31g'
mol.symmetry = 0
mol.charge = 0
mol.spin = 0
mol.verbose = 4
mol.build()
mf = scf.RHF( mol )
mf.verbose = 4
mf.scf()

from pyscf.lo import boys
import numpy
mo = mf.mo_coeff[:,[17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]]
nmo = mo.shape[1]
u = numpy.linalg.svd(numpy.eye(nmo)+1e-5*numpy.random.random((nmo,nmo)))[0]
boys.Boys(mol).kernel(mo.dot(u), verbose=4)

#filename_mo   = 'benzene-631g-mo.molden'
#filename_boys = 'benzene-631g-boys.molden'
#
#with open( filename_mo, 'w' ) as thefile:
#    molden.header( mol, thefile )
#    molden.orbital_coeff( mol, thefile, mf.mo_coeff )
#print("Molecular orbitals saved in", filename_mo)
#
## Localize the pi-type orbitals. Counting starts from 0! 12 orbitals as 6-31G is DZ.
#tolocalize = np.array([17, 20, 21, 22, 23, 30, 36, 41, 42, 47, 48, 49]) - 1
#loc  = localizer.localizer( mol, mf.mo_coeff[:,tolocalize], 'boys' )
#loc.verbose = param.VERBOSE_DEBUG
#new_coeff = loc.optimize()
#loc.dump_molden( filename_boys, new_coeff )