Ejemplo n.º 1
0
 def nuc_grad_method(self):
     from pyscf.grad import uks
     return uks.Gradients(self)
Ejemplo n.º 2
0
# Read the structure. 
# This starting structure includes both nuclei and FOD positions. 
ase_atoms = read('LiH.xyz') 
# We want only to optimize the nuclear positions. 
[geo,nuclei,fod1,fod2,included] =  xyz_to_nuclei_fod(ase_atoms)
ase_atoms  = nuclei 
# Calulation parameters. 
charge = 0 
spin = 0 
basis = get_dfo_basis('LiH')
xc = 'LDA,PW'
# Set up the pyscf structure object. 
mol = gto.M(atom=ase2pyscf(ase_atoms),spin=spin,charge=charge,basis=basis)
mol.verbose = 4 
# DFT pyscf calculation.
mf = dft.UKS(mol)
mf.max_cycle = 300
mf.conv_tol = 1e-6
mf.xc = xc
mf = mf.newton()
mf = mf.as_scanner()
# SCF single point for starting geometry. 
e = mf.kernel()
# Starting Gradients  
gf = uks.Gradients(mf)
gf.grid_response = True
gf.kernel()
# Optimization
optimize(mf)
Ejemplo n.º 3
0
    def test_get_vxc(self):
        mol = gto.Mole()
        mol.verbose = 0
        mol.atom = [['O', (0., 0., 0.)], [1, (0., -0.757, 0.587)],
                    [1, (0., 0.757, 0.587)]]
        mol.basis = '631g'
        mol.charge = -1
        mol.spin = 1
        mol.build()
        mf = dft.UKS(mol)
        mf.xc = 'b3lyp'
        mf.conv_tol = 1e-12
        e0 = mf.scf()
        g = uks.Gradients(mf)
        g.grid_response = True
        g0 = g.kernel()
        dm0 = mf.make_rdm1()

        denom = 1 / .00001 * lib.param.BOHR
        mol1 = gto.Mole()
        mol1.verbose = 0
        mol1.atom = [['O', (0., 0., 0.00001)], [1, (0., -0.757, 0.587)],
                     [1, (0., 0.757, 0.587)]]
        mol1.basis = '631g'
        mol1.charge = -1
        mol1.spin = 1
        mol1.build()
        mf1 = dft.UKS(mol1)
        mf1.xc = 'b3lyp'
        mf1.conv_tol = 1e-12
        e1 = mf1.scf()
        self.assertAlmostEqual((e1 - e0) * denom, g0[0, 2], 3)

        grids0 = dft.gen_grid.Grids(mol)
        grids0.atom_grid = (20, 86)
        grids0.build(with_non0tab=False)
        grids1 = dft.gen_grid.Grids(mol1)
        grids1.atom_grid = (20, 86)
        grids1.build(with_non0tab=False)
        exc0 = dft.numint.nr_uks(mf._numint, mol, grids0, mf.xc, dm0)[1]
        exc1 = dft.numint.nr_uks(mf1._numint, mol1, grids1, mf1.xc, dm0)[1]

        grids0_w = copy.copy(grids0)
        grids0_w.weights = grids1.weights
        grids0_c = copy.copy(grids0)
        grids0_c.coords = grids1.coords
        exc0_w = dft.numint.nr_uks(mf._numint, mol, grids0_w, mf.xc, dm0)[1]
        exc0_c = dft.numint.nr_uks(mf._numint, mol1, grids0_c, mf.xc, dm0)[1]

        dexc_t = (exc1 - exc0) * denom
        dexc_c = (exc0_c - exc0) * denom
        dexc_w = (exc0_w - exc0) * denom
        self.assertAlmostEqual(dexc_t, dexc_c + dexc_w, 4)

        vxc = uks.get_vxc(mf._numint, mol, grids0, mf.xc, dm0)[1]
        ev1, vxc1 = uks.get_vxc_full_response(mf._numint, mol, grids0, mf.xc,
                                              dm0)
        p0, p1 = mol.aoslice_by_atom()[0][2:]
        exc1_approx = numpy.einsum('sxij,sij->x', vxc[:, :, p0:p1],
                                   dm0[:, p0:p1]) * 2
        exc1_full = numpy.einsum('sxij,sij->x', vxc1[:, :, p0:p1],
                                 dm0[:, p0:p1]) * 2 + ev1[0]
        self.assertAlmostEqual(dexc_t, exc1_approx[2], 3)
        self.assertAlmostEqual(dexc_t, exc1_full[2], 5)
