def _dip_nuc(mol: gto.Mole) -> np.ndarray: """ this function returns the nuclear contribution to the molecular dipole moment """ # coordinates and charges of nuclei coords = mol.atom_coords() charges = mol.atom_charges() return contract('i,ix->ix', charges, coords)
def _e_nuc(mol: gto.Mole, mm_mol: Union[None, gto.Mole]) -> np.ndarray: """ this function returns the nuclear repulsion energy """ # coordinates and charges of nuclei coords = mol.atom_coords() charges = mol.atom_charges() # internuclear distances (with self-repulsion removed) dist = gto.inter_distance(mol) dist[np.diag_indices_from(dist)] = 1e200 e_nuc = contract('i,ij,j->i', charges, 1. / dist, charges) * .5 # possible interaction with mm sites if mm_mol is not None: mm_coords = mm_mol.atom_coords() mm_charges = mm_mol.atom_charges() for j in range(mol.natm): q2, r2 = charges[j], coords[j] r = lib.norm(r2 - mm_coords, axis=1) e_nuc[j] += q2 * np.sum(mm_charges / r) return e_nuc
def _mm_pot(mol: gto.Mole, mm_mol: gto.Mole) -> np.ndarray: """ this function returns the full mm potential (adapted from: qmmm/itrf.py:get_hcore() in PySCF) """ # settings coords = mm_mol.atom_coords() charges = mm_mol.atom_charges() blksize = BLKSIZE # integrals intor = 'int3c2e_cart' if mol.cart else 'int3c2e_sph' cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, intor) # compute interaction potential mm_pot = 0 for i0, i1 in lib.prange(0, charges.size, blksize): fakemol = gto.fakemol_for_charges(coords[i0:i1]) j3c = df.incore.aux_e2(mol, fakemol, intor=intor, aosym='s2ij', cintopt=cintopt) mm_pot += np.einsum('xk,k->x', j3c, -charges[i0:i1]) mm_pot = lib.unpack_tril(mm_pot) return mm_pot
def _h_core(mol: gto.Mole, mm_mol: Union[None, gto.Mole]) -> Tuple[np.ndarray, np.ndarray, \ np.ndarray, Union[None, np.ndarray]]: """ this function returns the components of the core hamiltonian """ # kinetic integrals kin = mol.intor_symmetric('int1e_kin') # coordinates and charges of nuclei coords = mol.atom_coords() charges = mol.atom_charges() # individual atomic potentials sub_nuc = np.zeros([mol.natm, mol.nao_nr(), mol.nao_nr()], dtype=np.float64) for k in range(mol.natm): with mol.with_rinv_origin(coords[k]): sub_nuc[k] = -1. * mol.intor('int1e_rinv') * charges[k] # total nuclear potential nuc = np.sum(sub_nuc, axis=0) # possible mm potential if mm_mol is not None: mm_pot = _mm_pot(mol, mm_mol) else: mm_pot = None return kin, nuc, sub_nuc, mm_pot