def _nao_sub(mol, pre_occ, pre_nao, s=None): if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') core_lst, val_lst, rydbg_lst = _core_val_ryd_list(mol) nbf = mol.nao_nr() cnao = numpy.empty((nbf,nbf)) if core_lst: c = pre_nao[:,core_lst].copy() s1 = reduce(lib.dot, (c.T, s, c)) cnao[:,core_lst] = c1 = lib.dot(c, orth.lowdin(s1)) c = pre_nao[:,val_lst].copy() c -= reduce(lib.dot, (c1, c1.T, s, c)) else: c = pre_nao[:,val_lst] if val_lst: s1 = reduce(lib.dot, (c.T, s, c)) wt = pre_occ[val_lst] cnao[:,val_lst] = lib.dot(c, orth.weight_orth(s1, wt)) if rydbg_lst: cvlst = core_lst + val_lst c1 = cnao[:,cvlst].copy() c = pre_nao[:,rydbg_lst].copy() c -= reduce(lib.dot, (c1, c1.T, s, c)) s1 = reduce(lib.dot, (c.T, s, c)) cnao[:,rydbg_lst] = lib.dot(c, orth.lowdin(s1)) snorm = numpy.linalg.norm(reduce(lib.dot, (cnao.T, s, cnao)) - numpy.eye(nbf)) if snorm > 1e-9: logger.warn(mol, 'Weak orthogonality for localized orbitals %s', snorm) return cnao
def _nao_sub(mol, pre_occ, pre_nao): core_lst, val_lst, rydbg_lst = _core_val_ryd_list(mol) s = mol.intor_symmetric('cint1e_ovlp_sph') nao = mol.nao_nr() cnao = numpy.zeros((nao,nao)) if core_lst: c = pre_nao[:,core_lst] s1 = reduce(numpy.dot, (c.T, s, c)) cnao[:,core_lst] = numpy.dot(c, orth.lowdin(s1)) c1 = cnao[:,core_lst] rm_core = numpy.eye(nao) - reduce(numpy.dot, (c1, c1.T, s)) c = numpy.dot(rm_core, pre_nao[:,val_lst]) s1 = reduce(numpy.dot, (c.T.conj(), s, c)) wt = pre_occ[val_lst] cnao[:,val_lst] = numpy.dot(c, orth.weight_orth(s1, wt)) if rydbg_lst: c1 = cnao[:,val_lst] rm_val = numpy.eye(nao)-reduce(numpy.dot, (c1, c1.T, s)) c = reduce(numpy.dot, (rm_core, rm_val, pre_nao[:,rydbg_lst])) s1 = reduce(numpy.dot, (c.T.conj(), s, c)) cnao[:,rydbg_lst] = numpy.dot(c, orth.lowdin(s1)) return cnao
def _nao_sub(mol, pre_occ, pre_nao, s=None): if s is None: s = mol.intor_symmetric('cint1e_ovlp_sph') core_lst, val_lst, rydbg_lst = _core_val_ryd_list(mol) nbf = mol.nao_nr() cnao = numpy.empty((nbf,nbf)) if core_lst: c = pre_nao[:,core_lst] s1 = reduce(numpy.dot, (c.T, s, c)) cnao[:,core_lst] = c1 = numpy.dot(c, orth.lowdin(s1)) c = pre_nao[:,val_lst] c -= reduce(numpy.dot, (c1, c1.T, s, c)) else: c = pre_nao[:,val_lst] s1 = reduce(numpy.dot, (c.T, s, c)) wt = pre_occ[val_lst] cnao[:,val_lst] = numpy.dot(c, orth.weight_orth(s1, wt)) if rydbg_lst: cvlst = core_lst + val_lst c1 = cnao[:,cvlst] c = pre_nao[:,rydbg_lst] c -= reduce(numpy.dot, (c1, c1.T, s, c)) s1 = reduce(numpy.dot, (c.T, s, c)) cnao[:,rydbg_lst] = numpy.dot(c, orth.lowdin(s1)) snorm = numpy.linalg.norm(reduce(numpy.dot, (cnao.T, s, cnao)) - numpy.eye(nbf)) if snorm > 1e-9: logger.warn(mol, 'Weak orthogonality for localized orbitals %s', snorm) return cnao
def _iao_complementary_orbitals(mol, iao_ref): """Get the IAOs for complementary space (virtual orbitals). Args: mol (pyscf.gto.Mole): The molecule to simulate. iao_ref (numpy.array): IAO in occupied space (float64). Returns: iao_comp (numpy.array): IAO in complementary space (float64). """ # Get the total number of AOs norbital_total = mol.nao_nr() # Calculate the Overlaps for total basis s1 = mol.intor_symmetric('int1e_ovlp') # Construct the complementary space AO number_iaos = iao_ref.shape[1] number_inactive = norbital_total - number_iaos iao_com_ref = _iao_complementary_space(iao_ref, s1, number_inactive) # Get a list of active orbitals min_mol = iao.reference_mol(mol) norbital_active, active_list = _iao_count_active(mol, min_mol) # Obtain the Overlap-like matrices s21 = s1[active_list, : ] s2 = s21[ : , active_list] s12 = s21.T # Calculate P_12 = S_1^-1 * S_12 using Cholesky decomposition s1_sqrt = scipy.linalg.cho_factor(s1) s2_sqrt = scipy.linalg.cho_factor(s2) p12 = scipy.linalg.cho_solve(s1_sqrt, s12) # C~ = orth ( second_half ( S_1^-1 * S_12 * first_half ( S_2^-1 * S_21 * C ) ) ) c_tilde = scipy.linalg.cho_solve(s2_sqrt, np.dot(s21, iao_com_ref)) c_tilde = scipy.linalg.cho_solve(s1_sqrt, np.dot(s12, c_tilde)) c_tilde = np.dot(c_tilde, orth.lowdin(reduce(np.dot, (c_tilde.T, s1, c_tilde)))) # Obtain C * C^T * S1 and C~ * C~^T * S1 ccs1 = reduce(np.dot, (iao_com_ref, iao_com_ref.conj().T, s1)) ctcts1 = reduce(np.dot, (c_tilde, c_tilde.conj().T, s1)) # Calculate A = ccs1 * ctcts1 * p12 + ( 1 - ccs1 ) * ( 1 - ctcts1 ) * p12 iao_comp = (p12 + reduce(np.dot, (ccs1, ctcts1, p12)) * 2 - np.dot(ccs1, p12) - np.dot(ctcts1, p12)) iao_comp = np.dot(iao_comp, orth.lowdin(reduce(np.dot, (iao_comp.T, s1, iao_comp)))) return iao_comp
def _iao_occupied_orbitals(mol, mf): """Get the IAOs for occupied space. Args: mol (pyscf.gto.Mole): The molecule to simulate. mf (pyscf.scf.RHF): The mean field of the molecule. Returns: iao_active (numpy.array): The localized orbitals for the occupied space (float64). """ # Get MO coefficient of occupied MOs occupied_orbitals = mf.mo_coeff[:, mf.mo_occ > 0.5] # Get mol data in minao basis min_mol = iao.reference_mol(mol) # Calculate the overlaps for total basis s1 = mol.intor_symmetric('int1e_ovlp') # ... for minao basis s2 = min_mol.intor_symmetric('int1e_ovlp') # ... between the two basis (and transpose) s12 = gto.mole.intor_cross('int1e_ovlp', mol, min_mol) s21 = s12.T # Calculate P_12 = S_1^-1 * S_12 using Cholesky decomposition s1_sqrt = scipy.linalg.cho_factor(s1) s2_sqrt = scipy.linalg.cho_factor(s2) p12 = scipy.linalg.cho_solve(s1_sqrt, s12) # C~ = second_half ( S_1^-1 * S_12 * first_half ( S_2^-1 * S_21 * C ) ) c_tilde = scipy.linalg.cho_solve(s2_sqrt, np.dot(s21, occupied_orbitals)) c_tilde = scipy.linalg.cho_solve(s1_sqrt, np.dot(s12, c_tilde)) c_tilde = np.dot(c_tilde, orth.lowdin(reduce(np.dot, (c_tilde.T, s1, c_tilde)))) # Obtain C * C^T * S1 and C~ * C~^T * S1 ccs1 = reduce(np.dot, (occupied_orbitals, occupied_orbitals.conj().T, s1)) ctcts1 = reduce(np.dot, (c_tilde, c_tilde.conj().T, s1)) # Calculate A = ccs1 * ctcts1 * p12 + ( 1 - ccs1 ) * ( 1 - ctcts1 ) * p12 iao_active = (p12 + reduce(np.dot, (ccs1, ctcts1, p12)) * 2 - np.dot(ccs1, p12) - np.dot(ctcts1, p12)) # Orthogonalize A iao_active = np.dot(iao_active, orth.lowdin(reduce(np.dot, (iao_active.T, s1, iao_active)))) return iao_active
def _nao_sub(mol, pre_occ, pre_nao, s=None): if s is None: if getattr(mol, 'pbc_intor', None): # whether mol object is a cell s = mol.pbc_intor('int1e_ovlp', hermi=1) else: s = mol.intor_symmetric('int1e_ovlp') core_lst, val_lst, rydbg_lst = _core_val_ryd_list(mol) nbf = mol.nao_nr() pre_nao = pre_nao.astype(s.dtype) cnao = numpy.empty((nbf, nbf), dtype=s.dtype) if core_lst: c = pre_nao[:, core_lst].copy() s1 = reduce(lib.dot, (c.conj().T, s, c)) cnao[:, core_lst] = c1 = lib.dot(c, orth.lowdin(s1)) c = pre_nao[:, val_lst].copy() c -= reduce(lib.dot, (c1, c1.conj().T, s, c)) else: c = pre_nao[:, val_lst] if val_lst: s1 = reduce(lib.dot, (c.conj().T, s, c)) wt = pre_occ[val_lst] cnao[:, val_lst] = lib.dot(c, orth.weight_orth(s1, wt)) if rydbg_lst: cvlst = core_lst + val_lst c1 = cnao[:, cvlst].copy() c = pre_nao[:, rydbg_lst].copy() c -= reduce(lib.dot, (c1, c1.conj().T, s, c)) s1 = reduce(lib.dot, (c.conj().T, s, c)) cnao[:, rydbg_lst] = lib.dot(c, orth.lowdin(s1)) snorm = numpy.linalg.norm( reduce(lib.dot, (cnao.conj().T, s, cnao)) - numpy.eye(nbf)) if snorm > 1e-9: logger.warn(mol, 'Weak orthogonality for localized orbitals %s', snorm) return cnao
def _nao_sub(mol, pre_occ, pre_nao, s=None): if s is None: if getattr(mol, 'pbc_intor', None): # whether mol object is a cell s = mol.pbc_intor('int1e_ovlp', hermi=1) else: s = mol.intor_symmetric('int1e_ovlp') core_lst, val_lst, rydbg_lst = _core_val_ryd_list(mol) nbf = mol.nao_nr() pre_nao = pre_nao.astype(s.dtype) cnao = numpy.empty((nbf,nbf), dtype=s.dtype) if core_lst: c = pre_nao[:,core_lst].copy() s1 = reduce(lib.dot, (c.conj().T, s, c)) cnao[:,core_lst] = c1 = lib.dot(c, orth.lowdin(s1)) c = pre_nao[:,val_lst].copy() c -= reduce(lib.dot, (c1, c1.conj().T, s, c)) else: c = pre_nao[:,val_lst] if val_lst: s1 = reduce(lib.dot, (c.conj().T, s, c)) wt = pre_occ[val_lst] cnao[:,val_lst] = lib.dot(c, orth.weight_orth(s1, wt)) if rydbg_lst: cvlst = core_lst + val_lst c1 = cnao[:,cvlst].copy() c = pre_nao[:,rydbg_lst].copy() c -= reduce(lib.dot, (c1, c1.conj().T, s, c)) s1 = reduce(lib.dot, (c.conj().T, s, c)) cnao[:,rydbg_lst] = lib.dot(c, orth.lowdin(s1)) snorm = numpy.linalg.norm(reduce(lib.dot, (cnao.conj().T, s, cnao)) - numpy.eye(nbf)) if snorm > 1e-9: logger.warn(mol, 'Weak orthogonality for localized orbitals %s', snorm) return cnao
def test_orth(self): numpy.random.seed(10) n = 100 a = numpy.random.random((n,n)) s = numpy.dot(a.T, a) c = orth.lowdin(s) self.assertTrue(numpy.allclose(reduce(numpy.dot, (c.T, s, c)), numpy.eye(n))) x1 = numpy.dot(a, c) x2 = orth.vec_lowdin(a) d = numpy.dot(x1.T,x2) d[numpy.diag_indices(n)] = 0 self.assertAlmostEqual(numpy.linalg.norm(d), 0, 9) self.assertAlmostEqual(numpy.linalg.norm(c), 36.56738258719514, 9) self.assertAlmostEqual(abs(c).sum(), 2655.5580057303964, 7)
def test_orth(self): numpy.random.seed(10) n = 100 a = numpy.random.random((n, n)) s = numpy.dot(a.T, a) c = orth.lowdin(s) self.assertTrue( numpy.allclose(reduce(numpy.dot, (c.T, s, c)), numpy.eye(n))) x1 = numpy.dot(a, c) x2 = orth.vec_lowdin(a) d = numpy.dot(x1.T, x2) d[numpy.diag_indices(n)] = 0 self.assertAlmostEqual(numpy.linalg.norm(d), 0, 9) self.assertAlmostEqual(numpy.linalg.norm(c), 36.56738258719514, 9) self.assertAlmostEqual(abs(c).sum(), 2655.5580057303964, 7)
def _iao_atoms(mol, iao1, iao2): """Assign IAO to atom centers and rearrange the IAOs. Args: mol (pyscf.gto.Mole): The molecule to simulate. mf (pyscf.scf.RHF): The mean field of the molecule. iao1 (numpy.array): IAO for occupied space (float64). iao2 (numpy.array): IAO for complementary space (float64). Returns: iao_combined (numpy.array): The rearranged IAO (float64). """ # Calclate the integrals for assignment number_orbitals = mol.nao_nr() r_int1e = mol.intor('cint1e_r_sph', 3) iao_combine = np.hstack((iao1, iao2)) # Calculate atom center for each orbital x = np.diag(reduce(np.dot,(iao_combine.T, r_int1e[0], iao_combine))) y = np.diag(reduce(np.dot,(iao_combine.T, r_int1e[1], iao_combine))) z = np.diag(reduce(np.dot,(iao_combine.T, r_int1e[2], iao_combine))) # Align the coordinates orbitals_temp = np.vstack((x, y, z)) orbitals = orbitals_temp.T # Assign each orbital to atom center atom_list = _dmet_atom_list(mol, orbitals) # Prepare the orbital labels orb_list = _dmet_orb_list(mol, atom_list) # Rearrange the orbitals iao_combine = iao_combine[ : , orb_list] # Orthogonalize the orbitals s1 = mol.intor_symmetric('int1e_ovlp') iao_combine = np.dot(iao_combine, orth.lowdin(reduce(np.dot, (iao_combine.T, s1, iao_combine)))) return iao_combine
def simple_1iao(mol, atm_id, minao='minao'): atm = minao_atm(mol, atm_id, minao) c1 = pyscf.scf.addons.project_mo_nr2nr(atm, 1, mol) s = reduce(numpy.dot, (c1.T, mol.intor_symmetric('cint1e_ovlp_sph'), c1)) return orth.lowdin(s)