Example #1
0
def aug_etb_for_dfbasis(mol, dfbasis='weigend', beta=2.3, start_at='Rb'):
    '''augment weigend basis with even tempered gaussian basis
    exps = alpha*beta^i for i = 1..N
    '''
    nuc_start = gto.mole._charge(start_at)
    uniq_atoms = set([a[0] for a in mol._atom])

    newbasis = {}
    for symb in uniq_atoms:
        nuc_charge = gto.mole._charge(symb)
        if nuc_charge < nuc_start:
            newbasis[symb] = dfbasis
        #?elif symb in mol._ecp:
        else:
            conf = lib.parameters.ELEMENTS[nuc_charge][2]
            max_shells = 4 - conf.count(0)
            emin_by_l = [1e99] * 8
            emax_by_l = [0] * 8
            for b in mol._basis[symb]:
                l = b[0]
                if l >= max_shells + 1:
                    continue

                if isinstance(b[1], int):
                    e_c = numpy.array(b[2:])
                else:
                    e_c = numpy.array(b[1:])
                es = e_c[:, 0]
                cs = e_c[:, 1:]
                es = es[abs(cs).max(axis=1) > 1e-3]
                emax_by_l[l] = max(es.max(), emax_by_l[l])
                emin_by_l[l] = min(es.min(), emin_by_l[l])

            l_max = 8 - emax_by_l.count(0)
            emin_by_l = numpy.array(emin_by_l[:l_max])
            emax_by_l = numpy.array(emax_by_l[:l_max])
            # Estimate the exponents ranges by geometric average
            emax = numpy.sqrt(numpy.einsum('i,j->ij', emax_by_l, emax_by_l))
            emin = numpy.sqrt(numpy.einsum('i,j->ij', emin_by_l, emin_by_l))
            liljsum = numpy.arange(l_max)[:, None] + numpy.arange(l_max)
            emax_by_l = [
                emax[liljsum == ll].max() for ll in range(l_max * 2 - 1)
            ]
            emin_by_l = [
                emin[liljsum == ll].min() for ll in range(l_max * 2 - 1)
            ]
            # Tune emin and emax
            emin_by_l = numpy.array(
                emin_by_l) * 2  # *2 for alpha+alpha on same center
            emax_by_l = numpy.array(
                emax_by_l) * 2  #/ (numpy.arange(l_max*2-1)*.5+1)

            ns = numpy.log(
                (emax_by_l + emin_by_l) / emin_by_l) / numpy.log(beta)
            etb = [(l, max(n, 1), emin_by_l[l], beta)
                   for l, n in enumerate(numpy.ceil(ns).astype(int))]
            newbasis[symb] = gto.expand_etbs(etb)

    return newbasis
Example #2
0
def aug_etb_for_dfbasis(mol, dfbasis=DFBASIS, beta=ETB_BETA,
                        start_at=FIRST_ETB_ELEMENT):
    '''augment weigend basis with even-tempered gaussian basis
    exps = alpha*beta^i for i = 1..N
    '''
    nuc_start = gto.charge(start_at)
    uniq_atoms = set([a[0] for a in mol._atom])

    newbasis = {}
    for symb in uniq_atoms:
        nuc_charge = gto.charge(symb)
        if nuc_charge < nuc_start:
            newbasis[symb] = dfbasis
        #?elif symb in mol._ecp:
        else:
            conf = elements.CONFIGURATION[nuc_charge]
            max_shells = 4 - conf.count(0)
            emin_by_l = [1e99] * 8
            emax_by_l = [0] * 8
            l_max = 0
            for b in mol._basis[symb]:
                l = b[0]
                l_max = max(l_max, l)
                if l >= max_shells+1:
                    continue

                if isinstance(b[1], int):
                    e_c = numpy.array(b[2:])
                else:
                    e_c = numpy.array(b[1:])
                es = e_c[:,0]
                cs = e_c[:,1:]
                es = es[abs(cs).max(axis=1) > 1e-3]
                emax_by_l[l] = max(es.max(), emax_by_l[l])
                emin_by_l[l] = min(es.min(), emin_by_l[l])

            l_max1 = l_max + 1
            emin_by_l = numpy.array(emin_by_l[:l_max1])
            emax_by_l = numpy.array(emax_by_l[:l_max1])

