def test_init(self): hf = scf.RHF(mol) ks = scf.RKS(mol) kshf = scf.RKS(mol).set(xc='HF') self.assertTrue(isinstance(tdscf.TDA(hf), tdscf.rhf.TDA)) self.assertTrue(isinstance(tdscf.TDA(ks), tdscf.rks.TDA)) self.assertTrue(isinstance(tdscf.TDA(kshf), tdscf.rks.TDA)) self.assertTrue(isinstance(tdscf.RPA(hf), tdscf.rhf.TDHF)) self.assertTrue(isinstance(tdscf.RPA(ks), tdscf.rks.TDDFTNoHybrid)) self.assertTrue(isinstance(tdscf.RPA(kshf), tdscf.rks.TDDFT)) self.assertTrue(isinstance(tdscf.TDDFT(hf), tdscf.rhf.TDHF)) self.assertTrue(isinstance(tdscf.TDDFT(ks), tdscf.rks.TDDFTNoHybrid)) self.assertTrue(isinstance(tdscf.TDDFT(kshf), tdscf.rks.TDDFT)) self.assertRaises(RuntimeError, tdscf.dRPA, hf) self.assertTrue(isinstance(tdscf.dRPA(kshf), tdscf.rks.dRPA)) self.assertTrue(isinstance(tdscf.dRPA(ks), tdscf.rks.dRPA)) self.assertRaises(RuntimeError, tdscf.dTDA, hf) self.assertTrue(isinstance(tdscf.dTDA(kshf), tdscf.rks.dTDA)) self.assertTrue(isinstance(tdscf.dTDA(ks), tdscf.rks.dTDA)) kshf.xc = '' self.assertTrue(isinstance(tdscf.dTDA(kshf), tdscf.rks.dTDA)) self.assertTrue(isinstance(tdscf.dRPA(kshf), tdscf.rks.dRPA))
def test_nto(self): mf = scf.UHF(mol).run() td = tdscf.TDA(mf).run() w, nto = td.get_nto(state=1) self.assertAlmostEqual(w[0][0], 0.00018520143461015, 9) self.assertAlmostEqual(w[1][0], 0.99963372674044326, 9) self.assertAlmostEqual(lib.finger(w[0]), 0.00027305600430816, 9) self.assertAlmostEqual(lib.finger(w[1]), 0.99964370569529093, 9) pmol = copy.copy(mol) pmol.symmetry = True pmol.build(0, 0) mf = scf.UHF(mol).run() td = tdscf.TDA(mf).run() w, nto = td.get_nto(state=0) self.assertAlmostEqual(w[0][0], 0.00018520143461016, 9) self.assertAlmostEqual(w[1][0], 0.99963372674044326, 9) self.assertAlmostEqual(lib.finger(w[0]), 0.00027305600430816, 9) self.assertAlmostEqual(lib.finger(w[1]), 0.99964370569529093, 9)
def test_tda_b88(self): td = tdscf.TDA(mf_gga).run(nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(state=3) self.assertAlmostEqual(g1[0, 2], -0.8120037135120326, 6) td_solver = td.as_scanner() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual((e1[2] - e2[2]) / .002, g1[0, 2], 5)
def run_pyscf_tdscf(xyz, basis, charge=0, multiplicity=1, conv_tol=1e-12, conv_tol_grad=1e-11, max_iter=150, pcm_options=None): mol = gto.M( atom=xyz, basis=basis, unit="Bohr", charge=charge, # spin in the pyscf world is 2S spin=multiplicity - 1, verbose=0, # Disable commandline argument parsing in pyscf parse_arg=False, dump_input=False, ) if pcm_options: mf = ddCOSMO(scf.RHF(mol)) mf.with_solvent.eps = pcm_options.get("eps") else: mf = scf.RHF(mol) mf.conv_tol = conv_tol mf.conv_tol_grad = conv_tol_grad mf.max_cycle = max_iter mf.kernel() if pcm_options: mf.with_solvent.eps = pcm_options.get("eps_opt") # for n_eq solvation only PTE implemented mf.with_solvent.equilibrium_solvation = True cis = ddCOSMO(tdscf.TDA(mf)) else: cis = tdscf.TDA(mf) cis.nstates = 5 cis.conv_tol = 1e-7 cis.kernel() return mf, cis
def test_tda_triplet(self): td = tdscf.TDA(mf).run(singlet=False, nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(state=3) self.assertAlmostEqual(g1[0, 2], -0.47296513687621511, 8) td_solver = td.as_scanner() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual((e1[2] - e2[2]) / .002, g1[0, 2], 5)
def test_tda(self): td = tdscf.TDA(mf).run(nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(state=3) self.assertAlmostEqual(g1[0,2], -0.78246882668628404, 7) td_solver = td.as_scanner() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual((e1[2]-e2[2])/.002, g1[0,2], 4)
def test_tda_lda(self): td = tdscf.TDA(mf_lda).run(nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(td.xy[2]) self.assertAlmostEqual(g1[0, 2], -0.40279473514282405, 6) td_solver = td.as_scanner() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual((e1[2] - e2[2]) / .002, g1[0, 2], 5)
def test_tda_triplet_lda(self): td = tdscf.TDA(mf_lda).run(singlet=False, nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(state=3) self.assertAlmostEqual(g1[0,2], -0.3633334, 8) td_solver = td.as_scanner() pmol = mol.copy() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual(abs((e1[2]-e2[2])/.002 - g1[0,2]).max(), 0, 5)
def test_tda_lda(self): td = tdscf.TDA(mf_lda).set(conv_tol=1e-12) es = td.kernel(nstates=5)[0] * 27.2114 self.assertAlmostEqual(lib.fp(es[:3]), 1.4581538269747121, 6) ref = [2.14644585, 3.27738191, 5.90913787, 12.14980714, 13.15535042] self.assertAlmostEqual(abs(es - ref).max(), 0, 5) mf = dft.UKS(mol1).run(xc='lda,vwn').run() td = mf.TDA() td.nstates = 5 es = td.kernel()[0] * 27.2114 ref = [6.88046608, 7.58244885, 8.49961771, 9.30209259, 9.79775972] self.assertAlmostEqual(abs(es - ref).max(), 0, 5)
def test_tda_singlet(self): td = tdscf.TDA(mf).run(nstates=3) tdg = td.nuc_grad_method().as_scanner() g1 = tdg(mol.atom_coords(), state=3)[1] self.assertAlmostEqual(g1[0, 2], -0.23226123352352346, 8) td_solver = td.as_scanner() e1 = td_solver(pmol.set_geom_('H 0 0 1.805; F 0 0 0', unit='B')) e2 = td_solver(pmol.set_geom_('H 0 0 1.803; F 0 0 0', unit='B')) self.assertAlmostEqual((e1[2] - e2[2]) / .002, g1[0, 2], 6) self.assertAlmostEqual( abs(tdg.kernel(state=0) - mf.nuc_grad_method().kernel()).max(), 0, 8)
def test_nto(self): mf = mf_uhf td = tdscf.TDA(mf).run() w, nto = td.get_nto(state=1) self.assertAlmostEqual(w[0][0], 0.00018520143461015, 9) self.assertAlmostEqual(w[1][0], 0.99963372674044326, 9) self.assertAlmostEqual(lib.fp(w[0]), 0.00027305600430816, 9) self.assertAlmostEqual(lib.fp(w[1]), 0.99964370569529093, 9) pmol = copy.copy(mol) pmol.symmetry = True pmol.build(0, 0) mf = scf.UHF(pmol).run() td = tdscf.TDA(mf).run(nstates=3) w, nto = td.get_nto(state=0) self.assertAlmostEqual(w[0][0], 0.00018520143461016, 9) self.assertAlmostEqual(w[1][0], 0.99963372674044326, 9) self.assertAlmostEqual(lib.fp(w[0]), 0.00027305600430816, 9) self.assertAlmostEqual(lib.fp(w[1]), 0.99964370569529093, 9) w, nto = td.get_nto(state=-1) self.assertAlmostEqual(w[0][0], 0.00236940007134660, 9) self.assertAlmostEqual(w[1][0], 0.99759687228056182, 9)
def test_tda_grad(self): mol0 = gto.M(atom='H 0 0 0 ; H .5 .5 .1', unit='B', basis='321g') mol1 = gto.M(atom='H 0 0 -.001; H .5 .5 .1', unit='B', basis='321g') mol2 = gto.M(atom='H 0 0 0.001; H .5 .5 .1', unit='B', basis='321g') mf = scf.RHF(mol0).ddCOSMO().run() td = solvent.ddCOSMO(tdscf.TDA(mf)).run(equilibrium_solvation=True) ref = tda_grad(td, td.xy[0]) + mf.nuc_grad_method().kernel() e, de = td.nuc_grad_method().as_scanner(state=1)(mol0) de = td.nuc_grad_method().kernel() self.assertAlmostEqual(abs(ref - de).max(), 0, 12) td1 = mol1.RHF().ddCOSMO().run().TDA().ddCOSMO().run( equilibrium_solvation=True) td2 = mol2.RHF().ddCOSMO().run().TDA().ddCOSMO().run( equilibrium_solvation=True) e1 = td1.e_tot[0] e2 = td2.e_tot[0] self.assertAlmostEqual((e2 - e1) / 0.002, de[0, 2], 5)
def test_tda_lda(self): td = tdscf.TDA(mf_lda).set(conv_tol=1e-12) es = td.kernel(nstates=4)[0] * 27.2114 self.assertAlmostEqual(lib.finger(es[:3]), 1.4581538269747121, 6)
def test_tda_b3lyp(self): td = tdscf.TDA(mf_b3lyp).set(conv_tol=1e-12) es = td.kernel(nstates=4)[0] * 27.2114 self.assertAlmostEqual(lib.finger(es[:3]), 1.4303636271767162, 6)
def test_tda_singlet_b88(self): td = tdscf.TDA(mf_gga).run(nstates=3) tdg = td.nuc_grad_method() g1 = tdg.kernel(state=3) self.assertAlmostEqual(g1[0,2], -9.32506535e-02, 8)
def test_tda_singlet_lda(self): td = tdscf.TDA(mf_lda).run(nstates=3) tdg = td.nuc_grad_method() g1 = tdrks_grad.kernel(tdg, td.xy[2]) g1 += tdg.grad_nuc() self.assertAlmostEqual(g1[0,2], -9.23916667e-02, 8)
''' The default XC functional library (libxc) supports the energy and nuclear gradients for range separated functionals. Nuclear Hessian and TDDFT gradients need xcfun library. See also example 32-xcfun_as_default.py for how to set xcfun library as the default XC functional library. ''' from pyscf import gto, dft mol = gto.M(atom="H; F 1 1.", basis='631g') mf = dft.UKS(mol) mf.xc = 'CAMB3LYP' mf.kernel() mf.nuc_grad_method().kernel() from pyscf.hessian import uks as uks_hess # Switching to xcfun library on the fly mf._numint.libxc = dft.xcfun hess = uks_hess.Hessian(mf).kernel() print(hess.reshape(2, 3, 2, 3)) from pyscf import tdscf # Switching to xcfun library on the fly mf._numint.libxc = dft.xcfun tdks = tdscf.TDA(mf) tdks.nstates = 3 tdks.kernel() tdks.nuc_grad_method().kernel()
CIS excited state density with TDA amplitudes ''' import numpy as np from pyscf import gto, dft, tdscf mol = gto.M( atom='H 0 0 0; F 0 0 1.1', basis='631g', ) mf = dft.RKS(mol) mf.xc = 'b3lyp' mf.kernel() mytd = tdscf.TDA(mf).run(nstates=3) #mytd.analyze() def tda_denisty_matrix(td, state_id): ''' Taking the TDA amplitudes as the CIS coefficients, calculate the density matrix (in AO basis) of the excited states ''' cis_t1 = td.xy[state_id][0] dm_oo = -np.einsum('ia,ka->ik', cis_t1.conj(), cis_t1) dm_vv = np.einsum('ia,ic->ac', cis_t1, cis_t1.conj()) # The ground state density matrix in mo_basis mf = td._scf dm = np.diag(mf.mo_occ)