/** \param boxIn Box coordinates of Frame to image. * \param bp Output: Box + boundary. * \param bm Output: Box - boundary. * \param origin If true, image w.r.t. coordinate origin, otherwise box center. * \return 1 if box lengths are zero, 0 if setup completed successfully. */ int Image::SetupOrtho(Box const& boxIn, Vec3& bp, Vec3& bm, bool origin) { // Set up boundary information for orthorhombic cell if (origin) { bp = boxIn.Center(); bm.SetVec( -bp[0], -bp[1], -bp[2] ); } else { bp.SetVec( boxIn.BoxX(), boxIn.BoxY(), boxIn.BoxZ() ); bm.Zero(); } if (bp.IsZero()) return 1; return 0; }
// Ewald::Recip_ParticleMesh() double Ewald_ParticleMesh::Recip_ParticleMesh(Box const& boxIn) { t_recip_.Start(); // This essentially makes coordsD and chargesD point to arrays. Mat coordsD(&coordsD_[0], Charge_.size(), 3); Mat chargesD(&Charge_[0], Charge_.size(), 1); int nfft1 = nfft_[0]; int nfft2 = nfft_[1]; int nfft3 = nfft_[2]; if ( DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { mprinterr("Error: Could not determine grid spacing.\n"); return 0.0; } // Instantiate double precision PME object // Args: 1 = Exponent of the distance kernel: 1 for Coulomb // 2 = Kappa // 3 = Spline order // 4 = nfft1 // 5 = nfft2 // 6 = nfft3 // 7 = scale factor to be applied to all computed energies and derivatives thereof // 8 = max # threads to use for each MPI instance; 0 = all available threads used. // NOTE: Scale factor for Charmm is 332.0716 // NOTE: The electrostatic constant has been baked into the Charge_ array already. //auto pme_object = std::unique_ptr<PMEInstanceD>(new PMEInstanceD()); pme_object_.setup(1, ew_coeff_, order_, nfft1, nfft2, nfft3, 1.0, 0); // Sets the unit cell lattice vectors, with units consistent with those used to specify coordinates. // Args: 1 = the A lattice parameter in units consistent with the coordinates. // 2 = the B lattice parameter in units consistent with the coordinates. // 3 = the C lattice parameter in units consistent with the coordinates. // 4 = the alpha lattice parameter in degrees. // 5 = the beta lattice parameter in degrees. // 6 = the gamma lattice parameter in degrees. // 7 = lattice type pme_object_.setLatticeVectors(boxIn.BoxX(), boxIn.BoxY(), boxIn.BoxZ(), boxIn.Alpha(), boxIn.Beta(), boxIn.Gamma(), PMEInstanceD::LatticeType::XAligned); double erecip = pme_object_.computeERec(0, chargesD, coordsD); t_recip_.Stop(); return erecip; }
/** Given a box, determine number of FFT grid points in each dimension. */ int Ewald_ParticleMesh::DetermineNfft(int& nfft1, int& nfft2, int& nfft3, Box const& boxIn) const { if (nfft1 < 1) { // Need even dimension for X direction nfft1 = ComputeNFFT( (boxIn.BoxX() + 1.0) * 0.5 ); nfft1 *= 2; } if (nfft2 < 1) nfft2 = ComputeNFFT( boxIn.BoxY() ); if (nfft3 < 1) nfft3 = ComputeNFFT( boxIn.BoxZ() ); if (nfft1 < 1 || nfft2 < 1 || nfft3 < 1) { mprinterr("Error: Bad NFFT values: %i %i %i\n", nfft1, nfft2, nfft3); return 1; } if (debug_ > 0) mprintf("DEBUG: NFFTs: %i %i %i\n", nfft1, nfft2, nfft3); return 0; }
/** The LJ PME reciprocal term. */ double Ewald_ParticleMesh::LJ_Recip_ParticleMesh(Box const& boxIn) { t_recip_.Start(); int nfft1 = nfft_[0]; int nfft2 = nfft_[1]; int nfft3 = nfft_[2]; if ( DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { mprinterr("Error: Could not determine grid spacing.\n"); return 0.0; } Mat coordsD(&coordsD_[0], Charge_.size(), 3); Mat cparamD(&Cparam_[0], Cparam_.size(), 1); //auto pme_vdw = std::unique_ptr<PMEInstanceD>(new PMEInstanceD()); pme_vdw_.setup(6, lw_coeff_, order_, nfft1, nfft2, nfft3, -1.0, 0); pme_vdw_.setLatticeVectors(boxIn.BoxX(), boxIn.BoxY(), boxIn.BoxZ(), boxIn.Alpha(), boxIn.Beta(), boxIn.Gamma(), PMEInstanceD::LatticeType::XAligned); double evdwrecip = pme_vdw_.computeERec(0, cparamD, coordsD); t_recip_.Stop(); return evdwrecip; }