# Estimate the exponents ranges by geometric average
            emax = numpy.sqrt(numpy.einsum('i,j->ij', emax_by_l, emax_by_l))
            emin = numpy.sqrt(numpy.einsum('i,j->ij', emin_by_l, emin_by_l))
            liljsum = numpy.arange(l_max1)[:,None] + numpy.arange(l_max1)
            emax_by_l = [emax[liljsum==ll].max() for ll in range(l_max1*2-1)]
            emin_by_l = [emin[liljsum==ll].min() for ll in range(l_max1*2-1)]
            # Tune emin and emax
            emin_by_l = numpy.array(emin_by_l) * 2  # *2 for alpha+alpha on same center
            emax_by_l = numpy.array(emax_by_l) * 2  #/ (numpy.arange(l_max1*2-1)*.5+1)

            ns = numpy.log((emax_by_l+emin_by_l)/emin_by_l) / numpy.log(beta)
            etb = []
            for l, n in enumerate(numpy.ceil(ns).astype(int)):
                if n > 0:
                    etb.append((l, n, emin_by_l[l], beta))
            newbasis[symb] = gto.expand_etbs(etb)

    return newbasis
Example #3
0
    def build_nuc_mole(self, atom_index, frac=None):
        '''
        Return a Mole object for specified quantum nuclei.

        Nuclear basis:

        H: PB4-D  J. Chem. Phys. 152, 244123 (2020)
        D: scaled PB4-D
        other atoms: 12s12p12d, alpha=2*sqrt(2)*mass, beta=sqrt(3)
        '''

        nuc = gto.Mole() # a Mole object for quantum nuclei
        nuc.atom_index = atom_index
        nuc.super_mol = self

        dirnow = os.path.realpath(os.path.join(__file__, '..'))
        if self.atom_symbol(atom_index) == 'H@2':
            basis = gto.basis.parse(open(os.path.join(dirnow, 'basis/s-pb4d.dat')).read())
        elif self.atom_pure_symbol(atom_index) == 'H':
            basis = gto.basis.parse(open(os.path.join(dirnow, 'basis/pb4d.dat')).read())
            #alpha = 2 * numpy.sqrt(2) * self.mass[atom_index]
            #beta = numpy.sqrt(2)
            #n = 8
            #basis = gto.expand_etbs([(0, n, alpha, beta), (1, n, alpha, beta), (2, n, alpha, beta)])
        else:
            # even-tempered basis
            alpha = 2 * numpy.sqrt(2) * self.mass[atom_index]
            beta = numpy.sqrt(3)
            n = 12
            basis = gto.expand_etbs([(0, n, alpha, beta), (1, n, alpha, beta), (2, n, alpha, beta)])
            #logger.info(self, 'Nuclear basis for %s: n %s alpha %s beta %s' %(self.atom_symbol(atom_index), n, alpha, beta))
        nuc.build(atom = self.atom, basis={self.atom_symbol(atom_index): basis},
                  charge = self.charge, cart = self.cart, spin = self.spin)

        # set all quantum nuclei to have zero charges
        quantum_nuclear_charge = 0
        for i in range(self.natm):
            if self.quantum_nuc[i] is True:
                quantum_nuclear_charge -= nuc._atm[i, 0]
                nuc._atm[i, 0] = 0 # set nuclear charges of quantum nuclei to 0
        nuc.charge += quantum_nuclear_charge

        # avoid UHF
        nuc.spin = 0
        nuc.nelectron = 2

        # fractional
        if frac is not None:
            nuc.nnuc = frac
        else:
            nuc.nnuc = 1

        return nuc
Example #4
0
def aug_etb_for_dfbasis(mol, dfbasis='weigend', beta=2.3, start_at='Rb'):
    '''augment weigend basis with even tempered gaussian basis
    exps = alpha*beta^i for i = 1..N
    '''
    nuc_start = gto.mole._charge(start_at)
    uniq_atoms = set([a[0] for a in mol._atom])

    newbasis = {}
    for symb in uniq_atoms:
        nuc_charge = gto.mole._charge(symb)
        if nuc_charge < nuc_start:
            newbasis[symb] = dfbasis
        #?elif symb in mol._ecp:
        else:
            conf = lib.parameters.ELEMENTS[nuc_charge][2]
            max_shells = 4 - conf.count(0)
            emin_by_l = [1e99] * 8
            emax_by_l = [0] * 8
            for b in mol._basis[symb]:
                l = b[0]
                if l >= max_shells+1:
                    continue

                if isinstance(b[1], int):
                    e_c = numpy.array(b[2:])
                else:
                    e_c = numpy.array(b[1:])
                es = e_c[:,0]
                cs = e_c[:,1:]
                es = es[abs(cs).max(axis=1) > 1e-3]
                emax_by_l[l] = max(es.max(), emax_by_l[l])
                emin_by_l[l] = min(es.min(), emin_by_l[l])

            l_max = 8 - emax_by_l.count(0)
            emin_by_l = numpy.array(emin_by_l[:l_max])
            emax_by_l = numpy.array(emax_by_l[:l_max])
