diff --git a/examples/0-readme.py b/examples/0-readme.py index 2190389cd3..7466294e24 100644 --- a/examples/0-readme.py +++ b/examples/0-readme.py @@ -6,11 +6,10 @@ Before going throught the rest part, be sure the PySCF path is added in PYTHONPATH. ''' -from pyscf import gto -from pyscf import scf +import pyscf # mol is an object to hold molecule information. -mol = gto.M( +mol = pyscf.M( verbose = 4, output = 'out_h2o', atom = ''' @@ -26,7 +25,7 @@ # control parameters. The calculation can be executed by the kernel function. # Eg, to do Hartree-Fock, (1) create HF object, (2) call kernel function # -mf = scf.RHF(mol) +mf = mol.RHF() print('E=%.15g' % mf.kernel()) @@ -34,14 +33,18 @@ # # The above code can be simplified using stream operations. # There are three stream functions ".set", ".run", ".apply" to pipe computing -# streams. Stream operations allows writing computing script in one line. +# streams. Stream operations allows writing multiple computing tasks in one +# line. # -mf = gto.M( +mf = pyscf.M( atom = ''' O 0 0 0 h 0 -.757 .587 1 0 .757 .587''', basis = '6-31g' -).apply(scf.RHF).run() +).RHF().run() print('E=%.15g' % mf.e_tot) + +mp2 = mol.RHF().run().MP2().run() +print('E=%.15g' % mp2.e_tot) diff --git a/examples/cc/00-simple_ccsd.py b/examples/cc/00-simple_ccsd.py index e955271f2d..16d27ec167 100644 --- a/examples/cc/00-simple_ccsd.py +++ b/examples/cc/00-simple_ccsd.py @@ -7,14 +7,14 @@ A simple example to run CCSD calculation. ''' -from pyscf import gto, scf, cc +import pyscf -mol = gto.M( +mol = pyscf.M( atom = 'H 0 0 0; F 0 0 1.1', basis = 'ccpvdz') -mf = scf.RHF(mol).run() +mf = mol.RHF().run() -mycc = cc.CCSD(mf).run() +mycc = mf.CCSD().run() print('CCSD correlation energy', mycc.e_corr) diff --git a/examples/cc/00-simple_ccsd_t.py b/examples/cc/00-simple_ccsd_t.py index 32fac47da3..7da97f6a98 100644 --- a/examples/cc/00-simple_ccsd_t.py +++ b/examples/cc/00-simple_ccsd_t.py @@ -7,19 +7,19 @@ A simple example to run CCSD(T) and UCCSD(T) calculation. ''' -from pyscf import gto, scf, cc +import pyscf -mol = gto.M( +mol = pyscf.M( atom = 'H 0 0 0; F 0 0 1.1', basis = 'ccpvdz') -mf = scf.RHF(mol).run() -mycc = cc.CCSD(mf).run() +mf = mol.RHF().run() +mycc = mf.CCSD().run() et = mycc.ccsd_t() print('CCSD(T) correlation energy', mycc.e_corr + et) -mf = scf.UHF(mol).run() -mycc = cc.UCCSD(mf).run() +mf = mol.UHF().run() +mycc = mf.CCSD().run() et = mycc.ccsd_t() print('UCCSD(T) correlation energy', mycc.e_corr + et) diff --git a/examples/ci/00-simple_cisd.py b/examples/ci/00-simple_cisd.py index 0719aa4765..a65ef7404e 100644 --- a/examples/ci/00-simple_cisd.py +++ b/examples/ci/00-simple_cisd.py @@ -7,17 +7,17 @@ A simple example to run CISD calculation. ''' -from pyscf import gto, scf, ci +import pyscf -mol = gto.M( +mol = pyscf.M( atom = 'H 0 0 0; F 0 0 1.1', basis = 'ccpvdz') -mf = scf.RHF(mol).run() -mycc = ci.CISD(mf).run() +mf = mol.HF().run() +mycc = mf.CISD().run() print('RCISD correlation energy', mycc.e_corr) -mf = scf.UHF(mol).run() -mycc = ci.CISD(mf).run() +mf = mol.UHF().run() +mycc = mf.CISD().run() print('UCISD correlation energy', mycc.e_corr) diff --git a/examples/dft/00-simple_dft.py b/examples/dft/00-simple_dft.py index 755a24f953..eca8306a55 100644 --- a/examples/dft/00-simple_dft.py +++ b/examples/dft/00-simple_dft.py @@ -3,7 +3,7 @@ # Author: Qiming Sun # -from pyscf import gto, dft +import pyscf ''' A simple example to run DFT calculation. @@ -12,14 +12,13 @@ available XC functionals. ''' -mol = gto.Mole() -mol.build( +mol = pyscf.M( atom = 'H 0 0 0; F 0 0 1.1', # in Angstrom basis = '631g', symmetry = True, ) -mf = dft.RKS(mol) +mf = mol.KS() #mf.xc = 'svwn' # shorthand for slater,vwn #mf.xc = 'bp86' # shorthand for b88,p86 #mf.xc = 'blyp' # shorthand for b88,lyp diff --git a/examples/mcscf/00-simple_casci.py b/examples/mcscf/00-simple_casci.py index d0632ddf60..9e5d933aca 100644 --- a/examples/mcscf/00-simple_casci.py +++ b/examples/mcscf/00-simple_casci.py @@ -7,20 +7,22 @@ A simple example to run CASCI calculation. ''' -import numpy -from pyscf import gto, scf, mcscf +import pyscf -mol = gto.M( +mol = pyscf.M( atom = 'O 0 0 0; O 0 0 1.2', basis = 'ccpvdz', spin = 2) -myhf = scf.RHF(mol) -myhf.kernel() +myhf = mol.RHF().run() # 6 orbitals, 8 electrons -mycas = mcscf.CASCI(myhf, 6, 8) -mycas.kernel() +mycas = myhf.CASCI(6, 8).run() +# +# Note this mycas object can also be created using the APIs of mcscf module: +# +# from pyscf import mcscf +# mycas = mcscf.CASCI(myhf, 6, 8).run() # Natural occupancy in CAS space, Mulliken population etc. mycas.verbose = 4 diff --git a/examples/mcscf/00-simple_casscf.py b/examples/mcscf/00-simple_casscf.py index 899c37771f..97c99ceca5 100644 --- a/examples/mcscf/00-simple_casscf.py +++ b/examples/mcscf/00-simple_casscf.py @@ -7,20 +7,22 @@ A simple example to run CASSCF calculation. ''' -import numpy -from pyscf import gto, scf, mcscf +import pyscf -mol = gto.M( +mol = pyscf.M( atom = 'O 0 0 0; O 0 0 1.2', basis = 'ccpvdz', spin = 2) -myhf = scf.RHF(mol) -myhf.kernel() +myhf = mol.RHF().run() # 6 orbitals, 8 electrons -mycas = mcscf.CASSCF(myhf, 6, 8) -mycas.kernel() +mycas = myhf.CASSCF(6, 8).run() +# +# Note this mycas object can also be created using the APIs of mcscf module: +# +# from pyscf import mcscf +# mycas = mcscf.CASSCF(myhf, 6, 8).run() # Natural occupancy in CAS space, Mulliken population etc. # See also 00-simple_casci.py for the instruction of the output of analyze() diff --git a/examples/scf/00-simple_hf.py b/examples/scf/00-simple_hf.py index 50ccada0f4..56c8f2a8a9 100644 --- a/examples/scf/00-simple_hf.py +++ b/examples/scf/00-simple_hf.py @@ -10,17 +10,30 @@ .analyze() function calls the Mulliken population analysis etc. ''' -from pyscf import gto, scf +import pyscf -mol = gto.Mole() -mol.build( +mol = pyscf.M( atom = 'H 0 0 0; F 0 0 1.1', # in Angstrom basis = 'ccpvdz', symmetry = True, ) -myhf = scf.RHF(mol) +myhf = mol.HF() myhf.kernel() # Orbital energies, Mulliken population etc. myhf.analyze() + + +# +# myhf object can also be created using the APIs of gto, scf module +# +from pyscf import gto, scf +mol = gto.M( + atom = 'H 0 0 0; F 0 0 1.1', # in Angstrom + basis = 'ccpvdz', + symmetry = True, +) +myhf = scf.HF(mol) +myhf.kernel() + diff --git a/pyscf/__all__.py b/pyscf/__all__.py new file mode 100644 index 0000000000..866d8eccef --- /dev/null +++ b/pyscf/__all__.py @@ -0,0 +1,40 @@ +from . import post_scf +from . import grad +from . import gw +from . import hci +from . import hessian +from . import lo +from . import mrpt +from . import prop +from . import qmmm +#from . import semiempirical +from . import sgx +from . import solvent +from . import tools + +#from . import geomopt + +#try: +# from . import dftd3 +#except ImportError: +# pass +#try: +# from . import dmrgscf +#except ImportError: +# pass +#try: +# from . import icmpspt +#except ImportError: +# pass +#try: +# from . import shciscf +#except ImportError: +# pass +#try: +# from . import cornell_shci +#except ImportError: +# pass + +from .pbc import __all__ +del __all__ + diff --git a/pyscf/__init__.py b/pyscf/__init__.py index bbd036e383..5b2d08e01f 100644 --- a/pyscf/__init__.py +++ b/pyscf/__init__.py @@ -35,7 +35,7 @@ ''' -__version__ = '1.6.1' +__version__ = '1.7.1' import os import sys @@ -59,4 +59,12 @@ DEBUG = __config__.DEBUG +def M(**kwargs): + '''Main driver to create Molecule object (mol) or Material crystal object (cell)''' + if kwargs.get('a') is not None: # a is crystal lattice parameter + from pyscf.pbc import gto as pgto + return pgto.M(**kwargs) + else: # Molecule + return gto.M(**kwargs) + del(os, sys, LooseVersion, numpy) diff --git a/pyscf/cornell_shci/shci.py b/pyscf/cornell_shci/shci.py index 3989eaacc4..de1392f2c9 100644 --- a/pyscf/cornell_shci/shci.py +++ b/pyscf/cornell_shci/shci.py @@ -52,7 +52,7 @@ settings.MPIPREFIX = getattr(__config__, 'shci_MPIPREFIX', None) if settings.SHCIEXE is None: import sys - sys.stderr.write('settings.py not found. Please create %s\n' + sys.stderr.write('settings.py not found for module cornell_shci. Please create %s\n' % os.path.join(os.path.dirname(__file__), 'settings.py')) raise ImportError('settings.py not found') diff --git a/pyscf/dft/__init__.py b/pyscf/dft/__init__.py index 7b3109799c..54b1501d9a 100644 --- a/pyscf/dft/__init__.py +++ b/pyscf/dft/__init__.py @@ -27,10 +27,12 @@ try: from pyscf.dft import libxc + XC = libxc.XC except (ImportError, OSError): pass try: from pyscf.dft import xcfun + XC = xcfun.XC except (ImportError, OSError): pass #from pyscf.dft import xc diff --git a/pyscf/dmrgscf/dmrgci.py b/pyscf/dmrgscf/dmrgci.py index a445b31115..a8a11e3f8d 100644 --- a/pyscf/dmrgscf/dmrgci.py +++ b/pyscf/dmrgscf/dmrgci.py @@ -55,7 +55,7 @@ settings.BLOCKVERSION = getattr(__config__, 'dmrgscf_BLOCKVERSION', None) if (settings.BLOCKEXE is None or settings.BLOCKSCRATCHDIR is None): import sys - sys.stderr.write('settings.py not found. Please create %s\n' + sys.stderr.write('settings.py not found for module dmrgci. Please create %s\n' % os.path.join(os.path.dirname(__file__), 'settings.py')) raise ImportError('settings.py not found') diff --git a/pyscf/fciqmcscf/fciqmc.py b/pyscf/fciqmcscf/fciqmc.py index 81802ae91e..d0d9f3697d 100644 --- a/pyscf/fciqmcscf/fciqmc.py +++ b/pyscf/fciqmcscf/fciqmc.py @@ -31,7 +31,7 @@ try: from pyscf.fciqmcscf import settings except ImportError: - msg = '''settings.py not found. Please create %s + msg = '''settings.py not found for module fciqmcscf. Please create %s ''' % os.path.join(os.path.dirname(__file__), 'settings.py') sys.stderr.write(msg) diff --git a/pyscf/gto/mole.py b/pyscf/gto/mole.py index 72c44658f9..5c97531a9d 100644 --- a/pyscf/gto/mole.py +++ b/pyscf/gto/mole.py @@ -1947,6 +1947,44 @@ def ms(self): def ms(self, x): self.spin = int(round(2*x, 4)) + def __getattr__(self, key): + '''To support accessing methods (mol.HF, mol.KS, mol.CCSD, mol.CASSCF, ...) + from Mole object. + ''' + # https://github.com/mewwts/addict/issues/26 + # https://github.com/jupyter/notebook/issues/2014 + if key in ('_ipython_canary_method_should_not_exist_', + '_repr_mimebundle_'): + raise AttributeError + + # Import all available modules. Some methods are registered to other + # classes/modules when importing modules in __all__. + from pyscf import __all__ + from pyscf import scf, dft + for mod in (scf, dft): + method = getattr(mod, key, None) + if callable(method): + return method(self) + + if 'TD' in key[:3]: + if key in ('TDHF', 'TDA'): + mf = scf.HF(self) + else: + mf = dft.KS(self) + xc = key.split('TD', 1)[1] + if xc in dft.XC: + mf.xc = xc + key = 'TDDFT' + else: + mf = scf.HF(self) + + method = getattr(mf, key) + if method is None: + raise AttributeError + + mf.run() + return method + # need "deepcopy" here because in shallow copy, _env may get new elements but # with ptr_env unchanged # def __copy__(self): @@ -3065,28 +3103,8 @@ def apply(self, fn, *args, **kwargs): if callable(fn): return lib.StreamObject.apply(self, fn, *args, **kwargs) elif isinstance(fn, (str, unicode)): - from pyscf import scf, dft, mp, cc, ci, mcscf, tdscf - # Import all available modules. Some methods are registered when - # loading these modules. - from pyscf import grad, hessian, solvent, qmmm, prop - for mod in (scf, dft): - method = getattr(mod, fn.upper(), None) - if method is not None and callable(method): - return method(self, *args, **kwargs) - - for mod in (mp, cc, ci, mcscf): - method = getattr(mod, fn.upper(), None) - if method is not None and callable(method): - return method(scf.HF(self).run(), *args, **kwargs) - - if fn.upper() == 'TDHF': - return tdscf.TDHF(scf.HF(self).run(), *args, **kwargs) - else: - method = getattr(tdscf, fn.upper(), None) - if method is not None and callable(method): - return method(scf.HF(self).run(), *args, **kwargs) - - raise ValueError('Unknown method %s' % fn) + method = getattr(self, fn.upper()) + return method(*args, **kwargs) else: raise TypeError('First argument of .apply method must be a ' 'function/class or a name (string) of a method.') diff --git a/pyscf/gto/test/test_mole.py b/pyscf/gto/test/test_mole.py index 0064c76bf1..2da7e3bf41 100644 --- a/pyscf/gto/test/test_mole.py +++ b/pyscf/gto/test/test_mole.py @@ -824,6 +824,20 @@ def test_to_uncontracted_cartesian_basis(self): self.assertAlmostEqual(abs(s-mol0.intor('int1e_ovlp')).max(), 0, 9) mol0.cart = False + def test_getattr(self): + from pyscf import scf, dft, ci, tdscf + mol = gto.M(atom='He') + self.assertEqual(mol.HF().__class__, scf.HF(mol).__class__) + self.assertEqual(mol.KS().__class__, dft.KS(mol).__class__) + self.assertEqual(mol.UKS().__class__, dft.UKS(mol).__class__) + self.assertEqual(mol.CISD().__class__, ci.cisd.RCISD) + self.assertEqual(mol.TDA().__class__, tdscf.rks.TDA) + self.assertEqual(mol.dTDA().__class__, tdscf.rks.dTDA) + self.assertEqual(mol.TDBP86().__class__, tdscf.rks.TDDFTNoHybrid) + self.assertEqual(mol.TDB3LYP().__class__, tdscf.rks.TDDFT) + self.assertRaises(AttributeError, lambda: mol.xyz) + self.assertRaises(AttributeError, lambda: mol.TDxyz) + if __name__ == "__main__": print("test mole.py") diff --git a/pyscf/lib/misc.py b/pyscf/lib/misc.py index 08d1456a5e..e8b38706a8 100644 --- a/pyscf/lib/misc.py +++ b/pyscf/lib/misc.py @@ -489,6 +489,9 @@ def set(self, **kwargs): setattr(self, k, v) return self + # An alias to .set method + __call__ = set + def apply(self, fn, *args, **kwargs): ''' Apply the fn to rest arguments: return fn(*args, **kwargs). The @@ -614,6 +617,7 @@ def fn(obj, *args, **kwargs): return cls(obj, *args, **kwargs) fn.__doc__ = cls.__doc__ fn.__name__ = cls.__name__ + fn.__module__ = cls.__module__ return fn def import_as_method(fn, default_keys=None): diff --git a/pyscf/pbc/__all__.py b/pyscf/pbc/__all__.py new file mode 100644 index 0000000000..0f10b953bf --- /dev/null +++ b/pyscf/pbc/__all__.py @@ -0,0 +1,9 @@ +from . import mp, ci, cc, tdscf +from . import ao2mo +from . import df +from . import dft +#from . import grad +#from . import lo +#from . import prop +from . import tools +from . import x2c diff --git a/pyscf/pbc/cc/__init__.py b/pyscf/pbc/cc/__init__.py index f0af9a0498..d9be0e8555 100644 --- a/pyscf/pbc/cc/__init__.py +++ b/pyscf/pbc/cc/__init__.py @@ -15,6 +15,9 @@ from pyscf.pbc import scf from pyscf.pbc.cc import ccsd +from pyscf.pbc.cc import kccsd_rhf as krccsd +from pyscf.pbc.cc import kccsd_uhf as kuccsd +from pyscf.pbc.cc import kccsd as kgccsd def RCCSD(mf, frozen=0, mo_coeff=None, mo_occ=None): mf = scf.addons.convert_to_rhf(mf) diff --git a/pyscf/pbc/cc/ccsd.py b/pyscf/pbc/cc/ccsd.py index 83df9af716..db23faae7a 100644 --- a/pyscf/pbc/cc/ccsd.py +++ b/pyscf/pbc/cc/ccsd.py @@ -145,3 +145,11 @@ def _adjust_occ(mo_energy, nocc, shift): mo_energy = mo_energy.copy() mo_energy[:nocc] += shift return mo_energy + + +from pyscf.pbc import scf +scf.hf.RHF.CCSD = lib.class_as_method(RCCSD) +scf.uhf.UHF.CCSD = lib.class_as_method(UCCSD) +scf.ghf.GHF.CCSD = lib.class_as_method(GCCSD) +scf.rohf.ROHF.CCSD = None + diff --git a/pyscf/pbc/cc/kccsd.py b/pyscf/pbc/cc/kccsd.py index 8193cd4970..3c51907de3 100644 --- a/pyscf/pbc/cc/kccsd.py +++ b/pyscf/pbc/cc/kccsd.py @@ -799,6 +799,11 @@ def make_ea(self, ea_partition=None): self.made_ea_imds = True log.timer('EOM-CCSD EA intermediates', *cput0) + +from pyscf.pbc import scf +scf.kghf.KGHF.CCSD = lib.class_as_method(KGCCSD) + + if __name__ == '__main__': from pyscf.pbc import gto, scf, cc diff --git a/pyscf/pbc/cc/kccsd_rhf.py b/pyscf/pbc/cc/kccsd_rhf.py index 8984ab1ad3..2500c6d87e 100644 --- a/pyscf/pbc/cc/kccsd_rhf.py +++ b/pyscf/pbc/cc/kccsd_rhf.py @@ -1103,6 +1103,11 @@ def _mem_usage(nkpts, nocc, nvir): return incore * 16 / 1e6, outcore * 16 / 1e6, basic * 16 / 1e6 +from pyscf.pbc import scf +scf.khf.KRHF.CCSD = lib.class_as_method(KRCCSD) +scf.krohf.KROHF.CCSD = None + + if __name__ == '__main__': from pyscf.pbc import gto, scf, cc diff --git a/pyscf/pbc/cc/kccsd_uhf.py b/pyscf/pbc/cc/kccsd_uhf.py index 00a355c759..223cf69563 100644 --- a/pyscf/pbc/cc/kccsd_uhf.py +++ b/pyscf/pbc/cc/kccsd_uhf.py @@ -1127,6 +1127,10 @@ def _make_df_eris(cc, mo_coeff=None): return eris +from pyscf.pbc import scf +scf.kuhf.KUHF.CCSD = lib.class_as_method(KUCCSD) + + if __name__ == '__main__': from pyscf.pbc import gto, scf, cc from pyscf import lo diff --git a/pyscf/pbc/ci/cisd.py b/pyscf/pbc/ci/cisd.py index 8847aaf570..7dfc2089a0 100644 --- a/pyscf/pbc/ci/cisd.py +++ b/pyscf/pbc/ci/cisd.py @@ -107,3 +107,11 @@ def ao2mofn(mo_coeff): madelung = tools.madelung(self._scf.cell, self._scf.kpt) eris.mo_energy = _adjust_occ(eris.mo_energy, eris.nocc, -madelung) return eris + + +from pyscf.pbc import scf +scf.hf.RHF.CISD = lib.class_as_method(RCISD) +scf.uhf.UHF.CISD = lib.class_as_method(UCISD) +scf.ghf.GHF.CISD = lib.class_as_method(GCISD) +scf.rohf.ROHF.CISD = None + diff --git a/pyscf/pbc/gto/cell.py b/pyscf/pbc/gto/cell.py index 066f184878..1b5116988d 100644 --- a/pyscf/pbc/gto/cell.py +++ b/pyscf/pbc/gto/cell.py @@ -1116,6 +1116,60 @@ def nelec(self): 'in unit cell\n' % (ne, self.spin)) return nalpha, nbeta + def __getattr__(self, key): + '''To support accessing methods (cell.HF, cell.KKS, cell.KUCCSD, ...) + from Cell object. + ''' + # https://github.com/mewwts/addict/issues/26 + # https://github.com/jupyter/notebook/issues/2014 + if key in ('_ipython_canary_method_should_not_exist_', + '_repr_mimebundle_'): + raise AttributeError + + # Import all available modules. Some methods are registered to other + # classes/modules when importing modules in __all__. + from pyscf.pbc import __all__ + from pyscf.pbc import scf, dft + from pyscf.dft import XC + for mod in (scf, dft): + method = getattr(mod, key, None) + if callable(method): + return method(self) + + if key[0] == 'K': # with k-point sampling + if 'TD' in key[:4]: + if key in ('KTDHF', 'KTDA'): + mf = scf.KHF(self) + else: + mf = dft.KKS(self) + xc = key.split('TD', 1)[1] + if xc in XC: + mf.xc = xc + key = 'KTDDFT' + else: + mf = scf.KHF(self) + # Remove prefix 'K' because methods are registered without the leading 'K' + key = key[1:] + else: + if 'TD' in key[:3]: + if key in ('TDHF', 'TDA'): + mf = scf.HF(self) + else: + mf = dft.KS(self) + xc = key.split('TD', 1)[1] + if xc in XC: + mf.xc = xc + key = 'TDDFT' + else: + mf = scf.HF(self) + + method = getattr(mf, key) + if method is None: + raise AttributeError + + mf.run() + return method + tot_electrons = tot_electrons #Note: Exculde dump_input, parse_arg, basis from kwargs to avoid parsing twice @@ -1589,24 +1643,4 @@ def has_ecp(self): '''Whether pseudo potential is used in the system.''' return self.pseudo or self._pseudo or (len(self._ecpbas) > 0) - def apply(self, fn, *args, **kwargs): - if callable(fn): - return lib.StreamObject.apply(self, fn, *args, **kwargs) - elif isinstance(fn, (str, unicode)): - from pyscf.pbc import scf, dft, mp, cc, ci, tdscf - for mod in (scf, dft): - method = getattr(mod, fn.upper(), None) - if method is not None and callable(method): - return method(self, *args, **kwargs) - - for mod in (mp, cc, ci, tdscf): - method = getattr(mod, fn.upper(), None) - if method is not None and callable(method): - return method(scf.HF(self).run(), *args, **kwargs) - - raise ValueError('Unknown method %s' % fn) - else: - raise TypeError('First argument of .apply method must be a ' - 'function or a string.') - del(INTEGRAL_PRECISION, WRAP_AROUND, WITH_GAMMA, EXP_DELIMITER) diff --git a/pyscf/pbc/gto/test/test_cell.py b/pyscf/pbc/gto/test/test_cell.py index e998b4125b..489137a091 100644 --- a/pyscf/pbc/gto/test/test_cell.py +++ b/pyscf/pbc/gto/test/test_cell.py @@ -327,6 +327,24 @@ def test_basis_truncation(self): self.assertEqual(len(b[0][1]), 4) self.assertEqual(len(b[1][1]), 2) + def test_getattr(self): + from pyscf.pbc import scf, dft, cc, tdscf + cell = pgto.M(atom='He', a=np.eye(3)*4, basis={'He': [[0, (1, 1)]]}) + self.assertEqual(cell.HF().__class__, scf.HF(cell).__class__) + self.assertEqual(cell.KS().__class__, dft.KS(cell).__class__) + self.assertEqual(cell.UKS().__class__, dft.UKS(cell).__class__) + self.assertEqual(cell.KROHF().__class__, scf.KROHF(cell).__class__) + self.assertEqual(cell.KKS().__class__, dft.KKS(cell).__class__) + self.assertEqual(cell.CCSD().__class__, cc.ccsd.RCCSD) + self.assertEqual(cell.TDA().__class__, tdscf.rks.TDA) + self.assertEqual(cell.TDBP86().__class__, tdscf.rks.TDDFTNoHybrid) + self.assertEqual(cell.TDB3LYP().__class__, tdscf.rks.TDDFT) + self.assertEqual(cell.KCCSD().__class__, cc.kccsd_rhf.KRCCSD) + self.assertEqual(cell.KTDA().__class__, tdscf.krks.TDA) + self.assertEqual(cell.KTDBP86().__class__, tdscf.krks.TDDFTNoHybrid) + self.assertRaises(AttributeError, lambda: cell.xyz) + self.assertRaises(AttributeError, lambda: cell.TDxyz) + if __name__ == '__main__': print("Full Tests for pbc.gto.cell") diff --git a/pyscf/pbc/mp/kmp2.py b/pyscf/pbc/mp/kmp2.py index b759d7e751..00df3e2e67 100644 --- a/pyscf/pbc/mp/kmp2.py +++ b/pyscf/pbc/mp/kmp2.py @@ -461,6 +461,12 @@ def kernel(self, mo_energy=None, mo_coeff=None): KRMP2 = KMP2 +from pyscf.pbc import scf +scf.khf.KRHF.MP2 = lib.class_as_method(KRMP2) +scf.kghf.KGHF.MP2 = None +scf.krohf.KROHF.MP2 = None + + if __name__ == '__main__': from pyscf.pbc import gto, scf, mp diff --git a/pyscf/pbc/mp/kump2.py b/pyscf/pbc/mp/kump2.py index d525897dc7..0738d0f991 100644 --- a/pyscf/pbc/mp/kump2.py +++ b/pyscf/pbc/mp/kump2.py @@ -404,6 +404,11 @@ def kernel(self, mo_energy=None, mo_coeff=None): logger.log(self, 'KMP2 energy = %.15g', self.e_corr) return self.e_corr, self.t2 + +from pyscf.pbc import scf +scf.kuhf.KUHF.MP2 = lib.class_as_method(KUMP2) + + if __name__ == '__main__': from pyscf.pbc import gto, scf, mp diff --git a/pyscf/pbc/mp/mp2.py b/pyscf/pbc/mp/mp2.py index d66cc1f5d0..b31062303f 100644 --- a/pyscf/pbc/mp/mp2.py +++ b/pyscf/pbc/mp/mp2.py @@ -86,3 +86,11 @@ def _gen_ao2mofn(mf): def ao2mofn(mo_coeff): return with_df.ao2mo(mo_coeff, kpt, compact=False) return ao2mofn + + +from pyscf.pbc import scf +scf.hf.RHF.MP2 = lib.class_as_method(RMP2) +scf.uhf.UHF.MP2 = lib.class_as_method(UMP2) +scf.ghf.GHF.MP2 = lib.class_as_method(GMP2) +scf.rohf.ROHF.MP2 = None + diff --git a/pyscf/pbc/tdscf/__init__.py b/pyscf/pbc/tdscf/__init__.py index 8884e1035f..fd2fe7d0c2 100644 --- a/pyscf/pbc/tdscf/__init__.py +++ b/pyscf/pbc/tdscf/__init__.py @@ -65,19 +65,13 @@ def TDDFT(mf): if isinstance(mf, scf.uhf.UHF): #mf = scf.addons.convert_to_uhf(mf) if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return uks.TDDFT(mf) - else: - return uks.TDDFTNoHybrid(mf) + return uks.tddft(mf) else: return uhf.TDHF(mf) else: #mf = scf.addons.convert_to_rhf(mf) if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return rks.TDDFT(mf) - else: - return rks.TDDFTNoHybrid(mf) + return rks.tddft(mf) else: return rhf.TDHF(mf) @@ -107,18 +101,12 @@ def KTDDFT(mf): from pyscf.pbc import scf if isinstance(mf, scf.uhf.UHF): if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return kuks.TDDFT(mf) - else: - return kuks.TDDFTNoHybrid(mf) + return kuks.tddft(mf) else: return kuhf.TDHF(mf) else: if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return krks.TDDFT(mf) - else: - return krks.TDDFTNoHybrid(mf) + return krks.tddft(mf) else: return krhf.TDHF(mf) diff --git a/pyscf/pbc/tdscf/krhf.py b/pyscf/pbc/tdscf/krhf.py index e9c2dce98e..15f626473e 100644 --- a/pyscf/pbc/tdscf/krhf.py +++ b/pyscf/pbc/tdscf/krhf.py @@ -262,6 +262,13 @@ def _unpack(vo, mo_occ): return z +from pyscf.pbc import scf +scf.khf.KRHF.TDA = lib.class_as_method(KTDA) +scf.khf.KRHF.TDHF = lib.class_as_method(KTDHF) +scf.krohf.KROHF.TDA = None +scf.krohf.KROHF.TDHF = None + + if __name__ == '__main__': from pyscf.pbc import gto from pyscf.pbc import scf diff --git a/pyscf/pbc/tdscf/krks.py b/pyscf/pbc/tdscf/krks.py index 03a5b978a9..e89d51e426 100644 --- a/pyscf/pbc/tdscf/krks.py +++ b/pyscf/pbc/tdscf/krks.py @@ -38,6 +38,22 @@ TDDFTNoHybrid = TDDFT +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + +from pyscf.pbc import dft +dft.krks.KRKS.TDA = lib.class_as_method(KTDA) +dft.krks.KRKS.TDHF = None +dft.krks.KRKS.TDDFT = tddft +dft.kroks.KROKS.TDA = None +dft.kroks.KROKS.TDHF = None +dft.kroks.KROKS.TDDFT = None + + if __name__ == '__main__': from pyscf.pbc import gto from pyscf.pbc import scf diff --git a/pyscf/pbc/tdscf/kuhf.py b/pyscf/pbc/tdscf/kuhf.py index c387203009..a91225483d 100644 --- a/pyscf/pbc/tdscf/kuhf.py +++ b/pyscf/pbc/tdscf/kuhf.py @@ -291,6 +291,11 @@ def _unpack(vo, mo_occ): return za, zb +from pyscf.pbc import scf +scf.kuhf.KUHF.TDA = lib.class_as_method(KTDA) +scf.kuhf.KUHF.TDHF = lib.class_as_method(KTDHF) + + if __name__ == '__main__': from pyscf.pbc import gto from pyscf.pbc import scf diff --git a/pyscf/pbc/tdscf/kuks.py b/pyscf/pbc/tdscf/kuks.py index 1cd12280c3..6f4b998465 100644 --- a/pyscf/pbc/tdscf/kuks.py +++ b/pyscf/pbc/tdscf/kuks.py @@ -26,6 +26,20 @@ TDDFTNoHybrid = TDDFT +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + +from pyscf import lib +from pyscf.pbc import dft +dft.kuks.KUKS.TDA = lib.class_as_method(KTDA) +dft.kuks.KUKS.TDHF = None +dft.kuks.KUKS.TDDFT = tddft + + if __name__ == '__main__': from pyscf.pbc import gto diff --git a/pyscf/pbc/tdscf/rhf.py b/pyscf/pbc/tdscf/rhf.py index ec17d86650..ac67a2b47d 100644 --- a/pyscf/pbc/tdscf/rhf.py +++ b/pyscf/pbc/tdscf/rhf.py @@ -51,3 +51,10 @@ def nuc_grad_method(self): RPA = TDRHF = TDHF + +from pyscf.pbc import scf +scf.hf.RHF.TDA = lib.class_as_method(TDA) +scf.hf.RHF.TDHF = lib.class_as_method(TDHF) +scf.rohf.ROHF.TDA = None +scf.rohf.ROHF.TDHF = None + diff --git a/pyscf/pbc/tdscf/rks.py b/pyscf/pbc/tdscf/rks.py index e8a5efde84..775d81b8ee 100644 --- a/pyscf/pbc/tdscf/rks.py +++ b/pyscf/pbc/tdscf/rks.py @@ -33,3 +33,18 @@ def vindp(x): def nuc_grad_method(self): raise NotImplementedError +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + +from pyscf import lib +from pyscf.pbc import dft +dft.rks.RKS.TDA = lib.class_as_method(TDA) +dft.rks.RKS.TDHF = None +dft.rks.RKS.TDDFT = tddft +#dft.rks.RKS.dTDA = lib.class_as_method(dTDA) +#dft.rks.RKS.dRPA = lib.class_as_method(dRPA) + diff --git a/pyscf/pbc/tdscf/uhf.py b/pyscf/pbc/tdscf/uhf.py index 3022559511..9dbd0406d0 100644 --- a/pyscf/pbc/tdscf/uhf.py +++ b/pyscf/pbc/tdscf/uhf.py @@ -45,49 +45,10 @@ def vindp(x): def nuc_grad_method(self): raise NotImplementedError - RPA = TDUHF = TDHF - -if __name__ == '__main__': - from pyscf import gto - from pyscf import scf - mol = gto.Mole() - mol.verbose = 0 - mol.output = None - - mol.atom = [ - ['H' , (0. , 0. , .917)], - ['F' , (0. , 0. , 0.)], ] - mol.basis = '631g' - mol.build() - - mf = scf.UHF(mol).run() - td = TDA(mf) - td.nstates = 5 - td.verbose = 3 - print(td.kernel()[0] * 27.2114) -# [ 11.01748568 11.01748568 11.90277134 11.90277134 13.16955369] - - td = TDHF(mf) - td.nstates = 5 - td.verbose = 3 - print(td.kernel()[0] * 27.2114) -# [ 10.89192986 10.89192986 11.83487865 11.83487865 12.6344099 ] - - mol.spin = 2 - mf = scf.UHF(mol).run() - td = TDA(mf) - td.nstates = 6 - td.verbose = 3 - print(td.kernel()[0] * 27.2114) -# FIXME: first state -# [ 0.02231607274 3.32113736 18.55977052 21.01474222 21.61501962 25.0938973 ] - - td = TDHF(mf) - td.nstates = 4 - td.verbose = 3 - print(td.kernel()[0] * 27.2114) -# [ 3.31267103 18.4954748 20.84935404 21.54808392] +from pyscf.pbc import scf +scf.uhf.UHF.TDA = lib.class_as_method(TDA) +scf.uhf.UHF.TDHF = lib.class_as_method(TDHF) diff --git a/pyscf/pbc/tdscf/uks.py b/pyscf/pbc/tdscf/uks.py index a6f26d45a8..bd4afd180b 100644 --- a/pyscf/pbc/tdscf/uks.py +++ b/pyscf/pbc/tdscf/uks.py @@ -34,3 +34,18 @@ def vindp(x): def nuc_grad_method(self): raise NotImplementedError +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + +from pyscf import lib +from pyscf.pbc import dft +dft.uks.UKS.TDA = lib.class_as_method(TDA) +dft.uks.UKS.TDHF = None +dft.uks.UKS.TDDFT = tddft +#dft.rks.RKS.dTDA = lib.class_as_method(dTDA) +#dft.rks.RKS.dRPA = lib.class_as_method(dRPA) + diff --git a/pyscf/post_scf.py b/pyscf/post_scf.py new file mode 100644 index 0000000000..6f99fc1694 --- /dev/null +++ b/pyscf/post_scf.py @@ -0,0 +1 @@ +from . import mp, ci, cc, mcscf, fci, tdscf diff --git a/pyscf/shciscf/shci.py b/pyscf/shciscf/shci.py index 200b4229c4..faff43bcfb 100644 --- a/pyscf/shciscf/shci.py +++ b/pyscf/shciscf/shci.py @@ -49,7 +49,7 @@ settings.MPIPREFIX = getattr(__config__, 'shci_MPIPREFIX', None) if (settings.SHCIEXE is None or settings.SHCISCRATCHDIR is None): import sys - sys.stderr.write('settings.py not found. Please create %s\n' + sys.stderr.write('settings.py not found for module shciscf. Please create %s\n' % os.path.join(os.path.dirname(__file__), 'settings.py')) raise ImportError('settings.py not found') diff --git a/pyscf/tdscf/__init__.py b/pyscf/tdscf/__init__.py index cddaad4f0b..b642d353e9 100644 --- a/pyscf/tdscf/__init__.py +++ b/pyscf/tdscf/__init__.py @@ -54,19 +54,13 @@ def TDDFT(mf): if isinstance(mf, scf.uhf.UHF): mf = scf.addons.convert_to_uhf(mf) if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return uks.TDDFT(mf) - else: - return uks.TDDFTNoHybrid(mf) + return uks.tddft(mf) else: return uhf.TDHF(mf) else: mf = scf.addons.convert_to_rhf(mf) if getattr(mf, 'xc', None): - if mf._numint.libxc.is_hybrid_xc(mf.xc): - return rks.TDDFT(mf) - else: - return rks.TDDFTNoHybrid(mf) + return rks.tddft(mf) else: return rhf.TDHF(mf) diff --git a/pyscf/tdscf/rks.py b/pyscf/tdscf/rks.py index d6a685f272..ec66628f34 100644 --- a/pyscf/tdscf/rks.py +++ b/pyscf/tdscf/rks.py @@ -184,11 +184,20 @@ def __init__(self, mf): mf.xc = '' TDA.__init__(self, mf) + +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + from pyscf import dft dft.rks.RKS.TDA = dft.rks_symm.RKS.TDA = lib.class_as_method(TDA) dft.rks.RKS.TDHF = dft.rks_symm.RKS.TDHF = None -dft.rks.RKS.TDDFT = dft.rks_symm.RKS.TDDFT = lib.class_as_method(TDDFT) -dft.rks.RKS.TDDFTNoHybrid = dft.rks_symm.RKS.TDDFTNoHybrid = lib.class_as_method(TDDFTNoHybrid) +#dft.rks.RKS.TDDFT = dft.rks_symm.RKS.TDDFT = lib.class_as_method(TDDFT) +#dft.rks.RKS.TDDFTNoHybrid = dft.rks_symm.RKS.TDDFTNoHybrid = lib.class_as_method(TDDFTNoHybrid) +dft.rks.RKS.TDDFT = dft.rks_symm.RKS.TDDFT = tddft dft.rks.RKS.dTDA = dft.rks_symm.RKS.dTDA = lib.class_as_method(dTDA) dft.rks.RKS.dRPA = dft.rks_symm.RKS.dRPA = lib.class_as_method(dRPA) dft.roks.ROKS.TDA = dft.rks_symm.ROKS.TDA = None diff --git a/pyscf/tdscf/uks.py b/pyscf/tdscf/uks.py index fcb79c9e69..37812175ce 100644 --- a/pyscf/tdscf/uks.py +++ b/pyscf/tdscf/uks.py @@ -220,11 +220,19 @@ def __init__(self, mf): TDA.__init__(self, mf) +def tddft(mf): + '''Driver to create TDDFT or TDDFTNoHybrid object''' + if mf._numint.libxc.is_hybrid_xc(mf.xc): + return TDDFT(mf) + else: + return TDDFTNoHybrid(mf) + from pyscf import dft dft.uks.UKS.TDA = dft.uks_symm.UKS.TDA = lib.class_as_method(TDA) dft.uks.UKS.TDHF = dft.uks_symm.UKS.TDHF = None -dft.uks.UKS.TDDFT = dft.uks_symm.UKS.TDDFT = lib.class_as_method(TDDFT) -dft.uks.UKS.TDDFTNoHybrid = dft.uks_symm.UKS.TDDFTNoHybrid = lib.class_as_method(TDDFTNoHybrid) +#dft.uks.UKS.TDDFT = dft.uks_symm.UKS.TDDFT = lib.class_as_method(TDDFT) +#dft.uks.UKS.TDDFTNoHybrid = dft.uks_symm.UKS.TDDFTNoHybrid = lib.class_as_method(TDDFTNoHybrid) +dft.uks.UKS.TDDFT = dft.uks_symm.UKS.TDDFT = tddft dft.uks.UKS.dTDA = dft.uks_symm.UKS.dTDA = lib.class_as_method(dTDA) dft.uks.UKS.dRPA = dft.uks_symm.UKS.dRPA = lib.class_as_method(dRPA)