def get_potential(self, gd=None): """Create the Coulomb potential on the grid.""" if hasattr(self, 'potential'): if gd == self.gd or gd is None: # nothing changed return self.potential if gd is None: gd = self.gd assert gd.orthogonal potential = gd.empty() n = len(self) pc_nc = np.empty((n, 3)) charge_n = np.empty((n)) for a, pc in enumerate(self): pc_nc[a] = pc.position / Bohr charge_n[a] = pc.charge self.pc_nc = pc_nc self.charge_n = charge_n _gpaw.pc_potential(potential, pc_nc, charge_n, gd.beg_c, gd.end_c, gd.h_cv.diagonal()) # save grid descriptor and potential for future use self.potential = potential self.gd = gd return potential
def get_potential(self, gd=None): """Create the Coulomb potential on the grid.""" if hasattr(self, "potential"): if gd == self.gd or gd is None: # nothing changed return self.potential if gd is None: gd = self.gd assert gd.orthogonal potential = gd.empty() n = len(self) pc_nc = np.empty((n, 3)) charge_n = np.empty((n)) for a, pc in enumerate(self): pc_nc[a] = pc.position / Bohr charge_n[a] = pc.charge self.pc_nc = pc_nc self.charge_n = charge_n _gpaw.pc_potential(potential, pc_nc, charge_n, gd.beg_c, gd.end_c, gd.h_cv.diagonal()) # save grid descriptor and potential for future use self.potential = potential self.gd = gd return potential
def calculate_potential(self, gd): assert gd.orthogonal self.vext_g = gd.zeros() dcom_pv = self._molecule_distances(gd) _gpaw.pc_potential(gd.beg_c, gd.h_cv.diagonal().copy(), self.q_p, self.R_pv, self.rc, self.rc2, self.width, self.vext_g, dcom_pv)
def get_forces(self, calc): """Calculate forces from QM charge density on point-charges.""" dens = calc.density F_pv = np.zeros_like(self.R_pv) gd = dens.finegd _gpaw.pc_potential(gd.beg_c, gd.h_cv.diagonal().copy(), self.q_p, self.R_pv, self.rc, self.rc2, self.width, self.vext_g, dens.rhot_g, F_pv) gd.comm.sum(F_pv) return F_pv * Hartree / Bohr
def pc_potential(self, beg_c, end_c, h_cv): """ Set the potential up on the grid. Distances in Bohr. Take the whole list of charges, and compute all distances. User specific potential. """ # Create a grid having dim gd.end_c (finegd sent) potential = np.zeros(end_c-beg_c) pos = np.zeros(3) h = np.array([h_cv[0,0], h_cv[1,1], h_cv[2,2]]) # Potential is setup via v_ales, defined in qmmm_potentials _gpaw.pc_potential(potential,self.pc_nc,self.charge_n,beg_c,end_c,h) return potential
def pc_potential(self, beg_c, end_c, h_cv): """ Set the potential up on the grid. Create the empty potential grid and pass on to the appropriate c code """ # All values in [Bohr] potential = np.zeros(end_c - beg_c) h = np.array([h_cv[0,0],h_cv[1,1],h_cv[2,2]]) C = self.atoms.cell.diagonal() / Bohr # Only cubic cells work (ATM) if self.qmmm_pbc == 2 or self.qmmm_pbc is None: _gpaw.pc_potential(potential, self.pc_nc, self.charge_n, \ beg_c, end_c, h) elif self.qmmm_pbc == 1: _gpaw.wolf_potential(potential, self.pc_nc, self.charge_n, \ beg_c, end_c, h, C) # Missing PBC input in WOLF schemes! return potential
def calculate_potential(self, gd): assert gd.orthogonal self.vext_g = gd.zeros() _gpaw.pc_potential(gd.beg_c, gd.h_cv.diagonal().copy(), self.q_p, self.R_pv, self.rc, self.rc2, self.width, self.vext_g)
def f(rc): vext_G[:] = 0.0 _gpaw.pc_potential(beg_v, h_v, q_p, R_pv, rc, np.inf, 1.0, vext_G) return -vext_G[0, 0, 0]
_gpaw.pc_potential(beg_v, h_v, q_p, R_pv, rc, np.inf, 1.0, vext_G) return -vext_G[0, 0, 0] d = (R_pv[0]**2).sum()**0.5 for rc in [0.9 * d, 1.1 * d]: if d > rc: v0 = q / d else: v0 = np.polyval(c[::-1], (d / rc)**2) * q / rc equal(f(rc), v0, 1e-12) F_pv = np.zeros((1, 3)) _gpaw.pc_potential(beg_v, h_v, q_p, R_pv, rc, np.inf, 1.0, vext_G, rhot_G, F_pv) eps = 0.0001 for v in range(3): R_pv[0, v] += eps ep = f(rc) R_pv[0, v] -= 2 * eps em = f(rc) R_pv[0, v] += eps F = -(ep - em) / (2 * eps) * h**3 equal(F, -F_pv[0, v], 1e-9) # High-level test: lih = Atoms('LiH') lih[1].y += 1.64 lih.center(vacuum=3)