Ejemplo n.º 4
0
    def get_forces(self, atoms=None):
        if atoms != None:
            self.atoms = atoms
        # get nuclei and FOD forces
        # calculates forces if required
        if self.atoms == None:
            self.atoms = atoms
        # Note: The gradients for UKS are only available in the dev branch of pyscf.
        if self.mode == 'dft' or self.mode == 'both':
            from pyscf.grad import uks
            if self.mf == None:
                from pyscf import gto, scf, dft
                [geo, nuclei, fod1, fod2,
                 included] = xyz_to_nuclei_fod(self.atoms)
                nuclei = ase2pyscf(nuclei)
                mol = gto.M(atom=nuclei,
                            basis=self.basis,
                            spin=self.spin,
                            charge=self.charge)
                mf = scf.UKS(mol)
                mf.xc = self.xc
                mf.conv_tol = self.conv_tol
                mf.max_cycle = self.max_cycle
                mf.verbose = self.verbose
                mf.grids.level = self.grid
                if self.n_rad is not None and self.n_ang is not None:
                    mf.grids.atom_grid = (self.n_rad, self.n_ang)
                mf.grids.prune = prune_dict[self.prune]
                if self.xc == 'LDA,PW' or self.xc == 'PBE,PBE':
                    # The 2nd order scf cycle (Newton) speed up calculations,
                    # but does not work for MGGAs like SCAN,SCAN.
                    mf = mf.as_scanner()
                    mf = mf.newton()
                mf.kernel()
                self.mf = mf
                gf = uks.Gradients(mf)
                forces = gf.kernel()
            #if self.mf != None:
            #	gf = uks.Gradients(self.mf)
            #        forces = gf.kernel()
            gf = uks.Gradients(self.mf)
            forces = gf.kernel() * (Ha / Bohr)
            #print(forces)

        if self.mode == 'flosic-os' or self.mode == 'flosic-scf':
            [geo, nuclei, fod1, fod2, included] = xyz_to_nuclei_fod(self.atoms)
            forces = np.zeros_like(nuclei.get_positions())

        if self.mode == 'dft':
            # mode for nuclei only optimization (fods fixed)
            forces = forces.tolist()
            totalforces = []
            totalforces.extend(forces)
            [geo, nuclei, fod1, fod2, included] = xyz_to_nuclei_fod(self.atoms)
            fod1forces = np.zeros_like(fod1.get_positions())
            fod2forces = np.zeros_like(fod2.get_positions())
            totalforces.extend(fod1forces)
            totalforces.extend(fod2forces)
            totalforces = np.array(totalforces)
            # pyscf gives the gradient not the force
            totalforces = -1 * totalforces

        if self.mode == 'flosic-os' or self.mode == 'flosic-scf':
            # mode for FOD only optimization (nuclei fixed)
            if self.results['fodforces'] is None:
                fodforces = self.get_fodforces(self.atoms)
            fodforces = self.results['fodforces']
            # fix nuclei with zeroing the forces
            forces = forces
            forces = forces.tolist()
            totalforces = []
            totalforces.extend(forces)
            totalforces.extend(fodforces)
            totalforces = np.array(totalforces)

        if self.mode == 'both':
            # mode for both (nuclei+fods) optimzation
            if self.results['fodforces'] is None:
                fodforces = self.get_fodforces(self.atoms)
            fodforces = self.results['fodforces']
            forces = forces.tolist()
            totalforces = []
            totalforces.extend(forces)
            totalforces.extend(fodforces)
            totalforces = np.array(totalforces)

        return totalforces