# Estimate the exponents ranges by geometric average
            emax = numpy.sqrt(numpy.einsum('i,j->ij', emax_by_l, emax_by_l))
            emin = numpy.sqrt(numpy.einsum('i,j->ij', emin_by_l, emin_by_l))
            liljsum = numpy.arange(l_max)[:,None] + numpy.arange(l_max)
            emax_by_l = [emax[liljsum==ll].max() for ll in range(l_max*2-1)]
            emin_by_l = [emin[liljsum==ll].min() for ll in range(l_max*2-1)]
            # Tune emin and emax
            emin_by_l = numpy.array(emin_by_l) * 2  # *2 for alpha+alpha on same center
            emax_by_l = numpy.array(emax_by_l) * 2  #/ (numpy.arange(l_max*2-1)*.5+1)

            ns = numpy.log((emax_by_l+emin_by_l)/emin_by_l) / numpy.log(beta)
            etb = [(l, max(n,1), emin_by_l[l], beta)
                   for l, n in enumerate(numpy.ceil(ns).astype(int))]
            newbasis[symb] = gto.expand_etbs(etb)

    return newbasis
Example #5
0
O    SP
      5.0331513             -0.09996723             0.15591627       
      1.1695961              0.39951283             0.60768372       
      0.3803890              0.70011547             0.39195739       
                                '''),
             'H1': gto.load(basis_file_from_user, 'H'),
             'H2': gto.load('sto-3g', 'He')  # or use basis of another atom
            }
)

mol = gto.M(
    atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
    basis = {'O': 'unc-ccpvdz', # prefix "unc-" will uncontract the ccpvdz basis.
                                # It is equivalent to assigning
                                #   'O': gto.uncontract(gto.load('ccpvdz', 'O')),
             'H': 'ccpvdz'  # H1 H2 will use the same basis ccpvdz
            }
)


mol = gto.M(
    atom = '''O 0 0 0; H1 0 1 0; H2 0 0 1''',
    basis = {'H': 'sto3g',
# even-temper gaussians alpha*beta^i, where i = 0,..,n
#                                  (l, n, alpha, beta)
             'O': gto.expand_etbs([(0, 4, 1.5, 2.2),  # s-function
                                   (1, 2, 0.5, 2.2)]) # p-function
            }
)

# better resolution of auxiliary basis) is the use of function gto.expand_etbs.
#
# Note the PBC Gaussian DF module will automatically remove diffused Gaussian
# fitting functions. It is controlled by the parameter eta.  The default value is
# 0.2 which removes all Gaussians whose exponents are smaller than 0.2.
# When your input DF basis has diffused functions, you need to reduce the
# value of  mf.with_df.eta  to reserve the diffused functions.  However,
# keeping diffused functions occasionally lead numerical noise in the GDF
# method.
#
auxbasis = {
    'C':
    # (l, N, alpha, beta)
    mol_gto.expand_etbs([
        (0, 25, 0.15, 1.6),  # 25s
        (1, 20, 0.15, 1.6),  # 20p
        (2, 10, 0.15, 1.6),  # 10d
        (3, 5, 0.15, 1.6),  # 5f
    ])
}
mf = scf.RHF(cell).density_fit(auxbasis=auxbasis)
mf.with_df.eta = 0.1
mf.kernel()

#
# The 3-index density fitting tensor can be loaded from the _cderi file.
# Using the 3-index tensor, the 4-center integrals can be constructed:
#    (pq|rs) = \sum_L A_lpq A_lrs
#
# The 3-index tensor for gamma point can be accessed with the code snippet
# below.  Assuming in the first pass, the GDF 3-index tensors are saved with
# the following code
Example #7
0
mf = scf.RHF(mol)
mf.kernel()

#
# First method is to explicit call the functions provided by molden.py
#
with open("C6H6mo.molden", "w") as f1:
    molden.header(mol, f1)
    molden.orbital_coeff(mol, f1, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)

#
# Second method is to simply call from_mo function to write the orbitals
#
c_loc_orth = lo.orth.orth_ao(mol)
molden.from_mo(mol, "C6H6loc.molden", c_loc_orth)


#
# Molden format does not support high angular momentum basis.  To handle the
# orbitals which have l>=5 functions, a hacky way is to call molden.remove_high_l
# function.  However, the resultant orbitals may not be orthnormal.
#
mol = gto.M(atom="He 0 0 0", basis={"He": gto.expand_etbs(((0, 3, 1.0, 2.0), (5, 2, 1.0, 2.0)))})
mf = scf.RHF(mol).run()
try:
    molden.from_mo(mol, "He_without_h.molden", mf.mo_coeff)
except RuntimeError:
    print("    Found l=5 in basis.")
    molden.from_mo(mol, "He_without_h.molden", mf.mo_coeff, ignore_h=True)
Example #8
0
import numpy as np
from pyscf import gto, scf
from kspies import wy

mol = gto.M(atom='N 0 0 0 ; N 1.1 0 0', basis='cc-pVDZ')
mf = scf.RHF(mol).run()
dm_tar = mf.make_rdm1()

PBS = gto.expand_etbs([(0, 13, 2**-4, 2), (1, 3, 2**-2, 2)])
mw = wy.RWY(mol, dm_tar, pbas=PBS)
#Note that for this designed-to-be ill-conditioned problem,
#Hessian-based optimization algorithms are problematic.
mw.method = 'bfgs'
mw.tol = 2e-7
mw.run()
mw.info()
Ws_fin = mw.Ws

etas = [2.**(-a) for a in np.linspace(5., 27., 45)]
v = np.zeros(len(etas))
W = np.zeros(len(etas))
for i, eta in enumerate(etas):
    mw.reg = eta
    mw.run()
    v[i] = mw.Dvb()
    W[i] = mw.Ws
    mw.info()

import matplotlib.pyplot as plt
fig, ax = plt.subplots(2)
ax[0].scatter(np.log10(Ws_fin - W), np.log10(v))
Example #9
0
mf.kernel()

#
# First method is to explicit call the functions provided by molden.py
#
with open('C6H6mo.molden', 'w') as f1:
    molden.header(mol, f1)
    molden.orbital_coeff(mol, f1, mf.mo_coeff, ene=mf.mo_energy, occ=mf.mo_occ)

#
# Second method is to simply call from_mo function to write the orbitals
#
c_loc_orth = lo.orth.orth_ao(mol)
molden.from_mo(mol, 'C6H6loc.molden', c_loc_orth)


#
# Molden format does not support high angular momentum basis.  To handle the
# orbitals which have l>=5 functions, a hacky way is to call molden.remove_high_l
# function.  However, the resultant orbitals may not be orthnormal.
#
mol = gto.M(
    atom = 'He 0 0 0',
    basis = {'He': gto.expand_etbs(((0, 3, 1., 2.), (5, 2, 1., 2.)))})
mf = scf.RHF(mol).run()
try:
    molden.from_mo(mol, 'He_without_h.molden', mf.mo_coeff)
except RuntimeError:
    print('    Found l=5 in basis.')
    molden.from_mo(mol, 'He_without_h.molden', mf.mo_coeff, ignore_h=True)
Example #10
0
# Another straightforward way to input even-tempered Gaussian basis (for
# better resolution of auxiliary basis) is the use of function gto.expand_etbs.
#
# Note the PBC Gaussian DF module will automatically remove diffused Gaussian
# fitting functions. It is controlled by the parameter eta.  The default value is
# 0.2 which removes all Gaussians whose exponents are smaller than 0.2.
# When your input DF basis has diffused functions, you need to reduce the
# value of  mf.with_df.eta  to reserve the diffused functions.  However,
# keeping diffused functions occasionally lead numerical noise in the GDF
# method.
#
auxbasis = {'C':
                               # (l, N, alpha, beta)
            mol_gto.expand_etbs([(0, 25, 0.15, 1.6), # 25s
                                 (1, 20, 0.15, 1.6), # 20p
                                 (2, 10, 0.15, 1.6), # 10d
                                 (3, 5 , 0.15, 1.6), # 5f
                                ])
           }
mf = scf.RHF(cell).density_fit(auxbasis=auxbasis)
mf.with_df.eta = 0.1
mf.kernel()


#
# The 3-index density fitting tensor can be loaded from the _cderi file.
# Using the 3-index tensor, the 4-center integrals can be constructed:
#    (pq|rs) = \sum_L A_lpq A_lrs
#
# The 3-index tensor for gamma point can be accessed with the code snippet
# below.  Assuming in the first pass, the GDF 3-index tensors are saved with