def get_dft_energy(self,xc='b3lyp',optg=False): if self.spin == 0: mf = dft.RKS(self.mol) else: mf = dft.UKS(self.mol) mf.xc = xc if optg: berny_solver.optimize(mf, include_ghost=False) e = mf.kernel() return e
def test_as_pyscf_method(self): gs = scf.RHF(mol).nuc_grad_method().as_scanner() f = lambda mol: gs(mol) m = berny_solver.as_pyscf_method(mol, f) mol1 = berny_solver.optimize(m) self.assertAlmostEqual(lib.fp(mol1.atom_coords()), 2.20003359484436, 4) self.assertEqual(mol1.symmetry, 'C2v')
def opt_no(): mol = gto.M(atom=""" N 0.0 0.0 0.0 O 0.0 0.0 1.5 """, basis="sto-3g", spin=1) mf = scf.UKS(mol) mol1 = optimize(mf)
def opt_h2o(): mol = gto.M(atom=""" O -0.00000000 -0.11081188 0.00000000 H 0.78397589 0.44324751 0.00000000 H -0.78397589 0.44324751 0.00000000 """, basis="sto-3g") mf = scf.RHF(mol) mol1 = optimize(mf, maxsteps=1)
def opt_fluorethylene(): mol = gto.M(atom=""" C -0.061684 0.673790 0.000000 C -0.061684 -0.726210 0.000000 F 1.174443 1.331050 0.000000 H -0.927709 1.173790 0.000000 H -0.927709 -1.226210 0.000000 H 0.804342 -1.226210 0.000000 """, basis="sto-3g") mf = scf.RHF(mol) mol1 = optimize(mf)
def test_as_pyscf_method(self): mol = gto.M(atom=''' O 0. 0. 0. H 0. -0.757 0.587 H 0. 0.757 0.587 ''', verbose=0) gs = scf.RHF(mol).nuc_grad_method().as_scanner() f = lambda mol: gs(mol) m = berny_solver.as_pyscf_method(mol, f) mol1 = berny_solver.optimize(m) self.assertAlmostEqual(lib.finger(mol1.atom_coords()), 2.2000335948443315, 5)
def test_as_pyscf_method(self): mol = gto.M(atom=''' O 0. 0. 0. H 0. -0.757 0.587 H 0. 0.757 0.587 ''', verbose=0) gs = scf.RHF(mol).nuc_grad_method().as_scanner() f = lambda mol: gs(mol) m = berny_solver.as_pyscf_method(mol, f) mol1 = berny_solver.optimize(m) self.assertAlmostEqual(lib.finger(mol1.atom_coords()), 2.2000335948443315, 5)
def test_as_pyscf_method(self): mol = gto.M(atom=''' O 0. 0. 0. H 0. -0.757 0.587 H 0. 0.757 0.587 ''', symmetry=True, verbose=0) gs = scf.RHF(mol).nuc_grad_method().as_scanner() f = lambda mol: gs(mol) m = berny_solver.as_pyscf_method(mol, f) mol1 = berny_solver.optimize(m) self.assertAlmostEqual(lib.finger(mol1.atom_coords()), 3.039311839766823, 4) self.assertEqual(mol1.symmetry, 'C2v')
def opt_sf6(): sf6_mol = gto.M(atom=""" S -0.59356137 0.59356136 0.00000000 F -0.59356137 0.59356136 -1.59000000 F -0.59356137 2.18356136 0.00000000 F -2.18356137 0.59356136 0.00000000 F -0.59356137 0.59356136 1.59000000 F -0.59356137 -0.99643864 0.00000000 F 0.99643863 0.59356136 0.00000000 """, basis="sto-3g") mf = scf.RHF(sf6_mol) mol1 = optimize(mf) #, maxsteps=1)
def opt_azetidine(): mol = gto.M(atom=""" C -2.34863259 0.70994422 0.14975543 H -1.82664215 -0.18774343 -0.10828112 H -3.39537825 0.49299009 0.10333942 N -1.96488182 1.28417466 1.38787045 H -0.98378042 1.23964802 1.57617181 C -2.38604561 2.48589673 0.76463760 H -3.44072555 2.64557427 0.84862153 H -1.90158885 3.36988967 1.12346645 C -2.01779803 2.00680465 -0.70250775 H -2.49979795 1.48773285 -1.50446820 H -2.52937959 2.89193912 -1.01829449 """, basis="sto-3g") mf = scf.RHF(mol) mol1 = optimize(mf)
def refine_pyscf(charge, multiplicity, calc_result, tdir, log=None): from pyscf import gto, dft from pyscf.geomopt.berny_solver import optimize mol = gto.M(atom="".join(calc_result.data[2:]), basis='cc-pVDZ', output=f'{tdir}/my_log.txt', verbose=4, charge=charge, spin=multiplicity - 1) mf = dft.RKS(mol, xc="B3LYP") #mf.xcfun = "SCAN" mol_opt = optimize(mf) energy = dft.RKS(mol_opt, xc="B3LYP").kernel() at_count = len(mol_opt.atom_coords()) coord = [ f"{x[0]} {x[1][0]} {x[1][1]} {x[1][2]}" for x in mol_opt.atom ] coord.insert(0, "") coord.insert(0, f"{at_count}") if log: with open(f'{tdir}/my_log.txt') as f: return CalcResult(data=coord, min_energy=energy, log=f.readlines()) else: return CalcResult(data=coord, min_energy=energy, log=None)
''' import numpy from pyscf import gto, scf, cc, qmmm from pyscf.geomopt import berny_solver mol = gto.M(atom=''' C 1.1879 -0.3829 0.0000 C 0.0000 0.5526 0.0000 O -1.1867 -0.2472 0.0000 H -1.9237 0.3850 0.0000 H 2.0985 0.2306 0.0000 H 1.1184 -1.0093 0.8869 H 1.1184 -1.0093 -0.8869 H -0.0227 1.1812 0.8852 H -0.0227 1.1812 -0.8852 ''', basis='3-21g') numpy.random.seed(1) coords = numpy.random.random((5,3)) * 10 charges = (numpy.arange(5) + 1.) * -.001 mf = qmmm.mm_charge(scf.RHF(mol), coords, charges) #mf.verbose=4 #mf.kernel() mol1 = berny_solver.optimize(mf) from pyscf.geomopt import geometric_solver mycc = cc.CCSD(mf) mol1 = geometric_solver.optimize(mycc)
import numpy from pyscf import gto, scf, cc, qmmm from pyscf.geomopt import berny_solver mol = gto.M(atom=''' C 1.1879 -0.3829 0.0000 C 0.0000 0.5526 0.0000 O -1.1867 -0.2472 0.0000 H -1.9237 0.3850 0.0000 H 2.0985 0.2306 0.0000 H 1.1184 -1.0093 0.8869 H 1.1184 -1.0093 -0.8869 H -0.0227 1.1812 0.8852 H -0.0227 1.1812 -0.8852 ''', basis='3-21g') numpy.random.seed(1) coords = numpy.random.random((5, 3)) * 10 charges = (numpy.arange(5) + 1.) * -.001 mf = qmmm.mm_charge(scf.RHF(mol), coords, charges) #mf.verbose=4 #mf.kernel() mol1 = berny_solver.optimize(mf) mycc = cc.CCSD(mf) mol1 = berny_solver.optimize(mycc)
force.append(grad[0, 2]) plt.plot(bond, e_hf[::-1]) plt.show() plt.plot(bond, force[::-1]) plt.show() # When a molecular geometry is input to the scanner, it uses the SAME unit as # the one in the previous calculation. mol = gto.Mole(atom='N; N 1 1.2', unit='Ang', basis='ccpvdz') mf_grad_scan = scf.RHF(mol).nuc_grad_method().as_scanner() e0, grad0 = mf_grad_scan('N; N 1 1.2') e1, grad1 = mf_grad_scan('N; N 1 1.199') e2, grad2 = mf_grad_scan('N; N 1 1.201') e_diff = (e2 - e1) / 0.002 * 0.529 print('finite difference', e_diff, 'analytical gradients', grad0[1, 0]) mf_grad_scan.mol.unit = 'Bohr' e0, grad0 = mf_grad_scan('N; N 1 1.8') e1, grad1 = mf_grad_scan('N; N 1 1.799') e2, grad2 = mf_grad_scan('N; N 1 1.801') e_diff = (e2 - e1) / 0.002 print('finite difference', e_diff, 'analytical gradients', grad0[1, 0]) # The gradients scanner can be pass to pyberny geometry optimizer # See also examples/geomopt/01-pyberny.py and # examples/geomopt/02-as_pyscf_method.py from pyscf.geomopt import berny_solver berny_solver.optimize(mf_grad_scan)
#!/usr/bin/env python ''' Optimize molecular geometry with or w/o ghost atoms. (In testing) ''' from pyscf.geomopt import berny_solver from pyscf import gto, scf mol = gto.M(atom=''' GHOST-O 0. 0. 0. H 0. -0.757 0.587 H 0. 0.757 0.587 ''', basis='631g') mf = scf.RHF(mol) berny_solver.optimize(mf, include_ghost=True) berny_solver.optimize(mf, include_ghost=False)
results.multiplicity) if results.multiplicity is not None else 1 spin = (multiplicity - 1) / 2 num_frozen_cores = int( results.frozen_cores) if results.frozen_cores is not None else 0 sys.argv = [sys.argv[0]] # ----------------------- # PYSCF # ----------------------- mol = gto.M(atom=atomic_coords, basis=basis_set, spin=spin, charge=charge, verbose=4) mf = scf.RHF(mol) mf.conv_tol = 1e-4 mf.max_cycle = 100 if density_fit: mf = mf.density_fit() mf.with_df.auxbasis = aux_basis_set new_mol = berny_solver.optimize(mf, assert_convergence=True) print("New geometry (unit A)") for atom_index, atomic_coord in enumerate(new_mol.atom): print("{:4} {:s} {:18.12f} {:16.12f} {:16.12f}".format( atom_index, atomic_coord[0], atomic_coord[1][0], atomic_coord[1][1], atomic_coord[1][2]))
# 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)
from pyscf import gto, mp, scf from pyscf.geomopt import berny_solver # Starting geometry mol = gto.M( atom='S 0 0 0;' 'H 0 0 1.795239827225189;' 'H 1.693194615993441 0 -0.599043184453037', basis='cc-pvtz', verbose=3, unit="Bohr" ) # HF optimisation mf = scf.RHF(mol) mol_hf_eq = berny_solver.optimize(mf) # MP2 optimisation mp2 = mp.MP2(scf.RHF(mol_hf_eq)) mol_mp2_eq = berny_solver.optimize(mp2) print() print("=========== Final MP2 geometry (bohr) ============") print() fmt = "{} {:15.11g} {:15.11g} {:15.11g}" coords = mol_mp2_eq.atom_coords() n_atoms = len(coords) for i in range(n_atoms): print(fmt.format(mol_mp2_eq.atom_symbol(i), *coords[i]))
import sys import os import matplotlib.pyplot as plt # Some input parameters, where obviously looping over dists is possible basisname = "cc-pvdz" # reference basis set dist = 0.7608986485 # equilibrium distance at this level of theory, verified! coord = 'H 0 0 0; H 0 0 {0}'.format(str(dist)) verb = 0 # integer verbosity flag # Do a mean-field KS-DFT calculation at dist mol = gto.Mole( atom=coord, basis=basisname, charge=0, spin=0) # build a molecule, neutral species, spin is N\alpha-N\beta here mol.build() mf = scf.RKS(mol) # run DFT calculation as reference mf.verbose = verb # reduce output mf.xc = 'lda,vwn' # we select an approximate xc functional, many options available e.g. 'pbe,pbe' or 'b3lyp' edft = mf.kernel() # get DFT energy nelec = mol.nelec # number of electrons print('The number of electrons is now {0}'.format(nelec)) print(' At a distance R = {0} angstrom:'.format(dist)) print(' DFT energy: {0} a.u.\n'.format(edft)) # total energies mol_eq = optimize(mf) #print(mol_eq.atom_coords()) dist = (mol_eq.atom_coords()[0][2] + mol_eq.atom_coords()[1][2]) * 0.529177 # bohr to angstrom conversion mf = scf.RKS(mol_eq).run(xc='lda,vwn', verbose=0) print(' At a distance R = {0} angstrom:'.format(dist)) print('DFT energy is now: {0} a.u.\n'.format(mf.e_tot))
#!/usr/bin/env python ''' For the customized energy and gradients function (e.g. adding DFT-D3 correction), a fake pyscf method need to be created before passing to berny_solver. ''' import numpy as np from pyscf import gto, scf from pyscf.geomopt import berny_solver mol = gto.M(atom='N 0 0 0; N 0 0 1.8', unit='Bohr', basis='ccpvdz') mf = scf.RHF(mol) grad_scan = scf.RHF(mol).nuc_grad_method().as_scanner() def f(mol): e, g = grad_scan(mol) r = mol.atom_coords() penalty = np.linalg.norm(r[0] - r[1])**2 * 0.1 e += penalty g[0] += (r[0] - r[1]) * 2 * 0.1 g[1] -= (r[0] - r[1]) * 2 * 0.1 print('Customized |g|', np.linalg.norm(g)) return e, g fake_method = berny_solver.as_pyscf_method(mol, f) mol1 = berny_solver.optimize(fake_method)
#!/usr/bin/env python ''' Use pyberny to get the molecular equilibrium geometry. ''' from pyscf import gto, scf from pyscf.geomopt import berny_solver mol = gto.M(atom='N 0 0 0; N 0 0 1.2', basis='ccpvdz') mf = scf.RHF(mol) # # geometry optimization for HF # mol_eq = berny_solver.optimize(mf) print(mol_eq.atom_coords()) # # geometry optimization for CASSCF # from pyscf import mcscf mf = scf.RHF(mol) mc = mcscf.CASSCF(mf, 4, 4) mol_eq = berny_solver.optimize(mc)
from pyscf.geomopt import berny_solver, as_pyscf_method mol = gto.M(atom='N 0 0 0; N 0 0 1.8', unit='Bohr', basis='ccpvdz') mf = scf.RHF(mol) grad_scan = scf.RHF(mol).nuc_grad_method().as_scanner() def f(mol): e, g = grad_scan(mol) r = mol.atom_coords() penalty = np.linalg.norm(r[0] - r[1])**2 * 0.1 e += penalty g[0] += (r[0] - r[1]) * 2 * 0.1 g[1] -= (r[0] - r[1]) * 2 * 0.1 print('Customized |g|', np.linalg.norm(g)) return e, g # # Function as_pyscf_method is a wrapper that convert the "energy-gradients" # function to berny_solver. The "energy-gradients" function takes the Mole # object as geometry input, and returns the energy and gradients of that # geometry. # fake_method = as_pyscf_method(mol, f) new_mol = berny_solver.optimize(fake_method) print('Old geometry (Bohr)') print(mol.atom_coords()) print('New geometry (Bohr)') print(new_mol.atom_coords())
def run_optim(mol, model=None, proj_basis=None, scf_args={}, conv_args={}): cf = DSCF(mol, model, proj_basis=proj_basis).set(**scf_args) mol_eq = optimize(cf, **conv_args) return mol_eq
def f(mol): e, g = grad_scan(mol) r = mol.atom_coords() penalty = np.linalg.norm(r[0] - r[1])**2 * 0.1 e += penalty g[0] += (r[0] - r[1]) * 2 * 0.1 g[1] -= (r[0] - r[1]) * 2 * 0.1 print('Customized |g|', np.linalg.norm(g)) return e, g # # Function as_pyscf_method is a wrapper that convert the "energy-gradients" # function to berny_solver. The "energy-gradients" function takes the Mole # object as geometry input, and returns the energy and gradients of that # geometry. # fake_method = as_pyscf_method(mol, f) new_mol = berny_solver.optimize(fake_method) print('Old geometry (Bohr)') print(mol.atom_coords()) print('New geometry (Bohr)') print(new_mol.atom_coords()) # # Geometry can be also optimized with geomeTRIC library # new_mol = geometric_solver.optimize(fake_method)
plt.plot(bond, force[::-1]) plt.show() # When a molecular geometry is input to the scanner, it uses the SAME unit as # the one in the previous calculation. mol = gto.Mole(atom='N; N 1 1.2', unit='Ang', basis='ccpvdz') mf_grad_scan = scf.RHF(mol).nuc_grad_method().as_scanner() e0, grad0 = mf_grad_scan('N; N 1 1.2') e1, grad1 = mf_grad_scan('N; N 1 1.199') e2, grad2 = mf_grad_scan('N; N 1 1.201') e_diff = (e2 - e1) / 0.002 * 0.529 print('finite difference', e_diff, 'analytical gradients', grad0[1,0]) mf_grad_scan.mol.unit = 'Bohr' e0, grad0 = mf_grad_scan('N; N 1 1.8') e1, grad1 = mf_grad_scan('N; N 1 1.799') e2, grad2 = mf_grad_scan('N; N 1 1.801') e_diff = (e2 - e1) / 0.002 print('finite difference', e_diff, 'analytical gradients', grad0[1,0]) # The gradients scanner can be pass to pyberny geometry optimizer # See also examples/geomopt/01-pyberny.py and # examples/geomopt/02-as_pyscf_method.py from pyscf.geomopt import berny_solver berny_solver.optimize(mf_grad_scan)
''' Use pyberny to get the molecular equilibrium geometry. ''' from pyscf import gto, scf from pyscf.geomopt.berny_solver import optimize mol = gto.M(atom='N 0 0 0; N 0 0 1.2', basis='ccpvdz') mf = scf.RHF(mol) # # geometry optimization for HF. There are two entries to invoke the berny # geometry optimization. # # method 1: import the optimize function from pyscf.geomopt.berny_solver mol_eq = optimize(mf) print(mol_eq.atom_coords()) # method 2: create the optimizer from Gradients class mol_eq = mf.Gradients().optimizer(solver='berny').kernel() # # geometry optimization for CASSCF # from pyscf import mcscf mf = scf.RHF(mol) mc = mcscf.CASSCF(mf, 4, 4) conv_params = { 'gradientmax': 6e-3, # Eh/AA 'gradientrms': 2e-3, # Eh/AA 'stepmax': 2e-2, # AA
mol = gto.M(atom=''' C 0.000000 0.000000 -0.542500 O 0.000000 0.000000 0.677500 H 0.000000 0.9353074360871938 -1.082500 H 0.000000 -0.9353074360871938 -1.082500 ''', basis='3-21g') mf = scf.RHF(mol) # Run analyze function in callback def cb(envs): mf = envs['g_scanner'].base mf.analyze(verbose=4) # # Method 1: Pass callback to optimize function # geometric_solver.optimize(mf, callback=cb) berny_solver.optimize(mf, callback=cb) # # Method 2: Add callback to geometry optimizer # opt = mf.nuc_grad_method().as_scanner().optimizer() opt.callback = cb opt.kernel()