def test_same_mol2(self): mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0464013747') mol2 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8746076326; F 0.0052917700 0.0000000000 0.0464013747') self.assertTrue(gto.same_mol(mol1, mol2)) mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747') mol2 = gto.M(atom='H 0.0000000000 0.0052917700 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747') mol3 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8693158626; F 0.0052917700 0.0000000000 0.0464013747') mol4 = gto.M(atom='H -0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0411096047') mols = (mol1, mol2, mol3, mol4) for i,mi in enumerate(mols): for j in range(i): self.assertTrue(gto.same_mol(mols[i], mols[j])) mol1 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000 H 0.9497795800 1.3265673200 0.0000000000 H 0.9444878100 -1.3265673200 0.0000000000 H1 -0.9444878100 0.0000000000 1.3265673200 H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'sto3g'}, charge=1) mol2 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000 H 0.9444878100 1.3265673200 0.0000000000 H 0.9497795800 -1.3265673200 0.0000000000 H1 -0.9444878100 0.0000000000 1.3265673200 H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'sto3g'}, charge=1) self.assertTrue(gto.same_mol(mol1, mol2)) self.assertEqual(len(gto.atom_types(mol1._atom)), 2) mol3 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000 H1 0.9497795800 1.3265673200 0.0000000000 H1 0.9444878100 -1.3265673200 0.0000000000 H1 -0.9444878100 0.0000000000 1.3265673200 H1 -0.9444878100 0.0000000000 -1.3265673200''', basis={'H':'sto3g', 'H1':'321g'}, charge=1) self.assertTrue(not gto.same_mol(mol3, mol2))
def test_same_mol2(self): mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0464013747') mol2 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8746076326; F 0.0052917700 0.0000000000 0.0464013747') self.assertTrue(gto.same_mol(mol1, mol2)) mol1 = gto.M(atom='H 0.0052917700 0.0000000000 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747') mol2 = gto.M(atom='H 0.0000000000 0.0052917700 -0.8693158626; F 0.0000000000 0.0000000000 0.0464013747') mol3 = gto.M(atom='H 0.0000000000 0.0000000000 -0.8693158626; F 0.0052917700 0.0000000000 0.0464013747') mol4 = gto.M(atom='H -0.0052917700 0.0000000000 -0.8746076326; F 0.0000000000 0.0000000000 0.0411096047') mols = (mol1, mol2, mol3, mol4) for i,mi in enumerate(mols): for j in range(i): self.assertTrue(gto.same_mol(mols[i], mols[j])) mol1 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000 H 0.9497795800 1.3265673200 0.0000000000 H 0.9444878100 -1.3265673200 0.0000000000 H -0.9444878100 0.0000000000 1.3265673200 H -0.9444878100 0.0000000000 -1.3265673200''',charge=1) mol2 = gto.M(atom='''H 0.0000000000 0.0000000000 0.0000000000 H 0.9444878100 1.3265673200 0.0000000000 H 0.9497795800 -1.3265673200 0.0000000000 H -0.9444878100 0.0000000000 1.3265673200 H -0.9444878100 0.0000000000 -1.3265673200''',charge=1) self.assertTrue(gto.same_mol(mol1, mol2))
def test_basic(self): test_mol_12 = helpers.concat_mols([self.mol1, self.mol2]) corr_mol12 = gto.M() corr_mol12.atom = """ H-0 -1.06 0.0 0.0 C-0 0.0 0.0 0.0 C-1 1.2 0.0 0.0 H-1 2.26 0.0 0.0 """ corr_mol12.spin = 0 corr_mol12.basis = { 'C-0': 'sto-3g', 'H-0': 'sto-3g', 'C-1': '6-311g', 'H-1': '6-311g' } corr_mol12.build() self.assertEqual(test_mol_12.spin, corr_mol12.spin) self.assertTrue(gto.same_mol(test_mol_12, corr_mol12)) self.assertTrue(gto.same_mol(test_mol_12, corr_mol12)) test_mol_345 = helpers.concat_mols([self.mol3, self.mol4, self.mol5]) corr_mol345 = gto.M() corr_mol345.atom = """ O-0 -1.16 0.0 0.0 C-1 0.0 0.0 0.0 O-2 1.16 0.0 0.0 """ corr_mol345.basis = {'O-0': 'sto-3g', 'C-1': '6-311g', 'O-2': 'sto-3g'} corr_mol345.build() self.assertTrue(gto.same_basis_set(test_mol_345, corr_mol345)) self.assertTrue(gto.same_mol(test_mol_345, corr_mol345))
def test_same_mol1(self): self.assertTrue(gto.same_mol(mol0, mol0)) mol1 = gto.M(atom='h 0 1 1; O1 0 0 0; h 1 1 0') self.assertTrue(not gto.same_mol(mol0, mol1)) self.assertTrue(gto.same_mol(mol0, mol1, cmp_basis=False)) mol1 = gto.M(atom='h 0 1 1; O1 0 0 0; h 1 1 0.01') self.assertTrue(not gto.same_mol(mol0, mol1, cmp_basis=False)) self.assertTrue(gto.same_mol(mol0, mol1, tol=.02, cmp_basis=False)) mol1 = gto.M(atom='''H 0.0052917700 0.0000000000 -0.8746076326 F 0.0000000000 0.0000000000 0.0516931447''') mol2 = gto.M(atom='''H 0.0000000000 0.0000000000 -0.8746076326 F 0.0000000000 0.0000000000 0.0516931447''') self.assertTrue(gto.same_mol(mol1, mol2)) self.assertTrue(not gto.same_mol(mol1, mol2, tol=1e-6)) mol3 = gto.M(atom='''H 0.0000000000 0.0000000000 -0.8746076326 H 0.0000000000 0.0000000000 0.0516931447''') self.assertTrue(not gto.same_mol(mol3, mol2))
def test_basic_supersystem(self): mol = gto.Mole() mol.verbose = 3 mol.atom = ''' H 0. -2.757 2.857 H 0. 2.757 2.857 ''' mol.basis = '3-21g' mol.build() env_method = 'm06' hl_method = 'ccsd' subsys = cluster_subsystem.ClusterHLSubSystem(mol, env_method, hl_method) mol2 = gto.Mole() mol2.verbose = 3 mol2.atom = ''' He 1.0 20.0 0.0 He 3.0 20.0 0.0''' mol2.basis = '3-21g' mol2.build() env_method = 'm06' subsys2 = cluster_subsystem.ClusterEnvSubSystem(mol2, env_method) mol12 = helpers.concat_mols([mol, mol2]) fs_scf_obj = helpers.gen_scf_obj(mol12, 'm06') supersystem = cluster_supersystem.ClusterSuperSystem([subsys, subsys2], 'm06', fs_scf_obj, init_guess='minao') self.assertEqual(supersystem.env_method, 'm06') self.assertEqual(supersystem.proj_oper, 'huz') self.assertEqual(supersystem.max_cycle, 200) self.assertEqual(supersystem.conv_tol, 1e-9) self.assertEqual(supersystem.damp, 0) self.assertEqual(supersystem.init_guess, 'minao') self.assertEqual(supersystem.fock_subcycles, 1) #Check SCF object scf_obj = supersystem.fs_scf_obj comp_scf_obj = dft.RKS(gto.mole.conc_mol(mol, mol2)) self.assertEqual(type(scf_obj), type(comp_scf_obj)) print (comp_scf_obj.mol._basis) print (supersystem.mol._basis) self.assertTrue(gto.same_mol(comp_scf_obj.mol, supersystem.mol, cmp_basis=False)) self.assertEqual(scf_obj.xc, 'm06')
def test_remove_ovlp(self): test_mol_16 = helpers.concat_mols([self.mol1, self.mol6]) corr_mol16 = gto.M() corr_mol16.atom = """ H-0 -1.06 0.0 0.0 C-0 0.0 0.0 0.0 C-1 1.2 0.0 0.0 H-1 2.26 0.0 0.0 """ corr_mol16.basis = { 'C-0': 'sto-3g', 'H-0': 'sto-3g', 'C-1': '6-311g', 'H-1': '6-311g' } with self.assertRaises(AssertionError): test_mol_166 = helpers.concat_mols([test_mol_16, self.mol6]) test_mol_378 = helpers.concat_mols([self.mol3, self.mol7, self.mol8]) corr_mol378 = gto.M() corr_mol378.atom = """ O-0 -1.16 0.0 0.0 GHOST-C-1 2.0 0.0 0.0 O-1 0.0 1.16 0.0 C-2 0.0 0.0 0.0 """ corr_mol378.basis = { 'O-0': 'sto-3g', 'O-1': 'cc-pVTZ', 'GHOST-C-1': 'aug-cc-pVDZ', 'C-2': 'cc-pVDZ' } corr_mol378.build() self.assertTrue(gto.same_basis_set(test_mol_378, corr_mol378)) self.assertTrue(gto.same_mol(test_mol_378, corr_mol378))
def project_init_guess(casscf, init_mo, prev_mol=None): '''Project the given initial guess to the current CASSCF problem. The projected initial guess has two parts. The core orbitals are directly taken from the Hartree-Fock orbitals, and the active orbitals are projected from the given initial guess. Args: casscf : an :class:`CASSCF` or :class:`CASCI` object init_mo : ndarray or list of ndarray Initial guess orbitals which are not orth-normal for the current molecule. When the casscf is UHF-CASSCF, the init_mo needs to be a list of two ndarrays, for alpha and beta orbitals Kwargs: prev_mol : an instance of :class:`Mole` If given, the inital guess orbitals are associated to the geometry and basis of prev_mol. Otherwise, the orbitals are based of the geometry and basis of casscf.mol Returns: New orthogonal initial guess orbitals with the core taken from Hartree-Fock orbitals and projected active space from original initial guess orbitals Examples: .. code:: python import numpy from pyscf import gto, scf, mcscf mol = gto.Mole() mol.build(atom='H 0 0 0; F 0 0 0.8', basis='ccpvdz', verbose=0) mf = scf.RHF(mol) mf.scf() mc = mcscf.CASSCF(mf, 6, 6) mo = mcscf.sort_mo(mc, mf.mo_coeff, [3,4,5,6,8,9]) print('E(0.8) = %.12f' % mc.kernel(mo)[0]) init_mo = mc.mo_coeff for b in numpy.arange(1.0, 3., .2): mol.atom = [['H', (0, 0, 0)], ['F', (0, 0, b)]] mol.build(0, 0) mf = scf.RHF(mol) mf.scf() mc = mcscf.CASSCF(mf, 6, 6) mo = mcscf.project_init_guess(mc, init_mo) print('E(%2.1f) = %.12f' % (b, mc.kernel(mo)[0])) init_mo = mc.mo_coeff ''' from pyscf import lo def project(mfmo, init_mo, ncore, s): s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo)) if abs(s_init_mo - 1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]: # Initial guess orbitals are orthonormal return init_mo # TODO: test whether the canonicalized orbitals are better than the projected orbitals # Be careful that the ordering of the canonicalized orbitals may be very different # to the CASSCF orbitals. # else: # fock = casscf.get_fock(mc, init_mo, casscf.ci) # return casscf._scf.eig(fock, s)[1] nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:, :ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:, coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = lo.orth.vec_lowdin(init_mo[:, :nocc], s) # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: if casscf.mol.symmetry: restorb = [] orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s) for ir in set(orbsym): mo_ir = mfmo[:, orbsym == ir] rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir)) e, u = numpy.linalg.eigh( reduce(numpy.dot, (rest.T, s, rest))) restorb.append(numpy.dot(rest, u[:, e > 1e-7])) restorb = numpy.hstack(restorb) else: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:, e > 1e-7]) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:, ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i, j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore + i + 1, j + 1, s1[i, j]) return mo ncore = casscf.ncore mfmo = casscf._scf.mo_coeff s = casscf._scf.get_ovlp() if prev_mol is None: if init_mo.shape[0] != mfmo.shape[0]: raise RuntimeError('Initial guess orbitals has wrong dimension') elif gto.same_mol(prev_mol, casscf.mol, cmp_basis=False): if isinstance(ncore, (int, numpy.integer)): # RHF init_mo = scf.addons.project_mo_nr2nr(prev_mol, init_mo, casscf.mol) else: init_mo = (scf.addons.project_mo_nr2nr(prev_mol, init_mo[0], casscf.mol), scf.addons.project_mo_nr2nr(prev_mol, init_mo[1], casscf.mol)) elif gto.same_basis_set(prev_mol, casscf.mol): if isinstance(ncore, (int, numpy.integer)): # RHF fock = casscf.get_fock(init_mo, casscf.ci) return casscf._scf.eig(fock, s)[1] else: raise NotImplementedError('Project initial for UHF orbitals.') else: raise NotImplementedError( 'Project initial guess from different system.') # Be careful with the orbital projection. The projection may lead to bad # initial guess orbitals if the geometry is dramatically changed. if isinstance(ncore, (int, numpy.integer)): mo = project(mfmo, init_mo, ncore, s) else: # UHF-based CASSCF mo = (project(mfmo[0], init_mo[0], ncore[0], s), project(mfmo[1], init_mo[1], ncore[1], s)) return mo
def project_init_guess(casscf, init_mo, prev_mol=None): '''Project the given initial guess to the current CASSCF problem. The projected initial guess has two parts. The core orbitals are directly taken from the Hartree-Fock orbitals, and the active orbitals are projected from the given initial guess. Args: casscf : an :class:`CASSCF` or :class:`CASCI` object init_mo : ndarray or list of ndarray Initial guess orbitals which are not orth-normal for the current molecule. When the casscf is UHF-CASSCF, the init_mo needs to be a list of two ndarrays, for alpha and beta orbitals Kwargs: prev_mol : an instance of :class:`Mole` If given, the inital guess orbitals are associated to the geometry and basis of prev_mol. Otherwise, the orbitals are based of the geometry and basis of casscf.mol Returns: New orthogonal initial guess orbitals with the core taken from Hartree-Fock orbitals and projected active space from original initial guess orbitals Examples: .. code:: python import numpy from pyscf import gto, scf, mcscf mol = gto.Mole() mol.build(atom='H 0 0 0; F 0 0 0.8', basis='ccpvdz', verbose=0) mf = scf.RHF(mol) mf.scf() mc = mcscf.CASSCF(mf, 6, 6) mo = mcscf.sort_mo(mc, mf.mo_coeff, [3,4,5,6,8,9]) print('E(0.8) = %.12f' % mc.kernel(mo)[0]) init_mo = mc.mo_coeff for b in numpy.arange(1.0, 3., .2): mol.atom = [['H', (0, 0, 0)], ['F', (0, 0, b)]] mol.build(0, 0) mf = scf.RHF(mol) mf.scf() mc = mcscf.CASSCF(mf, 6, 6) mo = mcscf.project_init_guess(mc, init_mo) print('E(%2.1f) = %.12f' % (b, mc.kernel(mo)[0])) init_mo = mc.mo_coeff ''' from pyscf import lo def project(mfmo, init_mo, ncore, s): s_init_mo = numpy.einsum('pi,pi->i', init_mo.conj(), s.dot(init_mo)) if abs(s_init_mo - 1).max() < 1e-7 and mfmo.shape[1] == init_mo.shape[1]: # Initial guess orbitals are orthonormal return init_mo # TODO: test whether the canonicalized orbitals are better than the projected orbitals # Be careful that the ordering of the canonicalized orbitals may be very different # to the CASSCF orbitals. # else: # fock = casscf.get_fock(mc, init_mo, casscf.ci) # return casscf._scf.eig(fock, s)[1] nocc = ncore + casscf.ncas if ncore > 0: mo0core = init_mo[:,:ncore] s1 = reduce(numpy.dot, (mfmo.T, s, mo0core)) s1core = reduce(numpy.dot, (mo0core.T, s, mo0core)) coreocc = numpy.einsum('ij,ji->i', s1, lib.cho_solve(s1core, s1.T)) coreidx = numpy.sort(numpy.argsort(-coreocc)[:ncore]) logger.debug(casscf, 'Core indices %s', coreidx) logger.debug(casscf, 'Core components %s', coreocc[coreidx]) # take HF core mocore = mfmo[:,coreidx] # take projected CAS space mocas = init_mo[:,ncore:nocc] \ - reduce(numpy.dot, (mocore, mocore.T, s, init_mo[:,ncore:nocc])) mocc = lo.orth.vec_lowdin(numpy.hstack((mocore, mocas)), s) else: mocc = lo.orth.vec_lowdin(init_mo[:,:nocc], s) # remove core and active space from rest if mocc.shape[1] < mfmo.shape[1]: if casscf.mol.symmetry: restorb = [] orbsym = scf.hf_symm.get_orbsym(casscf.mol, mfmo, s) for ir in set(orbsym): mo_ir = mfmo[:,orbsym==ir] rest = mo_ir - reduce(numpy.dot, (mocc, mocc.T, s, mo_ir)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb.append(numpy.dot(rest, u[:,e>1e-7])) restorb = numpy.hstack(restorb) else: rest = mfmo - reduce(numpy.dot, (mocc, mocc.T, s, mfmo)) e, u = numpy.linalg.eigh(reduce(numpy.dot, (rest.T, s, rest))) restorb = numpy.dot(rest, u[:,e>1e-7]) mo = numpy.hstack((mocc, restorb)) else: mo = mocc if casscf.verbose >= logger.DEBUG: s1 = reduce(numpy.dot, (mo[:,ncore:nocc].T, s, mfmo)) idx = numpy.argwhere(abs(s1) > 0.4) for i,j in idx: logger.debug(casscf, 'Init guess <mo-CAS|mo-hf> %d %d %12.8f', ncore+i+1, j+1, s1[i,j]) return mo ncore = casscf.ncore mfmo = casscf._scf.mo_coeff s = casscf._scf.get_ovlp() if prev_mol is None: if init_mo.shape[0] != mfmo.shape[0]: raise RuntimeError('Initial guess orbitals has wrong dimension') elif gto.same_mol(prev_mol, casscf.mol, cmp_basis=False): if isinstance(ncore, (int, numpy.integer)): # RHF init_mo = scf.addons.project_mo_nr2nr(prev_mol, init_mo, casscf.mol) else: init_mo = (scf.addons.project_mo_nr2nr(prev_mol, init_mo[0], casscf.mol), scf.addons.project_mo_nr2nr(prev_mol, init_mo[1], casscf.mol)) elif gto.same_basis_set(prev_mol, casscf.mol): if isinstance(ncore, (int, numpy.integer)): # RHF fock = casscf.get_fock(init_mo, casscf.ci) return casscf._scf.eig(fock, s)[1] else: raise NotImplementedError('Project initial for UHF orbitals.') else: raise NotImplementedError('Project initial guess from different system.') # Be careful with the orbital projection. The projection may lead to bad # initial guess orbitals if the geometry is dramatically changed. if isinstance(ncore, (int, numpy.integer)): mo = project(mfmo, init_mo, ncore, s) else: # UHF-based CASSCF mo = (project(mfmo[0], init_mo[0], ncore[0], s), project(mfmo[1], init_mo[1], ncore[1], s)) return mo