diff --git a/configure b/configure index 3ea8373fb6..19a5cdad43 100755 --- a/configure +++ b/configure @@ -41,7 +41,7 @@ UsageFull() { echo " -debugon : Add -DDEBUG flag to activate additional internal debugging." echo " -nolfs : Do not enable large file support." echo " -shared : Configure for generating libcpptraj (implies -nosanderlib)." - echo " -fftw3 : Use FFTW instead of pubfft for FFT." + echo " -pubfft : Use pubfft instead of FFTW for FFT (disables PME functionality)." echo " -windows : Set up for use with MinGW compilers for a native Windows build." echo " LIBRARY OPTIONS" echo " - : Enable library." @@ -1038,7 +1038,7 @@ EOF if [ "${LIB_STAT[$LFFTW3]}" = 'optional' ] ; then WrnMsg "FFTW test failed. CPPTRAJ will use the built-in PubFFT routines." if [ $BUILD_LIBS -eq 1 ] ; then - echo "To force CPPTRAJ to build its own FFTW, reconfigure and specify '-fftw3'." + echo "To force CPPTRAJ to build its own FFTW, reconfigure and specify '--buildlibs'." fi LIB_STAT[$LFFTW3]='off' elif [ "${LIB_STAT[$LFFTW3]}" = 'enabled' ] ; then @@ -2605,6 +2605,7 @@ while [ ! -z "$1" ] ; do '-tune' ) USE_OPT=2 ;; '-noc++11' ) C11_SUPPORT='no' ;; '-windows' ) PLATFORM='windows' ;; + '-pubfft' ) LIB_STAT[$LFFTW3]='off' ;; # Cpptraj options '-nolfs' ) LFS='' ;; '-single-ensemble' ) USE_SINGLEENSEMBLE=1 ;; diff --git a/devtools/CreateMake.sh b/devtools/CreateMake.sh index a476427901..ca0a683265 100755 --- a/devtools/CreateMake.sh +++ b/devtools/CreateMake.sh @@ -38,6 +38,11 @@ DEL_FILE = /bin/rm -f # Objects OBJECTS=\$($VARNAME:.cpp=.o) +# General rules +.cpp.o: + \$(VB)echo CXX $< + \$(VB)\$(CXX) \$(DIRECTIVES) \$(CPPTRAJ_INC) \$(CXXFLAGS) -c -o \$@ $< + # Default target: objects all: \$(OBJECTS) diff --git a/doc/CpptrajManual.pdf b/doc/CpptrajManual.pdf index 70719f82c0..b6c344a580 100644 Binary files a/doc/CpptrajManual.pdf and b/doc/CpptrajManual.pdf differ diff --git a/doc/DocumentChecksums.txt b/doc/DocumentChecksums.txt index 60e6cefb03..5bc24381c3 100644 --- a/doc/DocumentChecksums.txt +++ b/doc/DocumentChecksums.txt @@ -1,3 +1,3 @@ b37726e7a841f6fc695ecd7fb040ffbf CpptrajDevelopmentGuide.lyx -736ee725ca9cc67d349f67d714f41c20 cpptraj.lyx +151841b1d3283890c425aaae5a923e7f cpptraj.lyx 07c4039e732fc2eb1df0c1e0863cb949 CpptrajManual.lyx diff --git a/doc/cpptraj.lyx b/doc/cpptraj.lyx index a97dd7af40..60732e1e34 100644 --- a/doc/cpptraj.lyx +++ b/doc/cpptraj.lyx @@ -20478,7 +20478,7 @@ Mod \begin_layout Standard \align center \begin_inset Tabular - + @@ -21385,6 +21385,35 @@ Calculate secondary structure content using the DSSP algorithm \begin_inset Text +\begin_layout Plain Layout +enedecomp +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Perform per-atom energy decomposition. +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + \begin_layout Plain Layout energy \end_layout @@ -27788,6 +27817,144 @@ nolink "false" . \end_layout +\begin_layout Subsection +enedecomp +\end_layout + +\begin_layout LyX-Code +enedecomp [] [] [out ] +\end_layout + +\begin_layout LyX-Code + [ pme [cut ] [dsumtol ] [ewcoeff ] +\end_layout + +\begin_layout LyX-Code + [erfcdx ] [skinnb ] [ljswidth ] +\end_layout + +\begin_layout LyX-Code + [order ] [nfft ,,] +\end_layout + +\begin_deeper +\begin_layout Description +[] Data set name. +\end_layout + +\begin_layout Description +[] Mask of atoms to calculate energy for. +\end_layout + +\begin_layout Description +[out +\begin_inset space ~ +\end_inset + +] File to write results to. +\end_layout + +\begin_layout Description +[pme] Use particle mesh Ewald for electrostatics; + van der Waals energy will be calculated using a long-range correction for periodicity. +\end_layout + +\begin_deeper +\begin_layout Description +cut +\begin_inset space ~ +\end_inset + + Direct space cutoff in Angstroms (default 8.0). +\end_layout + +\begin_layout Description +dsumtol +\begin_inset space ~ +\end_inset + + Direct sum tolerance (default 0.00001). + Used to determine Ewald coefficient. +\end_layout + +\begin_layout Description +ewcoeff +\begin_inset space ~ +\end_inset + + Ewald coefficient in 1/Ang. +\end_layout + +\begin_layout Description +erfcdx +\begin_inset space ~ +\end_inset + + Spacing to use for the ERFC splines (default 0.0002 Ang.). +\end_layout + +\begin_layout Description +skinnb Used to determine pairlist atoms (added to cut, + so pairlist cutoff is +\series bold +cut +\series default + + +\series bold +skinnb +\series default +); + included in order to maintain consistency with results from sander. +\end_layout + +\begin_layout Description +ljswidth +\begin_inset space ~ +\end_inset + + If specified, + use a force-switching form for the Lennard-Jones calculation from - to . +\end_layout + +\begin_layout Description +order +\begin_inset space ~ +\end_inset + + Spline order for charges. +\end_layout + +\begin_layout Description +nfft +\begin_inset space ~ +\end_inset + +,, Explicitly set the number of FFT grid points in each dimension. + Will be determined automatically from unit cell dimensions if not specified. +\end_layout + +\end_deeper +\begin_layout Standard +DataSets created: +\end_layout + +\begin_layout Description + Set containing atom index and the corresponding average energy over frames. +\end_layout + +\end_deeper +\begin_layout Standard +Perform per-atom energy decomposition for selected atoms. + The energy is calculated for the entire system but only the energies for selected atoms will be reported. + The energy is composed of the regular bond, + angle, + torsion, + 1-4 nonbonded, + and nonbonded terms. + If 'pme' is specified the non-bonded terms will us PME for electrostatics and a long-range periodic correction for van der Waals, + otherwise a simple model with no cutoff will be used. +\end_layout + \begin_layout Subsection energy \end_layout @@ -28154,7 +28321,7 @@ nfft \end_inset ,, Explicitly set the number of FFT grid points in each dimension. - Will be determined automatically if not specified. + Will be determined automatically from unit cell dimensions if not specified. \end_layout \begin_layout Description diff --git a/src/Action_EneDecomp.cpp b/src/Action_EneDecomp.cpp new file mode 100644 index 0000000000..370741747a --- /dev/null +++ b/src/Action_EneDecomp.cpp @@ -0,0 +1,51 @@ +#include "Action_EneDecomp.h" +#include "CpptrajStdio.h" + +// Action_EneDecomp::Help() +void Action_EneDecomp::Help() const { + Cpptraj::Energy::EnergyDecomposer::HelpText(); +} + +// Action_EneDecomp::Init() +Action::RetType Action_EneDecomp::Init(ArgList& actionArgs, ActionInit& init, int debugIn) +{ +# ifdef MPI + trajComm_ = init.TrajComm(); +# endif + if (eneDecomp_.InitDecomposer( actionArgs, init.DSL(), init.DFL(), debugIn )) + return Action::ERR; + mprintf(" ENEDECOMP: Decomposing energy for selected atoms.\n"); + eneDecomp_.PrintOpts(); + + return Action::OK; +} + +// Action_EneDecomp::Setup() +Action::RetType Action_EneDecomp::Setup(ActionSetup& setup) +{ + int ret = eneDecomp_.SetupDecomposer( setup.Top(), setup.CoordInfo().TrajBox() ); + if (ret == -1) + return Action::SKIP; + else if (ret == 1) + return Action::ERR; + return Action::OK; +} + +// Action_EneDecomp::DoAction() +Action::RetType Action_EneDecomp::DoAction(int frameNum, ActionFrame& frm) +{ + if (eneDecomp_.CalcEne( frm.Frm() )) + return Action::ERR; + return Action::OK; +} + +#ifdef MPI +int Action_EneDecomp::SyncAction() { + return eneDecomp_.ReduceToMaster(trajComm_); +} +#endif + +// Action_EneDecomp::Print() +void Action_EneDecomp::Print() { + eneDecomp_.FinishCalc(); +} diff --git a/src/Action_EneDecomp.h b/src/Action_EneDecomp.h new file mode 100644 index 0000000000..e7383249d6 --- /dev/null +++ b/src/Action_EneDecomp.h @@ -0,0 +1,32 @@ +#ifndef INC_ACTION_ENEDECOMP_H +#define INC_ACTION_ENEDECOMP_H +#include "Action.h" +#include "Energy/EnergyDecomposer.h" +/// Used to decompose the pairwise additive energy of a system +class Action_EneDecomp : public Action { + public: + /// CONSTRUCTOR + Action_EneDecomp() {} + /// Allocator + DispatchObject* Alloc() const { return (DispatchObject*)new Action_EneDecomp(); } + /// Help text + void Help() const; + private: + /// Initialization + Action::RetType Init(ArgList&, ActionInit&, int); + /// Topology-based setup + Action::RetType Setup(ActionSetup&); + /// Do the action + Action::RetType DoAction(int, ActionFrame&); + /// Print results/finish calculations + void Print(); +# ifdef MPI + int SyncAction(); +# endif + + Cpptraj::Energy::EnergyDecomposer eneDecomp_; ///< Do the actual decomposition +# ifdef MPI + Parallel::Comm trajComm_; ///< Across-trajectory communicator +# endif +}; +#endif diff --git a/src/Action_Energy.cpp b/src/Action_Energy.cpp index 1f8f6c299d..2146d68be8 100644 --- a/src/Action_Energy.cpp +++ b/src/Action_Energy.cpp @@ -1,10 +1,10 @@ #include "Action_Energy.h" #include "CpptrajStdio.h" -#include "Ewald_Regular.h" -#include "Ewald_ParticleMesh.h" #include "PotentialFunction.h" #include "MdOpts.h" +using namespace Cpptraj::Energy; + /// CONSTRUCTOR Action_Energy::Action_Energy() : elecType_(NO_ELE), @@ -12,7 +12,7 @@ Action_Energy::Action_Energy() : currentParm_(0), npoints_(0), debug_(0), - EW_(0), + nbCalcType_(Ecalc_Nonbond::UNSPECIFIED), potential_(0), use_openmm_(false), dt_(0), @@ -23,7 +23,6 @@ Action_Energy::Action_Energy() : /// DESTRUCTOR Action_Energy::~Action_Energy() { - if (EW_ != 0) delete EW_; if (potential_ != 0) delete potential_; } @@ -160,7 +159,6 @@ Action::RetType Action_Energy::Init(ArgList& actionArgs, ActionInit& init, int d // Electrostatics type. std::string etypearg = actionArgs.GetStringKey("etype"); elecType_ = NO_ELE; - EW_ = 0; if (!etypearg.empty()) { termEnabled[ELEC] = true; if (etypearg == "directsum") { @@ -170,16 +168,18 @@ Action::RetType Action_Energy::Init(ArgList& actionArgs, ActionInit& init, int d } else if (etypearg == "ewald") { // Ewald method elecType_ = EWALD; + nbCalcType_ = Ecalc_Nonbond::REGULAR_EWALD; if (ewaldOpts_.GetOptions(EwaldOptions::REG_EWALD, actionArgs, "energy")) return Action::ERR; - EW_ = (Ewald*)new Ewald_Regular(); } else if (etypearg == "pme") { // particle mesh Ewald method # ifdef LIBPME elecType_ = PME; + nbCalcType_ = Ecalc_Nonbond::PME; if (ewaldOpts_.GetOptions(EwaldOptions::PME, actionArgs, "energy")) return Action::ERR; - EW_ = (Ewald*)new Ewald_ParticleMesh(); + if (ewaldOpts_.Type() == EwaldOptions::LJPME) + nbCalcType_ = Ecalc_Nonbond::LJPME; # else mprinterr("Error: 'pme' requires compiling with LIBPME (FFTW3 and C++11 support).\n"); return Action::ERR; @@ -361,10 +361,11 @@ Action::RetType Action_Energy::Setup(ActionSetup& setup) { } } // Set up Ewald if necessary. - if (elecType_ == EWALD || elecType_ == PME) { - if (EW_->Init(setup.CoordInfo().TrajBox(), ewaldOpts_, debug_)) + if (nbCalcType_ != Ecalc_Nonbond::UNSPECIFIED) { + if (NB_.InitNonbondCalc(nbCalcType_, false, setup.CoordInfo().TrajBox(), ewaldOpts_, debug_)) + return Action::ERR; + if (NB_.SetupNonbondCalc( setup.Top(), Imask_ )) return Action::ERR; - EW_->Setup( setup.Top(), Imask_ ); } // For KE, check for velocities/forces if (KEtype_ != KE_NONE) { @@ -479,9 +480,9 @@ Action::RetType Action_Energy::DoAction(int frameNum, ActionFrame& frm) { break; case C_EWALD: case C_PME: // Elec must be enabled, vdw may not be - time_NB_.Start(); - err = EW_->CalcNonbondEnergy(frm.Frm(), Imask_, ene, ene2); - time_NB_.Stop(); + //time_NB_.Start(); + err = NB_.NonbondEnergy(frm.Frm(), Imask_, ene, ene2); + //time_NB_.Stop(); if (err != 0) return Action::ERR; Energy_[ELEC]->Add(frameNum, &ene); if (Energy_[VDW] != 0) Energy_[VDW]->Add(frameNum, &ene2); @@ -532,10 +533,10 @@ void Action_Energy::Print() { time_tors_.WriteTiming(1, "TORSION :", time_total_.Total()); if (time_14_.Total() > 0.0) time_14_.WriteTiming(1, "1-4_NONBOND :", time_total_.Total()); - if (time_NB_.Total() > 0.0) { + if (nbCalcType_ != Ecalc_Nonbond::UNSPECIFIED) + NB_.PrintTiming(time_total_.Total()); + else if (time_NB_.Total() > 0.0) { time_NB_.WriteTiming(1, "NONBOND :", time_total_.Total()); - if (elecType_ == EWALD || elecType_ == PME) - EW_->Timing(time_NB_.Total()); } if (time_ke_.Total() > 0.0) time_ke_.WriteTiming(1, "KE :", time_total_.Total()); diff --git a/src/Action_Energy.h b/src/Action_Energy.h index 19dec5a387..7d47a6a07b 100644 --- a/src/Action_Energy.h +++ b/src/Action_Energy.h @@ -6,7 +6,7 @@ #include "Timer.h" #include "ExclusionArray.h" #include "EwaldOptions.h" -class Ewald; +#include "Energy/Ecalc_Nonbond.h" class PotentialFunction; /// Calculate energy class Action_Energy: public Action { @@ -50,7 +50,8 @@ class Action_Energy: public Action { std::string setname_; ///< Output DataSet name int npoints_; ///< # cells in each direction (DIRECT) int debug_; - Ewald* EW_; ///< Ewald energy class. + Cpptraj::Energy::Ecalc_Nonbond NB_; ///< Nonbond energy calc class. + Cpptraj::Energy::Ecalc_Nonbond::CalcType nbCalcType_; ///< Nonbond calculation type EwaldOptions ewaldOpts_; ///< Ewald options PotentialFunction* potential_; ///< TODO currently just for openmm, use for everything diff --git a/src/Action_GIST.cpp b/src/Action_GIST.cpp index 58929ea3be..37a2273dad 100644 --- a/src/Action_GIST.cpp +++ b/src/Action_GIST.cpp @@ -965,7 +965,6 @@ void Action_GIST::setSoluteSolvent(const Topology& top) const Vec3 Action_GIST::x_lab_ = Vec3(1.0, 0.0, 0.0); const Vec3 Action_GIST::y_lab_ = Vec3(0.0, 1.0, 0.0); const Vec3 Action_GIST::z_lab_ = Vec3(0.0, 0.0, 1.0); -const double Action_GIST::QFAC_ = Constants::ELECTOAMBER * Constants::ELECTOAMBER; const int Action_GIST::OFF_GRID_ = -1; const int Action_GIST::UNKNOWN_MOLECULE_ = -1; @@ -1023,7 +1022,7 @@ void Action_GIST::Ecalc(double rij2, double q1, double q2, NonbondType const& LJ double f6 = LJ.B() * r6; // B/r^6 Evdw = f12 - f6; // (A/r^12)-(B/r^6) // Coulomb - double qiqj = QFAC_ * q1 * q2; + double qiqj = Constants::COULOMBFACTOR * q1 * q2; Eelec = qiqj / rij; } diff --git a/src/Action_GIST.h b/src/Action_GIST.h index f8de4fa71a..5f01dcc867 100644 --- a/src/Action_GIST.h +++ b/src/Action_GIST.h @@ -184,7 +184,6 @@ class Action_GIST : public Action { static const Vec3 y_lab_; static const Vec3 z_lab_; static const double maxD_; - static const double QFAC_; static const int OFF_GRID_; ///< Value in atom_voxel_ that indicates atom is off the grid static const int UNKNOWN_MOLECULE_; diff --git a/src/Action_PairDist.cpp b/src/Action_PairDist.cpp index f27155d1d7..fd758db3f9 100644 --- a/src/Action_PairDist.cpp +++ b/src/Action_PairDist.cpp @@ -1,11 +1,12 @@ #include - #include "Action_PairDist.h" #include "CpptrajStdio.h" #include "StringRoutines.h" #include "DistRoutines.h" #include "DataSet_Mesh.h" - +#ifdef MPI +# include "Stats_Reduce.h" +#endif /** Calculate pair distribution function P(r) between two masks. * \author Hannes H. Loeffler. @@ -243,6 +244,8 @@ int Action_PairDist::SyncAction() { trajComm_.Barrier(); // END DEBUG */ + Cpptraj::Stats_Reduce(trajComm_, histogram_, maxbin_); +/* std::vector buffer; unsigned long rank_size; if (trajComm_.Master()) { @@ -283,7 +286,7 @@ int Action_PairDist::SyncAction() { buffer.push_back( (double)histogram_[i].nData() ); } trajComm_.SendMaster(&buffer[0], buffer.size(), trajComm_.Rank(), MPI_DOUBLE); - } + }*/ } return 0; } diff --git a/src/Action_Pairwise.cpp b/src/Action_Pairwise.cpp index 92e0a6a0ef..5d809c41b5 100644 --- a/src/Action_Pairwise.cpp +++ b/src/Action_Pairwise.cpp @@ -43,8 +43,6 @@ void Action_Pairwise::Help() const { " and : Print both energies if both cutoffs are satisfied.\n"); } -const double Action_Pairwise::QFAC = Constants::ELECTOAMBER * Constants::ELECTOAMBER; - // Action_Pairwise::Init() Action::RetType Action_Pairwise::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { @@ -369,7 +367,7 @@ void Action_Pairwise::NonbondEnergy(Frame const& frameIn, Topology const& parmIn //force=((12*f12)-(6*f6))*r2; // (12A/r^13)-(6B/r^7) //scalarmult(f,JI,F); // Coulomb energy - double qiqj = QFAC * parmIn[maskatom1].Charge() * parmIn[maskatom2].Charge(); + double qiqj = Constants::COULOMBFACTOR * parmIn[maskatom1].Charge() * parmIn[maskatom2].Charge(); double e_elec = qiqj / rij; Eelec_ += e_elec; // Coulomb Force diff --git a/src/Action_Pairwise.h b/src/Action_Pairwise.h index 6b27eb90da..3e6382a8bc 100644 --- a/src/Action_Pairwise.h +++ b/src/Action_Pairwise.h @@ -70,7 +70,6 @@ class Action_Pairwise: public Action { CpptrajFile* avgout_; ///< File for printing average energies PDBfile PdbOut_; ///< PDB with atoms colored by evdw/eelec CpptrajFile* Eout_; ///< Output file for atom energies. - static const double QFAC; ///< Convert charges to kcal/mol units bool scalePdbE_; ///< If true scale PDB energy each frame between 0 and 100 ExclusionArray Excluded0_; ///< Hold exclusion arrays for atoms selected by Mask0_ ExclusionArray ExcludedR_; ///< Hold exclusion arrays for atoms selected by RefMask_ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4977c05e15..70c8e644c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,6 +115,7 @@ endif() add_library(cpptraj_common_obj OBJECT ${CPPTRAJ_COMMON_SOURCES}) add_subdirectory(Cluster) add_subdirectory(Structure) +add_subdirectory(Energy) make_pic_if_needed(cpptraj_common_obj) #normally this would be applied by target_link_libraries, but since we use that intermediary object library, we have to apply it manually diff --git a/src/Command.cpp b/src/Command.cpp index 545514dea5..b4c6b91013 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -164,6 +164,7 @@ #include "Action_ToroidalDiffusion.h" #include "Action_MinMaxDist.h" #include "Action_AddAtom.h" +#include "Action_EneDecomp.h" // ----- ANALYSIS -------------------------------------------------------------- #include "Analysis_Hist.h" #include "Analysis_Corr.h" @@ -347,6 +348,7 @@ void Command::Init() { Command::AddCmd( new Action_DNAionTracker(), Cmd::ACT, 1, "dnaiontracker" ); // hidden Command::AddCmd( new Action_DistRmsd(), Cmd::ACT, 2, "drms", "drmsd" ); Command::AddCmd( new Action_DSSP(), Cmd::ACT, 2, "dssp", "secstruct" ); + Command::AddCmd( new Action_EneDecomp(), Cmd::ACT, 1, "enedecomp" ); Command::AddCmd( new Action_Energy(), Cmd::ACT, 1, "energy" ); Command::AddCmd( new Action_Esander(), Cmd::ACT, 1, "esander" ); Command::AddCmd( new Action_FilterByData(), Cmd::ACT, 1, "filter" ); diff --git a/src/Constants.h b/src/Constants.h index 2fc72e1f0e..f835a2aca2 100644 --- a/src/Constants.h +++ b/src/Constants.h @@ -58,6 +58,8 @@ namespace Constants { const double ELECTOAMBER = 18.2223; /// Convert Amber charge to electron charge const double AMBERTOELEC = 1.0 / ELECTOAMBER; + /// Calculate energy in kcal/mol from charge^2/Ang + const double COULOMBFACTOR = ELECTOAMBER * ELECTOAMBER; /// Convert from Amber internal units of time (1/20.455 ps) to ps. /** Amber operates in kcal/mol units for energy, amu for masses, * and Angstoms for distances. For convenience when calculating KE from diff --git a/src/DataSet_Mesh.h b/src/DataSet_Mesh.h index 48613cf8c9..a8888364e6 100644 --- a/src/DataSet_Mesh.h +++ b/src/DataSet_Mesh.h @@ -13,6 +13,7 @@ class DataSet_Mesh : public DataSet_1D { DataSet_Mesh(int,double,double); static DataSet* Alloc() { return (DataSet*)new DataSet_Mesh(); } void Resize(size_t n) { mesh_x_.resize(n, 0.0); mesh_y_.resize(n, 0.0); } + void Clear() { mesh_x_.clear(); mesh_y_.clear(); } // ----- DataSet functions ------------------- size_t Size() const { return mesh_x_.size(); } # ifdef MPI diff --git a/src/Energy.cpp b/src/Energy.cpp index 936414ecd0..72255af143 100644 --- a/src/Energy.cpp +++ b/src/Energy.cpp @@ -9,8 +9,7 @@ #include "ExclusionArray.h" #include "Energy/Ene_Angle.h" #include "Energy/Ene_Bond.h" - -const double Energy_Amber::QFAC = Constants::ELECTOAMBER * Constants::ELECTOAMBER; +#include "Energy/Ene_LJ_6_12.h" // CONSTRUCTOR Energy_Amber::Energy_Amber() : debug_(0) {} @@ -176,16 +175,17 @@ double Energy_Amber::Calc_14_Energy(Frame const& fIn, DihedralArray const& Dihed double rij = sqrt( rij2 ); // VDW NonbondType const& LJ = tIn.GetLJparam(d->A1(), d->A4()); - double r2 = 1.0 / rij2; + double e_vdw = Cpptraj::Energy::Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); +/* double r2 = 1.0 / rij2; double r6 = r2 * r2 * r2; double r12 = r6 * r6; double f12 = LJ.A() * r12; // A/r^12 double f6 = LJ.B() * r6; // B/r^6 - double e_vdw = f12 - f6; // (A/r^12)-(B/r^6) + double e_vdw = f12 - f6; // (A/r^12)-(B/r^6)*/ e_vdw /= dp.SCNB(); Evdw14 += e_vdw; // Coulomb - double qiqj = QFAC * tIn[d->A1()].Charge() * tIn[d->A4()].Charge(); + double qiqj = Constants::COULOMBFACTOR * tIn[d->A1()].Charge() * tIn[d->A4()].Charge(); double e_elec = qiqj / rij; e_elec /= dp.SCEE(); Eq14 += e_elec; @@ -235,15 +235,16 @@ double Energy_Amber::E_Nonbond(Frame const& fIn, Topology const& tIn, AtomMask c double rij = sqrt( rij2 ); // VDW NonbondType const& LJ = tIn.GetLJparam(atom1, atom2); - double r2 = 1.0 / rij2; + double e_vdw = Cpptraj::Energy::Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); + /*double r2 = 1.0 / rij2; double r6 = r2 * r2 * r2; double r12 = r6 * r6; double f12 = LJ.A() * r12; // A/r^12 double f6 = LJ.B() * r6; // B/r^6 - double e_vdw = f12 - f6; // (A/r^12)-(B/r^6) + double e_vdw = f12 - f6; // (A/r^12)-(B/r^6)*/ Evdw += e_vdw; // Coulomb - double qiqj = QFAC * tIn[atom1].Charge() * tIn[atom2].Charge(); + double qiqj = Constants::COULOMBFACTOR * tIn[atom1].Charge() * tIn[atom2].Charge(); double e_elec = qiqj / rij; Eelec += e_elec; # ifdef DEBUG_ENERGY @@ -294,12 +295,13 @@ double Energy_Amber::E_VDW(Frame const& fIn, Topology const& tIn, AtomMask const double rij2 = DIST2_NoImage( crd1, fIn.XYZ( atom2 ) ); // VDW NonbondType const& LJ = tIn.GetLJparam(atom1, atom2); - double r2 = 1.0 / rij2; + double e_vdw = Cpptraj::Energy::Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); + /*double r2 = 1.0 / rij2; double r6 = r2 * r2 * r2; double r12 = r6 * r6; double f12 = LJ.A() * r12; // A/r^12 double f6 = LJ.B() * r6; // B/r^6 - double e_vdw = f12 - f6; // (A/r^12)-(B/r^6) + double e_vdw = f12 - f6; // (A/r^12)-(B/r^6)*/ Evdw += e_vdw; # ifdef DEBUG_ENERGY mprintf("\tEVDW %4i -- %4i: A= %12.5e B= %12.5e r2= %12.5f E= %12.5e\n", @@ -345,7 +347,7 @@ double Energy_Amber::E_Elec(Frame const& fIn, Topology const& tIn, AtomMask cons double rij2 = DIST2_NoImage( crd1, fIn.XYZ( atom2 ) ); double rij = sqrt( rij2 ); // Coulomb - double qiqj = QFAC * tIn[atom1].Charge() * tIn[atom2].Charge(); + double qiqj = Constants::COULOMBFACTOR * tIn[atom1].Charge() * tIn[atom2].Charge(); double e_elec = qiqj / rij; Eelec += e_elec; # ifdef DEBUG_ENERGY @@ -388,7 +390,7 @@ double Energy_Amber::E_DirectSum(Frame const& fIn, Topology const& tIn, AtomMask for (AtomMask::const_iterator atom2 = mask.begin(); atom2 != mask.end(); ++atom2) { Vec3 frac2 = fIn.BoxCrd().FracCell() * Vec3(fIn.XYZ( *atom2 )); // atom j in fractional coords - double qiqj = QFAC * tIn[*atom1].Charge() * tIn[*atom2].Charge(); + double qiqj = Constants::COULOMBFACTOR * tIn[*atom1].Charge() * tIn[*atom2].Charge(); // Loop over images of atom j for (std::vector::const_iterator ixyz = Cells.begin(); ixyz != Cells.end(); ++ixyz) { diff --git a/src/Energy.h b/src/Energy.h index 08d5e4c674..61a8b24eff 100644 --- a/src/Energy.h +++ b/src/Energy.h @@ -37,7 +37,6 @@ class Energy_Amber { double Calc_14_Energy(Frame const&, DihedralArray const&, DihedralParmArray const&, Topology const&, CharMask const&, double&); - static const double QFAC; int debug_; }; #endif diff --git a/src/Energy/CMakeLists.txt b/src/Energy/CMakeLists.txt new file mode 100644 index 0000000000..d8fffe4717 --- /dev/null +++ b/src/Energy/CMakeLists.txt @@ -0,0 +1,17 @@ +#CMake buildfile for CPPTRAJ Energy subdirectory. +target_sources(cpptraj_common_obj PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/Ecalc_Nonbond.cpp + ${CMAKE_CURRENT_LIST_DIR}/EnergyDecomposer.cpp + ${CMAKE_CURRENT_LIST_DIR}/ErfcFxn.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldCalc_Decomp_LJPME.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldCalc_Decomp_PME.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldCalc_LJPME.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldCalc_PME.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldCalc_Regular.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldParams.cpp + ${CMAKE_CURRENT_LIST_DIR}/EwaldParams_LJPME.cpp + ${CMAKE_CURRENT_LIST_DIR}/Ewald_Recip.cpp + ${CMAKE_CURRENT_LIST_DIR}/PME_Recip.cpp + ${CMAKE_CURRENT_LIST_DIR}/PME_RecipParams.cpp + ${CMAKE_CURRENT_LIST_DIR}/VDW_LongRange_Correction.cpp +) diff --git a/src/Energy/Ecalc_Nonbond.cpp b/src/Energy/Ecalc_Nonbond.cpp new file mode 100644 index 0000000000..3de7a16a7f --- /dev/null +++ b/src/Energy/Ecalc_Nonbond.cpp @@ -0,0 +1,200 @@ +#include "Ecalc_Nonbond.h" +#include "EwaldCalc_Regular.h" +#ifdef LIBPME +# include "EwaldCalc_LJPME.h" +# include "EwaldCalc_PME.h" +# include "EwaldCalc_Decomp_LJPME.h" +# include "EwaldCalc_Decomp_PME.h" +#else +// TODO This is here for when LIBPME is not defined because there is +// currently no decomp version of regular Ewald. If there ever is +// this inlclude can be removed. +# include "EwaldCalc_Decomp.h" +#endif +#include "../CharMask.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Topology.h" +#include // sqrt for Ene_Nonbond, Ene_Decomp_Nonbond +#include "Ene_Nonbond.h" +#include "Ene_Decomp_Nonbond.h" + +using namespace Cpptraj::Energy; + +/** CONSTRUCTOR */ +Ecalc_Nonbond::Ecalc_Nonbond() : + calc_(0), + currentTop_(0), + type_(UNSPECIFIED), + decompose_energy_(false) +{} + +/** DESTRUCTOR */ +Ecalc_Nonbond::~Ecalc_Nonbond() { + if (calc_ != 0) + delete calc_; +} + +/** Init */ +int Ecalc_Nonbond::InitNonbondCalc(CalcType typeIn, bool decompose_energyIn, + Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + currentTop_ = 0; + type_ = typeIn; + decompose_energy_ = decompose_energyIn; + + calc_ = 0; + switch (type_) { + case SIMPLE : + break; +# ifdef LIBPME + case PME : + if (decompose_energy_) + calc_ = new EwaldCalc_Decomp_PME(); + else + calc_ = new EwaldCalc_PME(); + break; + case LJPME : + if (decompose_energy_) + calc_ = new EwaldCalc_Decomp_LJPME(); + else + calc_ = new EwaldCalc_LJPME(); + break; +# else + case PME : mprinterr("Error: PME requires compiling with LIBPME (FFTW3 and C++11 support).\n"); return 1; + case LJPME : mprinterr("Error: LJPME requires compiling with LIBPME (FFTW3 and C++11 support).\n"); return 1; +# endif + case REGULAR_EWALD : + if (decompose_energy_) { + mprinterr("Internal Error: Ecalc_Nonbond::InitNonbondCalc(): Cannot decompose regular Ewald calc.\n"); + return 1; + } else + calc_ = new EwaldCalc_Regular(); + break; + case UNSPECIFIED : + mprinterr("Internal Error: Ecalc_Nonbond::InitNonbondCalc(): No nonbonded calc type specified.\n"); + return 1; + } + if (type_ != SIMPLE && calc_ == 0) { + mprinterr("Internal Error: Ecalc_Nonbond::InitNonbondCalc(): Ewald calc alloc failed.\n"); + return 1; + } + + if (type_ != SIMPLE && !boxIn.HasBox()) { + mprinterr("Error: Ewald requires unit cell information.\n"); + return 1; + } + + if (calc_ != 0) { + // Ewald calcs need pairlist + if (pairList_.InitPairList(pmeOpts.Cutoff(), pmeOpts.SkinNB(), debugIn)) + return 1; + if (pairList_.SetupPairList( boxIn )) + return 1; + if (calc_->Init( boxIn, pmeOpts, debugIn )) + return 1; + } + + return 0; +} + +/** Setup */ +int Ecalc_Nonbond::SetupNonbondCalc(Topology const& topIn, AtomMask const& maskIn) { + currentTop_ = &topIn; + // Setup exclusion list + // Use distance of 4 (up to dihedrals) + if (Excluded_.SetupExcluded(topIn.Atoms(), maskIn, 4, + ExclusionArray::EXCLUDE_SELF, + ExclusionArray::FULL)) + { + mprinterr("Error: Could not set up exclusion list for nonbonded calculation.\n"); + return 1; + } + if (calc_ != 0) { + if (calc_->Setup(topIn, maskIn)) { + mprinterr("Error: Nonbonded calculation setup failed.\n"); + return 1; + } + } + return 0; +} + +/** Calc */ +int Ecalc_Nonbond::NonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + + int err = 0; + if (type_ == SIMPLE) { + Ene_Nonbond(frameIn, *currentTop_, maskIn, Excluded_, Constants::COULOMBFACTOR, + e_elec, e_vdw); + } else if (calc_ != 0) { + if (pairList_.CreatePairList(frameIn, frameIn.BoxCrd().UnitCell(), + frameIn.BoxCrd().FracCell(), maskIn) != 0) + { + mprinterr("Error: Pairlist creation failed for nonbond calc.\n"); + return 1; + } + + err = calc_->CalcNonbondEnergy(frameIn, maskIn, pairList_, Excluded_, + e_elec, e_vdw); + } else + return 1; // Sanity check + + t_total_.Stop(); + return err; +} + +/** Energy decomp calc */ +int Ecalc_Nonbond::DecomposedNonbondEnergy(Frame const& frameIn, CharMask const& cmaskIn, + double& e_elec, double& e_vdw, + Darray& atom_elec, Darray& atom_vdw) +{ + // sanity check + if (!decompose_energy_) { + mprinterr("Internal Error: Ecalc_Nonbond::DecomposedNonbondEnergy(): Not set up for energy decomp.\n"); + return 1; + } + t_total_.Start(); + + int err = 0; + if (type_ == SIMPLE) { + Ene_Decomp_Nonbond(frameIn, *currentTop_, cmaskIn, Excluded_, Constants::COULOMBFACTOR, + e_elec, e_vdw, atom_elec, atom_vdw); + } else if (calc_ != 0) { + // FIXME this is an unneeded atom mask. + AtomMask tmpMask(0, frameIn.Natom()); + + if (pairList_.CreatePairList(frameIn, frameIn.BoxCrd().UnitCell(), + frameIn.BoxCrd().FracCell(), tmpMask) != 0) + { + mprinterr("Error: Pairlist creation failed for nonbond calc.\n"); + return 1; + } + + err = calc_->CalcNonbondEnergy(frameIn, tmpMask, pairList_, Excluded_, + e_elec, e_vdw); + EwaldCalc_Decomp const* EW_ENE = static_cast( calc_ ); + for (int at = 0; at < frameIn.Natom(); at++) { + if (cmaskIn.AtomInCharMask(at)) { + atom_elec[at] += EW_ENE->Atom_Elec()[at]; + atom_vdw[at] += EW_ENE->Atom_VDW()[at]; + } + } + } else + return 1; // sanity check + + t_total_.Stop(); + return err; +} + + +/** Print timing */ +void Ecalc_Nonbond::PrintTiming(double total) const { + t_total_.WriteTiming(1, "NONBOND :", total); + if (calc_ != 0) { + calc_->Timing( t_total_.Total() ); + pairList_.Timing( t_total_.Total() ); + } +} diff --git a/src/Energy/Ecalc_Nonbond.h b/src/Energy/Ecalc_Nonbond.h new file mode 100644 index 0000000000..aa1c792cb8 --- /dev/null +++ b/src/Energy/Ecalc_Nonbond.h @@ -0,0 +1,43 @@ +#ifndef INC_ENERGY_ECALC_NONBOND_H +#define INC_ENERGY_ECALC_NONBOND_H +#include "../ExclusionArray.h" +#include "../PairList.h" +class CharMask; +class EwaldOptions; +class Topology; +namespace Cpptraj { +namespace Energy { +class EwaldCalc; +/// Calculate nonbonded energy for atoms +class Ecalc_Nonbond { + public: + typedef std::vector Darray; + + enum CalcType { SIMPLE = 0, PME, LJPME, REGULAR_EWALD, UNSPECIFIED }; + /// CONSTRUCTOR + Ecalc_Nonbond(); + /// DESTRUCTOR + ~Ecalc_Nonbond(); + /// Init - Calc type, decomp?, box, options, debug + int InitNonbondCalc(CalcType, bool, Box const&, EwaldOptions const&, int); + /// Setup + int SetupNonbondCalc(Topology const&, AtomMask const&); + /// Calculate energy + int NonbondEnergy(Frame const&, AtomMask const&, double&, double&); + /// Calculate decomposed energy + int DecomposedNonbondEnergy(Frame const&, CharMask const&, double&, double&, + Darray&, Darray&); + /// Print timing to stdout + void PrintTiming(double) const; + private: + EwaldCalc* calc_; + Topology const* currentTop_; ///< Current Topology, set by SetupNonbondCalc() + PairList pairList_; + ExclusionArray Excluded_; + Timer t_total_; + CalcType type_; + bool decompose_energy_; +}; +} +} +#endif diff --git a/src/Energy/Ene_Decomp_Nonbond.h b/src/Energy/Ene_Decomp_Nonbond.h new file mode 100644 index 0000000000..1bc0a6b0ec --- /dev/null +++ b/src/Energy/Ene_Decomp_Nonbond.h @@ -0,0 +1,67 @@ +#ifndef INC_ENERGY_ENE_DECOMP_NONBOND_H +#define INC_ENERGY_ENE_DECOMP_NONBOND_H +#include "Ene_LJ_6_12.h" +namespace Cpptraj { +namespace Energy { +/// Calculate simple decomposed nonbond energy with Coulomb and LJ 6-12 +/** NOTE: To make this file more lightweight, there are no includes for + * Frame, CharMask, etc. It is assumed that before this file is + * included there will be at least '#include "Topology.h" and + * 'include ' (for the sqrt). + * Comple with -DCPPTRAJ_DEBUG_ENEDECOMP for more details on the individual + * contributions. + */ +template +void Ene_Decomp_Nonbond(Frame const& fIn, Topology const& tIn, CharMask const& selectedAtoms, + ExclusionArray const& Excluded, T const& QFAC, + T& Eelec, T& Evdw, + std::vector& atom_elec, + std::vector& atom_vdw) +{ + Eelec = 0; + Evdw = 0; + for (int atom1 = 0; atom1 < tIn.Natom(); atom1++) { + bool atom1_is_selected = selectedAtoms.AtomInCharMask( atom1 ); + const double* crd1 = fIn.XYZ( atom1 ); + ExclusionArray::ExListType const& excludedAtoms = Excluded[atom1]; + for (int atom2 = atom1 + 1; atom2 < tIn.Natom(); atom2++) { + bool atom2_is_selected = selectedAtoms.AtomInCharMask( atom2 ); + if (atom1_is_selected || atom2_is_selected) { + ExclusionArray::ExListType::const_iterator it = excludedAtoms.find( atom2 ); + if (it == excludedAtoms.end()) { + // Either atom1 or atom2 is selected and the interaction is not excluded. + // TODO image distances? + const double* crd2 = fIn.XYZ( atom2 ); + T dx = crd1[0] - crd2[0]; + T dy = crd1[1] - crd2[1]; + T dz = crd1[2] - crd2[2]; + T rij2 = (dx*dx) + (dy*dy) + (dz*dz); + // VDW + NonbondType const& LJ = tIn.GetLJparam(atom1, atom2); + T e_vdw = Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: VDW %f\n", e_vdw); +# endif + Evdw += e_vdw; + T ene_half = e_vdw * 0.5; + if (atom1_is_selected) atom_vdw[atom1] += ene_half; + if (atom2_is_selected) atom_vdw[atom2] += ene_half; + // Coulomb energy + T rij = sqrt(rij2); + T qiqj = QFAC * tIn[atom1].Charge() * tIn[atom2].Charge(); + T e_elec = qiqj / rij; +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: ELE %f\n", e_elec); +# endif + Eelec += e_elec; + ene_half = e_elec * 0.5; + if (atom1_is_selected) atom_elec[atom1] += ene_half; + if (atom2_is_selected) atom_elec[atom2] += ene_half; + } // END atom2 not excluded from atom1 + } // END atom1 or atom2 is selected + } // END inner loop over atoms + } // END outer loop over atoms +} +} // END namespace Energy +} // END namespace Cpptraj +#endif diff --git a/src/Energy/Ene_LJPME_6_12.h b/src/Energy/Ene_LJPME_6_12.h new file mode 100644 index 0000000000..14f80165b3 --- /dev/null +++ b/src/Energy/Ene_LJPME_6_12.h @@ -0,0 +1,27 @@ +#ifndef INC_ENERGY_ENE_LJPME_6_12_H +#define INC_ENERGY_ENE_LJPME_6_12_H +namespace Cpptraj { +namespace Energy { +/// \return LJ 6-12 energy +template +void Ene_LJPME_6_12(T& e_vdw, T& e_pmevdw, + T const& rij2, T const& LJA, T const& LJB, T const& lj_ewcoeff, T const& Cij) +{ + T r2 = 1.0 / rij2; + T r6 = r2 * r2 * r2; + T r12 = r6 * r6; + T f12 = LJA * r12; // A/r^12 + T f6 = LJB * r6; // B/r^6 + e_vdw = f12 - f6; // (A/r^12)-(B/r^6) + // LJ PME direct space correction + T kr2 = lj_ewcoeff * lj_ewcoeff * rij2; + T kr4 = kr2 * kr2; + //double kr6 = kr2 * kr4; + T expterm = exp(-kr2); + //T Cij = EW_.CalcCij(atom0.Idx(), atom1.Idx()); //Cparam_[it0->Idx()] * Cparam_[it1->Idx()]; + //Eljpme_correction_ += (1.0 - (1.0 + kr2 + kr4/2.0)*expterm) * r6 * vswitch * Cij; + e_pmevdw = (1.0 - (1.0 + kr2 + kr4/2.0)*expterm) * r6 * Cij; +} +} +} +#endif diff --git a/src/Energy/Ene_LJ_6_12.h b/src/Energy/Ene_LJ_6_12.h new file mode 100644 index 0000000000..a8bd1d31b4 --- /dev/null +++ b/src/Energy/Ene_LJ_6_12.h @@ -0,0 +1,19 @@ +#ifndef INC_ENERGY_ENE_LJ_6_12_H +#define INC_ENERGY_ENE_LJ_6_12_H +namespace Cpptraj { +namespace Energy { +/// \return LJ 6-12 energy +template +T Ene_LJ_6_12(T const& rij2, T const& LJA, T const& LJB) +{ + T r2 = 1.0 / rij2; + T r6 = r2 * r2 * r2; + T r12 = r6 * r6; + T f12 = LJA * r12; // A/r^12 + T f6 = LJB * r6; // B/r^6 + T e_vdw = f12 - f6; // (A/r^12)-(B/r^6) + return e_vdw; +} +} +} +#endif diff --git a/src/Energy/Ene_Nonbond.h b/src/Energy/Ene_Nonbond.h new file mode 100644 index 0000000000..d443954b6c --- /dev/null +++ b/src/Energy/Ene_Nonbond.h @@ -0,0 +1,71 @@ +#ifndef INC_ENERGY_ENE_NONBOND_H +#define INC_ENERGY_ENE_NONBOND_H +#include "Ene_LJ_6_12.h" +namespace Cpptraj { +namespace Energy { +/// Calculate simple nonbond energy with Coulomb and LJ 6-12 +/** NOTE: To make this file more lightweight, there are no includes for + * Frame, AtomMask, etc. It is assumed that before this file is + * included there will be at least '#include "Topology.h" and + * 'include ' (for the sqrt). + */ +template +void Ene_Nonbond(Frame const& fIn, Topology const& tIn, AtomMask const& mask, + ExclusionArray const& Excluded, T const& QFAC, T& Eelec, T& Evdw) +{ + Evdw = 0; + Eelec = 0; + int idx1; +# ifdef _OPENMP +# pragma omp parallel private(idx1) reduction(+ : Eelec, Evdw) + { +# pragma omp for +# endif + for (idx1 = 0; idx1 < mask.Nselected(); idx1++) + { + int atom1 = mask[idx1]; + // Set up coord for this atom + const double* crd1 = fIn.XYZ( atom1 ); + // Set up exclusion list for this atom + // TODO refactor inner loop to be more like StructureCheck, more efficient. + ExclusionArray::ExListType::const_iterator excluded_idx = Excluded[idx1].begin(); + for (int idx2 = idx1 + 1; idx2 < mask.Nselected(); idx2++) + { + int atom2 = mask[idx2]; + // Advance excluded list up to current selected atom + while (excluded_idx != Excluded[idx1].end() && *excluded_idx < idx2) ++excluded_idx; + // If atom is excluded, just increment to next excluded atom. + if (excluded_idx != Excluded[idx1].end() && idx2 == *excluded_idx) + ++excluded_idx; + else { + const double* crd2 = fIn.XYZ( atom2 ); + T dx = crd1[0] - crd2[0]; + T dy = crd1[1] - crd2[1]; + T dz = crd1[2] - crd2[2]; + T rij2 = (dx*dx) + (dy*dy) + (dz*dz); + // VDW + NonbondType const& LJ = tIn.GetLJparam(atom1, atom2); + T e_vdw = Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); + Evdw += e_vdw; + // Coulomb + T qiqj = QFAC * tIn[atom1].Charge() * tIn[atom2].Charge(); + T rij = sqrt( rij2 ); + T e_elec = qiqj / rij; + Eelec += e_elec; +# ifdef DEBUG_ENERGY + mprintf("\tEVDW %4i -- %4i: A= %12.5e B= %12.5e r2= %12.5f E= %12.5e\n", + atom1+1, atom2+1, LJ.A(), LJ.B(), rij2, e_vdw); + mprintf("\tEELEC %4i -- %4i: q1= %12.5e q2= %12.5e r= %12.5f E= %12.5e\n", + atom1+1, atom2+1, tIn[atom1].Charge(), tIn[atom2].Charge(), + rij, e_elec); +# endif + } + } + } +# ifdef _OPENMP + } // END omp parallel +# endif +} +} // END namespace Energy +} // END namespace Cpptraj +#endif diff --git a/src/Energy/EnergyDecomposer.cpp b/src/Energy/EnergyDecomposer.cpp new file mode 100644 index 0000000000..0908ab6e76 --- /dev/null +++ b/src/Energy/EnergyDecomposer.cpp @@ -0,0 +1,398 @@ +#include "EnergyDecomposer.h" +#include // sqrt for Ene_Bond etc +#include "Ene_Angle.h" +#include "Ene_Bond.h" +#include "Ene_LJ_6_12.h" +#include "Kernel_Fourier.h" +#include "../ArgList.h" +#include "../CpptrajStdio.h" +#include "../DataFileList.h" +#include "../DataSet_Mesh.h" +#include "../DataSetList.h" +#include "../DistRoutines.h" +#include "../ParameterTypes.h" +#include "../TorsionRoutines.h" +#ifdef MPI +# include "../Stats_Reduce.h" +#endif +#include //std::sort + +using namespace Cpptraj::Energy; + +/** CONSTRUCTOR */ +EnergyDecomposer::EnergyDecomposer() : + eneOut_(0), + outfile_(0), + debug_(0), + currentTop_(0) +{ } + +void EnergyDecomposer::HelpText() { + mprintf("\t[] [] [out ]\n" + "\t[ pme %s\n" + "\t %s\n" + "\t %s\n", + EwaldOptions::KeywordsCommon1(), + EwaldOptions::KeywordsCommon2(), + EwaldOptions::KeywordsPME()); +} + +/** Initialize decomposer. */ +int EnergyDecomposer::InitDecomposer(ArgList& argIn, DataSetList& DSLin, DataFileList& DFLin, + int debugIn) +{ + debug_ = debugIn; + // Process keywords + outfile_ = DFLin.AddDataFile( argIn.GetStringKey("out"), argIn ); + nbcalctype_ = Ecalc_Nonbond::SIMPLE; + if (argIn.hasKey("pme")) + nbcalctype_ = Ecalc_Nonbond::PME; + if (nbcalctype_ != Ecalc_Nonbond::SIMPLE) { +# ifdef LIBPME + ewaldOpts_.AllowLjPme(false); // TODO enable LJPME decomp + if (ewaldOpts_.GetOptions(EwaldOptions::PME, argIn, "enedecomp")) + return 1; + if (ewaldOpts_.Type() == EwaldOptions::LJPME) + nbcalctype_ = Ecalc_Nonbond::LJPME; +# else + mprinterr("Error: 'pme' with energy decomposition requires compilation with LIBPME.\n"); + return 1; +# endif + } + // Get atom mask + if (selectedAtoms_.SetMaskString( argIn.GetMaskNext() )) + return 1; + // Output DataSet + std::string setname = argIn.GetStringNext(); + if (setname.empty()) + setname = DSLin.GenerateDefaultName("DECOMP"); + eneOut_ = DSLin.AddSet(DataSet::XYMESH, MetaData(setname)); + if (eneOut_ == 0) { + mprinterr("Error: Could not allocate decomp. output set '%s'\n", setname.c_str()); + return 1; + } +# ifdef MPI + eneOut_->SetNeedsSync( false ); // Not a time series +# endif + eneOut_->ModifyDim(Dimension::X).SetLabel("Atom"); + if (outfile_ != 0) + outfile_->AddDataSet( eneOut_ ); + + return 0; +} + +/** Print options to stdout. */ +void EnergyDecomposer::PrintOpts() const { + if (eneOut_ == 0) { + mprinterr("Internal Error: EnergyDecomposer::PrintOpts() called before initialization.\n"); + return; + } + mprintf("\tCalculating for atoms selected by mask: %s\n", selectedAtoms_.MaskString()); + mprintf("\tData set name: %s\n", eneOut_->legend()); + if (outfile_ != 0) + mprintf("\tOutput file: %s\n", outfile_->DataFilename().full()); + if (nbcalctype_ != Ecalc_Nonbond::SIMPLE) { + mprintf("\tUsing PME.\n"); + ewaldOpts_.PrintOptions(); + } +} + +// ----------------------------------------------------------------------------- +/** Set up bonds. */ +int EnergyDecomposer::setupBonds(BndArrayType const& bondsIn) { + for (BndArrayType::const_iterator bnd = bondsIn.begin(); bnd != bondsIn.end(); ++bnd) + { + if ( selectedAtoms_.AtomInCharMask( bnd->A1() ) || + selectedAtoms_.AtomInCharMask( bnd->A2() ) ) + { + if (bnd->Idx() < 0) { + mprinterr("Error: Bond %i - %i does not have parameters, cannot calculate energy.\n", + bnd->A1()+1, bnd->A2()+1); + return 1; + } + bonds_.push_back( *bnd ); + } + } + return 0; +} + +/** Set up angles. */ +int EnergyDecomposer::setupAngles(AngArrayType const& anglesIn) { + for (AngArrayType::const_iterator ang = anglesIn.begin(); ang != anglesIn.end(); ++ang) + { + if ( selectedAtoms_.AtomInCharMask( ang->A1() ) || + selectedAtoms_.AtomInCharMask( ang->A2() ) || + selectedAtoms_.AtomInCharMask( ang->A3() ) ) + { + if (ang->Idx() < 0) { + mprinterr("Error: Angle %i - %i - %i does not have parameters, cannot calculate energy.\n", + ang->A1()+1, ang->A2()+1, ang->A3()+1); + return 1; + } + angles_.push_back( *ang ); + } + } + return 0; +} + +/** Set up dihedrals. */ +int EnergyDecomposer::setupDihedrals(DihArrayType const& dihedralsIn) { + for (DihArrayType::const_iterator dih = dihedralsIn.begin(); dih != dihedralsIn.end(); ++dih) + { + if ( selectedAtoms_.AtomInCharMask( dih->A1() ) || + selectedAtoms_.AtomInCharMask( dih->A2() ) || + selectedAtoms_.AtomInCharMask( dih->A3() ) || + selectedAtoms_.AtomInCharMask( dih->A4() ) ) + { + if (dih->Idx() < 0) { + mprinterr("Error: Dihedral %i - %i - %i - %i does not have parameters, cannot calculate energy.\n", + dih->A1()+1, dih->A2()+1, dih->A3()+1, dih->A4()+1); + return 1; + } + dihedrals_.push_back( *dih ); + } + } + return 0; +} + +/** Topology-based setup. + * \return 0 if setup OK, 1 if error, -1 if nothing selected. + */ +int EnergyDecomposer::SetupDecomposer(Topology const& topIn, Box const& boxIn) { + // First set up the mask + if (topIn.SetupCharMask( selectedAtoms_ )) { + mprinterr("Error: Could not set up mask '%s'\n", selectedAtoms_.MaskString()); + return 1; + } + selectedAtoms_.MaskInfo(); + if (selectedAtoms_.None()) { + mprintf("Warning: Nothing selected by mask '%s'\n", selectedAtoms_.MaskString()); + return -1; + } + // Set up calculation arrays + if (energies_.empty()) { + // First time setup +// indices_.reserve( selectedAtoms_.Nselected() ); +// for (int idx = 0; idx != topIn.Natom(); idx++) +// if (selectedAtoms_.AtomInCharMask( idx )) +// indices_.push_back( idx ); + energies_.resize( topIn.Natom() ); + } else { + // Already setup. Warn if indices have changed. + //if ((unsigned int)selectedAtoms_.Nselected() != indices_.size()) + if ((unsigned int)topIn.Natom() != energies_.size()) + { + // FIXME implement this + mprinterr("Error: Number of atoms has changed in topology '%s'\n", topIn.c_str()); + mprinterr("Error: Now %i atoms, expected %zu\n", topIn.Natom(), energies_.size()); + mprinterr("Error: Not yet supported by energy decomposition.\n"); + return 1; + } + } + // Set up bonds + bonds_.clear(); + if (setupBonds( topIn.Bonds() )) return 1; + if (setupBonds( topIn.BondsH() )) return 1; + std::sort( bonds_.begin(), bonds_.end() ); + // Set up angles + angles_.clear(); + if (setupAngles( topIn.Angles() )) return 1; + if (setupAngles( topIn.AnglesH() )) return 1; + std::sort( angles_.begin(), angles_.end() ); + // Set up dihedrals + dihedrals_.clear(); + if (setupDihedrals( topIn.Dihedrals() )) return 1; + if (setupDihedrals( topIn.DihedralsH() )) return 1; + std::sort( dihedrals_.begin(), dihedrals_.end() ); + // Set up nonbonds + // Set up for all atoms FIXME + AtomMask Imask(0, topIn.Natom()); + if (NB_.InitNonbondCalc(nbcalctype_, true, boxIn, ewaldOpts_, debug_)) { + mprinterr("Error: Nonbond decomp init failed.\n"); + return 1; + } + if (NB_.SetupNonbondCalc(topIn, Imask)) { + mprinterr("Error: Nonbond decomp setup failed.\n"); + return 1; + } + + // DEBUG + if (debug_ > 0) { + mprintf("DEBUG: Saving energy for atoms:\n"); + for (int idx = 0; idx != topIn.Natom(); idx++) + if (selectedAtoms_.AtomInCharMask( idx )) + mprintf("\t%s\n", topIn.AtomMaskName( idx ).c_str()); + mprintf("DEBUG: Bonds:\n"); + for (BndArrayType::const_iterator bnd = bonds_.begin(); bnd != bonds_.end(); ++bnd) + mprintf("\t%s - %s\n", topIn.AtomMaskName(bnd->A1()).c_str(), topIn.AtomMaskName(bnd->A2()).c_str()); + mprintf("DEBUG: Angles:\n"); + for (AngArrayType::const_iterator ang = angles_.begin(); ang != angles_.end(); ++ang) + mprintf("\t%s - %s - %s\n", topIn.AtomMaskName(ang->A1()).c_str(), topIn.AtomMaskName(ang->A2()).c_str(), topIn.AtomMaskName(ang->A3()).c_str()); + mprintf("DEBUG: Dihedrals:\n"); + for (DihArrayType::const_iterator dih = dihedrals_.begin(); dih != dihedrals_.end(); ++dih) + mprintf("\t%s - %s - %s - %s\n", topIn.AtomMaskName(dih->A1()).c_str(), topIn.AtomMaskName(dih->A2()).c_str(), topIn.AtomMaskName(dih->A3()).c_str(), topIn.AtomMaskName(dih->A4()).c_str()); + } + + currentTop_ = &topIn; + + return 0; +} + +// ----------------------------------------------------------------------------- +/** Save energy contribution to atom if it is selected. */ +void EnergyDecomposer::saveEne(int idx, double ene_cont) { + if (selectedAtoms_.AtomInCharMask( idx )) + currentEne_[ idx ] += ene_cont; +} + +/** Calculate bond energies. */ +void EnergyDecomposer::calcBonds( Frame const& frameIn ) { + for (BndArrayType::const_iterator bnd = bonds_.begin(); bnd != bonds_.end(); ++bnd) + { + BondParmType const& BP = currentTop_->BondParm()[ bnd->Idx() ]; + double ene = Ene_Bond( frameIn.XYZ( bnd->A1() ), + frameIn.XYZ( bnd->A2() ), + BP.Req(), BP.Rk() ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: BND %f\n", ene); +# endif + // Divide the energy equally between the two atoms. + double ene_half = ene * 0.5; + saveEne( bnd->A1(), ene_half ); + saveEne( bnd->A2(), ene_half ); + } +} + +/** Calculate angle energies. */ +void EnergyDecomposer::calcAngles( Frame const& frameIn ) { + for (AngArrayType::const_iterator ang = angles_.begin(); ang != angles_.end(); ++ang) + { + AngleParmType const& AP = currentTop_->AngleParm()[ ang->Idx() ]; + double ene = Ene_Angle( frameIn.XYZ( ang->A1() ), + frameIn.XYZ( ang->A2() ), + frameIn.XYZ( ang->A3() ), + AP.Teq(), AP.Tk() ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: ANG %f\n", ene); +# endif + // Divide the energy equally between the three atoms. + double ene_third = ene / 3.0; + saveEne( ang->A1(), ene_third ); + saveEne( ang->A2(), ene_third ); + saveEne( ang->A3(), ene_third ); + } +} + +/** Calculate dihedral and LJ 1-4 energies. */ +void EnergyDecomposer::calcDihedrals( Frame const& frameIn ) { + for (DihArrayType::const_iterator dih = dihedrals_.begin(); dih != dihedrals_.end(); ++dih) + { + DihedralParmType const& DP = currentTop_->DihedralParm()[ dih->Idx() ]; + + double theta = Torsion( frameIn.XYZ(dih->A1()), + frameIn.XYZ(dih->A2()), + frameIn.XYZ(dih->A3()), + frameIn.XYZ(dih->A4()) ); + double ene = Kernel_Fourier( theta, DP.Pk(), DP.Pn(), DP.Phase() ); + +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: DIH %f\n", ene); +# endif + // Divide the energy equally between the four atoms. + double ene_fourth = ene / 4.0; + saveEne( dih->A1(), ene_fourth ); + saveEne( dih->A2(), ene_fourth ); + saveEne( dih->A3(), ene_fourth ); + saveEne( dih->A4(), ene_fourth ); + if (dih->Type() == DihedralType::NORMAL) { + // 1-4 vdw energy + double rij2 = DIST2_NoImage( frameIn.XYZ(dih->A1()), frameIn.XYZ(dih->A4()) ); + NonbondType const& LJ = currentTop_->GetLJparam(dih->A1(), dih->A4()); + double e_vdw = Ene_LJ_6_12( rij2, LJ.A(), LJ.B() ); + e_vdw /= DP.SCNB(); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: V14 %f\n", e_vdw); +# endif + double ene_half = e_vdw * 0.5; + saveEne( dih->A1(), ene_half ); + saveEne( dih->A4(), ene_half ); + // 1-4 coulomb energy + double rij = sqrt(rij2); + double qiqj = Constants::COULOMBFACTOR * (*currentTop_)[dih->A1()].Charge() * (*currentTop_)[dih->A4()].Charge(); + double e_elec = qiqj / rij; + e_elec /= DP.SCEE(); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: E14 %f\n", e_elec); +# endif + ene_half = e_elec * 0.5; + saveEne( dih->A1(), ene_half ); + saveEne( dih->A4(), ene_half ); + } + } +} + +/** Calculate and decompose energies. */ +int EnergyDecomposer::CalcEne(Frame const& frameIn) { + t_total_.Start(); + if (currentTop_ == 0) { + mprinterr("Internal Error: EnergyDecomposer::CalcEne() called before setup.\n"); + return 1; + } + currentEne_.assign( energies_.size(), 0.0 ); + // Bonds + calcBonds(frameIn); + // Angles + calcAngles(frameIn); + // Dihedrals + calcDihedrals(frameIn); + // Nonbonds + double e_elec, e_vdw; + if (NB_.DecomposedNonbondEnergy(frameIn, selectedAtoms_, e_elec, e_vdw, + currentEne_, currentEne_)) + { + mprinterr("Error: Decompose nonbond energy calc failed.\n"); + return 1; + } + + // Accumulate the energies + for (unsigned int idx = 0; idx != energies_.size(); idx++) { + if (selectedAtoms_.AtomInCharMask( idx )) + energies_[idx].accumulate( currentEne_[idx] ); + } + t_total_.Stop(); + + return 0; +} + +// ----------------------------------------------------------------------------- +/** Finish the calculation by putting the results into the output DataSet. */ +int EnergyDecomposer::FinishCalc() { + if (energies_.empty() || eneOut_ == 0) { + mprinterr("Internal Error: EnergyDecomposer::FinishCalc() called before setup.\n"); + return 1; + } + // Only add entities that have data. + DataSet_Mesh& set = static_cast( *eneOut_ ); + set.Clear(); + // TODO allocate? + for (unsigned int idx = 0; idx != energies_.size(); idx++) { + if ( energies_[idx].nData() > 0 ) { + set.AddXY( idx+1, energies_[idx].mean() ); + } + } + mprintf("Timing for energy decomposition: '%s'\n", eneOut_->legend()); + t_total_.WriteTiming(0, " Decomp total:"); + NB_.PrintTiming(t_total_.Total()); + return 0; +} + +#ifdef MPI +/** Reduce the per-atom energy array to the master rank. + * Should be called before FinishCalc(). + */ +int EnergyDecomposer::ReduceToMaster(Parallel::Comm const& trajComm) { + unsigned long maxbin; + Stats_Reduce( trajComm, energies_, maxbin ); + return 0; +} +#endif diff --git a/src/Energy/EnergyDecomposer.h b/src/Energy/EnergyDecomposer.h new file mode 100644 index 0000000000..4a0f514214 --- /dev/null +++ b/src/Energy/EnergyDecomposer.h @@ -0,0 +1,93 @@ +#ifndef INC_ENERGY_ENERGYDECOMPOSER_H +#define INC_ENERGY_ENERGYDECOMPOSER_H +#include +#include "Ecalc_Nonbond.h" +#include "../CharMask.h" +#include "../EwaldOptions.h" +#include "../OnlineVarT.h" +#include "../Timer.h" +#ifdef MPI +# include "../Parallel.h" +#endif +class AngleType; +class ArgList; +class BondType; +class DataFile; +class DataFileList; +class DataSet; +class DataSetList; +class DihedralType; +class Frame; +class Topology; +namespace Cpptraj { +namespace Energy { +/// Used to break down pairwise-additive energy by atom +/** Comple with -DCPPTRAJ_DEBUG_ENEDECOMP for more details on the individual + * contributions. + */ +class EnergyDecomposer { + public: + /// CONSTRUCTOR + EnergyDecomposer(); + /// Print help text to stdout + static void HelpText(); + /// Initialize with arguments + int InitDecomposer(ArgList&, DataSetList&, DataFileList&, int); + /// Print options to stdout + void PrintOpts() const; + /// Topology-based setup. Box only needed for PME + int SetupDecomposer(Topology const&, Box const& boxIn); + /// Calculate and decompose energies for given frame. + int CalcEne(Frame const&); + /// Finish the calculation by putting energies in output DataSet + int FinishCalc(); +# ifdef MPI + /// Reduce the decomposed array to the master rank + int ReduceToMaster(Parallel::Comm const&); +# endif + private: + typedef std::vector Darray; + typedef std::vector< Stats > EneArrayType; + typedef std::vector BndArrayType; + typedef std::vector AngArrayType; + typedef std::vector DihArrayType; + + /// Set up selected bonds + int setupBonds(BndArrayType const&); + /// Set up selected angles + int setupAngles(AngArrayType const&); + /// Set up selected dihedrals + int setupDihedrals(DihArrayType const&); + + /// Save energy contribution for atom if it is selected + inline void saveEne(int, double); + /// Calculate bond energies + void calcBonds(Frame const&); + /// Calculate angle energies + void calcAngles(Frame const&); + /// Calculate dihedral energies + void calcDihedrals(Frame const&); + + CharMask selectedAtoms_; ///< Mask of atoms that energy will be recorded for. + DataSet* eneOut_; ///< Will hold the average energy of each selected entity for output. + DataFile* outfile_; ///< Output file + int debug_; ///< Debug level + EwaldOptions ewaldOpts_; ///< Hold Ewald options + Cpptraj::Energy::Ecalc_Nonbond::CalcType nbcalctype_; + + BndArrayType bonds_; ///< Hold all bonds to be calculated + AngArrayType angles_; ///< Hold all angles to be calculated + DihArrayType dihedrals_; ///< Hold all dihedrals to be calculated + //AtomMask mask_; ///< Atom mask for nonbonded calculations + EneArrayType energies_; ///< Used to accumulate the average energy of each selected entity. + Topology const* currentTop_; ///< Current topology from Setup + + Ecalc_Nonbond NB_; ///< For calculating pairwise decomposed nonbond energies + + Darray currentEne_; ///< Hold the total energy of each atom for the current frame + + Timer t_total_; ///< Total calc time +}; +} +} +#endif diff --git a/src/Energy/ErfcFxn.cpp b/src/Energy/ErfcFxn.cpp new file mode 100644 index 0000000000..5e086210ba --- /dev/null +++ b/src/Energy/ErfcFxn.cpp @@ -0,0 +1,71 @@ +#include "ErfcFxn.h" +#include "../CpptrajStdio.h" +#include + +using namespace Cpptraj::Energy; + +static inline double DABS(double xIn) { if (xIn < 0.0) return -xIn; else return xIn; } + +/** Complimentary error function: 2/sqrt(PI) * SUM[exp(-t^2)*dt] + * Original code: SANDER: erfcfun.F90 + */ +double ErfcFxn::erfc_func(double xIn) { + double erfc; + double absx = DABS( xIn ); + + if (xIn > 26.0) + erfc = 0.0; + else if (xIn < -5.5) + erfc = 2.0; + else if (absx <= 0.5) { + double cval = xIn * xIn; + double pval = ((-0.356098437018154E-1*cval+0.699638348861914E1)*cval + 0.219792616182942E2) * + cval + 0.242667955230532E3; + double qval = ((cval+0.150827976304078E2)*cval+0.911649054045149E2)*cval + 0.215058875869861E3; + double erf = xIn * pval/qval; + erfc = 1.0 - erf; + } else if (absx < 4.0) { + double cval = absx; + double pval=((((((-0.136864857382717E-6*cval+0.564195517478974)*cval+ + 0.721175825088309E1)*cval+0.431622272220567E2)*cval+ + 0.152989285046940E3)*cval+0.339320816734344E3)*cval+ + 0.451918953711873E3)*cval+0.300459261020162E3; + double qval=((((((cval+0.127827273196294E2)*cval+0.770001529352295E2)*cval+ + 0.277585444743988E3)*cval+0.638980264465631E3)*cval+ + 0.931354094850610E3)*cval+0.790950925327898E3)*cval+ + 0.300459260956983E3; + double nonexperfc; + if ( xIn > 0.0 ) + nonexperfc = pval/qval; + else + nonexperfc = 2.0*exp(xIn*xIn) - pval/qval; + erfc = exp(-absx*absx)*nonexperfc; + } else { + double cval = 1.0/(xIn*xIn); + double pval = (((0.223192459734185E-1*cval+0.278661308609648)*cval+ + 0.226956593539687)*cval+0.494730910623251E-1)*cval+ + 0.299610707703542E-2; + double qval = (((cval+0.198733201817135E1)*cval+0.105167510706793E1)*cval+ + 0.191308926107830)*cval+0.106209230528468E-1; + cval = (-cval*pval/qval + 0.564189583547756)/absx; + double nonexperfc; + if ( xIn > 0.0 ) + nonexperfc = cval; + else + nonexperfc = 2.0*exp(xIn*xIn) - cval; + erfc = exp(-absx*absx)*nonexperfc; + } + return erfc; +} + +/** Fill table with values. */ +int ErfcFxn::FillErfcTable( double erfcTableDx, double beg, double end ) +{ + if (table_.FillTable( erfc_func, erfcTableDx, beg, end )) { + mprinterr("Error: Could not set up spline table for ERFC\n"); + return 1; + } + table_.PrintMemUsage("\t "); + table_.PrintTableInfo("\t "); + return 0; +} diff --git a/src/Energy/ErfcFxn.h b/src/Energy/ErfcFxn.h new file mode 100644 index 0000000000..d9d709fe31 --- /dev/null +++ b/src/Energy/ErfcFxn.h @@ -0,0 +1,21 @@ +#ifndef INC_ERFCFXN_H +#define INC_ERFCFXN_H +#include "../SplineFxnTable.h" +namespace Cpptraj { +namespace Energy { +/// Complimentary error function +class ErfcFxn { + public: + ErfcFxn() {} + /// Fill table with ERFC values using given spacing, begin, and end + int FillErfcTable(double, double, double); + /// \return Interpolated erfc value + double ErfcInterpolated(double xIn) const { return table_.Yval( xIn); } + /// ERFC function from sander + static double erfc_func(double); + private: + SplineFxnTable table_; +}; +} +} +#endif diff --git a/src/Energy/EwaldCalc.h b/src/Energy/EwaldCalc.h new file mode 100644 index 0000000000..b9e06855c6 --- /dev/null +++ b/src/Energy/EwaldCalc.h @@ -0,0 +1,32 @@ +#ifndef INC_ENERGY_EWALDCALC_H +#define INC_ENERGY_EWALDCALC_H +#include "../Timer.h" +class AtomMask; +class Box; +class EwaldOptions; +class ExclusionArray; +class Frame; +class PairList; +class Topology; +namespace Cpptraj { +namespace Energy { +/// Abstract base class for Ewald calcs +class EwaldCalc { + public: + EwaldCalc() {} + // virtual since inherited + virtual ~EwaldCalc() {} + + virtual int Init(Box const&, EwaldOptions const&, int) = 0; + virtual int Setup(Topology const&, AtomMask const&) = 0; + virtual int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&) = 0; + virtual void Timing(double) const = 0; + protected: + Timer t_total_; + Timer t_direct_; +}; +} +} +#endif diff --git a/src/Energy/EwaldCalc_Decomp.h b/src/Energy/EwaldCalc_Decomp.h new file mode 100644 index 0000000000..f2a7841893 --- /dev/null +++ b/src/Energy/EwaldCalc_Decomp.h @@ -0,0 +1,32 @@ +#ifndef INC_ENERGY_EWALDCALC_DECOMP_H +#define INC_ENERGY_EWALDCALC_DECOMP_H +#include "EwaldCalc.h" +#include +namespace Cpptraj { +namespace Energy { +/// Abstract base class for decomposable Ewald calcs. +class EwaldCalc_Decomp : public EwaldCalc { + public: + typedef std::vector Darray; + + EwaldCalc_Decomp() {} + // virtual since inherited + ~EwaldCalc_Decomp() {} + + Darray const& Atom_Elec() const { return atom_elec_; } + Darray const& Atom_VDW() const { return atom_vdw_; } + protected: + /// For DEBUG, \return sum of given array + static inline double sumArray(Darray const& arrayIn) { + double sum = 0; + for (Darray::const_iterator it = arrayIn.begin(); it != arrayIn.end(); ++it) + sum += *it; + return sum; + } + + Darray atom_elec_; ///< Hold electrostatic contribution for each atom + Darray atom_vdw_; ///< Hold VDW contribution for each atom +}; +} +} +#endif diff --git a/src/Energy/EwaldCalc_Decomp_LJPME.cpp b/src/Energy/EwaldCalc_Decomp_LJPME.cpp new file mode 100644 index 0000000000..d69cba87ee --- /dev/null +++ b/src/Energy/EwaldCalc_Decomp_LJPME.cpp @@ -0,0 +1,145 @@ +#include "EwaldCalc_Decomp_LJPME.h" +#ifdef LIBPME +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Frame.h" +#include "../PairListTemplate.h" + +using namespace Cpptraj::Energy; + +EwaldCalc_Decomp_LJPME::EwaldCalc_Decomp_LJPME() : + Recip_(PME_Recip::COULOMB), + LJrecip_(PME_Recip::LJ) +{} + +/** Set up LJPME parameters. */ +int EwaldCalc_Decomp_LJPME::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (!pmeOpts.IsPmeType()) { + mprinterr("Internal Error: EwaldCalc_Decomp_LJPME::Init(): Options were not set up for PME.\n"); + return 1; + } + mprintf("\tDecomposable Particle Mesh Ewald (LJPME) params:\n"); + if (NBengine_.ModifyEwaldParams().InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: Decomposable LJPME calculation init failed.\n"); + return 1; + } + if (Recip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: Decomposable LJPME recip init failed.\n"); + return 1; + } + if (LJrecip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: Decomposable LJPME LJ recip init failed.\n"); + return 1; + } + + return 0; +} + +/** Setup LJPME calculation. */ +int EwaldCalc_Decomp_LJPME::Setup(Topology const& topIn, AtomMask const& maskIn) { + if (NBengine_.ModifyEwaldParams().SetupEwald(topIn, maskIn)) { + mprinterr("Error: LJPME calculation setup failed.\n"); + return 1; + } + NBengine_.ModifyEwaldParams().CalcDecomposedSelf6Energy(); + // TODO reserve atom_elec and atom_vdw? + + return 0; +} + +/** Calculate full nonbonded energy with LJPME */ +int EwaldCalc_Decomp_LJPME::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + PairList const& pairList_, ExclusionArray const& Excluded_, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + double volume = frameIn.BoxCrd().CellVolume(); + // Do decomposed self + Darray atom_self; + double e_self = NBengine_.EwaldParams().DecomposedSelfEnergy( atom_self, volume ); + mprintf("DEBUG: Total self energy: %f\n", e_self); + mprintf("DEBUG: Sum of self array: %f\n", sumArray(atom_self)); + // Do decomposed self6 + Darray const& atom_vdwself6 = NBengine_.EwaldParams().Atom_Self6Energies(); + mprintf("DEBUG: Total self6 energy: %f\n", NBengine_.EwaldParams().Self6()); + mprintf("DEBUG: Sum of self6 array: %f\n", sumArray(atom_vdwself6)); + + // TODO make more efficient + NBengine_.ModifyEwaldParams().FillRecipCoords( frameIn, maskIn ); + + Darray atom_recip; + // FIXME helPME requires coords and charge arrays to be non-const + double e_recip = Recip_.Recip_Decomp( atom_recip, + NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedCharges(), + NBengine_.EwaldParams().EwaldCoeff() + ); + mprintf("DEBUG: Recip energy : %f\n", e_recip); + mprintf("DEBUG: Sum of recip array: %f\n", sumArray(atom_recip)); + Darray atom_vdw6recip; + double e_vdw6recip = LJrecip_.Recip_Decomp( atom_vdw6recip, + NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedC6params(), + NBengine_.EwaldParams().LJ_EwaldCoeff() + ); + mprintf("DEBUG: VDW Recip energy : %f\n", e_vdw6recip); + mprintf("DEBUG: Sum of VDW recip array: %f\n", sumArray(atom_vdw6recip)); + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: e_vdw6self = %16.8f\n", NBengine_.EwaldParams().Self6()); + mprintf("DEBUG: Evdwrecip = %16.8f\n", e_vdw6recip); + } + + t_direct_.Start(); + Cpptraj::PairListTemplate(pairList_, Excluded_, + NBengine_.EwaldParams().Cut2(), NBengine_); + t_direct_.Stop(); + mprintf("DEBUG: Direct Elec. energy : %f\n", NBengine_.Eelec()); + mprintf("DEBUG: Sum of elec. energy : %f\n", sumArray(NBengine_.Eatom_Elec())); + mprintf("DEBUG: Direct VDW energy : %f\n", NBengine_.Evdw()); + mprintf("DEBUG: Sum of VDW energy : %f\n", sumArray(NBengine_.Eatom_EVDW())); + mprintf("DEBUG: Direct Adjust energy: %f\n", NBengine_.Eadjust()); + mprintf("DEBUG: Sum of Adjust energy: %f\n", sumArray(NBengine_.Eatom_EAdjust())); + + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: Nonbond energy components:\n"); + mprintf(" Evdw = %24.12f\n", NBengine_.Evdw() + + NBengine_.EwaldParams().Self6() + + e_vdw6recip); + mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + + NBengine_.Eelec() + + NBengine_.Eadjust()); + mprintf("\n"); + mprintf(" E electrostatic (self) = %24.12f\n", e_self); + mprintf(" (rec) = %24.12f\n", e_recip); + mprintf(" (dir) = %24.12f\n", NBengine_.Eelec()); + mprintf(" (adj) = %24.12f\n", NBengine_.Eadjust()); + mprintf(" E vanDerWaals (dir) = %24.12f\n", NBengine_.Evdw()); + mprintf(" (6slf) = %24.12f\n", NBengine_.EwaldParams().Self6()); + mprintf(" (6rcp) = %24.12f\n", e_vdw6recip); + } + e_vdw = NBengine_.Evdw() + NBengine_.EwaldParams().Self6() + e_vdw6recip; + e_elec = e_self + e_recip + NBengine_.Eelec() + NBengine_.Eadjust(); + // TODO preallocate? + atom_elec_.resize( NBengine_.Eatom_Elec().size() ); + atom_vdw_.resize( NBengine_.Eatom_EVDW().size() ); + for (unsigned int idx = 0; idx != atom_elec_.size(); idx++) + { + atom_elec_[idx] = atom_self[idx] + atom_recip[idx] + NBengine_.Eatom_Elec()[idx] + NBengine_.Eatom_EAdjust()[idx]; + atom_vdw_[idx] = NBengine_.Eatom_EVDW()[idx] + atom_vdwself6[idx] + atom_vdw6recip[idx]; + } + + t_total_.Stop(); + return 0; +} + +void EwaldCalc_Decomp_LJPME::Timing(double total) const { + t_total_.WriteTiming(1, " LJPME Total:", total); + Recip_.Timing_Total().WriteTiming(2, "Recip: ", t_total_.Total()); + LJrecip_.Timing_Total().WriteTiming(2,"LJRecip: ", t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +} +#endif /* LIBPME */ diff --git a/src/Energy/EwaldCalc_Decomp_LJPME.h b/src/Energy/EwaldCalc_Decomp_LJPME.h new file mode 100644 index 0000000000..fa5fd8feb4 --- /dev/null +++ b/src/Energy/EwaldCalc_Decomp_LJPME.h @@ -0,0 +1,28 @@ +#ifndef INC_ENERGY_EWALDCALC_DECOMP_LJPME_H +#define INC_ENERGY_EWALDCALC_DECOMP_LJPME_H +#ifdef LIBPME +#include "EwaldCalc_Decomp.h" +#include "PME_Recip.h" +#include "../PairListEngine_Ewald_Decomp_LJPME.h" +namespace Cpptraj { +namespace Energy { +class EwaldCalc_Decomp_LJPME : public EwaldCalc_Decomp { + public: + EwaldCalc_Decomp_LJPME(); + /// Init with Box, EwaldOptions and debug level + int Init(Box const&, EwaldOptions const&, int); + int Setup(Topology const&, AtomMask const&); + int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&); + + void Timing(double) const; + private: + PairListEngine_Ewald_Decomp_LJPME NBengine_; + PME_Recip Recip_; + PME_Recip LJrecip_; +}; +} +} +#endif +#endif diff --git a/src/Energy/EwaldCalc_Decomp_PME.cpp b/src/Energy/EwaldCalc_Decomp_PME.cpp new file mode 100644 index 0000000000..1a3fce114f --- /dev/null +++ b/src/Energy/EwaldCalc_Decomp_PME.cpp @@ -0,0 +1,132 @@ +#include "EwaldCalc_Decomp_PME.h" +#ifdef LIBPME +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Frame.h" +#include "../PairListTemplate.h" + +using namespace Cpptraj::Energy; + +EwaldCalc_Decomp_PME::EwaldCalc_Decomp_PME() : + Recip_(PME_Recip::COULOMB) +{} + +/** Set up PME parameters. */ +int EwaldCalc_Decomp_PME::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (!pmeOpts.IsPmeType()) { + mprinterr("Internal Error: EwaldCalc_Decomp_PME::Init(): Options were not set up for PME.\n"); + return 1; + } + mprintf("\tDecomposed Particle Mesh Ewald params:\n"); + if (NBengine_.ModifyEwaldParams().InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: Decomposable PME calculation init failed.\n"); + return 1; + } + VDW_LR_.SetDebug( debugIn ); + if (Recip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: PME recip init failed.\n"); + return 1; + } + + return 0; +} + +/** Setup PME calculation. */ +int EwaldCalc_Decomp_PME::Setup(Topology const& topIn, AtomMask const& maskIn) { + if (NBengine_.ModifyEwaldParams().SetupEwald(topIn, maskIn)) { + mprinterr("Error: PME calculation setup failed.\n"); + return 1; + } + if (VDW_LR_.Setup_VDW_Correction( topIn, maskIn )) { + mprinterr("Error: PME calculation long range VDW correction setup failed.\n"); + return 1; + } + // TODO reserve atom_elec and atom_vdw? + + return 0; +} + +/** Calculate full decompoesd nonbonded energy with PME */ +int EwaldCalc_Decomp_PME::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + PairList const& pairList_, ExclusionArray const& Excluded_, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + double volume = frameIn.BoxCrd().CellVolume(); + Darray atom_self; + double e_self = NBengine_.EwaldParams().DecomposedSelfEnergy( atom_self, volume ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: Total self energy: %f\n", e_self); + mprintf("DEBUG: Sum of self array: %f\n", sumArray(atom_self)); +# endif + // TODO make more efficient + NBengine_.ModifyEwaldParams().FillRecipCoords( frameIn, maskIn ); + + Darray atom_recip; + // FIXME helPME requires coords and charge arrays to be non-const + double e_recip = Recip_.Recip_Decomp( atom_recip, + NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedCharges(), + NBengine_.EwaldParams().EwaldCoeff() + ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: Recip energy : %f\n", e_recip); + mprintf("DEBUG: Sum of recip array: %f\n", sumArray(atom_recip)); +# endif + // TODO distribute + Darray atom_vdwlr; + double e_vdw_lr_correction = VDW_LR_.Vdw_Decomp_Correction( atom_vdwlr, + NBengine_.EwaldParams().Cutoff(), volume ); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: VDW correction : %f\n", e_vdw_lr_correction); + mprintf("DEBUG: Sum of VDW correction: %f\n", sumArray(atom_vdwlr)); +# endif + t_direct_.Start(); + Cpptraj::PairListTemplate(pairList_, Excluded_, + NBengine_.EwaldParams().Cut2(), NBengine_); + t_direct_.Stop(); +# ifdef CPPTRAJ_DEBUG_ENEDECOMP + mprintf("DEBUG: Direct Elec. energy : %f\n", NBengine_.Eelec()); + mprintf("DEBUG: Sum of elec. energy : %f\n", sumArray(NBengine_.Eatom_Elec())); + mprintf("DEBUG: Direct VDW energy : %f\n", NBengine_.Evdw()); + mprintf("DEBUG: Sum of VDW energy : %f\n", sumArray(NBengine_.Eatom_EVDW())); + mprintf("DEBUG: Direct Adjust energy: %f\n", NBengine_.Eadjust()); + mprintf("DEBUG: Sum of Adjust energy: %f\n", sumArray(NBengine_.Eatom_EAdjust())); +# endif + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: Nonbond energy components:\n"); + mprintf(" Evdw = %24.12f\n", NBengine_.Evdw() + e_vdw_lr_correction ); + mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + + NBengine_.Eelec() + + NBengine_.Eadjust()); + mprintf("\n"); + mprintf(" E electrostatic (self) = %24.12f\n", e_self); + mprintf(" (rec) = %24.12f\n", e_recip); + mprintf(" (dir) = %24.12f\n", NBengine_.Eelec()); + mprintf(" (adj) = %24.12f\n", NBengine_.Eadjust()); + mprintf(" E vanDerWaals (dir) = %24.12f\n", NBengine_.Evdw()); + mprintf(" (LR) = %24.12f\n", e_vdw_lr_correction); + } + e_vdw = NBengine_.Evdw() + e_vdw_lr_correction; + e_elec = e_self + e_recip + NBengine_.Eelec() + NBengine_.Eadjust(); + // TODO preallocate? + atom_elec_.resize( NBengine_.Eatom_Elec().size() ); + atom_vdw_.resize( NBengine_.Eatom_EVDW().size() ); + for (unsigned int idx = 0; idx != atom_elec_.size(); idx++) + { + atom_elec_[idx] = atom_self[idx] + atom_recip[idx] + NBengine_.Eatom_Elec()[idx] + NBengine_.Eatom_EAdjust()[idx]; + atom_vdw_[idx] = NBengine_.Eatom_EVDW()[idx] + atom_vdwlr[idx]; + } + t_total_.Stop(); + return 0; +} + +void EwaldCalc_Decomp_PME::Timing(double total) const { + t_total_.WriteTiming(1, " PME decomp Total:", total); + Recip_.Timing_Total().WriteTiming(2, "Recip: ", t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +} +#endif /* LIBPME */ diff --git a/src/Energy/EwaldCalc_Decomp_PME.h b/src/Energy/EwaldCalc_Decomp_PME.h new file mode 100644 index 0000000000..f3f5d9654d --- /dev/null +++ b/src/Energy/EwaldCalc_Decomp_PME.h @@ -0,0 +1,32 @@ +#ifndef INC_ENERGY_EWALDCALC_DECOMP_PME_H +#define INC_ENERGY_EWALDCALC_DECOMP_PME_H +#ifdef LIBPME +#include "EwaldCalc_Decomp.h" +#include "PME_Recip.h" +#include "VDW_LongRange_Correction.h" +#include "../PairListEngine_Ewald_Decomp_LJLR.h" +namespace Cpptraj { +namespace Energy { +/** Energy decomposition for nonbonded calculation using PME and VDW + * long-range correction. + * Comple with -DCPPTRAJ_DEBUG_ENEDECOMP for more details on the individual + * contributions. + */ +class EwaldCalc_Decomp_PME : public EwaldCalc_Decomp { + public: + EwaldCalc_Decomp_PME(); + int Init(Box const&, EwaldOptions const&, int); + int Setup(Topology const&, AtomMask const&); // TODO CharMask? + int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&); + void Timing(double) const; + private: + PairListEngine_Ewald_Decomp_LJLR NBengine_; + PME_Recip Recip_; + VDW_LongRange_Correction VDW_LR_; ///< For calculating the long range VDW correction +}; +} +} +#endif /* LIBPME */ +#endif diff --git a/src/Energy/EwaldCalc_LJPME.cpp b/src/Energy/EwaldCalc_LJPME.cpp new file mode 100644 index 0000000000..ea376d5597 --- /dev/null +++ b/src/Energy/EwaldCalc_LJPME.cpp @@ -0,0 +1,112 @@ +#include "EwaldCalc_LJPME.h" +#ifdef LIBPME +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Frame.h" +#include "../PairListTemplate.h" + +using namespace Cpptraj::Energy; + +EwaldCalc_LJPME::EwaldCalc_LJPME() : + Recip_(PME_Recip::COULOMB), + LJrecip_(PME_Recip::LJ) +{} + +/** Set up LJPME parameters. */ +int EwaldCalc_LJPME::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (!pmeOpts.IsPmeType()) { + mprinterr("Internal Error: EwaldCalc_LJPME::Init(): Options were not set up for PME.\n"); + return 1; + } + mprintf("\tParticle Mesh Ewald (LJPME) params:\n"); + if (NBengine_.ModifyEwaldParams().InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: LJPME calculation init failed.\n"); + return 1; + } + if (Recip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: LJPME recip init failed.\n"); + return 1; + } + if (LJrecip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: LJPME LJ recip init failed.\n"); + return 1; + } + + return 0; +} + +/** Setup LJPME calculation. */ +int EwaldCalc_LJPME::Setup(Topology const& topIn, AtomMask const& maskIn) { + if (NBengine_.ModifyEwaldParams().SetupEwald(topIn, maskIn)) { + mprinterr("Error: LJPME calculation setup failed.\n"); + return 1; + } + + return 0; +} + +/** Calculate full nonbonded energy with LJPME */ +int EwaldCalc_LJPME::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + PairList const& pairList_, ExclusionArray const& Excluded_, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + double volume = frameIn.BoxCrd().CellVolume(); + double e_self = NBengine_.EwaldParams().SelfEnergy( volume ); + + // TODO make more efficient + NBengine_.ModifyEwaldParams().FillRecipCoords( frameIn, maskIn ); + + // FIXME helPME requires coords and charge arrays to be non-const + double e_recip = Recip_.Recip_ParticleMesh( NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedCharges(), + NBengine_.EwaldParams().EwaldCoeff() + ); + double e_vdw6recip = LJrecip_.Recip_ParticleMesh( NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedC6params(), + NBengine_.EwaldParams().LJ_EwaldCoeff() + ); + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: e_vdw6self = %16.8f\n", NBengine_.EwaldParams().Self6()); + mprintf("DEBUG: Evdwrecip = %16.8f\n", e_vdw6recip); + } + + t_direct_.Start(); + Cpptraj::PairListTemplate(pairList_, Excluded_, + NBengine_.EwaldParams().Cut2(), NBengine_); + t_direct_.Stop(); + + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: Nonbond energy components:\n"); + mprintf(" Evdw = %24.12f\n", NBengine_.Evdw() + + NBengine_.EwaldParams().Self6() + + e_vdw6recip); + mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + + NBengine_.Eelec() + + NBengine_.Eadjust()); + mprintf("\n"); + mprintf(" E electrostatic (self) = %24.12f\n", e_self); + mprintf(" (rec) = %24.12f\n", e_recip); + mprintf(" (dir) = %24.12f\n", NBengine_.Eelec()); + mprintf(" (adj) = %24.12f\n", NBengine_.Eadjust()); + mprintf(" E vanDerWaals (dir) = %24.12f\n", NBengine_.Evdw()); + mprintf(" (6slf) = %24.12f\n", NBengine_.EwaldParams().Self6()); + mprintf(" (6rcp) = %24.12f\n", e_vdw6recip); + } + e_vdw = NBengine_.Evdw() + NBengine_.EwaldParams().Self6() + e_vdw6recip; + e_elec = e_self + e_recip + NBengine_.Eelec() + NBengine_.Eadjust(); + t_total_.Stop(); + return 0; +} + +void EwaldCalc_LJPME::Timing(double total) const { + t_total_.WriteTiming(1, " LJPME Total:", total); + Recip_.Timing_Total().WriteTiming(2, "Recip: ", t_total_.Total()); + LJrecip_.Timing_Total().WriteTiming(2,"LJRecip: ", t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +} +#endif /* LIBPME */ diff --git a/src/Energy/EwaldCalc_LJPME.h b/src/Energy/EwaldCalc_LJPME.h new file mode 100644 index 0000000000..9a5cf8a272 --- /dev/null +++ b/src/Energy/EwaldCalc_LJPME.h @@ -0,0 +1,28 @@ +#ifndef INC_ENERGY_EWALDCALC_LJPME_H +#define INC_ENERGY_EWALDCALC_LJPME_H +#ifdef LIBPME +#include "EwaldCalc.h" +#include "PME_Recip.h" +#include "../PairListEngine_Ewald_LJPME.h" +namespace Cpptraj { +namespace Energy { +class EwaldCalc_LJPME : public EwaldCalc { + public: + EwaldCalc_LJPME(); + /// Init with Box, EwaldOptions and debug level + int Init(Box const&, EwaldOptions const&, int); + int Setup(Topology const&, AtomMask const&); + int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&); + + void Timing(double) const; + private: + PairListEngine_Ewald_LJPME NBengine_; + PME_Recip Recip_; + PME_Recip LJrecip_; +}; +} +} +#endif +#endif diff --git a/src/Energy/EwaldCalc_PME.cpp b/src/Energy/EwaldCalc_PME.cpp new file mode 100644 index 0000000000..e61626eb67 --- /dev/null +++ b/src/Energy/EwaldCalc_PME.cpp @@ -0,0 +1,101 @@ +#include "EwaldCalc_PME.h" +#ifdef LIBPME +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Frame.h" +#include "../PairListTemplate.h" + +using namespace Cpptraj::Energy; + +EwaldCalc_PME::EwaldCalc_PME() : + Recip_(PME_Recip::COULOMB) +{} + +/** Set up PME parameters. */ +int EwaldCalc_PME::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (!pmeOpts.IsPmeType()) { + mprinterr("Internal Error: EwaldCalc_PME::Init(): Options were not set up for PME.\n"); + return 1; + } + mprintf("\tParticle Mesh Ewald params:\n"); + if (NBengine_.ModifyEwaldParams().InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: PME calculation init failed.\n"); + return 1; + } + VDW_LR_.SetDebug( debugIn ); + if (Recip_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: PME recip init failed.\n"); + return 1; + } + + return 0; +} + +/** Setup PME calculation. */ +int EwaldCalc_PME::Setup(Topology const& topIn, AtomMask const& maskIn) { + if (NBengine_.ModifyEwaldParams().SetupEwald(topIn, maskIn)) { + mprinterr("Error: PME calculation setup failed.\n"); + return 1; + } + if (VDW_LR_.Setup_VDW_Correction( topIn, maskIn )) { + mprinterr("Error: PME calculation long range VDW correction setup failed.\n"); + return 1; + } + + return 0; +} + +/** Calculate full nonbonded energy with PME */ +int EwaldCalc_PME::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + PairList const& pairList_, ExclusionArray const& Excluded_, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + double volume = frameIn.BoxCrd().CellVolume(); + double e_self = NBengine_.EwaldParams().SelfEnergy( volume ); + + // TODO make more efficient + NBengine_.ModifyEwaldParams().FillRecipCoords( frameIn, maskIn ); + + // FIXME helPME requires coords and charge arrays to be non-const + double e_recip = Recip_.Recip_ParticleMesh( NBengine_.ModifyEwaldParams().SelectedCoords(), + frameIn.BoxCrd(), + NBengine_.ModifyEwaldParams().SelectedCharges(), + NBengine_.EwaldParams().EwaldCoeff() + ); + + double e_vdw_lr_correction = VDW_LR_.Vdw_Correction( NBengine_.EwaldParams().Cutoff(), volume ); + + t_direct_.Start(); + Cpptraj::PairListTemplate(pairList_, Excluded_, + NBengine_.EwaldParams().Cut2(), NBengine_); + t_direct_.Stop(); + + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: Nonbond energy components:\n"); + mprintf(" Evdw = %24.12f\n", NBengine_.Evdw() + e_vdw_lr_correction ); + mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + + NBengine_.Eelec() + + NBengine_.Eadjust()); + mprintf("\n"); + mprintf(" E electrostatic (self) = %24.12f\n", e_self); + mprintf(" (rec) = %24.12f\n", e_recip); + mprintf(" (dir) = %24.12f\n", NBengine_.Eelec()); + mprintf(" (adj) = %24.12f\n", NBengine_.Eadjust()); + mprintf(" E vanDerWaals (dir) = %24.12f\n", NBengine_.Evdw()); + mprintf(" (LR) = %24.12f\n", e_vdw_lr_correction); + } + e_vdw = NBengine_.Evdw() + e_vdw_lr_correction; + e_elec = e_self + e_recip + NBengine_.Eelec() + NBengine_.Eadjust(); + t_total_.Stop(); + return 0; +} + +void EwaldCalc_PME::Timing(double total) const { + t_total_.WriteTiming(1, " PME Total:", total); + Recip_.Timing_Total().WriteTiming(2, "Recip: ", t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +} +#endif /* LIBPME */ diff --git a/src/Energy/EwaldCalc_PME.h b/src/Energy/EwaldCalc_PME.h new file mode 100644 index 0000000000..367a1b2d1b --- /dev/null +++ b/src/Energy/EwaldCalc_PME.h @@ -0,0 +1,29 @@ +#ifndef INC_ENERGY_EWALDCALC_PME_H +#define INC_ENERGY_EWALDCALC_PME_H +#ifdef LIBPME +#include "EwaldCalc.h" +#include "PME_Recip.h" +#include "VDW_LongRange_Correction.h" +#include "../PairListEngine_Ewald_LJLR.h" +namespace Cpptraj { +namespace Energy { +class EwaldCalc_PME : public EwaldCalc { + public: + EwaldCalc_PME(); + /// Init with Box, EwaldOptions and debug level + int Init(Box const&, EwaldOptions const&, int); + int Setup(Topology const&, AtomMask const&); + int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&); + + void Timing(double) const; + private: + PairListEngine_Ewald_LJLR NBengine_; + PME_Recip Recip_; + VDW_LongRange_Correction VDW_LR_; ///< For calculating the long range VDW correction +}; +} +} +#endif +#endif diff --git a/src/Energy/EwaldCalc_Regular.cpp b/src/Energy/EwaldCalc_Regular.cpp new file mode 100644 index 0000000000..788bdaa123 --- /dev/null +++ b/src/Energy/EwaldCalc_Regular.cpp @@ -0,0 +1,100 @@ +#include "EwaldCalc_Regular.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Frame.h" +#include "../PairListTemplate.h" + +using namespace Cpptraj::Energy; + +EwaldCalc_Regular::EwaldCalc_Regular() +{} + +/** Set up regular Ewald parameters. */ +int EwaldCalc_Regular::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (pmeOpts.IsPmeType()) { + mprinterr("Internal Error: EwaldCalc_Regular::Init(): Options were set up for PME only.\n"); + return 1; + } + mprintf("\tRegular Ewald params:\n"); + if (NBengine_.ModifyEwaldParams().InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: Ewald calculation init failed.\n"); + return 1; + } + VDW_LR_.SetDebug( debugIn ); + if (Recip_.InitRecip(pmeOpts, NBengine_.EwaldParams().EwaldCoeff(), boxIn, debugIn)) { + mprinterr("Error: Ewald recip init failed.\n"); + return 1; + } + + return 0; +} + +/** Setup PME calculation. */ +int EwaldCalc_Regular::Setup(Topology const& topIn, AtomMask const& maskIn) { + if (NBengine_.ModifyEwaldParams().SetupEwald(topIn, maskIn)) { + mprinterr("Error: Ewald calculation setup failed.\n"); + return 1; + } + if (VDW_LR_.Setup_VDW_Correction( topIn, maskIn )) { + mprinterr("Error: Ewald calculation long range VDW correction setup failed.\n"); + return 1; + } + if (Recip_.SetupRecip( maskIn.Nselected() )) { + mprinterr("Error: Ewald calculation recip setup failed.\n"); + return 1; + } + + return 0; +} + +/** Calculate full nonbonded energy with regular Ewald */ +int EwaldCalc_Regular::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, + PairList const& pairList_, ExclusionArray const& Excluded_, + double& e_elec, double& e_vdw) +{ + t_total_.Start(); + double volume = frameIn.BoxCrd().CellVolume(); + double e_self = NBengine_.EwaldParams().SelfEnergy( volume ); + + // TODO make more efficient + //NBengine_.ModifyEwaldParams().FillRecipCoords( frameIn, maskIn ); + + double e_recip = Recip_.Recip_Regular( frameIn.BoxCrd().FracCell(), + volume, + pairList_.FracCoords(), + NBengine_.EwaldParams().Charge() ); + + double e_vdw_lr_correction = VDW_LR_.Vdw_Correction( NBengine_.EwaldParams().Cutoff(), volume ); + + t_direct_.Start(); + Cpptraj::PairListTemplate(pairList_, Excluded_, + NBengine_.EwaldParams().Cut2(), NBengine_); + t_direct_.Stop(); + + if (NBengine_.EwaldParams().Debug() > 0) { + mprintf("DEBUG: Nonbond energy components:\n"); + mprintf(" Evdw = %24.12f\n", NBengine_.Evdw() + e_vdw_lr_correction ); + mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + + NBengine_.Eelec() + + NBengine_.Eadjust()); + mprintf("\n"); + mprintf(" E electrostatic (self) = %24.12f\n", e_self); + mprintf(" (rec) = %24.12f\n", e_recip); + mprintf(" (dir) = %24.12f\n", NBengine_.Eelec()); + mprintf(" (adj) = %24.12f\n", NBengine_.Eadjust()); + mprintf(" E vanDerWaals (dir) = %24.12f\n", NBengine_.Evdw()); + mprintf(" (LR) = %24.12f\n", e_vdw_lr_correction); + } + e_vdw = NBengine_.Evdw() + e_vdw_lr_correction; + e_elec = e_self + e_recip + NBengine_.Eelec() + NBengine_.Eadjust(); + t_total_.Stop(); + return 0; +} + +void EwaldCalc_Regular::Timing(double total) const { + t_total_.WriteTiming(1, " Ewald Total:", total); + Recip_.PrintTiming(t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +} diff --git a/src/Energy/EwaldCalc_Regular.h b/src/Energy/EwaldCalc_Regular.h new file mode 100644 index 0000000000..d7bde906d0 --- /dev/null +++ b/src/Energy/EwaldCalc_Regular.h @@ -0,0 +1,28 @@ +#ifndef INC_ENERGY_EWALDCALC_REGULAR_H +#define INC_ENERGY_EWALDCALC_REGULAR_H +#include "EwaldCalc.h" +#include "Ewald_Recip.h" +#include "VDW_LongRange_Correction.h" +#include "../PairListEngine_Ewald_LJLR.h" +namespace Cpptraj { +namespace Energy { +class EwaldCalc_Regular : public EwaldCalc { + public: + EwaldCalc_Regular(); + /// Init with Box, EwaldOptions and debug level + int Init(Box const&, EwaldOptions const&, int); + int Setup(Topology const&, AtomMask const&); + int CalcNonbondEnergy(Frame const&, AtomMask const&, + PairList const&, ExclusionArray const&, + double&, double&); + + void Timing(double) const; + private: + PairListEngine_Ewald_LJLR NBengine_; + Ewald_Recip Recip_; + VDW_LongRange_Correction VDW_LR_; ///< For calculating the long range VDW correction +}; +} +} + +#endif diff --git a/src/Energy/EwaldParams.cpp b/src/Energy/EwaldParams.cpp new file mode 100644 index 0000000000..c52a410669 --- /dev/null +++ b/src/Energy/EwaldParams.cpp @@ -0,0 +1,205 @@ +#include "EwaldParams.h" +#include "../Box.h" +#include "../Constants.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Topology.h" + +using namespace Cpptraj::Energy; + +const double EwaldParams::INVSQRTPI_ = 1.0 / sqrt(Constants::PI); + +/** CONSTRUCTOR */ +EwaldParams::EwaldParams() : + ew_coeff_(0.0), + switch_width_(0.0), + cutoff_(0.0), + cut2_(0.0), + cut2_0_(0.0), + dsumTol_(0.0), + debug_(0), + NB_(0), + sumq_(0), + sumq2_(0) +{} + + +/** Determine Ewald coefficient from cutoff and direct sum tolerance. + * Original Code: SANDER: findewaldcof + */ +double EwaldParams::FindEwaldCoefficient(double cutoff, double dsum_tol) +{ + // First get direct sum tolerance. How big must the Ewald coefficient be to + // get terms outside the cutoff below tolerance? + double xval = 0.5; + int nloop = 0; + double term = 0.0; + do { + xval = 2.0 * xval; + nloop++; + double yval = xval * cutoff; + term = ErfcFxn::erfc_func(yval) / cutoff; + } while (term >= dsum_tol); + + // Binary search tolerance is 2^-50 + int ntimes = nloop + 50; + double xlo = 0.0; + double xhi = xval; + for (int i = 0; i != ntimes; i++) { + xval = (xlo + xhi) / 2.0; + double yval = xval * cutoff; + double term = ErfcFxn::erfc_func(yval) / cutoff; + if (term >= dsum_tol) + xlo = xval; + else + xhi = xval; + } + mprintf("\t Ewald coefficient determined using cut=%g, direct sum tol=%g is %g\n", + cutoff, dsum_tol, xval); + return xval; +} + +/** Check some common input. */ +int EwaldParams::CheckInput(Box const& boxIn, int debugIn, double cutoffIn, double dsumTolIn, + double ew_coeffIn, double switch_widthIn, double erfcTableDxIn, double skinnbIn) +{ + debug_ = debugIn; + cutoff_ = cutoffIn; + dsumTol_ = dsumTolIn; + ew_coeff_ = ew_coeffIn; + switch_width_ = switch_widthIn; + double erfcTableDx = erfcTableDxIn; + // Check input + if (cutoff_ < Constants::SMALL) { + mprinterr("Error: Direct space cutoff (%g) is too small.\n", cutoff_); + return 1; + } + char dir[3] = {'X', 'Y', 'Z'}; + // NOTE: First 3 box parameters are X Y Z + for (int i = 0; i < 3; i++) { + if (cutoff_ > boxIn.Param((Box::ParamType)i)/2.0) { + mprinterr("Error: Cutoff must be less than half the box length (%g > %g, %c)\n", + cutoff_, boxIn.Param((Box::ParamType)i)/2.0, dir[i]); + return 1; + } + } + if (skinnbIn < 0.0) { + mprinterr("Error: skinnb is less than 0.0\n"); + return 1; + } + if (switch_width_ < 0.0) switch_width_ = 0.0; + if (switch_width_ > cutoff_) { + mprinterr("Error: Switch width must be less than the cutoff.\n"); + return 1; + } + + // Set defaults if necessary + if (dsumTol_ < Constants::SMALL) + dsumTol_ = 1E-5; + if (DABS(ew_coeff_) < Constants::SMALL) + ew_coeff_ = FindEwaldCoefficient( cutoff_, dsumTol_ ); + if (erfcTableDx <= 0.0) erfcTableDx = 1.0 / 5000; + // TODO make this optional + if (erfc_.FillErfcTable( erfcTableDx, 0.0, cutoff_*ew_coeff_*1.5 )) { + mprinterr("Error: Could not set up spline table for ERFC\n"); + return 1; + } + + // Calculate some common factors. + cut2_ = cutoff_ * cutoff_; + double cut0 = cutoff_ - switch_width_; + cut2_0_ = cut0 * cut0; + + return 0; +} + +/** Initialize */ +int EwaldParams::InitEwald(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + if (CheckInput(boxIn, debugIn, pmeOpts.Cutoff(), pmeOpts.DsumTol(), pmeOpts.EwCoeff(), + pmeOpts.LJ_SwWidth(), pmeOpts.ErfcDx(), pmeOpts.SkinNB())) + return 1; + mprintf("\t Cutoff= %g Direct Sum Tol= %g Ewald coeff.= %g NB skin= %g\n", + Cutoff(), DirectSumTol(), EwaldCoeff(), pmeOpts.SkinNB()); + if (LJ_SwitchWidth() > 0.0) + mprintf("\t LJ switch width= %g\n", LJ_SwitchWidth()); + //mprintf("\t Erfc table dx= %g, size= %zu\n", erfcTableDx_, erfc_table_.size()/4); + return 0; +} + +/** Reserve space for selected atoms */ +void EwaldParams::reserveRecipCoords(AtomMask const& maskIn) { + coordsD_.reserve( maskIn.Nselected()*3 ); +} + +/** Fill recip coords with XYZ coords of selected atoms. */ +void EwaldParams::FillRecipCoords(Frame const& frameIn, AtomMask const& maskIn) +{ + coordsD_.clear(); + for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm) { + const double* XYZ = frameIn.XYZ( *atm ); + coordsD_.push_back( XYZ[0] ); + coordsD_.push_back( XYZ[1] ); + coordsD_.push_back( XYZ[2] ); + } +} + +/** Convert charges to Amber units. Calculate sum of charges and squared charges. + * Store LJ type indices for selected atoms. + */ +int EwaldParams::SetupEwald(Topology const& topIn, AtomMask const& maskIn) { + NB_ = static_cast( &(topIn.Nonbond()) ); + + sumq_ = 0.0; + sumq2_ = 0.0; + Charge_.clear(); + Charge_.reserve( maskIn.Nselected() ); + TypeIndices_.clear(); + TypeIndices_.reserve( maskIn.Nselected() ); + for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) { + double qi = topIn[*atom].Charge() * Constants::ELECTOAMBER; + Charge_.push_back(qi); + sumq_ += qi; + sumq2_ += (qi * qi); + // Store atom type indices for selected atoms. + TypeIndices_.push_back( topIn[*atom].TypeIndex() ); + } + //mprintf("DEBUG: sumq= %20.10f sumq2= %20.10f\n", sumq_, sumq2_); + //Setup_VDW_Correction( topIn, maskIn ); + reserveRecipCoords(maskIn); + return 0; +} + +/** Electrostatic self energy. This is the cancelling Gaussian plus the "neutralizing plasma". */ +double EwaldParams::SelfEnergy(double volume) const { +// t_self_.Start(); + double d0 = -ew_coeff_ * INVSQRTPI_; + double ene = sumq2_ * d0; +// mprintf("DEBUG: d0= %20.10f ene= %20.10f\n", d0, ene); + double factor = Constants::PI / (ew_coeff_ * ew_coeff_ * volume); + double ee_plasma = -0.5 * factor * sumq_ * sumq_; + ene += ee_plasma; +// t_self_.Stop(); + return ene; +} + +/** Electrostatic self energy on each atom. */ +double EwaldParams::DecomposedSelfEnergy(Darray& atom_self, double volume) const { + double d0 = -ew_coeff_ * INVSQRTPI_; + double ene = sumq2_ * d0; +// mprintf("DEBUG: d0= %20.10f ene= %20.10f\n", d0, ene); + double factor = Constants::PI / (ew_coeff_ * ew_coeff_ * volume); + double ee_plasma = -0.5 * factor * sumq_ * sumq_; + + atom_self.resize( Charge_.size() ); + + // Distribute the "neutrilizing plasma" to atoms equally + for (unsigned int i = 0; i < Charge_.size(); i++) + { + atom_self[i] = Charge_[i]*Charge_[i]*d0 + ee_plasma/Charge_.size(); + //mprintf("DEBUG: Self energy atom %i = %f\n", i+1, atom_self[i]); + } + + ene += ee_plasma; + return ene; +} diff --git a/src/Energy/EwaldParams.h b/src/Energy/EwaldParams.h new file mode 100644 index 0000000000..efdd4fb451 --- /dev/null +++ b/src/Energy/EwaldParams.h @@ -0,0 +1,112 @@ +#ifndef INC_ENERGY_EWALDPARAMS_H +#define INC_ENERGY_EWALDPARAMS_H +#include "ErfcFxn.h" +#include "../ParameterTypes.h" // NonbondParmType +class AtomMask; +class Box; +class EwaldOptions; +class Frame; +class Topology; +namespace Cpptraj { +namespace Energy { +/// Parameters common to all Ewald methods +class EwaldParams { + static const double INVSQRTPI_; + public: + EwaldParams(); + // Virtual since inherited + virtual ~EwaldParams() {} + // ------------------------------------------- + virtual int InitEwald(Box const&, EwaldOptions const&, int); + virtual int SetupEwald(Topology const&, AtomMask const&); + // ------------------------------------------- + + /// Fill recip coords with XYZ coords of selected atoms. + void FillRecipCoords(Frame const&, AtomMask const&); + /// \return ERFC value of given distance times the Ewald coefficient + double ErfcEW(double rIn) const { return erfc_.ErfcInterpolated( ew_coeff_*rIn ); } + /// \return LJ switch fn value + double Switch_Fn(double rij2) const { + double cut2_1 = cut2_; + if (rij2 <= cut2_0_) + return 1.0; + else if (rij2 > cut2_1) + return 0.0; + else { + double xoff_m_x = cut2_1 - rij2; + double fac = 1.0 / (cut2_1 - cut2_0_); + return (xoff_m_x*xoff_m_x) * (cut2_1 + 2.0*rij2 - 3.0*cut2_0_) * (fac*fac*fac); + } + } + /// \return Self energy for the given volume + double SelfEnergy(double) const; + /// \return Self energy for given volume. Set self energy for each atom. + double DecomposedSelfEnergy(std::vector&, double) const; + + /// \return Direct space cutoff (in Ang squared) + double Cut2() const { return cut2_; } + /// \return Charge for given atom index + double Charge(int idx) const { return Charge_[idx]; } + /// \return Nonbonded index for given atom indices + int NbIndex(int idx0, int idx1) const { return NB_->GetLJindex(TypeIndices_[idx0], TypeIndices_[idx1]); } + /// \return Nonbonded parameter at nonobonded parameter index + NonbondType const& GetLJ(int nbindex) const { return NB_->NBarray()[ nbindex ]; } + /// \return Number of atoms (current size of charge array) + unsigned int Natom() const { return Charge_.size(); } + + /// \return Debug level + int Debug() const { return debug_; } + /// \return Direct space cutoff (in Ang) + double Cutoff() const { return cutoff_; } + /// \return Direct sum tolerance + double DirectSumTol() const { return dsumTol_; } + /// \return Ewald coefficient + double EwaldCoeff() const { return ew_coeff_; } + /// \return LJ switch width (in Ang.) + double LJ_SwitchWidth() const { return switch_width_; } + /// \return 1 / sqrt(PI) + static const double INVSQRTPI() { return INVSQRTPI_; } + /// \return Charge array + std::vector const& Charge() const { return Charge_; } + + // FIXME do not return const because helPME needs the array to be non-const. Should be fixed + std::vector& SelectedCharges() { return Charge_; } + // FIXME do not return const because helPME needs the array to be non-const. Should be fixed + std::vector& SelectedCoords() { return coordsD_; } + + // FIXME these can probably go away after GIST_PME is converted + double SumQ() const { return sumq_; } + double SumQ2() const { return sumq2_; } + protected: + typedef std::vector Darray; + typedef std::vector Iarray; + + static inline double DABS(double xIn) { if (xIn < 0.0) return -xIn; else return xIn; } + /// Set Ewald parametsr, check them and set defaults if needed. + int CheckInput(Box const&, int, double, double, + double, double, double, double); + private: + double FindEwaldCoefficient(double, double); + /// Reserve space for selected coordinates for recip calcs + void reserveRecipCoords(AtomMask const&); + + double ew_coeff_; ///< Ewald coefficient + double switch_width_; ///< Switching window size for LJ switch if active + double cutoff_; ///< Direct space cutoff + double cut2_; ///< Direct space cutoff squared. + double cut2_0_; ///< Direct space cutoff minus switch width, squared. + double dsumTol_; ///< Direct space sum tolerance. + int debug_; + + ErfcFxn erfc_; ///< Hold spline interpolation for erfc + + Darray coordsD_; ///< Hold selected coords for recip calcs + Darray Charge_; ///< Hold charges for selected atoms + Iarray TypeIndices_; ///< Hold atom type indices for selected atoms + NonbondParmType const* NB_; ///< Pointer to nonbonded parameters + double sumq_; ///< Sum of charges + double sumq2_; ///< Sum of charges squared +}; +} +} +#endif diff --git a/src/Energy/EwaldParams_LJPME.cpp b/src/Energy/EwaldParams_LJPME.cpp new file mode 100644 index 0000000000..9014387a93 --- /dev/null +++ b/src/Energy/EwaldParams_LJPME.cpp @@ -0,0 +1,79 @@ +#include "EwaldParams_LJPME.h" +#include "../AtomMask.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Topology.h" + +using namespace Cpptraj::Energy; + +/** CONSTRUCTOR */ +EwaldParams_LJPME::EwaldParams_LJPME() : + lw_coeff_(0.0), + ljpme_self_(0.0) +{} + +/** Set up LJPME parameters. */ +int EwaldParams_LJPME::InitEwald(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + if (EwaldParams::InitEwald(boxIn, pmeOpts, debugIn)) return 1; + + lw_coeff_ = pmeOpts.LwCoeff(); + + // TODO do for C6 as well + // TODO for C6 correction term + if (lw_coeff_ < 0.0) { + mprinterr("Internal Error: LJ PME requested but LJ Ewald coefficient is < 0\n"); + return 1; + } + // lw_coeff_ = 0.0; + //else + if (DABS(lw_coeff_) < Constants::SMALL) + lw_coeff_ = EwaldCoeff(); + + if (LJ_EwaldCoeff() > 0.0) + mprintf("\t LJ Ewald coeff.= %g\n", LJ_EwaldCoeff()); + return 0; +} + +/** Setup LJPME calculation. */ +int EwaldParams_LJPME::SetupEwald(Topology const& topIn, AtomMask const& maskIn) { + if (EwaldParams::SetupEwald(topIn, maskIn)) return 1; + + // Calcuate C6 parameters + if (lw_coeff_ > 0.0) { + for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) + { + double rmin = topIn.GetVDWradius( *atom ); + double eps = topIn.GetVDWdepth( *atom ); + Cparam_.push_back( 8.0 * (rmin*rmin*rmin) * sqrt(2 * eps) ); + if (Debug() > 0) + mprintf("DEBUG: C6 param atom %8i = %16.8f\n", *atom+1, Cparam_.back()); + } + } else { + mprinterr("Internal Error: LJ PME setup called with LJ Ewald coefficient <= 0\n"); + return 1; + } + // Lennard-Jones self energy. (used to be Ewald::Self6()) + double ew2 = lw_coeff_ * lw_coeff_; + double ew6 = ew2 * ew2 * ew2; + double c6sum = 0.0; + for (Darray::const_iterator it = Cparam_.begin(); it != Cparam_.end(); ++it) + c6sum += ew6 * (*it * *it); + ljpme_self_ = c6sum / 12.0; + + return 0; +} + +/** Calculate decomposed self6 energies. */ +void EwaldParams_LJPME::CalcDecomposedSelf6Energy() { + atom_vdwself6_.clear(); + atom_vdwself6_.reserve( Cparam_.size() ); + double ew2 = lw_coeff_ * lw_coeff_; + double ew6 = ew2 * ew2 * ew2; + double c6sum = 0.0; + for (Darray::const_iterator it = Cparam_.begin(); it != Cparam_.end(); ++it) + { + c6sum += ew6 * (*it * *it); + atom_vdwself6_.push_back(ew6 * (*it * *it)/12.0); + } +} diff --git a/src/Energy/EwaldParams_LJPME.h b/src/Energy/EwaldParams_LJPME.h new file mode 100644 index 0000000000..a0eea59e5f --- /dev/null +++ b/src/Energy/EwaldParams_LJPME.h @@ -0,0 +1,36 @@ +#ifndef INC_ENERGY_EWALDPARAMS_LJPME_H +#define INC_ENERGY_EWALDPARAMS_LJPME_H +#include "EwaldParams.h" +namespace Cpptraj { +namespace Energy { +class EwaldParams_LJPME : public EwaldParams { + public: + EwaldParams_LJPME(); + + int InitEwald(Box const&, EwaldOptions const&, int); + int SetupEwald(Topology const&, AtomMask const&); + + /// \return LJ Ewald coefficient + double LJ_EwaldCoeff() const { return lw_coeff_; } + + /// \return LJPME self energy + double Self6() const { return ljpme_self_; } + /// \return C6 parameter pair for specified selected atoms + double CalcCij(int idx0, int idx1) const { return (Cparam_[idx0] * Cparam_[idx1]); } + /// Calculate decomposed LJPME self energy + void CalcDecomposedSelf6Energy(); + /// \return Array containing LJPME self energy decomposed by atom + std::vector const& Atom_Self6Energies() const { return atom_vdwself6_; } + + + // FIXME do not return const because helPME needs the array to be non-const. Should be fixed + std::vector& SelectedC6params() { return Cparam_; } + private: + Darray Cparam_; ///< Hold selected atomic C6 coefficients for LJ PME + double lw_coeff_; ///< LJ Ewald coefficient + double ljpme_self_; ///< LJ PME self energy calculated from C6 parameters and LJ Ewald coeff. + Darray atom_vdwself6_; ///< LJ PME self energy decomposed by atom +}; +} +} +#endif diff --git a/src/Ewald_Regular.cpp b/src/Energy/Ewald_Recip.cpp similarity index 72% rename from src/Ewald_Regular.cpp rename to src/Energy/Ewald_Recip.cpp index b03b263dcd..b9e9ac5f22 100644 --- a/src/Ewald_Regular.cpp +++ b/src/Energy/Ewald_Recip.cpp @@ -1,21 +1,31 @@ -#include // copy/fill/min/max -#include -#include "Ewald_Regular.h" -#include "CpptrajStdio.h" -#include "Constants.h" -#include "StringRoutines.h" // ByteString -#include "AtomMask.h" -#include "Frame.h" -#include "EwaldOptions.h" +#include "Ewald_Recip.h" +#include "ErfcFxn.h" // erfc_func +#include "EwaldParams.h" // INVSQRTPI +#include "../Box.h" +#include "../Constants.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" +#include "../Matrix_3x3.h" +#include "../StringRoutines.h" // ByteString +#include "../Vec3.h" +#include // sqrt, cos, sin +#include // std::max #ifdef _OPENMP # include -#endif +#endif -/// CONSTRUCTOR -Ewald_Regular::Ewald_Regular() : +using namespace Cpptraj::Energy; + +// Absolute value functions +static inline int IABS( int xIn) { if (xIn < 0 ) return -xIn; else return xIn; } +static inline double DABS(double xIn) { if (xIn < 0 ) return -xIn; else return xIn; } + +/** CONSTRUCTOR */ +Ewald_Recip::Ewald_Recip() : # ifdef _OPENMP multCut_(0), # endif + fac_(0.0), maxexp_(0.0), rsumTol_(0.0), maxmlim_(0) @@ -26,7 +36,7 @@ Ewald_Regular::Ewald_Regular() : } /** \return maxexp value based on mlimits */ -double Ewald_Regular::FindMaxexpFromMlim(const int* mlimit, Matrix_3x3 const& recip) { +double Ewald_Recip::FindMaxexpFromMlim(const int* mlimit, Matrix_3x3 const& recip) { double maxexp = DABS( (double)mlimit[0] * recip[0] ); double z2 = DABS( (double)mlimit[1] * recip[4] ); maxexp = std::max(maxexp, z2); @@ -36,7 +46,7 @@ double Ewald_Regular::FindMaxexpFromMlim(const int* mlimit, Matrix_3x3 const& re } /** \return maxexp value based on Ewald coefficient and reciprocal sum tolerance. */ -double Ewald_Regular::FindMaxexpFromTol(double ewCoeff, double rsumTol) { +double Ewald_Recip::FindMaxexpFromTol(double ewCoeff, double rsumTol) { double xval = 0.5; int nloop = 0; double term = 0.0; @@ -44,7 +54,7 @@ double Ewald_Regular::FindMaxexpFromTol(double ewCoeff, double rsumTol) { xval = 2.0 * xval; nloop++; double yval = Constants::PI * xval / ewCoeff; - term = 2.0 * ewCoeff * erfc_func(yval) * INVSQRTPI_; + term = 2.0 * ewCoeff * ErfcFxn::erfc_func(yval) * EwaldParams::INVSQRTPI(); } while (term >= rsumTol); // Binary search tolerance is 2^-60 @@ -54,21 +64,20 @@ double Ewald_Regular::FindMaxexpFromTol(double ewCoeff, double rsumTol) { for (int i = 0; i != ntimes; i++) { xval = (xlo + xhi) / 2.0; double yval = Constants::PI * xval / ewCoeff; - double term = 2.0 * ewCoeff * erfc_func(yval) * INVSQRTPI_; + double term = 2.0 * ewCoeff * ErfcFxn::erfc_func(yval) * EwaldParams::INVSQRTPI(); if (term > rsumTol) xlo = xval; else xhi = xval; } - mprintf("\tMaxExp for Ewald coefficient %g, direct sum tol %g is %g\n", + mprintf("\t MaxExp determined from Ewald coefficient %g, direct sum tol %g is %g\n", ewCoeff, rsumTol, xval); return xval; } -static inline int IABS(int xIn) { if (xIn < 0 ) return -xIn; else return xIn; } /** Get mlimits. */ -void Ewald_Regular::GetMlimits(int* mlimit, double maxexp, double eigmin, +void Ewald_Recip::GetMlimits(int* mlimit, double maxexp, double eigmin, Vec3 const& reclng, Matrix_3x3 const& recip) { //mprintf("DEBUG: Recip lengths %12.4f%12.4f%12.4f\n", reclng[0], reclng[1], reclng[2]); @@ -95,25 +104,17 @@ void Ewald_Regular::GetMlimits(int* mlimit, double maxexp, double eigmin, } } } - mprintf("\tNumber of reciprocal vectors: %i\n", nrecvecs); + mprintf("\t Number of reciprocal vectors: %i\n", nrecvecs); } -/** Init regular Ewald calculation. */ -int Ewald_Regular::Init(Box const& boxIn, EwaldOptions const& ewOpts, int debugIn) -//double cutoffIn, double dsumTolIn, double rsumTolIn, -// double ew_coeffIn, double maxexpIn, double skinnbIn, -// double erfcTableDxIn, int debugIn, const int* mlimitsIn) +/** Init */ +int Ewald_Recip::InitRecip(EwaldOptions const& ewOpts, double ew_coeffIn, + Box const& boxIn, int debugIn) { - if (ewOpts.Type() == EwaldOptions::PME) { - mprinterr("Internal Error: Ewald options set up for PME\n"); - return 1; - } - if (CheckInput(boxIn, debugIn, ewOpts.Cutoff(), ewOpts.DsumTol(), ewOpts.EwCoeff(), - -1.0, ewOpts.LJ_SwWidth(), - ewOpts.ErfcDx(), ewOpts.SkinNB())) - return 1; + debug_ = debugIn; rsumTol_ = ewOpts.RsumTol(); maxexp_ = ewOpts.MaxExp(); + fac_ = (Constants::PI*Constants::PI) / (ew_coeffIn * ew_coeffIn); mlimit_[0] = ewOpts.Mlimits1(); mlimit_[1] = ewOpts.Mlimits2(); mlimit_[2] = ewOpts.Mlimits3(); @@ -132,13 +133,14 @@ int Ewald_Regular::Init(Box const& boxIn, EwaldOptions const& ewOpts, int debugI } // Set defaults if necessary + mprintf("\tRecip opts (regular Ewald):\n"); if (rsumTol_ < Constants::SMALL) rsumTol_ = 5E-5; if (maxmlim_ > 0) maxexp_ = FindMaxexpFromMlim(mlimit_, boxIn.FracCell()); else { if ( maxexp_ < Constants::SMALL ) - maxexp_ = FindMaxexpFromTol(ew_coeff_, rsumTol_); + maxexp_ = FindMaxexpFromTol(ew_coeffIn, rsumTol_); // eigmin typically bigger than this unless cell is badly distorted. double eigmin = 0.5; // Calculate lengths of reciprocal vectors @@ -148,31 +150,25 @@ int Ewald_Regular::Init(Box const& boxIn, EwaldOptions const& ewOpts, int debugI maxmlim_ = std::max(maxmlim_, mlimit_[2]); } - mprintf("\tEwald params:\n"); - mprintf("\t Cutoff= %g Direct Sum Tol= %g Ewald coeff.= %g\n", - cutoff_, dsumTol_, ew_coeff_); - mprintf("\t MaxExp= %g Recip. Sum Tol= %g NB skin= %g\n", - maxexp_, rsumTol_, ewOpts.SkinNB()); - //mprintf("\t Erfc table dx= %g, size= %zu\n", erfcTableDx_, erfc_table_.size()/4); - mprintf("\t mlimits= {%i,%i,%i} Max=%i\n", mlimit_[0], mlimit_[1], mlimit_[2], maxmlim_); - // Set up pair list - if (Setup_Pairlist(boxIn, ewOpts.SkinNB())) return 1; - + PrintRecipOpts(); return 0; } -/** Setup regular Ewald calculation. */ -int Ewald_Regular::Setup(Topology const& topIn, AtomMask const& maskIn) { - CalculateCharges(topIn, maskIn); - // Blank C6 Arrays. TODO actually blank them - CalculateC6params( topIn, maskIn ); +/** Print options to stdout */ +void Ewald_Recip::PrintRecipOpts() const { + mprintf("\t MaxExp= %g Recip. Sum Tol= %g\n", maxexp_, rsumTol_); + //mprintf("\t Erfc table dx= %g, size= %zu\n", erfcTableDx_, erfc_table_.size()/4); + mprintf("\t mlimits= {%i,%i,%i} Max=%i\n", mlimit_[0], mlimit_[1], mlimit_[2], maxmlim_); +} +/** Setup trig tables for given number of selected atoms. */ +int Ewald_Recip::SetupRecip(int nselected) { // Build exponential factors for use in structure factors. // These arrays are laid out in 1D; value for each atom at each m, i.e. // A0M0 A1M0 A2M0 ... ANM0 A0M1 ... ANMX // Number of M values is the max + 1. int mmax = maxmlim_ + 1; - unsigned int tsize = maskIn.Nselected() * mmax; + unsigned int tsize = nselected * mmax; cosf1_.assign( tsize, 1.0 ); cosf2_.assign( tsize, 1.0 ); cosf3_.assign( tsize, 1.0 ); @@ -190,9 +186,6 @@ int Ewald_Regular::Setup(Topology const& topIn, AtomMask const& maskIn) { // sinf2_.push_back( 0.0 ); // sinf3_.push_back( 0.0 ); // } - - SetupExclusionList(topIn, maskIn); - # ifdef _OPENMP // Pre-calculate m1 and m2 indices mlim1_.clear(); @@ -217,27 +210,28 @@ int Ewald_Regular::Setup(Topology const& topIn, AtomMask const& maskIn) { mprintf("\tParallelizing calculation with %i threads\n", numthreads); } } - unsigned int asize = (unsigned int)maskIn.Nselected() * (unsigned int)numthreads; + unsigned int asize = (unsigned int)nselected * (unsigned int)numthreads; c12_.resize( asize ); s12_.resize( asize ); c3_.resize( asize ); s3_.resize( asize ); -#else - c12_.resize( maskIn.Nselected() ); - s12_.resize( maskIn.Nselected() ); - c3_.resize( maskIn.Nselected() ); - s3_.resize( maskIn.Nselected() ); -# endif +#else /* _OPENMP */ + c12_.resize( nselected ); + s12_.resize( nselected ); + c3_.resize( nselected ); + s3_.resize( nselected ); +# endif /* _OPENMP */ + return 0; } /** Reciprocal space energy counteracting the neutralizing charge distribution. */ -double Ewald_Regular::Recip_Regular(Matrix_3x3 const& recip, double volume) { +double Ewald_Recip::Recip_Regular(Matrix_3x3 const& recip, double volume, + Varray const& Frac, Darray const& Charge) +{ t_recip_.Start(); - double fac = (Constants::PI*Constants::PI) / (ew_coeff_ * ew_coeff_); double maxexp2 = maxexp_ * maxexp_; double ene = 0.0; - Varray const& Frac = pairList_.FracCoords(); // Number of M values is the max + 1. int mmax = maxmlim_ + 1; // Build exponential factors for use in structure factors. @@ -339,7 +333,7 @@ double Ewald_Regular::Recip_Regular(Matrix_3x3 const& recip, double volume) { double eterm = 0.0; // double vterm = 0.0; if ( m1*m1 + m2*m2 + m3*m3 > 0 ) { - eterm = exp(-fac*msq) / denom; + eterm = exp(-fac_*msq) / denom; // vterm = 2.0 * (fac*msq + 1.0) / msq; } // mult takes care to double count for symmetry. Can take care of @@ -363,8 +357,8 @@ double Ewald_Regular::Recip_Regular(Matrix_3x3 const& recip, double volume) { double cstruct = 0.0; double sstruct = 0.0; for (unsigned int i = 0; i != Frac.size(); i++) { - cstruct += Charge_[i] * c3[i]; - sstruct += Charge_[i] * s3[i]; + cstruct += Charge[i] * c3[i]; + sstruct += Charge[i] * s3[i]; } double struc2 = cstruct*cstruct + sstruct*sstruct; ene += eterm * struc2; @@ -383,30 +377,8 @@ double Ewald_Regular::Recip_Regular(Matrix_3x3 const& recip, double volume) { return ene * 0.5; } -/** Calculate Ewald energy. Faster version that uses pair list. */ -int Ewald_Regular::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, - double& e_elec, double& e_vdw) -{ - t_total_.Start(); - double volume = frameIn.BoxCrd().CellVolume(); - double e_self = Self( volume ); - double e_vdwr = Vdw_Correction( volume ); - - int retVal = pairList_.CreatePairList(frameIn, frameIn.BoxCrd().UnitCell(), frameIn.BoxCrd().FracCell(), maskIn); - if (retVal != 0) { - mprinterr("Error: Grid setup failed.\n"); - return 1; - } - -// MapCoords(frameIn, ucell, recip, maskIn); - double e_recip = Recip_Regular( frameIn.BoxCrd().FracCell(), volume ); - e_vdw = 0.0; - double e_adjust = 0.0; - double e_direct = Direct( pairList_, e_vdw, e_adjust ); - if (debug_ > 0) - mprintf("DEBUG: Eself= %20.10f Erecip= %20.10f Edirect= %20.10f Eadjust= %20.10f Evdw= %20.10f\n", e_self, e_recip, e_direct, e_adjust, e_vdw); - e_vdw += e_vdwr; - t_total_.Stop(); - e_elec = e_self + e_recip + e_direct + e_adjust; - return 0; +void Ewald_Recip::PrintTiming(double total) const { + t_recip_.WriteTiming(2, "Recip: ", total); + if (t_trig_tables_.Total() > 0.0) + t_trig_tables_.WriteTiming(3, "Calc trig tables:", t_recip_.Total()); } diff --git a/src/Ewald_Regular.h b/src/Energy/Ewald_Recip.h similarity index 50% rename from src/Ewald_Regular.h rename to src/Energy/Ewald_Recip.h index bd38662dda..cd7ca77bf2 100644 --- a/src/Ewald_Regular.h +++ b/src/Energy/Ewald_Recip.h @@ -1,28 +1,40 @@ -#ifndef INC_EWALD_REGULAR_H -#define INC_EWALD_REGULAR_H -#include "Ewald.h" -/// Calculate regular Ewald energy -class Ewald_Regular : public Ewald { +#ifndef INC_ENERGY_EWALD_RECIP_H +#define INC_ENERGY_EWALD_RECIP_H +#include +#include "../Timer.h" +class Box; +class EwaldOptions; +class Matrix_3x3; +class Vec3; +namespace Cpptraj { +namespace Energy { +/// For calculating reciprocal space energy using the "regular" Ewald summation +class Ewald_Recip { public: - Ewald_Regular(); - /// Box, cutoff, dsum tol, rsum tol, ew coeff, maxexp, nb skin, erfc dx, debug, mlimits - /*int Init(Box const&, double, double, double, double, double, double, - double, int, const int*);*/ - // ----- Inherited --------------------------- - int Init(Box const&, EwaldOptions const&, int); - int Setup(Topology const&, AtomMask const&); - int CalcNonbondEnergy(Frame const&, AtomMask const&, double&, double&); + typedef std::vector Darray; + typedef std::vector Varray; + + Ewald_Recip(); + + /// Init with options, Ewald coeff, box, debug + int InitRecip(EwaldOptions const&, double, Box const&, int); + /// Set up trig tables for the given number of selected atoms + int SetupRecip(int); + /// Regular Ewald recip energy (fractional cell vecs, volume, frac coords, charges) + double Recip_Regular(Matrix_3x3 const&, double, Varray const&, Darray const&); + /// Print timing + void PrintTiming(double) const; private: + /// print options to stdout + void PrintRecipOpts() const; + /// Determine max length for reciprocal calcs based on reciprocal limits static double FindMaxexpFromMlim(const int*, Matrix_3x3 const&); /// Determine max length for reciprocal calcs based on Ewald coefficient and recip tol. static double FindMaxexpFromTol(double, double); /// Determine reciprocal limits based on unit cell reciprocal vectors static void GetMlimits(int*, double, double, Vec3 const&, Matrix_3x3 const&); - /// Ewald reciprocal energy - double Recip_Regular(Matrix_3x3 const&, double); - typedef Ewald::Darray Darray; // Hold trig tables Darray cosf1_; Darray cosf2_; @@ -35,14 +47,21 @@ class Ewald_Regular : public Ewald { Darray c3_; Darray s3_; # ifdef _OPENMP - typedef Ewald::Iarray Iarray; + typedef std::vector Iarray; Iarray mlim1_; ///< Hold m1 reciprocal indices Iarray mlim2_; ///< Hold m2 reciprocal indices int multCut_; ///< Hold index after which multiplier should be 2.0. # endif + double fac_; ///< Hold (PI^2) / (Ewald coefficient)^2 double maxexp_; ///< Determines how far out recip vectors go? TODO check! double rsumTol_; ///< Reciprocal space sum tolerance. - int mlimit_[3]; ///< Number of units in each direction to calc recip. sum. / nfft - int maxmlim_; ///< The max of the three mlimit_ values. / pme spline order -}; + int mlimit_[3]; ///< Number of units in each direction to calc recip. sum. + int maxmlim_; ///< The max of the three mlimit_ values. + int debug_; + + Timer t_recip_; ///< Recip calc timer + Timer t_trig_tables_; ///< Trig tables calc timer +}; +} +} #endif diff --git a/src/Energy/Kernel_EwaldAdjust.h b/src/Energy/Kernel_EwaldAdjust.h new file mode 100644 index 0000000000..f4f51ab4ef --- /dev/null +++ b/src/Energy/Kernel_EwaldAdjust.h @@ -0,0 +1,13 @@ +#ifndef INC_KERNEL_EWALDADJUST_H +#define INC_KERNEL_EWALDADJUST_H +namespace Cpptraj { +namespace Energy { +/// Used to adjust Ewald energy for excluded atoms +template T Kernel_EwaldAdjust(T const& q0, T const& q1, T const& rij, T const& erfcval) +{ + T d0 = (erfcval - 1.0) / rij; + return (q0 * q1 * d0); +} +} +} +#endif diff --git a/src/Energy/Kernel_LJPME_Adjust.h b/src/Energy/Kernel_LJPME_Adjust.h new file mode 100644 index 0000000000..6569bdd0a6 --- /dev/null +++ b/src/Energy/Kernel_LJPME_Adjust.h @@ -0,0 +1,21 @@ +#ifndef INC_KERNEL_LJPME_ADJUST_H +#define INC_KERNEL_LJPME_ADJUST_H +namespace Cpptraj { +namespace Energy { +/// Used to adjust LJPME energy for excluded atoms +template T Kernel_LJPME_Adjust(T const& rij2, T const& lj_ewcoeff, T const& Cij) +{ + // LJ PME direct space exclusion correction + // NOTE: Assuming excluded pair is within cutoff + T kr2 = lj_ewcoeff * lj_ewcoeff * rij2; + T kr4 = kr2 * kr2; + //double kr6 = kr2 * kr4; + T expterm = exp(-kr2); + T r4 = rij2 * rij2; + T r6 = rij2 * r4; + //T Cij = EW_.CalcCij(atom0.Idx(), atom1.Idx()); //Cparam_[it0->Idx()] * Cparam_[it1->Idx()]; + return (1.0 - (1.0 + kr2 + kr4/2.0)*expterm) / r6 * Cij; +} +} +} +#endif diff --git a/src/Energy/Makefile b/src/Energy/Makefile new file mode 100644 index 0000000000..ff319845f7 --- /dev/null +++ b/src/Energy/Makefile @@ -0,0 +1,31 @@ +# Energy Makefile +include ../../config.h + +include energyfiles + +DEL_FILE = /bin/rm -f + +# Objects +OBJECTS=$(ENERGY_SOURCES:.cpp=.o) + +# General rules +.cpp.o: + $(VB)echo CXX $< + $(VB)$(CXX) $(DIRECTIVES) $(CPPTRAJ_INC) $(CXXFLAGS) -c -o $@ $< + +# Default target: objects +all: $(OBJECTS) + +clean: + $(DEL_FILE) *.o + +uninstall: clean + +# Dependency targets +../findDepend: + cd ../ && $(MAKE) findDepend + +depend: ../findDepend + ../findDepend $(ENERGY_SOURCES) > energydepend + +include energydepend diff --git a/src/Energy/PME_Recip.cpp b/src/Energy/PME_Recip.cpp new file mode 100644 index 0000000000..68cbe408d2 --- /dev/null +++ b/src/Energy/PME_Recip.cpp @@ -0,0 +1,150 @@ +#include "PME_Recip.h" +#ifdef LIBPME +#include "../Box.h" +#include "../CpptrajStdio.h" + +typedef helpme::Matrix Mat; + +using namespace Cpptraj::Energy; + +PME_Recip::PME_Recip(Type typeIn) +{ + switch (typeIn) { + case COULOMB: + distKernelExponent_ = 1; + scaleFac_ = 1.0; + break; + case LJ: + distKernelExponent_ = 6; + scaleFac_ = -1.0; + break; + } +} + +/** Init */ +int PME_Recip::InitRecip(EwaldOptions const& pmeOpts, int debugIn) { + if (recipParams_.InitRecip(pmeOpts, debugIn)) return 1; + PrintRecipOpts(); + return 0; +} + +/** Print options to stdout. */ +void PME_Recip::PrintRecipOpts() const { + if (distKernelExponent_ == 1) + mprintf("\tParticle Mesh Coulomb Reciprocal opts:\n"); + else if (distKernelExponent_ == 6) + mprintf("\tParticle Mesh LJ Reciprocal opts:\n"); + else + mprintf("\tReciprocal opts (distance kernel exponent= %i)\n", distKernelExponent_); + recipParams_.PrintRecipOpts(); +} + +/** \return 1 if the box type is invalid for helPME */ +int PME_Recip::set_lattice(PMEInstanceD::LatticeType& lattice, Box const& boxIn) { + lattice = PMEInstanceD::LatticeType::XAligned; + // TODO just pass in Ucell when helPME supports it + //boxIn.PrintDebug("pme"); + if (!boxIn.Is_X_Aligned()) { + if (boxIn.Is_Symmetric()) + lattice = PMEInstanceD::LatticeType::ShapeMatrix; + else { + mprinterr("Error: Unit cell is not X-aligned or symmetric; cannot set PME recip grid.\n"); + return 1; + } + } + return 0; +} + +/** \return Reciprocal space part of PME energy calc. */ +// TODO currently helPME needs the coords/charge arrays to be non-const, need to fix that +double PME_Recip::Recip_ParticleMesh(Darray& coordsDin, Box const& boxIn, + Darray& ChargeIn, double ew_coeffIn) +{ + t_recip_.Start(); + // This essentially makes coordsD and chargesD point to arrays. + Mat coordsD(&coordsDin[0], ChargeIn.size(), 3); + Mat chargesD(&ChargeIn[0], ChargeIn.size(), 1); + int nfft1, nfft2, nfft3; + + if ( recipParams_.DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { + mprinterr("Error: Could not determine FFT 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(new PMEInstanceD()); + pme_object_.setup(distKernelExponent_, ew_coeffIn, recipParams_.Order(), nfft1, nfft2, nfft3, scaleFac_, 0); + // Check the unit cell vectors + PMEInstanceD::LatticeType lattice; + if (set_lattice(lattice, boxIn)) return 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.Param(Box::X), boxIn.Param(Box::Y), boxIn.Param(Box::Z), + boxIn.Param(Box::ALPHA), boxIn.Param(Box::BETA), boxIn.Param(Box::GAMMA), + lattice); + //t_calc_.Start(); + double erecip = pme_object_.computeERec(0, chargesD, coordsD); + //t_calc_.Stop(); + t_recip_.Stop(); + return erecip; +} + +/** \return Reciprocal space part of PME energy calc. */ +// TODO currently helPME needs the coords/charge arrays to be non-const, need to fix that +double PME_Recip::Recip_Decomp(Darray& atom_recip, + Darray& coordsDin, Box const& boxIn, + Darray& ChargeIn, double ew_coeffIn) +{ + t_recip_.Start(); + atom_recip.resize( ChargeIn.size() ); + // This essentially makes coordsD and chargesD point to arrays. + Mat coordsD(&coordsDin[0], ChargeIn.size(), 3); + Mat chargesD(&ChargeIn[0], ChargeIn.size(), 1); + int nfft1, nfft2, nfft3; + + if ( recipParams_.DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { + mprinterr("Error: Could not determine FFT grid spacing.\n"); + return 0.0; + } + + // Instantiate double precision PME object + pme_object_.setup(distKernelExponent_, ew_coeffIn, recipParams_.Order(), nfft1, nfft2, nfft3, scaleFac_, 0); + // Check the unit cell vectors + PMEInstanceD::LatticeType lattice; + if (set_lattice(lattice, boxIn)) return 0; + // Sets the unit cell lattice vectors, with units consistent with those used to specify coordinates. + pme_object_.setLatticeVectors(boxIn.Param(Box::X), boxIn.Param(Box::Y), boxIn.Param(Box::Z), + boxIn.Param(Box::ALPHA), boxIn.Param(Box::BETA), boxIn.Param(Box::GAMMA), + lattice); + //t_calc_.Start(); + // TODO precalc + Mat e_potentialD_(ChargeIn.size(), 4); + e_potentialD_.setConstant(0.0); + pme_object_.computePRec(0, chargesD, coordsD, coordsD, 1, e_potentialD_); + double erecip = 0; + for(unsigned int i = 0; i < ChargeIn.size(); i++) + { + atom_recip[i]=0.5 * ChargeIn[i] * e_potentialD_(i,0); + erecip += atom_recip[i]; + } + + //t_calc_.Stop(); + t_recip_.Stop(); + return erecip; +} +#endif /* LIBPME */ diff --git a/src/Energy/PME_Recip.h b/src/Energy/PME_Recip.h new file mode 100644 index 0000000000..328c185769 --- /dev/null +++ b/src/Energy/PME_Recip.h @@ -0,0 +1,42 @@ +#ifndef INC_ENERGY_PME_RECIP_H +#define INC_ENERGY_PME_RECIP_H +#ifdef LIBPME +#include "../helpme_standalone.h" +#include "../Timer.h" +#include "PME_RecipParams.h" +class Box; +namespace Cpptraj { +namespace Energy { +/// Do the reciprocal part of a PME calculation +class PME_Recip { + typedef std::vector Darray; + public: + enum Type { COULOMB = 0, LJ }; + + PME_Recip(Type); + + /// Initialize + int InitRecip(EwaldOptions const& pmeOpts, int); + + double Recip_ParticleMesh(Darray&, Box const&, Darray&, double); + double Recip_Decomp(Darray&, Darray&, Box const&, Darray&, double); + + Timer const& Timing_Total() const { return t_recip_; } + //Timer const& Timing_Calc() const { return t_calc_; } + private: + /// Print options to stdout + void PrintRecipOpts() const; + + static int set_lattice(PMEInstanceD::LatticeType&, Box const&); + + PMEInstanceD pme_object_; + PME_RecipParams recipParams_; ///< Hold PME recip parameters + Timer t_recip_; ///< Recip calc timer + //Timer t_calc_; + int distKernelExponent_; ///< Exponent of the distance kernel: 1 for Coulomb, 6 for LJ + double scaleFac_; ///< scale factor to be applied to all computed energies and derivatives thereof +}; +} +} +#endif /* LIBPME */ +#endif diff --git a/src/Energy/PME_RecipParams.cpp b/src/Energy/PME_RecipParams.cpp new file mode 100644 index 0000000000..0d8fc61e36 --- /dev/null +++ b/src/Energy/PME_RecipParams.cpp @@ -0,0 +1,118 @@ +#include "PME_RecipParams.h" +#include "../Box.h" +#include "../CpptrajStdio.h" +#include "../EwaldOptions.h" + +using namespace Cpptraj::Energy; + +/** CONSTRUCTOR - NFFT=-1 means auto-assign. */ +PME_RecipParams::PME_RecipParams() : + order_(6), + debug_(0) +{ + nfft_[0] = -1; + nfft_[1] = -1; + nfft_[2] = -1; +} + +/** Initialize PME recip options. */ +int PME_RecipParams::InitRecip(EwaldOptions const& pmeOpts, int debugIn) { + debug_ = debugIn; + nfft_[0] = pmeOpts.Nfft1(); + nfft_[1] = pmeOpts.Nfft2(); + nfft_[2] = pmeOpts.Nfft3(); + order_ = pmeOpts.SplineOrder(); + // Set defaults if necessary + if (order_ < 1) order_ = 6; + return 0; +} + +/** Print options to stdout. */ +void PME_RecipParams::PrintRecipOpts() const { + //mprintf("\tRecip opts (distance kernel exponent= %i\n", distKernelExponent_); + mprintf("\t Bspline order= %i\n", order_); + mprintf("\t "); + for (int i = 0; i != 3; i++) + if (nfft_[i] == -1) + mprintf(" NFFT%i=auto", i+1); + else + mprintf(" NFFT%i=%i", i+1, nfft_[i]); + mprintf("\n"); +} + +/** \return true if given number is a product of powers of 2, 3, or 5. */ +bool PME_RecipParams::check_prime_factors(int nIn) { + if (nIn == 1) return true; + int NL = nIn; + int NQ; + // First divide down by 2 + while (NL > 0) { + NQ = NL / 2; + if (NQ * 2 != NL) break; + if (NQ == 1) return true; + NL = NQ; + } + // Next try 3 + while (NL > 0) { + NQ = NL / 3; + if (NQ * 3 != NL) break; + if (NQ == 1) return true; + NL = NQ; + } + // Last try 5 + while (NL > 0) { + NQ = NL / 5; + if (NQ * 5 != NL) break; + if (NQ == 1) return true; + NL = NQ; + } + return false; +} + +/** Compute the ceiling of len that is also a product of powers of 2, 3, 5. + * Use check_prime_factors to get the smallest integer greater or equal + * than len which is decomposable into powers of 2, 3, 5. + */ +int PME_RecipParams::ComputeNFFT(double len) { + int mval = (int)len - 1; + for (int i = 0; i < 100; i++) { + mval += 1; + // Sanity check + if (mval < 1) { + mprinterr("Error: Bad box length %g, cannot get NFFT value.\n", len); + return 0; + } + if (check_prime_factors(mval)) + return mval; + } + mprinterr("Error: Failed to get good FFT array size for length %g Ang.\n", len); + return 0; +} + +/** Given a box, determine number of FFT grid points in each dimension. */ +int PME_RecipParams::DetermineNfft(int& nfft1, int& nfft2, int& nfft3, Box const& boxIn) const +{ + // FIXME Should this be checking if NFFT would change instead? + nfft1 = nfft_[0]; + nfft2 = nfft_[1]; + nfft3 = nfft_[2]; + if (nfft1 < 1) { + // Need even dimension for X direction + nfft1 = ComputeNFFT( (boxIn.Param(Box::X) + 1.0) * 0.5 ); + nfft1 *= 2; + } + if (nfft2 < 1) + nfft2 = ComputeNFFT( boxIn.Param(Box::Y) ); + if (nfft3 < 1) + nfft3 = ComputeNFFT( boxIn.Param(Box::Z) ); + + 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; +} + + diff --git a/src/Energy/PME_RecipParams.h b/src/Energy/PME_RecipParams.h new file mode 100644 index 0000000000..757467f47b --- /dev/null +++ b/src/Energy/PME_RecipParams.h @@ -0,0 +1,35 @@ +#ifndef INC_ENERGY_PME_RECIPPARAMS_H +#define INC_ENERGY_PME_RECIPPARAMS_H +class Box; +class EwaldOptions; +namespace Cpptraj { +namespace Energy { +/// Hold parameters for the reciprocal part of PME +/** NOTE: This is kept separate from PME_Recip so that classes that + * do the recip. calculation a little differently (like GIST_PME) + * can have access to the routines that assign NFFT etc. + */ +class PME_RecipParams { + public: + /// CONSTRUCTOR + PME_RecipParams(); + /// Initilize recip options + int InitRecip(EwaldOptions const&, int); + /// Print recip options to stdout + void PrintRecipOpts() const; + /// Determine FFT grid points in X, Y, Z from box lengths + int DetermineNfft(int&, int&, int&, Box const&) const; + + /// \return B-Spline order + int Order() const { return order_; } + private: + static bool check_prime_factors(int); + static int ComputeNFFT(double); + + int nfft_[3]; ///< Number of grid points for FFT in X, Y, Z + int order_; ///< B-Spline order + int debug_; +}; +} +} +#endif diff --git a/src/Energy/VDW_LongRange_Correction.cpp b/src/Energy/VDW_LongRange_Correction.cpp new file mode 100644 index 0000000000..1e69c7beb6 --- /dev/null +++ b/src/Energy/VDW_LongRange_Correction.cpp @@ -0,0 +1,79 @@ +#include "VDW_LongRange_Correction.h" +#include "../CpptrajStdio.h" +#include "../Topology.h" + +using namespace Cpptraj::Energy; + +VDW_LongRange_Correction::VDW_LongRange_Correction() : + Vdw_Recip_term_(0), + debug_(0) +{} + +void VDW_LongRange_Correction::SetDebug(int debugIn) { debug_ = debugIn; } + +/** Determine VDW long range correction prefactor. */ +int VDW_LongRange_Correction::Setup_VDW_Correction(Topology const& topIn, + AtomMask const& maskIn) +{ + Vdw_Recip_term_ = 0.0; + NonbondParmType const* NB_ = static_cast( &(topIn.Nonbond()) ); + if (!NB_->HasNonbond()) { + mprinterr("Error: '%s' has no nonbonded parameters. Cannot calculate VDW correction.\n", + topIn.c_str()); + return 1; + } + // Count the number of each unique nonbonded type. + N_vdw_type_.assign( NB_->Ntypes(), 0 ); + atype_vdw_recip_terms_.clear(); + atype_vdw_recip_terms_.reserve( N_vdw_type_.size() ); + vdw_type_.clear(); + vdw_type_.reserve( maskIn.Nselected() ); + for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm) + { + N_vdw_type_[ topIn[*atm].TypeIndex() ]++; + vdw_type_.push_back( topIn[*atm].TypeIndex() ); + } + if (debug_ > 0) { + mprintf("DEBUG: %zu VDW types.\n", N_vdw_type_.size()); + for (Iarray::const_iterator it = N_vdw_type_.begin(); it != N_vdw_type_.end(); ++it) + mprintf("\tType %li = %i\n", it-N_vdw_type_.begin(), *it); + } + // Determine correction term from types and LJ B parameters + for (unsigned int itype = 0; itype != N_vdw_type_.size(); itype++) + { + double atype_vdw_term = 0.0; // term for each nonbond atom type + unsigned int offset = N_vdw_type_.size() * itype; + for (unsigned int jtype = 0; jtype != N_vdw_type_.size(); jtype++) + { + unsigned int idx = offset + jtype; + int nbidx = NB_->NBindex()[ idx ]; + if (nbidx > -1) { + atype_vdw_term += N_vdw_type_[itype] * N_vdw_type_[jtype] * NB_->NBarray()[ nbidx ].B(); + + Vdw_Recip_term_ += N_vdw_type_[itype] * N_vdw_type_[jtype] * NB_->NBarray()[ nbidx ].B(); + } + } + atype_vdw_recip_terms_.push_back(atype_vdw_term); + } + return 0; +} + +/** Decomposed long range VDW correction */ +double VDW_LongRange_Correction::Vdw_Decomp_Correction(std::vector& atom_ecorr, + double cutoff_, double volume) +const +{ + atom_ecorr.resize( vdw_type_.size() ); + double prefac = Constants::TWOPI / (3.0*volume*cutoff_*cutoff_*cutoff_); + double e_vdwr = -prefac * Vdw_Recip_term_; + + for (unsigned int i = 0; i != vdw_type_.size(); i++) + { + int v_type = vdw_type_[i]; + + double term = atype_vdw_recip_terms_[v_type] / N_vdw_type_[v_type]; + + atom_ecorr[i] = -prefac * term; + } + return e_vdwr; +} diff --git a/src/Energy/VDW_LongRange_Correction.h b/src/Energy/VDW_LongRange_Correction.h new file mode 100644 index 0000000000..ac10195406 --- /dev/null +++ b/src/Energy/VDW_LongRange_Correction.h @@ -0,0 +1,41 @@ +#ifndef INC_ENERGY_VDW_LONGRANGE_CORRECTION_H +#define INC_ENERGY_VDW_LONGRANGE_CORRECTION_H +#include +#include "../Constants.h" +class AtomMask; +class Topology; +namespace Cpptraj { +namespace Energy { +class VDW_LongRange_Correction { + typedef std::vector Iarray; + typedef std::vector Darray; + public: + VDW_LongRange_Correction(); + void SetDebug(int); + int Setup_VDW_Correction(Topology const&, AtomMask const&); + /// \return Full VDW long range correction from cutoff and volume + double Vdw_Correction(double cutoff_, double volume) const { + double prefac = Constants::TWOPI / (3.0*volume*cutoff_*cutoff_*cutoff_); + double e_vdwr = -prefac * Vdw_Recip_term_; + //if (debug_ > 0) mprintf("DEBUG: Vdw correction %20.10f\n", e_vdwr); + return e_vdwr; + } + /// VDW correction decomposed per atom + double Vdw_Decomp_Correction(std::vector&, double, double) const; + + // FIXME below are currently exposed for GIST_PME + double Vdw_Recip_Term() const { return Vdw_Recip_term_; } + Iarray const& VDW_Type() const { return vdw_type_; } + Darray const& Atype_VDW_Recip_Terms() const { return atype_vdw_recip_terms_; } + Iarray const& N_VDW_Type() const { return N_vdw_type_; } + private: + double Vdw_Recip_term_; + int debug_; + // Below variables are needed for per-atom decomp + Iarray vdw_type_; ///< VDW type for each seleccted atom (#atoms) + Iarray N_vdw_type_; ///< Count of atoms that have each VDW type index (#types) + Darray atype_vdw_recip_terms_; ///< the nonbond interaction for each atom type (#types) +}; +} +} +#endif diff --git a/src/Energy/energydepend b/src/Energy/energydepend new file mode 100644 index 0000000000..c6fb564234 --- /dev/null +++ b/src/Energy/energydepend @@ -0,0 +1,14 @@ +Ecalc_Nonbond.o : Ecalc_Nonbond.cpp ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJPME_6_12.h ../Energy/Ene_LJ_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/EwaldParams_LJPME.h ../Energy/Kernel_EwaldAdjust.h ../Energy/Kernel_LJPME_Adjust.h ../EwaldOptions.h ../ExclusionArray.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_Decomp_LJLR.h ../PairListEngine_Ewald_Decomp_LJPME.h ../PairListEngine_Ewald_LJLR.h ../PairListEngine_Ewald_LJPME.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h ../helpme_standalone.h Ecalc_Nonbond.h Ene_Decomp_Nonbond.h Ene_LJ_6_12.h Ene_Nonbond.h EwaldCalc.h EwaldCalc_Decomp.h EwaldCalc_Decomp_LJPME.h EwaldCalc_Decomp_PME.h EwaldCalc_LJPME.h EwaldCalc_PME.h EwaldCalc_Regular.h Ewald_Recip.h PME_Recip.h PME_RecipParams.h VDW_LongRange_Correction.h +EnergyDecomposer.o : EnergyDecomposer.cpp ../ArgList.h ../AssociatedData.h ../Atom.h ../AtomMask.h ../AtomType.h ../BaseIOtype.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataFileList.h ../DataSet.h ../DataSetList.h ../DataSet_1D.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../DataSet_Mesh.h ../Dimension.h ../DistRoutines.h ../EwaldOptions.h ../ExclusionArray.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../ImageOption.h ../MaskToken.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../OnlineVarT.h ../PairList.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../Spline.h ../SymbolExporting.h ../TextFormat.h ../Timer.h ../Topology.h ../TorsionRoutines.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Ecalc_Nonbond.h Ene_Angle.h Ene_Bond.h Ene_LJ_6_12.h EnergyDecomposer.h Kernel_Fourier.h Kernel_Harmonic.h +ErfcFxn.o : ErfcFxn.cpp ../CpptrajStdio.h ../SplineFxnTable.h ErfcFxn.h +EwaldCalc_Decomp_LJPME.o : EwaldCalc_Decomp_LJPME.cpp ../Atom.h ../AtomMask.h ../Box.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJPME_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/EwaldParams_LJPME.h ../Energy/Kernel_EwaldAdjust.h ../Energy/Kernel_LJPME_Adjust.h ../EwaldOptions.h ../ExclusionArray.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_Decomp_LJPME.h ../PairListTemplate.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Unit.h ../Vec3.h ../helpme_standalone.h EwaldCalc.h EwaldCalc_Decomp.h EwaldCalc_Decomp_LJPME.h PME_Recip.h PME_RecipParams.h +EwaldCalc_Decomp_PME.o : EwaldCalc_Decomp_PME.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJ_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/Kernel_EwaldAdjust.h ../EwaldOptions.h ../ExclusionArray.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_Decomp_LJLR.h ../PairListTemplate.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Unit.h ../Vec3.h ../helpme_standalone.h EwaldCalc.h EwaldCalc_Decomp.h EwaldCalc_Decomp_PME.h PME_Recip.h PME_RecipParams.h VDW_LongRange_Correction.h +EwaldCalc_LJPME.o : EwaldCalc_LJPME.cpp ../Atom.h ../AtomMask.h ../Box.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJPME_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/EwaldParams_LJPME.h ../Energy/Kernel_EwaldAdjust.h ../Energy/Kernel_LJPME_Adjust.h ../EwaldOptions.h ../ExclusionArray.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_LJPME.h ../PairListTemplate.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Unit.h ../Vec3.h ../helpme_standalone.h EwaldCalc.h EwaldCalc_LJPME.h PME_Recip.h PME_RecipParams.h +EwaldCalc_PME.o : EwaldCalc_PME.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJ_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/Kernel_EwaldAdjust.h ../EwaldOptions.h ../ExclusionArray.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_LJLR.h ../PairListTemplate.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Unit.h ../Vec3.h ../helpme_standalone.h EwaldCalc.h EwaldCalc_PME.h PME_Recip.h PME_RecipParams.h VDW_LongRange_Correction.h +EwaldCalc_Regular.o : EwaldCalc_Regular.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../Energy/../Constants.h ../Energy/../ParameterTypes.h ../Energy/../SplineFxnTable.h ../Energy/Ene_LJ_6_12.h ../Energy/ErfcFxn.h ../Energy/EwaldParams.h ../Energy/Kernel_EwaldAdjust.h ../EwaldOptions.h ../ExclusionArray.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../PairList.h ../PairListEngine_Ewald_LJLR.h ../PairListTemplate.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Timer.h ../Unit.h ../Vec3.h EwaldCalc.h EwaldCalc_Regular.h Ewald_Recip.h VDW_LongRange_Correction.h +EwaldParams.o : EwaldParams.cpp ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../EwaldOptions.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SplineFxnTable.h ../SymbolExporting.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h ErfcFxn.h EwaldParams.h +EwaldParams_LJPME.o : EwaldParams_LJPME.cpp ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../EwaldOptions.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SplineFxnTable.h ../SymbolExporting.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h ErfcFxn.h EwaldParams.h EwaldParams_LJPME.h +Ewald_Recip.o : Ewald_Recip.cpp ../Box.h ../Constants.h ../CpptrajStdio.h ../EwaldOptions.h ../Matrix_3x3.h ../Parallel.h ../ParameterTypes.h ../SplineFxnTable.h ../StringRoutines.h ../Timer.h ../Vec3.h ErfcFxn.h EwaldParams.h Ewald_Recip.h +PME_Recip.o : PME_Recip.cpp ../Box.h ../CpptrajStdio.h ../Matrix_3x3.h ../Parallel.h ../Timer.h ../Vec3.h ../helpme_standalone.h PME_Recip.h PME_RecipParams.h +PME_RecipParams.o : PME_RecipParams.cpp ../Box.h ../CpptrajStdio.h ../EwaldOptions.h ../Matrix_3x3.h ../Parallel.h ../Vec3.h PME_RecipParams.h +VDW_LongRange_Correction.o : VDW_LongRange_Correction.cpp ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h VDW_LongRange_Correction.h diff --git a/src/Energy/energyfiles b/src/Energy/energyfiles new file mode 100644 index 0000000000..f60e63168b --- /dev/null +++ b/src/Energy/energyfiles @@ -0,0 +1,16 @@ +# Files for Energy subdirectory. +ENERGY_SOURCES= \ + Ecalc_Nonbond.cpp \ + EnergyDecomposer.cpp \ + ErfcFxn.cpp \ + EwaldCalc_Decomp_LJPME.cpp \ + EwaldCalc_Decomp_PME.cpp \ + EwaldCalc_LJPME.cpp \ + EwaldCalc_PME.cpp \ + EwaldCalc_Regular.cpp \ + EwaldParams.cpp \ + EwaldParams_LJPME.cpp \ + Ewald_Recip.cpp \ + PME_Recip.cpp \ + PME_RecipParams.cpp \ + VDW_LongRange_Correction.cpp diff --git a/src/EnergyKernel_Adjust.h b/src/EnergyKernel_Adjust.h deleted file mode 100644 index 8ea81e953a..0000000000 --- a/src/EnergyKernel_Adjust.h +++ /dev/null @@ -1,13 +0,0 @@ - e_adjust += Adjust(q0, q1, sqrt(rij2)); -# ifdef CPPTRAJ_EKERNEL_LJPME - // LJ PME direct space correction - // NOTE: Assuming excluded pair is within cutoff - double kr2 = lw_coeff_ * lw_coeff_ * rij2; - double kr4 = kr2 * kr2; - //double kr6 = kr2 * kr4; - double expterm = exp(-kr2); - double r4 = rij2 * rij2; - double r6 = rij2 * r4; - double Cij = Cparam_[it0->Idx()] * Cparam_[it1->Idx()]; - Eljpme_correction_excl += (1.0 - (1.0 + kr2 + kr4/2.0)*expterm) / r6 * Cij; -# endif diff --git a/src/EnergyKernel_Nonbond.h b/src/EnergyKernel_Nonbond.h deleted file mode 100644 index d8c58bd91b..0000000000 --- a/src/EnergyKernel_Nonbond.h +++ /dev/null @@ -1,43 +0,0 @@ - double rij = sqrt( rij2 ); - double qiqj = q0 * q1; -# ifndef _OPENMP - t_erfc_.Start(); -# endif - //double erfc = erfc_func(ew_coeff_ * rij); - double erfc = ERFC(ew_coeff_ * rij); -# ifndef _OPENMP - t_erfc_.Stop(); -# endif - double e_elec = qiqj * erfc / rij; - Eelec += e_elec; - //mprintf("EELEC %4i%4i%12.5f%12.5f%12.5f%3.0f%3.0f%3.0f\n", - //int ta0, ta1; - //if (it0->Idx() < it1->Idx()) { - // ta0=it0->Idx(); ta1=it1->Idx(); - //} else { - // ta1=it0->Idx(); ta0=it1->Idx(); - //} - //mprintf("PELEC %6i%6i%12.5f%12.5f%12.5f\n", ta0, ta1, rij, erfc, e_elec); - int nbindex = NB_->GetLJindex(TypeIndices_[it0->Idx()], - TypeIndices_[it1->Idx()]); - if (nbindex > -1) { - double vswitch = switch_fn(rij2, cut2_0_, cut2_); - NonbondType const& LJ = NB_->NBarray()[ nbindex ]; - double r2 = 1.0 / rij2; - double r6 = r2 * r2 * r2; - double r12 = r6 * r6; - double f12 = LJ.A() * r12; // A/r^12 - double f6 = LJ.B() * r6; // B/r^6 - double e_vdw = f12 - f6; // (A/r^12)-(B/r^6) - Evdw += (e_vdw * vswitch); - //mprintf("PVDW %8i%8i%20.6f%20.6f\n", ta0+1, ta1+1, e_vdw, r2); -# ifdef CPPTRAJ_EKERNEL_LJPME - // LJ PME direct space correction - double kr2 = lw_coeff_ * lw_coeff_ * rij2; - double kr4 = kr2 * kr2; - //double kr6 = kr2 * kr4; - double expterm = exp(-kr2); - double Cij = Cparam_[it0->Idx()] * Cparam_[it1->Idx()]; - Eljpme_correction += (1.0 - (1.0 + kr2 + kr4/2.0)*expterm) * r6 * vswitch * Cij; -# endif - } diff --git a/src/Ewald.cpp b/src/Ewald.cpp deleted file mode 100644 index c1e0e068b8..0000000000 --- a/src/Ewald.cpp +++ /dev/null @@ -1,574 +0,0 @@ -#include //sqrt -#include "Ewald.h" -#include "CpptrajStdio.h" -#include "Constants.h" -#include "StringRoutines.h" // ByteString -#include "Spline.h" -#include "Topology.h" -#include "CharMask.h" -#include "ParameterTypes.h" -#ifdef DEBUG_PAIRLIST -#incl ude "PDBfile.h" -#endif - -/// CONSTRUCTOR -Ewald::Ewald() : - ew_coeff_(0.0), - lw_coeff_(0.0), - switch_width_(0.0), - cutoff_(0.0), - cut2_(0.0), - cut2_0_(0.0), - dsumTol_(0.0), - debug_(0), - sumq_(0.0), - sumq2_(0.0), - Vdw_Recip_term_(0) -{ -# ifdef DEBUG_EWALD - // Save fractional translations for 1 cell in each direction (and primary cell). - // This is only for the non-pairlist version of direct. - Cells_.reserve( 27 ); - for (int ix = -1; ix < 2; ix++) - for (int iy = -1; iy < 2; iy++) - for (int iz = -1; iz < 2; iz++) - Cells_.push_back( Vec3(ix, iy, iz) ); -# endif -} - -const double Ewald::INVSQRTPI_ = 1.0 / sqrt(Constants::PI); - -/** Complimentary error function: 2/sqrt(PI) * SUM[exp(-t^2)*dt] - * Original code: SANDER: erfcfun.F90 - */ -double Ewald::erfc_func(double xIn) { - double erfc; - double absx = DABS( xIn ); - - if (xIn > 26.0) - erfc = 0.0; - else if (xIn < -5.5) - erfc = 2.0; - else if (absx <= 0.5) { - double cval = xIn * xIn; - double pval = ((-0.356098437018154E-1*cval+0.699638348861914E1)*cval + 0.219792616182942E2) * - cval + 0.242667955230532E3; - double qval = ((cval+0.150827976304078E2)*cval+0.911649054045149E2)*cval + 0.215058875869861E3; - double erf = xIn * pval/qval; - erfc = 1.0 - erf; - } else if (absx < 4.0) { - double cval = absx; - double pval=((((((-0.136864857382717E-6*cval+0.564195517478974)*cval+ - 0.721175825088309E1)*cval+0.431622272220567E2)*cval+ - 0.152989285046940E3)*cval+0.339320816734344E3)*cval+ - 0.451918953711873E3)*cval+0.300459261020162E3; - double qval=((((((cval+0.127827273196294E2)*cval+0.770001529352295E2)*cval+ - 0.277585444743988E3)*cval+0.638980264465631E3)*cval+ - 0.931354094850610E3)*cval+0.790950925327898E3)*cval+ - 0.300459260956983E3; - double nonexperfc; - if ( xIn > 0.0 ) - nonexperfc = pval/qval; - else - nonexperfc = 2.0*exp(xIn*xIn) - pval/qval; - erfc = exp(-absx*absx)*nonexperfc; - } else { - double cval = 1.0/(xIn*xIn); - double pval = (((0.223192459734185E-1*cval+0.278661308609648)*cval+ - 0.226956593539687)*cval+0.494730910623251E-1)*cval+ - 0.299610707703542E-2; - double qval = (((cval+0.198733201817135E1)*cval+0.105167510706793E1)*cval+ - 0.191308926107830)*cval+0.106209230528468E-1; - cval = (-cval*pval/qval + 0.564189583547756)/absx; - double nonexperfc; - if ( xIn > 0.0 ) - nonexperfc = cval; - else - nonexperfc = 2.0*exp(xIn*xIn) - cval; - erfc = exp(-absx*absx)*nonexperfc; - } - return erfc; -} - -// Ewald::ERFC() -double Ewald::ERFC(double xIn) const { - return table_.Yval( xIn); -} - -/** Non-inlined version of ERFC */ -double Ewald::ErfcFxn(double xIn) const { - return table_.Yval( xIn ); -} - -/** Determine Ewald coefficient from cutoff and direct sum tolerance. - * Original Code: SANDER: findewaldcof - */ -double Ewald::FindEwaldCoefficient(double cutoff, double dsum_tol) -{ - // First get direct sum tolerance. How big must the Ewald coefficient be to - // get terms outside the cutoff below tolerance? - double xval = 0.5; - int nloop = 0; - double term = 0.0; - do { - xval = 2.0 * xval; - nloop++; - double yval = xval * cutoff; - term = erfc_func(yval) / cutoff; - } while (term >= dsum_tol); - - // Binary search tolerance is 2^-50 - int ntimes = nloop + 50; - double xlo = 0.0; - double xhi = xval; - for (int i = 0; i != ntimes; i++) { - xval = (xlo + xhi) / 2.0; - double yval = xval * cutoff; - double term = erfc_func(yval) / cutoff; - if (term >= dsum_tol) - xlo = xval; - else - xhi = xval; - } - mprintf("\tEwald coefficient for cut=%g, direct sum tol=%g is %g\n", - cutoff, dsum_tol, xval); - return xval; -} - -/** Convert charges to Amber units. Calculate sum of charges and squared charges. */ -void Ewald::CalculateCharges(Topology const& topIn, AtomMask const& maskIn) { - sumq_ = 0.0; - sumq2_ = 0.0; - Charge_.clear(); - TypeIndices_.clear(); - for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) { - double qi = topIn[*atom].Charge() * Constants::ELECTOAMBER; - Charge_.push_back(qi); - sumq_ += qi; - sumq2_ += (qi * qi); - // Store atom type indices for selected atoms. - TypeIndices_.push_back( topIn[*atom].TypeIndex() ); - } - //mprintf("DEBUG: sumq= %20.10f sumq2= %20.10f\n", sumq_, sumq2_); - Setup_VDW_Correction( topIn, maskIn ); -} - -void Ewald::CalculateC6params(Topology const& topIn, AtomMask const& maskIn) { - Cparam_.clear(); - if (lw_coeff_ > 0.0) { - for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) - { - double rmin = topIn.GetVDWradius( *atom ); - double eps = topIn.GetVDWdepth( *atom ); - Cparam_.push_back( 8.0 * (rmin*rmin*rmin) * sqrt(2 * eps) ); - if (debug_ > 0) - mprintf("DEBUG: C6 param atom %8i = %16.8f\n", *atom+1, Cparam_.back()); - } - } else - Cparam_.assign(maskIn.Nselected(), 0.0); -} - -/** Set up exclusion lists for selected atoms. */ -void Ewald::SetupExclusionList(Topology const& topIn, AtomMask const& maskIn) -{ - // Use distance of 4 (up to dihedrals) - if (Excluded_.SetupExcluded(topIn.Atoms(), maskIn, 4, - ExclusionArray::EXCLUDE_SELF, - ExclusionArray::FULL)) - { - mprinterr("Error: Ewald: Could not set up exclusion list.\n"); - return; - } -} - -/** Check some common input. */ -int Ewald::CheckInput(Box const& boxIn, int debugIn, double cutoffIn, double dsumTolIn, - double ew_coeffIn, double lw_coeffIn, double switch_widthIn, - double erfcTableDxIn, double skinnbIn) -{ - debug_ = debugIn; - cutoff_ = cutoffIn; - dsumTol_ = dsumTolIn; - ew_coeff_ = ew_coeffIn; - lw_coeff_ = lw_coeffIn; - switch_width_ = switch_widthIn; - double erfcTableDx = erfcTableDxIn; - // Check input - if (cutoff_ < Constants::SMALL) { - mprinterr("Error: Direct space cutoff (%g) is too small.\n", cutoff_); - return 1; - } - char dir[3] = {'X', 'Y', 'Z'}; - // NOTE: First 3 box parameters are X Y Z - for (int i = 0; i < 3; i++) { - if (cutoff_ > boxIn.Param((Box::ParamType)i)/2.0) { - mprinterr("Error: Cutoff must be less than half the box length (%g > %g, %c)\n", - cutoff_, boxIn.Param((Box::ParamType)i)/2.0, dir[i]); - return 1; - } - } - if (skinnbIn < 0.0) { - mprinterr("Error: skinnb is less than 0.0\n"); - return 1; - } - if (switch_width_ < 0.0) switch_width_ = 0.0; - if (switch_width_ > cutoff_) { - mprinterr("Error: Switch width must be less than the cutoff.\n"); - return 1; - } - - // Set defaults if necessary - if (dsumTol_ < Constants::SMALL) - dsumTol_ = 1E-5; - if (DABS(ew_coeff_) < Constants::SMALL) - ew_coeff_ = FindEwaldCoefficient( cutoff_, dsumTol_ ); - if (erfcTableDx <= 0.0) erfcTableDx = 1.0 / 5000; - // TODO make this optional - if (table_.FillTable( erfc_func, erfcTableDx, 0.0, cutoff_*ew_coeff_*1.5 )) { - mprinterr("Error: Could not set up spline table for ERFC\n"); - return 1; - } - table_.PrintMemUsage("\t"); - table_.PrintTableInfo("\t"); - // TODO do for C6 as well - // TODO for C6 correction term - if (lw_coeff_ < 0.0) - lw_coeff_ = 0.0; - else if (DABS(lw_coeff_) < Constants::SMALL) - lw_coeff_ = ew_coeff_; - - // Calculate some common factors. - cut2_ = cutoff_ * cutoff_; - double cut0 = cutoff_ - switch_width_; - cut2_0_ = cut0 * cut0; - - return 0; -} - -/** Initialize and set up pairlist. */ -int Ewald::Setup_Pairlist(Box const& boxIn, double skinnbIn) { - if (pairList_.InitPairList(cutoff_, skinnbIn, debug_)) return 1; - if (pairList_.SetupPairList( boxIn )) return 1; -# ifdef DEBUG_PAIRLIST - // Write grid PDB - PDBfile gridpdb; - gridpdb.OpenWrite("gridpoints.pdb"); - for (int iz = 0; iz != pairList_.NZ(); iz++) - for (int iy = 0; iy != pairList_.NY(); iy++) - for (int ix = 0; ix != pairList_.NX(); ix++) { - double fx = (double)ix / (double)pairList_.NX(); - double fy = (double)iy / (double)pairList_.NY(); - double fz = (double)iz / (double)pairList_.NZ(); - Vec3 cart = boxIn.UnitCell().TransposeMult( Vec3(fx,fy,fz) ); - gridpdb.WriteHET(1, cart[0], cart[1], cart[2]); - } - gridpdb.CloseFile(); -# endif - return 0; -} - -/** Electrostatic self energy. This is the cancelling Gaussian plus the "neutralizing plasma". */ -double Ewald::Self(double volume) { - t_self_.Start(); - double d0 = -ew_coeff_ * INVSQRTPI_; - double ene = sumq2_ * d0; -// mprintf("DEBUG: d0= %20.10f ene= %20.10f\n", d0, ene); - double factor = Constants::PI / (ew_coeff_ * ew_coeff_ * volume); - double ee_plasma = -0.5 * factor * sumq_ * sumq_; - ene += ee_plasma; - t_self_.Stop(); - return ene; -} - -/** Lennard-Jones self energy. */ -double Ewald::Self6() { - t_self_.Start(); // TODO precalc - double ew2 = lw_coeff_ * lw_coeff_; - double ew6 = ew2 * ew2 * ew2; - double c6sum = 0.0; - for (Darray::const_iterator it = Cparam_.begin(); it != Cparam_.end(); ++it) - c6sum += ew6 * (*it * *it); - t_self_.Stop(); - return c6sum / 12.0; -} - -// Ewald::Adjust() -# ifdef _OPENMP -double Ewald::Adjust(double q0, double q1, double rij) const { - double erfc = ERFC(ew_coeff_ * rij); - double d0 = (erfc - 1.0) / rij; - return (q0 * q1 * d0); -} -# else -double Ewald::Adjust(double q0, double q1, double rij) { - t_adjust_.Start(); - t_erfc_.Start(); - //double erfc = erfc_func(ew_coeff_ * rij); - double erfc = ERFC(ew_coeff_ * rij); - t_erfc_.Stop(); - double d0 = (erfc - 1.0) / rij; - t_adjust_.Stop(); - return (q0 * q1 * d0); -} -# endif - -/** Ewald adjustment, for inheriting classes. */ -#ifdef _OPENMP -double Ewald::AdjustFxn(double q0, double q1, double rij) const { - return Adjust(q0, q1, rij); -} -#else -double Ewald::AdjustFxn(double q0, double q1, double rij) { - return Adjust(q0, q1, rij); -} -#endif - -/** Switching function for Lennard-Jones. */ -static inline double switch_fn(double rij2, double cut2_0, double cut2_1) -{ - if (rij2 <= cut2_0) - return 1.0; - else if (rij2 > cut2_1) - return 0.0; - else { - double xoff_m_x = cut2_1 - rij2; - double fac = 1.0 / (cut2_1 - cut2_0); - return (xoff_m_x*xoff_m_x) * (cut2_1 + 2.0*rij2 - 3.0*cut2_0) * (fac*fac*fac); - } -} - -/** Switching function for Lennard-Jones, for inheriting classes. */ -double Ewald::SwitchFxn(double rij2, double cut2_0, double cut2_1) { - return switch_fn(rij2, cut2_0, cut2_1); -} - -/** Nonbond direct-space calculation for Coulomb electrostatics and Lennard-Jones, - * intended for use with long-range LJ correction. - */ -double Ewald::Direct_VDW_LongRangeCorrection(PairList const& PL, double& evdw_out, double& eadjust_out) -{ - t_direct_.Start(); - double Eelec = 0.0; - double e_adjust = 0.0; - double Evdw = 0.0; - int cidx; -# ifdef _OPENMP -# pragma omp parallel private(cidx) reduction(+: Eelec, Evdw, e_adjust) - { -# pragma omp for -# endif -# include "PairListLoop.h" -# ifdef _OPENMP - } // END pragma omp parallel -# endif - t_direct_.Stop(); -# ifdef DEBUG_PAIRLIST - mprintf("DEBUG: Elec = %16.8f\n", Eelec); - mprintf("DEBUG: Eadjust = %16.8f\n", e_adjust); - mprintf("DEBUG: LJ vdw = %16.8f\n", Evdw); -# endif - evdw_out = Evdw; - eadjust_out = e_adjust; - return Eelec; -} - -/** Nonbond direct-space calculation for Coulomb electrostatics and Lennard-Jones - * calculated via PME. - */ -double Ewald::Direct_VDW_LJPME(PairList const& PL, double& evdw_out, double& eadjust_out) -{ - t_direct_.Start(); - double Eelec = 0.0; - double e_adjust = 0.0; - double Evdw = 0.0; - double Eljpme_correction = 0.0; - double Eljpme_correction_excl = 0.0; - int cidx; -# define CPPTRAJ_EKERNEL_LJPME -# ifdef _OPENMP -# pragma omp parallel private(cidx) reduction(+: Eelec, Evdw, e_adjust, Eljpme_correction,Eljpme_correction_excl) - { -# pragma omp for -# endif -# include "PairListLoop.h" -# ifdef _OPENMP - } // END pragma omp parallel -# endif -# undef CPPTRAJ_EKERNEL_LJPME - t_direct_.Stop(); -# ifdef DEBUG_PAIRLIST - mprintf("DEBUG: Elec = %16.8f\n", Eelec); - mprintf("DEBUG: Eadjust = %16.8f\n", e_adjust); - mprintf("DEBUG: LJ vdw = %16.8f\n", Evdw); - mprintf("DEBUG: LJ vdw PME correction = %16.8f\n", Eljpme_correction); - mprintf("DEBUG: LJ vdw PME correction (excluded) = %16.8f\n", Eljpme_correction_excl); -# endif - evdw_out = Evdw + Eljpme_correction + Eljpme_correction_excl; - eadjust_out = e_adjust; - return Eelec; -} - - -// Ewald::Direct() -/** Calculate direct space energy. This is the faster version that uses - * a pair list. Also calculate the energy adjustment for excluded - * atoms. - * \param PL The pairlist used to calculate energy. - * \param e_adjust_out The electrostatic adjust energy for excluded atoms. - * \param evdw_out The direct space van der Waals term (corrected for exclusion if LJ PME). - * \return The electrostatics term. - */ -double Ewald::Direct(PairList const& PL, double& evdw_out, double& e_adjust_out) -{ - if (lw_coeff_ > 0.0) - return Direct_VDW_LJPME(PL, evdw_out, e_adjust_out); - else - return Direct_VDW_LongRangeCorrection(PL, evdw_out, e_adjust_out); -} - -/** Determine VDW long range correction prefactor. */ -void Ewald::Setup_VDW_Correction(Topology const& topIn, AtomMask const& maskIn) { - Vdw_Recip_term_ = 0.0; - NB_ = static_cast( &(topIn.Nonbond()) ); - if (!NB_->HasNonbond()) { - mprintf("Warning: '%s' has no nonbonded parameters. Cannot calculate VDW correction.\n", - topIn.c_str()); - return; - } - // Count the number of each unique nonbonded type. - N_vdw_type_.assign( NB_->Ntypes(), 0 ); - vdw_type_.clear(); - for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm) - { - N_vdw_type_[ topIn[*atm].TypeIndex() ]++; - vdw_type_.push_back( topIn[*atm].TypeIndex() ); - } - if (debug_ > 0) { - mprintf("DEBUG: %zu VDW types.\n", N_vdw_type_.size()); - for (Iarray::const_iterator it = N_vdw_type_.begin(); it != N_vdw_type_.end(); ++it) - mprintf("\tType %li = %i\n", it-N_vdw_type_.begin(), *it); - } - // Determine correction term from types and LJ B parameters - for (unsigned int itype = 0; itype != N_vdw_type_.size(); itype++) - { - double atype_vdw_term = 0.0; // term for each nonbond atom type - unsigned int offset = N_vdw_type_.size() * itype; - for (unsigned int jtype = 0; jtype != N_vdw_type_.size(); jtype++) - { - unsigned int idx = offset + jtype; - int nbidx = NB_->NBindex()[ idx ]; - if (nbidx > -1) { - atype_vdw_term += N_vdw_type_[itype] * N_vdw_type_[jtype] * NB_->NBarray()[ nbidx ].B(); - - Vdw_Recip_term_ += N_vdw_type_[itype] * N_vdw_type_[jtype] * NB_->NBarray()[ nbidx ].B(); - } - } - atype_vdw_recip_terms_.push_back(atype_vdw_term); // the nonbond interaction for each atom type - } -} - -/** Calculate full VDW long range correction from volume. */ -double Ewald::Vdw_Correction(double volume) { - double prefac = Constants::TWOPI / (3.0*volume*cutoff_*cutoff_*cutoff_); - double e_vdwr = -prefac * Vdw_Recip_term_; - if (debug_ > 0) mprintf("DEBUG: Vdw correction %20.10f\n", e_vdwr); - return e_vdwr; -} - -#ifdef DEBUG_EWALD -/** Calculate direct space energy. This is the slow version that doesn't - * use a pair list; for debug purposes only. - */ -double Ewald::Direct(Matrix_3x3 const& ucell, Topology const& tIn, AtomMask const& mask) -{ - t_direct_.Start(); - double cut2 = cutoff_ * cutoff_; - double Eelec = 0.0; - Varray const& Image = pairList_.ImageCoords(); - Varray const& Frac = pairList_.FracCoords(); - unsigned int maxidx = Image.size(); - for (unsigned int idx1 = 0; idx1 != maxidx; idx1++) - { - // Set up coord for this atom - Vec3 const& crd1 = Image[idx1]; - // Set up exclusion list for this atom - int atom1 = mask[idx1]; - Atom::excluded_iterator excluded_atom = tIn[atom1].excludedbegin(); - for (unsigned int idx2 = idx1 + 1; idx2 != maxidx; idx2++) - { - int atom2 = mask[idx2]; - // If atom is excluded, just increment to next excluded atom. - if (excluded_atom != tIn[atom1].excludedend() && atom2 == *excluded_atom) { - ++excluded_atom; - //mprintf("ATOM: Atom %4i to %4i excluded.\n", atom1+1, atom2+1); - } else { - // Only need to check nearest neighbors. - Vec3 const& frac2 = Frac[idx2]; - for (Varray::const_iterator ixyz = Cells_.begin(); ixyz != Cells_.end(); ++ixyz) - { - Vec3 dxyz = ucell.TransposeMult(frac2 + *ixyz) - crd1; - double rij2 = dxyz.Magnitude2(); - if ( rij2 < cut2 ) { - double rij = sqrt( rij2 ); - // Coulomb - double qiqj = Charge_[idx1] * Charge_[idx2]; - t_erfc_.Start(); - //double erfc = erfc_func(ew_coeff_ * rij); - double erfc = ERFC(ew_coeff_ * rij); - t_erfc_.Stop(); - double e_elec = qiqj * erfc / rij; - Eelec += e_elec; - //mprintf("EELEC %4i%4i%12.5f%12.5f%12.5f%3.0f%3.0f%3.0f\n", -// mprintf("EELEC %6i%6i%12.5f%12.5f%12.5f\n", atom1, atom2, rij, erfc, e_elec); - // TODO can we break here? - } //else - //mprintf("ATOM: Atom %4i to %4i outside cut, %6.2f > %6.2f %3.0f%3.0f%3.0f\n", - //mprintf("ATOM: Atom %4i to %4i outside cut, %6.2f > %6.2f\n", - // atom1, atom2,sqrt(rij2),cutoff_); - } - } - } - } - t_direct_.Stop(); - return Eelec; -} - -/** Calculate Ewald energy. - * Slow version that does not use pair list. Note that pair list is still - * called since we require the fractional and imaged coords. - * FIXME No Eadjust calc. - */ -double Ewald::CalcEnergy_NoPairList(Frame const& frameIn, Topology const& topIn, - AtomMask const& maskIn) -{ - t_total_.Start(); - double volume = frameIn.BoxCrd().CellVolume(); - double e_self = Self( volume ); - // Place atoms in pairlist. This calcs frac/imaged coords. - pairList_.CreatePairList(frameIn, frameIn.BoxCrd().UnitCell(), frameIn.BoxCrd().FracCell(), maskIn); - - double e_recip = Recip_Regular( recip, volume ); - - double e_direct = Direct( ucell, topIn, maskIn ); - - //mprintf("DEBUG: Eself= %20.10f Erecip= %20.10f Edirect= %20.10f\n", - // e_self, e_recip, e_direct); - t_total_.Stop(); - return e_self + e_recip + e_direct; -} -#endif /* DEBUG_EWALD */ - -// Ewald::Timing() -void Ewald::Timing(double total) const { - t_total_.WriteTiming(1, " EwaldTotal:", total); - t_self_.WriteTiming(2, "Self: ", t_total_.Total()); - t_recip_.WriteTiming(2, "Recip: ", t_total_.Total()); - if (t_trig_tables_.Total() > 0.0) - t_trig_tables_.WriteTiming(3, "Calc trig tables:", t_recip_.Total()); - t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); -# ifndef _OPENMP - t_erfc_.WriteTiming(3, "ERFC: ", t_direct_.Total()); - t_adjust_.WriteTiming(3,"Adjust:", t_direct_.Total()); -# endif - pairList_.Timing(total); -} diff --git a/src/Ewald.h b/src/Ewald.h deleted file mode 100644 index 5996e5a77d..0000000000 --- a/src/Ewald.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef INC_EWALD_H -#define INC_EWALD_H -class Topology; -class AtomMask; -class Frame; -class NonbondParmType; -class EwaldOptions; -#include "Timer.h" -#include "PairList.h" -#include "ExclusionArray.h" -#include "SplineFxnTable.h" -/// Base class for calculating non-bonded energy using Ewald methods. -class Ewald { - public: - Ewald(); - // ----- Virtual functions ------------------- - virtual ~Ewald() {} - virtual int Init(Box const&, EwaldOptions const&, int) = 0; - virtual int Setup(Topology const&, AtomMask const&) = 0; - /// Calculate electrostatic and van der Waals energy - virtual int CalcNonbondEnergy(Frame const&, AtomMask const&, double&, double&) = 0; - // ------------------------------------------- - /// Report timings. - void Timing(double) const; -# ifdef DEBUG_EWALD - /// Slow non-pairlist version of energy calc. For debug only. - double CalcEnergy_NoPairList(Frame const&, Topology const&, AtomMask const&); -# endif - protected: - typedef std::vector Darray; - typedef std::vector Iarray; - typedef std::vector Varray; - - static inline double DABS(double xIn) { if (xIn < 0.0) return -xIn; else return xIn; } - /// Complimentary error function, erfc. - static double erfc_func(double); - - /// Ewald "self" energy - double Self(double); - /// Ewald "self" energy for C6 term - double Self6(); - /// Get analytical estimate of energy due to dispersion interactions > cutoff - double Vdw_Correction(double); - /// Box, debug, cutoff, dsum tol, ew coeff, lj coeff, switch window, erfc dx, nb skin - int CheckInput(Box const&, int, double, double, double, double, double, double, double); - /// Set up pair list for given box and NB "skin" size - int Setup_Pairlist(Box const&, double); - /// Calculate sum q, sum q^2. Calls setup for vdw correction - void CalculateCharges(Topology const&, AtomMask const&); - /// Calculate VDW C6 parameters for LJ PME - void CalculateC6params(Topology const&, AtomMask const&); - /// Setup main excluded atom list - void SetupExclusionList(Topology const&, AtomMask const&); - -# ifdef DEBUG_EWALD - /// Slow version of direct space energy, no pairlist. - double Direct(Matrix_3x3 const&, Topology const&, AtomMask const&); -# endif - /// Fast version of direct space energy using a pairlist - double Direct(PairList const&, double&, double&); - /// \return adjusted energy for excluded atom pair -# ifdef _OPENMP - inline double Adjust(double,double,double) const; -# else - inline double Adjust(double,double,double); // Cannot be const bc timers -# endif - - /// \return sum of charges squared - double SumQ2() const { return sumq2_; } - /// \return sum of charges - double SumQ() const { return sumq_; } - /// \return VDW recip correction term from # types and B parameters - double Vdw_Recip_Term() const { return Vdw_Recip_term_; } - /// \return Atom exclusion array - ExclusionArray const& Excluded() const { return Excluded_; } - /// \return Value of Erfc at given value - double ErfcFxn(double) const; - /// \return Nonbond parameters - NonbondParmType const& NB() const { return *NB_; } - /// \return Type index for given atom - int TypeIdx(unsigned int idx) const { return TypeIndices_[idx]; } - /// \return Value of LJ switching function - static double SwitchFxn(double, double, double); - /// \return Value of Ewald adjustment -# ifdef _OPENMP - double AdjustFxn(double,double,double) const; -# else - double AdjustFxn(double,double,double); -# endif - - // TODO make variables private - Darray Charge_; ///< Hold selected atomic charges converted to Amber units. - Darray Cparam_; ///< Hold selected atomic C6 coefficients for LJ PME - PairList pairList_; ///< Atom pair list for direct sum. - - Iarray vdw_type_; ///< Store nonbond vdw type for each atom - Iarray N_vdw_type_; ///< Total number of atoms for each vdw type - Darray atype_vdw_recip_terms_; ///< Nonbond PME interaction correction for each vdw type - - static const double INVSQRTPI_; - double ew_coeff_; ///< Ewald coefficient for electrostatics - double lw_coeff_; ///< Ewald coefficient for LJ - double switch_width_; ///< Switching window size for LJ switch if active - double cutoff_; ///< Direct space cutoff - double cut2_; ///< Direct space cutoff squared. - double cut2_0_; ///< Direct space cutoff minus switch width, squared. - double dsumTol_; ///< Direct space sum tolerance. - int debug_; - Timer t_total_; // TODO make timing external - Timer t_self_; - Timer t_recip_; - Timer t_trig_tables_; - Timer t_direct_; - Timer t_erfc_; - Timer t_adjust_; - private: - /// \return erfc value from erfc lookup table. - inline double ERFC(double) const; - /// Determine Ewald coefficient from cutoff and direct sum tolerance. - static double FindEwaldCoefficient(double,double); - - /// Setup VDW correction for selected atom types - void Setup_VDW_Correction(Topology const&, AtomMask const&); - /// Direct-space energy with VDW long range corrected energy - double Direct_VDW_LongRangeCorrection(PairList const&, double&, double&); - /// Direct-space energy with VDW handled via PME - double Direct_VDW_LJPME(PairList const&, double&, double&); - - SplineFxnTable table_; ///< Hold spline interpolation for erfc -# ifdef DEBUG_EWALD - Varray Cells_; ///< Hold fractional translations to neighbor cells (non-pairlist only) -# endif - double sumq_; ///< Sum of charges - double sumq2_; ///< Sum of charges squared - double Vdw_Recip_term_; ///< VDW recip correction term from # types and B parameters - // TODO should Exlcusions be passed in? - ExclusionArray Excluded_; ///< Full exclusion list for each selected atom. - Iarray TypeIndices_; ///< Hold atom type indices for selected atoms - NonbondParmType const* NB_; ///< Pointer to nonbonded parameters - -}; -#endif diff --git a/src/EwaldOptions.cpp b/src/EwaldOptions.cpp index 05dbd53a20..868363b6ef 100644 --- a/src/EwaldOptions.cpp +++ b/src/EwaldOptions.cpp @@ -72,6 +72,10 @@ int EwaldOptions::GetCommaSeparatedArgs(ArgList& argIn, const char* keyword, int /** Parse Ewald options from ArgList. */ int EwaldOptions::GetOptions(OptType typeIn, ArgList& actionArgs, const char* desc) { + if (typeIn == NOT_SET) { + mprinterr("Internal Error: EwaldOptions::GetOptions(): Type is not set.\n"); + return 1; + } type_ = typeIn; // Common options cutoff_ = actionArgs.getKeyDouble("cut", 8.0); @@ -82,27 +86,31 @@ int EwaldOptions::GetOptions(OptType typeIn, ArgList& actionArgs, const char* de // LJ Options // NOTE: lwcoeff_ > 0 is LJPME on. An lwcoeff_ of -1 is off, and 0 is set from ewcoeff_. lwcoeff_ = -1; - if (actionArgs.hasKey("ljpme")) { + if (actionArgs.hasKey("ljpme") || type_ == LJPME) { if (!allowLjPme_) { mprinterr("Error: LJ PME option 'ljpme' not allowed for '%s'\n", desc); return 1; } + type_ = LJPME; lwcoeff_ = 0.4; } lwcoeff_ = actionArgs.getKeyDouble("ewcoefflj", lwcoeff_); - if (!allowLjPme_ && lwcoeff_ >= 0) { - mprinterr("Error: LJ PME option 'ewcoefflj' not allowed for '%s'\n", desc); - return 1; + if (lwcoeff_ >= 0) { + if (!allowLjPme_) { + mprinterr("Error: LJ PME option 'ewcoefflj' not allowed for '%s'\n", desc); + return 1; + } + type_ = LJPME; } ljswidth_ = actionArgs.getKeyDouble("ljswidth", 0.0); // Regular Ewald options - if (type_ != PME) { + if (!IsPmeType()) { rsumtol_ = actionArgs.getKeyDouble("rsumtol", 5E-5); maxexp_ = actionArgs.getKeyDouble("maxexp", 0.0); if (GetCommaSeparatedArgs(actionArgs, "mlimits", mlimits1_, mlimits2_, mlimits3_, 0)) return 1; } // PME options - if (type_ != REG_EWALD) { + if (IsPmeType()) { npoints_ = actionArgs.getKeyInt("order", 6); if (GetCommaSeparatedArgs(actionArgs, "nfft", nfft1_, nfft2_, nfft3_, -1)) return 1; } @@ -124,7 +132,7 @@ void EwaldOptions::PrintOptions() const { if (skinnb_ > 0) mprintf("\tSize of non-bonded \"skin\"= %.4f\n", skinnb_); // Regular Ewald options - if (type_ != PME) { + if (!IsPmeType()) { if (rsumtol_ != 0.0) mprintf("\tReciprocal sum tolerance= %g\n", rsumtol_); if (maxexp_ == 0.0) @@ -138,16 +146,14 @@ void EwaldOptions::PrintOptions() const { mlimits1_, mlimits2_, mlimits3_); } // PME options - if (type_ != REG_EWALD) { + if (IsPmeType()) { mprintf("\tSpline order= %i\n", npoints_); if (nfft1_ < 1 && nfft2_ < 1 && nfft3_ < 1) mprintf("\tWill determine number of FFT grid points from box size.\n"); else mprintf("\tNumber of FFT grid points in each direction= {%i,%i,%i}\n", nfft1_, nfft2_, nfft3_); - } - // LJ options - if (type_ != REG_EWALD) { + // LJ options if (lwcoeff_ < 0) mprintf("\tUsing long range correction for nonbond VDW calc.\n"); else if (lwcoeff_ > 0.0) diff --git a/src/EwaldOptions.h b/src/EwaldOptions.h index c9ded8ee0f..25dd1bad6c 100644 --- a/src/EwaldOptions.h +++ b/src/EwaldOptions.h @@ -6,7 +6,7 @@ class EwaldOptions { public: EwaldOptions(); /// Type of options - enum OptType { NOT_SET = 0, REG_EWALD, PME }; + enum OptType { NOT_SET = 0, REG_EWALD, PME, LJPME }; static const char* KeywordsCommon1(); static const char* KeywordsCommon2(); @@ -20,8 +20,10 @@ class EwaldOptions { int GetOptions(OptType, ArgList&, const char*); /// Print options to stdout void PrintOptions() const; - + /// \return Current calculation type OptType Type() const { return type_; } + /// \return True if current calculation is a PME type + bool IsPmeType() const { return (type_ == PME) || (type_ == LJPME); } // Options common to all Ewald double Cutoff() const { return cutoff_; } diff --git a/src/Ewald_ParticleMesh.cpp b/src/Ewald_ParticleMesh.cpp deleted file mode 100644 index 9336c00c78..0000000000 --- a/src/Ewald_ParticleMesh.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#ifdef LIBPME -#include // copy/fill -//#incl ude // unique_ptr -#include "Ewald_ParticleMesh.h" -#include "CpptrajStdio.h" -#include "AtomMask.h" -#include "Frame.h" -#include "EwaldOptions.h" - -typedef helpme::Matrix Mat; - -/// CONSTRUCTOR -Ewald_ParticleMesh::Ewald_ParticleMesh() : order_(6) -{ - nfft_[0] = -1; - nfft_[1] = -1; - nfft_[2] = -1; -} - -/** \return true if given number is a product of powers of 2, 3, or 5. */ -static inline bool check_prime_factors(int nIn) { - if (nIn == 1) return true; - int NL = nIn; - int NQ; - // First divide down by 2 - while (NL > 0) { - NQ = NL / 2; - if (NQ * 2 != NL) break; - if (NQ == 1) return true; - NL = NQ; - } - // Next try 3 - while (NL > 0) { - NQ = NL / 3; - if (NQ * 3 != NL) break; - if (NQ == 1) return true; - NL = NQ; - } - // Last try 5 - while (NL > 0) { - NQ = NL / 5; - if (NQ * 5 != NL) break; - if (NQ == 1) return true; - NL = NQ; - } - return false; -} - -/** Compute the ceiling of len that is also a product of powers of 2, 3, 5. - * Use check_prime_factors to get the smallest integer greater or equal - * than len which is decomposable into powers of 2, 3, 5. - */ -int Ewald_ParticleMesh::ComputeNFFT(double len) { - int mval = (int)len - 1; - for (int i = 0; i < 100; i++) { - mval += 1; - // Sanity check - if (mval < 1) { - mprinterr("Error: Bad box length %g, cannot get NFFT value.\n", len); - return 0; - } - if (check_prime_factors(mval)) - return mval; - } - mprinterr("Error: Failed to get good FFT array size for length %g Ang.\n", len); - return 0; -} - -/** 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.Param(Box::X) + 1.0) * 0.5 ); - nfft1 *= 2; - } - if (nfft2 < 1) - nfft2 = ComputeNFFT( boxIn.Param(Box::Y) ); - if (nfft3 < 1) - nfft3 = ComputeNFFT( boxIn.Param(Box::Z) ); - - 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; -} - -/** Set up PME parameters. */ -int Ewald_ParticleMesh::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) -{ - // Sanity check - if (pmeOpts.Type() == EwaldOptions::REG_EWALD) { - mprinterr("Internal Error: Options were set up for regular Ewald only.\n"); - return 1; - } - if (CheckInput(boxIn, debugIn, pmeOpts.Cutoff(), pmeOpts.DsumTol(), pmeOpts.EwCoeff(), - pmeOpts.LwCoeff(), pmeOpts.LJ_SwWidth(), - pmeOpts.ErfcDx(), pmeOpts.SkinNB())) - return 1; - nfft_[0] = pmeOpts.Nfft1(); - nfft_[1] = pmeOpts.Nfft2(); - nfft_[2] = pmeOpts.Nfft3(); - order_ = pmeOpts.SplineOrder(); - - // Set defaults if necessary - if (order_ < 1) order_ = 6; - - mprintf("\tParticle Mesh Ewald params:\n"); - mprintf("\t Cutoff= %g Direct Sum Tol= %g Ewald coeff.= %g NB skin= %g\n", - cutoff_, dsumTol_, ew_coeff_, pmeOpts.SkinNB()); - if (lw_coeff_ > 0.0) - mprintf("\t LJ Ewald coeff.= %g\n", lw_coeff_); - if (switch_width_ > 0.0) - mprintf("\t LJ switch width= %g\n", switch_width_); - mprintf("\t Bspline order= %i\n", order_); - //mprintf("\t Erfc table dx= %g, size= %zu\n", erfcTableDx_, erfc_table_.size()/4); - mprintf("\t "); - for (int i = 0; i != 3; i++) - if (nfft_[i] == -1) - mprintf(" NFFT%i=auto", i+1); - else - mprintf(" NFFT%i=%i", i+1, nfft_[i]); - mprintf("\n"); - - // Set up pair list - if (Setup_Pairlist(boxIn, pmeOpts.SkinNB())) return 1; - - return 0; -} - -/** Set up PME parameters. */ -/* -int Ewald_ParticleMesh::Init(Box const& boxIn, double cutoffIn, double dsumTolIn, - double ew_coeffIn, double lw_coeffIn, double switch_widthIn, - double skinnbIn, double erfcTableDxIn, - int orderIn, int debugIn, const int* nfftIn) -{ - if (CheckInput(boxIn, debugIn, cutoffIn, dsumTolIn, ew_coeffIn, lw_coeffIn, switch_widthIn, - erfcTableDxIn, skinnbIn)) - return 1; - if (nfftIn != 0) - std::copy(nfftIn, nfftIn+3, nfft_); - else - std::fill(nfft_, nfft_+3, -1); - order_ = orderIn; - - // Set defaults if necessary - if (order_ < 1) order_ = 6; - - mprintf("\tParticle Mesh Ewald params:\n"); - mprintf("\t Cutoff= %g Direct Sum Tol= %g Ewald coeff.= %g NB skin= %g\n", - cutoff_, dsumTol_, ew_coeff_, skinnbIn); - if (lw_coeff_ > 0.0) - mprintf("\t LJ Ewald coeff.= %g\n", lw_coeff_); - if (switch_width_ > 0.0) - mprintf("\t LJ switch width= %g\n", switch_width_); - mprintf("\t Bspline order= %i\n", order_); - //mprintf("\t Erfc table dx= %g, size= %zu\n", erfcTableDx_, erfc_table_.size()/4); - mprintf("\t "); - for (int i = 0; i != 3; i++) - if (nfft_[i] == -1) - mprintf(" NFFT%i=auto", i+1); - else - mprintf(" NFFT%i=%i", i+1, nfft_[i]); - mprintf("\n"); - - // Set up pair list - if (Setup_Pairlist(boxIn, skinnbIn)) return 1; - - return 0; -}*/ - -/** Setup PME calculation. */ -int Ewald_ParticleMesh::Setup(Topology const& topIn, AtomMask const& maskIn) { - CalculateCharges(topIn, maskIn); - // NOTE: These dont need to actually be calculated if the lj ewald coeff - // is 0.0, but do it here anyway to avoid segfaults. - CalculateC6params( topIn, maskIn ); - coordsD_.clear(); - coordsD_.reserve( maskIn.Nselected() * 3); - SetupExclusionList(topIn, maskIn); - return 0; -} - -/* -static inline void PrintM(const char* Title, Mat const& M_) -{ - mprintf(" %s\n",Title); - mprintf(" %16.10f %16.10f %16.10f\n", M_(0,0), M_(0,1), M_(0,2)); - mprintf(" %16.10f %16.10f %16.10f\n", M_(1,0), M_(1,1), M_(1,2)); - mprintf(" %16.10f %16.10f %16.10f\n", M_(2,0), M_(2,1), M_(2,2)); -}*/ - -// 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(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.Param(Box::X), boxIn.Param(Box::Y), boxIn.Param(Box::Z), - boxIn.Param(Box::ALPHA), boxIn.Param(Box::BETA), boxIn.Param(Box::GAMMA), - PMEInstanceD::LatticeType::XAligned); - double erecip = pme_object_.computeERec(0, chargesD, coordsD); - - t_recip_.Stop(); - return erecip; -} - -/** 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(new PMEInstanceD()); - pme_vdw_.setup(6, lw_coeff_, order_, nfft1, nfft2, nfft3, -1.0, 0); - PMEInstanceD::LatticeType lattice = PMEInstanceD::LatticeType::XAligned; - // TODO just pass in Ucell when helPME supports it - //boxIn.PrintDebug("pme"); - if (!boxIn.Is_X_Aligned()) { - if (boxIn.Is_Symmetric()) - lattice = PMEInstanceD::LatticeType::ShapeMatrix; - else { - mprinterr("Error: Unit cell is not X-aligned or symmetric; cannot set PME recip grid.\n"); - return 0; - } - } - pme_vdw_.setLatticeVectors(boxIn.Param(Box::X), boxIn.Param(Box::Y), boxIn.Param(Box::Z), - boxIn.Param(Box::ALPHA), boxIn.Param(Box::BETA), boxIn.Param(Box::GAMMA), - lattice); - double evdwrecip = pme_vdw_.computeERec(0, cparamD, coordsD); - t_recip_.Stop(); - return evdwrecip; -} - -/** Calculate full nonbonded energy with PME */ -int Ewald_ParticleMesh::CalcNonbondEnergy(Frame const& frameIn, AtomMask const& maskIn, - double& e_elec, double& e_vdw) -{ - t_total_.Start(); - double volume = frameIn.BoxCrd().CellVolume(); - double e_self = Self( volume ); - double e_vdw_lr_correction; - - int retVal = pairList_.CreatePairList(frameIn, frameIn.BoxCrd().UnitCell(), frameIn.BoxCrd().FracCell(), maskIn); - if (retVal != 0) { - mprinterr("Error: Grid setup failed.\n"); - return 1; - } - - // TODO make more efficient - int idx = 0; - coordsD_.clear(); - for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm, ++idx) { - const double* XYZ = frameIn.XYZ( *atm ); - coordsD_.push_back( XYZ[0] ); - coordsD_.push_back( XYZ[1] ); - coordsD_.push_back( XYZ[2] ); - } - -// MapCoords(frameIn, ucell, recip, maskIn); - double e_recip = Recip_ParticleMesh( frameIn.BoxCrd() ); - - // TODO branch - double e_vdw6self, e_vdw6recip; - if (lw_coeff_ > 0.0) { - e_vdw6self = Self6(); - e_vdw6recip = LJ_Recip_ParticleMesh( frameIn.BoxCrd() ); - if (debug_ > 0) { - mprintf("DEBUG: e_vdw6self = %16.8f\n", e_vdw6self); - mprintf("DEBUG: Evdwrecip = %16.8f\n", e_vdw6recip); - } - e_vdw_lr_correction = 0.0; - } else { - e_vdw6self = 0.0; - e_vdw6recip = 0.0; - e_vdw_lr_correction = Vdw_Correction( volume ); - } - - e_vdw = 0.0; - double e_adjust = 0.0; - double e_direct = Direct( pairList_, e_vdw, e_adjust ); - if (debug_ > 0) { - mprintf("DEBUG: Nonbond energy components:\n"); - mprintf(" Evdw = %24.12f\n", e_vdw + e_vdw_lr_correction + e_vdw6self + e_vdw6recip); - mprintf(" Ecoulomb = %24.12f\n", e_self + e_recip + e_direct + e_adjust); - mprintf("\n"); - mprintf(" E electrostatic (self) = %24.12f\n", e_self); - mprintf(" (rec) = %24.12f\n", e_recip); - mprintf(" (dir) = %24.12f\n", e_direct); - mprintf(" (adj) = %24.12f\n", e_adjust); - mprintf(" E vanDerWaals (dir) = %24.12f\n", e_vdw); - mprintf(" (LR) = %24.12f\n", e_vdw_lr_correction); - mprintf(" (6slf) = %24.12f\n", e_vdw6self); - mprintf(" (6rcp) = %24.12f\n", e_vdw6recip); - } - e_vdw += (e_vdw_lr_correction + e_vdw6self + e_vdw6recip); - t_total_.Stop(); - e_elec = e_self + e_recip + e_direct + e_adjust; - return 0; -} - -#endif /* LIBPME */ diff --git a/src/Ewald_ParticleMesh.h b/src/Ewald_ParticleMesh.h deleted file mode 100644 index 60cd76c5ac..0000000000 --- a/src/Ewald_ParticleMesh.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef INC_EWALD_PARTICLEMESH_H -#define INC_EWALD_PARTICLEMESH_H -#ifdef LIBPME -#include "Ewald.h" -#include "helpme_standalone.h" -/// Class for calculating electrostatics with particle mesh Ewald. -class Ewald_ParticleMesh : public Ewald { - public: - Ewald_ParticleMesh(); - /// Virtual destructor since this can be inherited - virtual ~Ewald_ParticleMesh() {} - /// Box, cut, dsum tol, ew coeff, lj ew coeff, switch width, NB skin, erfc dx, order, dbg, nfft - //int Init(Box const&, double, double, double, double, double, double, double, - // int, int, const int*); - // ----- Inherited --------------------------- - /// Init with Box, EwaldOptions and debug level - int Init(Box const&, EwaldOptions const&, int); - int Setup(Topology const&, AtomMask const&); - int CalcNonbondEnergy(Frame const&, AtomMask const&, double&, double&); - - protected: - /// Determine grid points for FFT in each dimension - int DetermineNfft(int&, int&, int&, Box const&) const; - /// \return Number of FFT grid points in specified direction - int Nfft(unsigned int idx) const { return nfft_[idx]; } - /// \return PME B-spline order - int Order() const { return order_; } - - Darray coordsD_; ///< Hold coordinates for selected atoms - PMEInstanceD pme_object_; - PMEInstanceD pme_vdw_; - - private: - typedef Ewald::Darray Darray; - /// Based on given length return number of grid points that is power of 2, 3, or 5 - static int ComputeNFFT(double); - /// Particle mesh Ewald reciprocal energy - double Recip_ParticleMesh(Box const&); - /// Particle mesh Ewald LJ recip energy - double LJ_Recip_ParticleMesh(Box const&); - - - int nfft_[3]; ///< Number of FFT grid points in each direction - int order_; ///< PME B spline order - - }; -#endif /* LIBPME */ -#endif diff --git a/src/GIST_PME.cpp b/src/GIST_PME.cpp index 5e336c81ec..52c145d2a2 100644 --- a/src/GIST_PME.cpp +++ b/src/GIST_PME.cpp @@ -6,6 +6,8 @@ #include "Constants.h" #include "ParameterTypes.h" #include "Topology.h" +#include "EwaldOptions.h" +#include "Energy/Kernel_EwaldAdjust.h" /** CONSTRUCTOR */ GIST_PME::GIST_PME() : @@ -22,6 +24,34 @@ const char* GIST_PME::InteractionTypeStr_[] = { "Both_Ongrid" }; +/** Init GIST PME calculation */ +int GIST_PME::Init(Box const& boxIn, EwaldOptions const& pmeOpts, int debugIn) +{ + // Sanity check + if (pmeOpts.Type() != EwaldOptions::PME) { + mprinterr("Internal Error: GIST_PME::Init(): Options were not set up for non-LJ PME.\n"); + return 1; + } + mprintf("\tGIST Particle Mesh Ewald params:\n"); + if (InitEwald(boxIn, pmeOpts, debugIn)) { + mprinterr("Error: GIST PME calculation init failed.\n"); + return 1; + } + if (recipParams_.InitRecip(pmeOpts, debugIn)) { + mprinterr("Error: GIST PME calculation recip init failed.\n"); + return 1; + } + VDW_LR_.SetDebug( debugIn ); + // Ewald calcs need pairlist + if (pairList_.InitPairList(pmeOpts.Cutoff(), pmeOpts.SkinNB(), debugIn)) + return 1; + if (pairList_.SetupPairList( boxIn )) + return 1; + + return 0; +} + + /** Setup up GIST PME calculation. Currently must be run on all atoms. */ int GIST_PME::Setup_PME_GIST(Topology const& topIn, unsigned int nthreads, double NeighborCut2_in) { @@ -29,10 +59,24 @@ int GIST_PME::Setup_PME_GIST(Topology const& topIn, unsigned int nthreads, doubl // Select everything allAtoms_ = AtomMask(0, topIn.Natom()); // Set up PME - if (Setup( topIn, allAtoms_ )) { + if (SetupEwald( topIn, allAtoms_ )) { mprinterr("Error: GIST PME setup failed.\n"); return 1; } + // Set up VDW long range correction + if (VDW_LR_.Setup_VDW_Correction( topIn, allAtoms_ )) { + mprinterr("Error: GIST PME calculation long range VDW correction setup failed.\n"); + return 1; + } + // Setup exclusion list + // Use distance of 4 (up to dihedrals) + if (excluded_.SetupExcluded(topIn.Atoms(), allAtoms_, 4, + ExclusionArray::EXCLUDE_SELF, + ExclusionArray::FULL)) + { + mprinterr("Error: Could not set up exclusion list for GIST PME calculation.\n"); + return 1; + } // Allocate voxel arrays int natoms = topIn.Natom(); // TODO unsigned int? @@ -112,7 +156,7 @@ int GIST_PME::CalcNonbondEnergy_GIST(Frame const& frameIn, coordsD_.push_back( XYZ[2] ); } - unsigned int natoms = E_elec_self_.size(); + //unsigned int natoms = E_elec_self_.size(); // Recip Potential for each atom e_potentialD_.setConstant(0.0); @@ -126,7 +170,7 @@ int GIST_PME::CalcNonbondEnergy_GIST(Frame const& frameIn, // TODO branch // e_vdw_lr_correction was previously set but unused. // double e_vdw_lr_correction; - double e_vdw6self, e_vdw6recip; + /*double e_vdw6self, e_vdw6recip; if (lw_coeff_ > 0.0) { std::fill(E_vdw_self_.begin(), E_vdw_self_.end(), 0); e_vdw6self = Self6_GIST(E_vdw_self_); @@ -151,12 +195,12 @@ int GIST_PME::CalcNonbondEnergy_GIST(Frame const& frameIn, // e_vdw_lr_correction = 0.0; } else { e_vdw6self = 0.0; - e_vdw6recip = 0.0; + e_vdw6recip = 0.0;*/ std::fill(E_vdw_lr_cor_.begin(), E_vdw_lr_cor_.end(), 0); // e_vdw_lr_correction = Vdw_Correction_GIST( volume, atomIsSolute, E_UV_in[0], E_VV_in[0] ); Vdw_Correction_GIST( volume, atomIsSolute, E_UV_in[0], E_VV_in[0] ); //mprintf("e_vdw_lr_correction: %f \n", e_vdw_lr_correction); - } + /*}*/ double e_vdw = 0.0; double e_direct = Direct_GIST( pairList_, e_vdw, atom_voxel, atomIsSolute, atomIsSolventO, @@ -166,7 +210,7 @@ int GIST_PME::CalcNonbondEnergy_GIST(Frame const& frameIn, //mprintf("e_elec_self: %f , e_elec_direct: %f, e_vdw6direct: %f \n", e_self, e_direct, e_vdw); - if (debug_ > 0) + if (Debug() > 0) mprintf("DEBUG: gistpme Eself= %20.10f Erecip= %20.10f Edirect= %20.10f Evdw= %20.10f\n", e_self, e_recip, e_direct, e_vdw); @@ -197,7 +241,7 @@ int GIST_PME::CalcNonbondEnergy_GIST(Frame const& frameIn, # endif // DEBUG - if (debug_ > 0) { + if (Debug() > 0) { // Calculate the sum of each terms double E_elec_direct_sum = SumDarray( E_elec_direct_[0] ); double E_vdw_direct_sum = SumDarray( E_vdw_direct_[0] ); @@ -225,12 +269,13 @@ double GIST_PME::Self_GIST(double volume, Darray& atom_self, Darray& e_vv_elec) { t_self_.Start(); - double d0 = -ew_coeff_ * INVSQRTPI_; + double d0 = -EwaldCoeff() * INVSQRTPI(); double ene = SumQ2() * d0; // mprintf("DEBUG: d0= %20.10f ene= %20.10f\n", d0, ene); - double factor = Constants::PI / (ew_coeff_ * ew_coeff_ * volume); + double factor = Constants::PI / (EwaldCoeff() * EwaldCoeff() * volume); double ee_plasma = -0.5 * factor * SumQ() * SumQ(); + Darray const& Charge_ = Charge(); for( unsigned int i=0; i< Charge_.size();i++) { // distribute the "neutrilizing plasma" to atoms equally @@ -253,7 +298,7 @@ double GIST_PME::Self_GIST(double volume, Darray& atom_self, } /** Lennard-Jones self energy. for GIST */ -double GIST_PME::Self6_GIST(Darray& atom_vdw_self) { +/*double GIST_PME::Self6_GIST(Darray& atom_vdw_self) { t_self_.Start(); // TODO precalc double ew2 = lw_coeff_ * lw_coeff_; double ew6 = ew2 * ew2 * ew2; @@ -267,7 +312,7 @@ double GIST_PME::Self6_GIST(Darray& atom_vdw_self) { } t_self_.Stop(); return c6sum / 12.0; -} +}*/ /** PME recip calc for GIST to store decomposed recipical energy for every atom. */ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, @@ -277,12 +322,10 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, { t_recip_.Start(); // This essentially makes coordsD and chargesD point to arrays. - MatType coordsD(&coordsD_[0], Charge_.size(), 3); - MatType chargesD(&Charge_[0], Charge_.size(), 1); - int nfft1 = Nfft(0); - int nfft2 = Nfft(1); - int nfft3 = Nfft(2); - if ( DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { + MatType coordsD(&coordsD_[0], Charge().size(), 3); + MatType chargesD(&SelectedCharges()[0], Charge().size(), 1); + int nfft1, nfft2, nfft3; + if ( recipParams_.DetermineNfft(nfft1, nfft2, nfft3, boxIn) ) { mprinterr("Error: Could not determine grid spacing.\n"); return 0.0; } @@ -298,7 +341,7 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, // 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(new PMEInstanceD()); - pme_object_.setup(1, ew_coeff_, Order(), nfft1, nfft2, nfft3, 1.0, 0); + pme_object_.setup(1, EwaldCoeff(), recipParams_.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. @@ -313,9 +356,9 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, //double erecip = pme_object_.computeERec(0, chargesD, coordsD); double erecip = 0; pme_object_.computePRec(0,chargesD,coordsD,coordsD,1,e_potentialD_); - for(unsigned int i =0; i < Charge_.size(); i++) + for(unsigned int i =0; i < Charge().size(); i++) { - E_elec_recip_[i]=0.5 * Charge_[i] * e_potentialD_(i,0); + E_elec_recip_[i]=0.5 * Charge()[i] * e_potentialD_(i,0); } // For UV interaction, we need solute charges + positions and on-grid solvent positions. @@ -326,18 +369,18 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, Darray Vcoords, Vcharges; unsigned int xidx = 0; // Index into coordsD_ unsigned int n_on_grid = 0; // Number of solvent atoms on grid - for (unsigned int atidx = 0; atidx != Charge_.size(); atidx++, xidx += 3) + for (unsigned int atidx = 0; atidx != Charge().size(); atidx++, xidx += 3) { if (atomIsSolute[atidx]) { Ucoords.push_back( coordsD_[xidx ] ); Ucoords.push_back( coordsD_[xidx+1] ); Ucoords.push_back( coordsD_[xidx+2] ); - Ucharges.push_back( Charge_[atidx] ); + Ucharges.push_back( Charge()[atidx] ); } else { Vcoords.push_back( coordsD_[xidx ] ); Vcoords.push_back( coordsD_[xidx+1] ); Vcoords.push_back( coordsD_[xidx+2] ); - Vcharges.push_back( Charge_[atidx] ); + Vcharges.push_back( Charge()[atidx] ); if (atom_voxel[atidx] > -1) { onGridCoords.push_back( coordsD_[xidx ] ); onGridCoords.push_back( coordsD_[xidx+1] ); @@ -360,7 +403,7 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, # ifdef DEBUG_GIST_PME mprintf("DEBUG: gistpme uv recip at %i erecip= %20.10g\n", onGridAt[i], Charge_[onGridAt[i]] * ongrid_potentialD(i, 0)); # endif - e_uv_elec[onGridAt[i]] += Charge_[onGridAt[i]] * ongrid_potentialD(i, 0); + e_uv_elec[onGridAt[i]] += Charge()[onGridAt[i]] * ongrid_potentialD(i, 0); } // VV recip. // NOTE: If we do not zero the potential matrix, it will be summed into @@ -370,7 +413,7 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, # ifdef DEBUG_GIST_PME mprintf("DEBUG: gistpme vv recip at %i erecip= %20.10g\n", onGridAt[i], Charge_[onGridAt[i]] * ongrid_potentialD(i, 0)); # endif - e_vv_elec[onGridAt[i]] += Charge_[onGridAt[i]] * ongrid_potentialD(i, 0); + e_vv_elec[onGridAt[i]] += Charge()[onGridAt[i]] * ongrid_potentialD(i, 0); } t_recip_.Stop(); @@ -378,7 +421,7 @@ double GIST_PME::Recip_ParticleMesh_GIST(Box const& boxIn, } /** The LJ PME reciprocal term for GIST*/ -double GIST_PME::LJ_Recip_ParticleMesh_GIST(Box const& boxIn, MatType& potential) +/*double GIST_PME::LJ_Recip_ParticleMesh_GIST(Box const& boxIn, MatType& potential) { t_recip_.Start(); int nfft1 = Nfft(0); @@ -402,7 +445,7 @@ double GIST_PME::LJ_Recip_ParticleMesh_GIST(Box const& boxIn, MatType& potential pme_vdw_.computePRec(0,cparamD,coordsD,coordsD,1,potential); t_recip_.Stop(); return evdwrecip; -} +}*/ /** Calculate full VDW long range correction from volume. */ double GIST_PME::Vdw_Correction_GIST(double volume, @@ -410,20 +453,20 @@ double GIST_PME::Vdw_Correction_GIST(double volume, std::vector const& atomIsSolute, Darray& e_uv_vdw, Darray& e_vv_vdw) { - double prefac = Constants::TWOPI / (3.0*volume*cutoff_*cutoff_*cutoff_); + double prefac = Constants::TWOPI / (3.0*volume*Cutoff()*Cutoff()*Cutoff()); //mprintf("VDW correction prefac: %.15f \n", prefac); - double e_vdwr = -prefac * Vdw_Recip_Term(); + double e_vdwr = -prefac * VDW_LR_.Vdw_Recip_Term(); //mprintf("Cparam size: %i \n",Cparam_.size()); //mprintf("volume of the unit cell: %f", volume); - for ( unsigned int i = 0; i != vdw_type_.size(); i++) + for ( unsigned int i = 0; i != VDW_LR_.VDW_Type().size(); i++) { double term(0); - int v_type=vdw_type_[i]; + int v_type = VDW_LR_.VDW_Type()[i]; //v_type is the vdw_type of atom i, each atom has a atom type @@ -433,7 +476,7 @@ double GIST_PME::Vdw_Correction_GIST(double volume, - term = atype_vdw_recip_terms_[v_type] / N_vdw_type_[v_type]; + term = VDW_LR_.Atype_VDW_Recip_Terms()[v_type] / VDW_LR_.N_VDW_Type()[v_type]; //mprintf("for i = %i,vdw_type = %i, Number of atoms in this vdw_type_= %i, Total vdw_recip_terms_ for this type= %f, vdw_recip_term for atom i= %f \n",i,vdw_type_[i],N_vdw_type_[vdw_type_[i]],atype_vdw_recip_terms_[vdw_type_[i]],term); @@ -458,7 +501,7 @@ double GIST_PME::Vdw_Correction_GIST(double volume, // } } - if (debug_ > 0) mprintf("DEBUG: gistpme Vdw correction %20.10f\n", e_vdwr); + if (Debug() > 0) mprintf("DEBUG: gistpme Vdw correction %20.10f\n", e_vdwr); return e_vdwr; } @@ -472,9 +515,9 @@ double GIST_PME::Direct_GIST(PairList const& PL, double& evdw_out, std::vector& Neighbor_in) { - if (lw_coeff_ > 0.0) - return Direct_VDW_LJPME_GIST(PL, evdw_out); - else + //if (lw_coeff_ > 0.0) + // return Direct_VDW_LJPME_GIST(PL, evdw_out); + //else return Direct_VDW_LongRangeCorrection_GIST(PL, evdw_out, atom_voxel, atomIsSolute, atomIsSolventO, E_UV_in, E_VV_in, @@ -567,18 +610,12 @@ void GIST_PME::Ekernel_NB(double& Eelec, double& Evdw, InteractionType interactionType,// int voxel0, int voxel1, double* e_uv,// double* e_uv_elec, double* e_vv)//, double* e_vv_elec) -//const Cannot be const because of the timer +const { double rij = sqrt( rij2 ); double qiqj = q0 * q1; -# ifndef _OPENMP - t_erfc_.Start(); -# endif //double erfc = erfc_func(ew_coeff_ * rij); - double erfc = ErfcFxn(ew_coeff_ * rij); -# ifndef _OPENMP - t_erfc_.Stop(); -# endif + double erfc = ErfcEW(rij); double e_elec = qiqj * erfc / rij; Eelec += e_elec; @@ -604,11 +641,10 @@ void GIST_PME::Ekernel_NB(double& Eelec, double& Evdw, e_vv[idx1] += e_elec; } - int nbindex = NB().GetLJindex(TypeIdx(idx0), - TypeIdx(idx1)); + int nbindex = NbIndex(idx0, idx1); if (nbindex > -1) { - double vswitch = SwitchFxn(rij2, cut2_0_, cut2_); - NonbondType const& LJ = NB().NBarray()[ nbindex ]; + double vswitch = Switch_Fn(rij2); + NonbondType const& LJ = GetLJ( nbindex ); double r2 = 1.0 / rij2; double r6 = r2 * r2 * r2; double r12 = r6 * r6; @@ -661,7 +697,10 @@ void GIST_PME::Ekernel_Adjust(double& e_adjust, double* e_uv_elec, double* e_vv_elec) { - double adjust = AdjustFxn(q0,q1,sqrt(rij2)); + //double adjust = AdjustFxn(q0,q1,sqrt(rij2)); + double rij = sqrt(rij2); + double erfcval = ErfcEW( rij ); + double adjust = Cpptraj::Energy::Kernel_EwaldAdjust( q0, q1, rij, erfcval ); e_adjust += adjust; @@ -757,7 +796,6 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& neighbor = &(Neighbor_in[mythread][0]); # pragma omp for # endif -//# include "PairListLoop.h" for (cidx = 0; cidx < PL.NGridMax(); cidx++) { PairList::CellType const& thisCell = PL.Cell( cidx ); @@ -772,7 +810,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& it0 != thisCell.end(); ++it0) { Vec3 const& xyz0 = it0->ImageCoords(); - double q0 = Charge_[it0->Idx()]; + double q0 = Charge()[it0->Idx()]; // The voxel # of it0 int it0_voxel = atom_voxel[it0->Idx()]; bool it0_solute = atomIsSolute[it0->Idx()]; @@ -782,7 +820,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& mprintf("DBG: Cell %6i (%6i atoms):\n", cidx+1, thisCell.NatomsInGrid()); # endif // Exclusion list for this atom - ExclusionArray::ExListType const& excluded = Excluded()[it0->Idx()]; + ExclusionArray::ExListType const& excluded = excluded_[it0->Idx()]; // Calc interaction of atom to all other atoms in thisCell. for (PairList::CellType::const_iterator it1 = it0 + 1; it1 != thisCell.end(); ++it1) @@ -792,7 +830,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& bool it1_solventO = atomIsSolventO[it1->Idx()]; if (it0_voxel > -1 || it1_voxel > -1) { Vec3 const& xyz1 = it1->ImageCoords(); - double q1 = Charge_[it1->Idx()]; + double q1 = Charge()[it1->Idx()]; Vec3 dxyz = xyz1 - xyz0; double rij2 = dxyz.Magnitude2(); # ifdef DEBUG_PAIRLIST @@ -802,7 +840,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& // If atom excluded, calc adjustment, otherwise calc elec. energy. if (excluded.find( it1->Idx() ) == excluded.end()) { - if ( rij2 < cut2_ ) { + if ( rij2 < Cut2() ) { Ekernel_NB(Eelec, Evdw, rij2, q0, q1, it0->Idx(), it1->Idx(), e_elec_direct, e_vdw_direct, interactionType,// it0_voxel, it1_voxel, // e_uv_vdw, e_uv_elec, e_vv_vdw, e_vv_elec); @@ -836,7 +874,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& bool it1_solventO = atomIsSolventO[it1->Idx()]; if (it0_voxel > -1 || it1_voxel > -1) { Vec3 const& xyz1 = it1->ImageCoords(); - double q1 = Charge_[it1->Idx()]; + double q1 = Charge()[it1->Idx()]; Vec3 dxyz = xyz1 + tVec - xyz0; double rij2 = dxyz.Magnitude2(); # ifdef DEBUG_PAIRLIST @@ -849,7 +887,7 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& if (excluded.find( it1->Idx() ) == excluded.end()) { //mprintf("\t\t\tdist= %f\n", sqrt(rij2)); - if ( rij2 < cut2_ ) { + if ( rij2 < Cut2() ) { Ekernel_NB(Eelec, Evdw, rij2, q0, q1, it0->Idx(), it1->Idx(), e_elec_direct, e_vdw_direct, interactionType,// it0_voxel, it1_voxel, // e_uv_vdw, e_uv_elec, e_vv_vdw, e_vv_elec); @@ -893,10 +931,10 @@ double GIST_PME::Direct_VDW_LongRangeCorrection_GIST(PairList const& PL, double& } /** Direct space calculation with LJ PME for GIST. */ // TODO enable -double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) -{ - mprinterr("Error: LJPME does not yet work with GIST.\n"); - return 0; +//double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) +//{ +// mprinterr("Error: LJPME does not yet work with GIST.\n"); +// return 0; /* t_direct_.Start(); double Eelec = 0.0; @@ -911,7 +949,6 @@ double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) { # pragma omp for # endif -//# include "PairListLoop.h" double Evdw_temp(0),Eljpme_correction_temp(0), Eljpme_correction_excl_temp(0); double Eelec_temp(0),E_adjust_temp(0); @@ -951,10 +988,10 @@ double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) if (excluded.find( it1->Idx() ) == excluded.end()) { if ( rij2 < cut2_ ) { -# include "EnergyKernel_Nonbond.h" +# incl ude "EnergyKernel_Nonbond.h" } } else { -# include "EnergyKernel_Adjust.h" +# incl ude "EnergyKernel_Adjust.h" } } // END loop over other atoms in thisCell // Loop over all neighbor cells @@ -985,10 +1022,10 @@ double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) { //mprintf("\t\t\tdist= %f\n", sqrt(rij2)); if ( rij2 < cut2_ ) { -# include "EnergyKernel_Nonbond.h" +# incl ude "EnergyKernel_Nonbond.h" } } else { -# include "EnergyKernel_Adjust.h" +# incl ude "EnergyKernel_Adjust.h" } } // END loop over neighbor cell atoms @@ -1026,5 +1063,18 @@ double GIST_PME::Direct_VDW_LJPME_GIST(PairList const& PL, double& evdw_out) evdw_out = Evdw + Eljpme_correction + Eljpme_correction_excl; return Eelec + e_adjust; */ -} +//} + +void GIST_PME::Timing(double total) const { + t_total_.WriteTiming(1, " GIST_PME_total:", total); + t_self_.WriteTiming(2, "Self: ", t_total_.Total()); + t_recip_.WriteTiming(2, "Recip: ", t_total_.Total()); + t_direct_.WriteTiming(2, "Direct: ", t_total_.Total()); +//# ifndef _OPENMP +// t_erfc_.WriteTiming(3, "ERFC: ", t_direct_.Total()); +// t_adjust_.WriteTiming(3,"Adjust:", t_direct_.Total()); +//# endif + pairList_.Timing(total); +} + #endif /* LIBPME */ diff --git a/src/GIST_PME.h b/src/GIST_PME.h index ca0baafe71..2f6865515e 100644 --- a/src/GIST_PME.h +++ b/src/GIST_PME.h @@ -2,29 +2,38 @@ #define INC_GIST_PME_H #ifdef LIBPME #include -#include "Ewald_ParticleMesh.h" #include "AtomMask.h" -class Frame; +#include "Energy/EwaldParams.h" +#include "Energy/PME_RecipParams.h" +#include "Energy/VDW_LongRange_Correction.h" +#include "ExclusionArray.h" +#include "helpme_standalone.h" +#include "PairList.h" +#include "Timer.h" class Box; +class Frame; class Topology; /// Class implementing the PME version of the nonbonded energy calc. for GIST /** For more debug info, compile with: * -DDEBUG_GIST_PME : Details on breakdown of PME calculation for the UV/VV grids. * -DDEBUG_PAIRLIST : Details on the use of the pair list in the direct space calc. */ -class GIST_PME : private Ewald_ParticleMesh { +class GIST_PME : private Cpptraj::Energy::EwaldParams { public: GIST_PME(); // Expose definitions/functions from Ewald_ParticleMesh - using Ewald::Darray; - using Ewald_ParticleMesh::Init; - using Ewald::Timing; + using Cpptraj::Energy::EwaldParams::Darray; + //using Ewald_ParticleMesh::Init; + //using Ewald::Timing; typedef std::vector Farray; + int Init(Box const&, EwaldOptions const&, int); /// Setup PME calc. for top, all atoms. Allocate memory for internal arrays (# threads) int Setup_PME_GIST(Topology const&, unsigned int, double); + /// Print timing data + void Timing(double) const; /// Calculate nonbonded energy with PME for GIST int CalcNonbondEnergy_GIST(Frame const&, std::vector const&, std::vector const&, @@ -70,7 +79,7 @@ class GIST_PME : private Ewald_ParticleMesh { /// Nonbond energy kernel inline void Ekernel_NB(double&, double&, double, double, double, int, int, double*, double*, - InteractionType, double*, double*); + InteractionType, double*, double*) const; // Adjust energy kernel inline void Ekernel_Adjust(double&, double, double, double, int, int, double*, InteractionType, double*, double*); @@ -78,12 +87,12 @@ class GIST_PME : private Ewald_ParticleMesh { /// Electrostatic self energy, decomposed onto atoms. double Self_GIST(double, Darray&, std::vector const&, std::vector const&, Darray&); /// Lennard-Jones self energy, decomposed onto atoms. - double Self6_GIST(Darray&); + //double Self6_GIST(Darray&); /// Reciprocal energy decomposed for every atom. double Recip_ParticleMesh_GIST(Box const&, std::vector const&, std::vector const&, Darray&, Darray&); /// LJ reciprocal term, decomposed for every atom. - double LJ_Recip_ParticleMesh_GIST(Box const&, MatType&); + //double LJ_Recip_ParticleMesh_GIST(Box const&, MatType&); /// VDW long range correction for GIST double Vdw_Correction_GIST(double, std::vector const&, Darray&, Darray&); @@ -102,7 +111,7 @@ class GIST_PME : private Ewald_ParticleMesh { std::vector&, std::vector&, std::vector&); /// Calculate direct space energy with LJ PME for GIST, decomposed for every atom. - double Direct_VDW_LJPME_GIST(PairList const&, double&); + //double Direct_VDW_LJPME_GIST(PairList const&, double&); // TODO could potentially make the calculation more efficient by skipping // the per-atom arrays below and just passing in the GIST PME @@ -123,6 +132,17 @@ class GIST_PME : private Ewald_ParticleMesh { AtomMask allAtoms_; ///< Select all atoms double NeighborCut2_; ///< Cutoff for the O-O neighbor calculation + Timer t_total_; + Timer t_recip_; + Timer t_direct_; + Timer t_self_; + + PairList pairList_; + Darray coordsD_; + Cpptraj::Energy::PME_RecipParams recipParams_; ///< Hold parameters for recip part of PME + PMEInstanceD pme_object_; + Cpptraj::Energy::VDW_LongRange_Correction VDW_LR_; ///< For calculating the long range VDW correction + ExclusionArray excluded_; }; #endif /* LIBPME */ #endif diff --git a/src/Makefile b/src/Makefile index 625e87e043..4c7d82db76 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,9 +8,11 @@ include Cluster/clusterfiles CLUSTER_SOURCEFILES=$(CLUSTER_SOURCES:%.cpp=Cluster/%.cpp) include Structure/structurefiles STRUCTURE_SOURCEFILES=$(STRUCTURE_SOURCES:%.cpp=Structure/%.cpp) +include Energy/energyfiles +ENERGY_SOURCEFILES=$(ENERGY_SOURCES:%.cpp=Energy/%.cpp) # All object files -OBJECTS=$(SOURCES:.cpp=.o) $(CSOURCES:.c=.o) $(CLUSTER_SOURCEFILES:.cpp=.o) $(STRUCTURE_SOURCEFILES:.cpp=.o) +OBJECTS=$(SOURCES:.cpp=.o) $(CSOURCES:.c=.o) $(CLUSTER_SOURCEFILES:.cpp=.o) $(STRUCTURE_SOURCEFILES:.cpp=.o) $(ENERGY_SOURCEFILES:.cpp=.o) # General rules .cpp.o: @@ -27,6 +29,7 @@ DEL_FILE = /bin/rm -f showsources: @echo $(CLUSTER_SOURCEFILES) @echo $(STRUCTURE_SOURCEFILES) + @echo $(ENERGY_SOURCEFILES) showobjects: @echo $(OBJECTS) @@ -137,7 +140,7 @@ findDepend: FindDepend.cpp FindDepend.o $(CXX) -o findDepend FindDepend.o depend: findDepend - ./findDepend $(SOURCES) $(CSOURCES) $(CLUSTER_SOURCEFILES) $(STRUCTURE_SOURCEFILES) > cpptrajdepend + ./findDepend $(SOURCES) $(CSOURCES) $(CLUSTER_SOURCEFILES) $(STRUCTURE_SOURCEFILES) $(ENERGY_SOURCEFILES) > cpptrajdepend dependclean: $(DEL_FILE) FindDepend.o findDepend @@ -151,6 +154,7 @@ clean: cd cuda_kernels && $(MAKE) clean cd Cluster && $(MAKE) clean cd Structure && $(MAKE) clean + cd Energy && $(MAKE) clean cd tng && $(MAKE) clean uninstall_lib: @@ -174,6 +178,7 @@ uninstall: uninstall_lib uninstall_inc cd cuda_kernels && $(MAKE) uninstall cd Cluster && $(MAKE) uninstall cd Structure && $(MAKE) uninstall + cd Energy && $(MAKE) uninstall # Header dependencies include cpptrajdepend diff --git a/src/MdOpts.cpp b/src/MdOpts.cpp index 8f9eb4e559..1efe37e12b 100644 --- a/src/MdOpts.cpp +++ b/src/MdOpts.cpp @@ -9,7 +9,7 @@ MdOpts::MdOpts() : scaleNB_(1.0/2.0), // Amber default cutEE_(8.0), // in Ang., Amber default cutNB_(8.0), // in Ang., Amber default - qfac_(Constants::ELECTOAMBER * Constants::ELECTOAMBER), // Assume charges in elec. units, Amber default + qfac_(Constants::COULOMBFACTOR), // Assume charges in elec. units, Amber default nExclude_(4) // Exclude dihedral, angle, bond {} @@ -53,7 +53,7 @@ int MdOpts::GetOptsFromArgs(ArgList& argIn) } } nExclude_ = argIn.getKeyInt("nexclude", 4); - qfac_ = argIn.getKeyDouble("qfac", Constants::ELECTOAMBER * Constants::ELECTOAMBER); + qfac_ = argIn.getKeyDouble("qfac", Constants::COULOMBFACTOR); return 0; } diff --git a/src/PairListEngine_Ewald_Decomp_LJLR.h b/src/PairListEngine_Ewald_Decomp_LJLR.h new file mode 100644 index 0000000000..61e4c7ecd4 --- /dev/null +++ b/src/PairListEngine_Ewald_Decomp_LJLR.h @@ -0,0 +1,111 @@ +#ifndef INC_PAIRLISTENGINE_EWALD_DECOMP_LJLR_H +#define INC_PAIRLISTENGINE_EWALD_DECOMP_LJLR_H +#include "Energy/Ene_LJ_6_12.h" +#include "Energy/EwaldParams.h" +#include "Energy/Kernel_EwaldAdjust.h" +#include "PairList.h" +namespace Cpptraj { +/// Direct space nonbond calculation using pairlist with decomposable Ewald and VDW LR correction +template +class PairListEngine_Ewald_Decomp_LJLR { + typedef std::vector Darray; + public: + PairListEngine_Ewald_Decomp_LJLR() {} + // ------------------------------------------- + /// Call at the beginning of the frame calculation + void FrameBeginCalc() { Evdw_ = 0; Eelec_ = 0; Eadjust_ = 0; + atom_elec_.assign(EW_.Natom(), 0); + atom_evdw_.assign(EW_.Natom(), 0); + atom_eadj_.assign(EW_.Natom(), 0); + } + /// Call for atom 0 when looping over atoms of thisCell + void SetupAtom0( PairList::AtmType const& atom0 ) { + q0_ = EW_.Charge(atom0.Idx()); + } + /// Call for atom 1 when looping over interaction atoms of this/other cell + void SetupAtom1( PairList::AtmType const& atom1 ) { + q1_ = EW_.Charge(atom1.Idx()); + } + /// Call when cutoff is satisfied + void CutoffSatisfied(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt( rij2 ); + T qiqj = q0_ * q1_; + //double erfc = erfc_func(ew_coeff_ * rij); + T erfcval = EW_.ErfcEW( rij ); + T e_elec = qiqj * erfcval / rij; + Eelec_ += e_elec; + T e_half = e_elec * 0.5; + atom_elec_[atom0.Idx()] += e_half; + atom_elec_[atom1.Idx()] += e_half; + + int nbindex = EW_.NbIndex(atom0.Idx(), atom1.Idx()); + if (nbindex > -1) { + double vswitch = EW_.Switch_Fn(rij2); + NonbondType const& LJ = EW_.GetLJ( nbindex ); + T e_vdw = Cpptraj::Energy::Ene_LJ_6_12(rij2, LJ.A(), LJ.B()); + e_vdw *= vswitch; + Evdw_ += e_vdw; + e_half = e_vdw * 0.5; + atom_evdw_[atom0.Idx()] += e_half; + atom_evdw_[atom1.Idx()] += e_half; + } + } + /// Call when cutoff is not satisfied + void AtomPairExcluded(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt(rij2); + T erfcval = EW_.ErfcEW( rij ); + T e_adj = Cpptraj::Energy::Kernel_EwaldAdjust( q0_, q1_, rij, erfcval ); + Eadjust_ += e_adj; + T e_half = e_adj * 0.5; + atom_eadj_[atom0.Idx()] += e_half; + atom_eadj_[atom1.Idx()] += e_half; + } + // ------------------------------------------- + Cpptraj::Energy::EwaldParams& ModifyEwaldParams() { return EW_; } + Cpptraj::Energy::EwaldParams const& EwaldParams() const { return EW_; } + + T Evdw() const { return Evdw_; } + T Eelec() const { return Eelec_; } + T Eadjust() const { return Eadjust_; } + Darray const& Eatom_Elec() const { return atom_elec_; } + Darray const& Eatom_EVDW() const { return atom_evdw_; } + Darray const& Eatom_EAdjust() const { return atom_eadj_; } +# ifdef _OPENMP + static void sum_Darray(Darray& lhs, Darray const& rhs) { + for (unsigned int idx = 0; idx != rhs.size(); ++idx) + lhs[idx] += rhs[idx]; + } + /// To allow reduction of the energy terms + void operator+=(PairListEngine_Ewald_Decomp_LJLR const& rhs) { + Evdw_ += rhs.Evdw_; + Eelec_ += rhs.Eelec_; + Eadjust_ += rhs.Eadjust_; + sum_Darray(atom_elec_, rhs.atom_elec_); + sum_Darray(atom_evdw_, rhs.atom_evdw_); + sum_Darray(atom_eadj_, rhs.atom_eadj_); + } +# endif + private: + T q0_; ///< Charge on atom 0 + T q1_; ///< Charge on atom 1 + T Evdw_; ///< VDW sum for current frame + T Eelec_; ///< Coulomb sum for current frame + T Eadjust_; ///< Adjust energy sum for current frame + + Darray atom_elec_; ///< Sum of Coulomb E on each atom for current frame + Darray atom_evdw_; ///< Sum of VDW E on each atom for current frame + Darray atom_eadj_; ///< Sum of excluded atom adjust E on each atom for current frame + + Cpptraj::Energy::EwaldParams EW_; ///< Hold Ewald parameters for PME +}; +#ifdef _OPENMP +#pragma omp declare reduction( + : PairListEngine_Ewald_Decomp_LJLR : omp_out += omp_in ) initializer( omp_priv = omp_orig ) +#endif +} // END namespace Cpptraj +#endif diff --git a/src/PairListEngine_Ewald_Decomp_LJPME.h b/src/PairListEngine_Ewald_Decomp_LJPME.h new file mode 100644 index 0000000000..0a1fb53137 --- /dev/null +++ b/src/PairListEngine_Ewald_Decomp_LJPME.h @@ -0,0 +1,130 @@ +#ifndef INC_PAIRLISTENGINE_EWALD_DECOMP_LJPME_H +#define INC_PAIRLISTENGINE_EWALD_DECOMP_LJPME_H +#include "Energy/EwaldParams_LJPME.h" +#include "Energy/Ene_LJPME_6_12.h" +#include "Energy/Kernel_EwaldAdjust.h" +#include "Energy/Kernel_LJPME_Adjust.h" +#include "PairList.h" +namespace Cpptraj { +/// Direct space nonbond calculation using pairlist with decomposable Ewald and LJPME for VDW +template +class PairListEngine_Ewald_Decomp_LJPME { + typedef std::vector Darray; + public: + PairListEngine_Ewald_Decomp_LJPME() {} + // ------------------------------------------- + /// Call at the beginning of the frame calculation + void FrameBeginCalc() { Evdw_ = 0; Eelec_ = 0; Eadjust_ = 0; + Eljpme_correction_ = 0; Eljpme_correction_excl_ = 0; + atom_elec_.assign(EW_.Natom(), 0); + atom_evdw_.assign(EW_.Natom(), 0); + atom_eadj_.assign(EW_.Natom(), 0); + } + /// Call for atom 0 when looping over atoms of thisCell + void SetupAtom0( PairList::AtmType const& atom0 ) { + q0_ = EW_.Charge(atom0.Idx()); + } + /// Call for atom 1 when looping over interaction atoms of this/other cell + void SetupAtom1( PairList::AtmType const& atom1 ) { + q1_ = EW_.Charge(atom1.Idx()); + } + /// Call when cutoff is satisfied + void CutoffSatisfied(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt( rij2 ); + T qiqj = q0_ * q1_; + //double erfc = erfc_func(ew_coeff_ * rij); + T erfcval = EW_.ErfcEW( rij ); + T e_elec = qiqj * erfcval / rij; + Eelec_ += e_elec; + T e_half = e_elec * 0.5; + atom_elec_[atom0.Idx()] += e_half; + atom_elec_[atom1.Idx()] += e_half; + + int nbindex = EW_.NbIndex(atom0.Idx(), atom1.Idx()); + if (nbindex > -1) { + double vswitch = EW_.Switch_Fn(rij2); + NonbondType const& LJ = EW_.GetLJ( nbindex ); + T e_vdw, e_pmevdw; + Cpptraj::Energy:: + Ene_LJPME_6_12( e_vdw, e_pmevdw, + rij2, LJ.A(), LJ.B(), EW_.LJ_EwaldCoeff(), + EW_.CalcCij(atom0.Idx(), atom1.Idx()) ); + e_vdw *= vswitch; + Evdw_ += e_vdw; + e_half = e_vdw * 0.5; + e_pmevdw *= vswitch; + Eljpme_correction_ += e_pmevdw; + e_half += (e_pmevdw * 0.5); + atom_evdw_[atom0.Idx()] += e_half; + atom_evdw_[atom1.Idx()] += e_half; + } + } + /// Call when cutoff is not satisfied + void AtomPairExcluded(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt(rij2); + T erfcval = EW_.ErfcEW( rij ); + T e_adj = Cpptraj::Energy::Kernel_EwaldAdjust( q0_, q1_, rij, erfcval ); + Eadjust_ += e_adj; + T e_half = e_adj * 0.5; + // LJ PME direct space exclusion correction + T e_ljpme_adj = Cpptraj::Energy:: + Kernel_LJPME_Adjust( rij2, EW_.LJ_EwaldCoeff(), + EW_.CalcCij(atom0.Idx(), atom1.Idx()) ); + Eljpme_correction_excl_ += e_ljpme_adj; + e_half += (e_ljpme_adj * 0.5); + atom_eadj_[atom0.Idx()] += e_half; + atom_eadj_[atom1.Idx()] += e_half; + } + // ------------------------------------------- + Cpptraj::Energy::EwaldParams_LJPME& ModifyEwaldParams() { return EW_; } + Cpptraj::Energy::EwaldParams_LJPME const& EwaldParams() const { return EW_; } + + T Evdw() const { return Evdw_ + Eljpme_correction_ + Eljpme_correction_excl_; } + T Eelec() const { return Eelec_; } + T Eadjust() const { return Eadjust_; } + Darray const& Eatom_Elec() const { return atom_elec_; } + Darray const& Eatom_EVDW() const { return atom_evdw_; } + Darray const& Eatom_EAdjust() const { return atom_eadj_; } +# ifdef _OPENMP + static void sum_Darray(Darray& lhs, Darray const& rhs) { + for (unsigned int idx = 0; idx != rhs.size(); ++idx) + lhs[idx] += rhs[idx]; + } + /// To allow reduction of the energy terms + void operator+=(PairListEngine_Ewald_Decomp_LJPME const& rhs) { + Evdw_ += rhs.Evdw_; + Eelec_ += rhs.Eelec_; + Eadjust_ += rhs.Eadjust_; + Eljpme_correction_ += rhs.Eljpme_correction_; + Eljpme_correction_excl_ += rhs.Eljpme_correction_excl_; + sum_Darray(atom_elec_, rhs.atom_elec_); + sum_Darray(atom_evdw_, rhs.atom_evdw_); + sum_Darray(atom_eadj_, rhs.atom_eadj_); + } +# endif + private: + T q0_; ///< Charge on atom 0 + T q1_; ///< Charge on atom 1 + T Evdw_; ///< VDW sum for current frame + T Eelec_; ///< Coulomb sum for current frame + T Eadjust_; ///< Adjust energy sum for current frame + T Eljpme_correction_; ///< LJ PME correction for VDW + T Eljpme_correction_excl_; ///< LJ PME correction for adjust + + Darray atom_elec_; ///< Sum of Coulomb E on each atom for current frame + Darray atom_evdw_; ///< Sum of VDW E on each atom for current frame + Darray atom_eadj_; ///< Sum of excluded atom adjust E on each atom for current frame + + Cpptraj::Energy::EwaldParams_LJPME EW_; ///< Hold Ewald parameters for LJPME +}; +#ifdef _OPENMP +#pragma omp declare reduction( + : PairListEngine_Ewald_Decomp_LJPME : omp_out += omp_in ) initializer( omp_priv = omp_orig ) +#endif +} // END namespace Cpptraj +#endif diff --git a/src/PairListEngine_Ewald_LJLR.h b/src/PairListEngine_Ewald_LJLR.h new file mode 100644 index 0000000000..d9cc8a0336 --- /dev/null +++ b/src/PairListEngine_Ewald_LJLR.h @@ -0,0 +1,81 @@ +#ifndef INC_PAIRLISTENGINE_EWALD_LJLR_H +#define INC_PAIRLISTENGINE_EWALD_LJLR_H +#include "Energy/Ene_LJ_6_12.h" +#include "Energy/EwaldParams.h" +#include "Energy/Kernel_EwaldAdjust.h" +#include "PairList.h" +namespace Cpptraj { +/// Direct space nonbond calculation using pairlist with Ewald and VDW LR correction +template +class PairListEngine_Ewald_LJLR { + public: + PairListEngine_Ewald_LJLR() {} + // ------------------------------------------- + /// Call at the beginning of the frame calculation + void FrameBeginCalc() { Evdw_ = 0; Eelec_ = 0; Eadjust_ = 0; } + /// Call for atom 0 when looping over atoms of thisCell + void SetupAtom0( PairList::AtmType const& atom0 ) { + q0_ = EW_.Charge(atom0.Idx()); + } + /// Call for atom 1 when looping over interaction atoms of this/other cell + void SetupAtom1( PairList::AtmType const& atom1 ) { + q1_ = EW_.Charge(atom1.Idx()); + } + /// Call when cutoff is satisfied + void CutoffSatisfied(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt( rij2 ); + T qiqj = q0_ * q1_; + //double erfc = erfc_func(ew_coeff_ * rij); + T erfcval = EW_.ErfcEW( rij ); + T e_elec = qiqj * erfcval / rij; + Eelec_ += e_elec; + + int nbindex = EW_.NbIndex(atom0.Idx(), atom1.Idx()); + if (nbindex > -1) { + double vswitch = EW_.Switch_Fn(rij2); + NonbondType const& LJ = EW_.GetLJ( nbindex ); + T e_vdw = Cpptraj::Energy::Ene_LJ_6_12(rij2, LJ.A(), LJ.B()); + Evdw_ += (e_vdw * vswitch); + } + } + /// Call when cutoff is not satisfied + void AtomPairExcluded(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt(rij2); + T erfcval = EW_.ErfcEW( rij ); + Eadjust_ += Cpptraj::Energy::Kernel_EwaldAdjust( q0_, q1_, rij, erfcval ); + } + // ------------------------------------------- + Cpptraj::Energy::EwaldParams& ModifyEwaldParams() { return EW_; } + Cpptraj::Energy::EwaldParams const& EwaldParams() const { return EW_; } + + T Evdw() const { return Evdw_; } + T Eelec() const { return Eelec_; } + T Eadjust() const { return Eadjust_; } +# ifdef _OPENMP + /// To allow reduction of the energy terms + void operator+=(PairListEngine_Ewald_LJLR const& rhs) { + Evdw_ += rhs.Evdw_; + Eelec_ += rhs.Eelec_; + Eadjust_ += rhs.Eadjust_; + } +# endif + private: + T q0_; ///< Charge on atom 0 + T q1_; ///< Charge on atom 1 + T Evdw_; ///< VDW sum for current frame + T Eelec_; ///< Coulomb sum for current frame + T Eadjust_; ///< Adjust energy sum for current frame + + Cpptraj::Energy::EwaldParams EW_; ///< Hold Ewald parameters for PME +}; +#ifdef _OPENMP +#pragma omp declare reduction( + : PairListEngine_Ewald_LJLR : omp_out += omp_in ) initializer( omp_priv = omp_orig ) +#endif +} // END namespace Cpptraj +#endif diff --git a/src/PairListEngine_Ewald_LJPME.h b/src/PairListEngine_Ewald_LJPME.h new file mode 100644 index 0000000000..6a6dba25df --- /dev/null +++ b/src/PairListEngine_Ewald_LJPME.h @@ -0,0 +1,96 @@ +#ifndef INC_PAIRLISTENGINE_EWALD_LJPME_H +#define INC_PAIRLISTENGINE_EWALD_LJPME_H +#include "Energy/EwaldParams_LJPME.h" +#include "Energy/Ene_LJPME_6_12.h" +#include "Energy/Kernel_EwaldAdjust.h" +#include "Energy/Kernel_LJPME_Adjust.h" +#include "PairList.h" +namespace Cpptraj { +/// Direct space nonbond calculation using pairlist with Ewald and LJPME for VDW +template +class PairListEngine_Ewald_LJPME { + public: + PairListEngine_Ewald_LJPME() {} + // ------------------------------------------- + /// Call at the beginning of the frame calculation + void FrameBeginCalc() { Evdw_ = 0; Eelec_ = 0; Eadjust_ = 0; + Eljpme_correction_ = 0; Eljpme_correction_excl_ = 0; } + /// Call for atom 0 when looping over atoms of thisCell + void SetupAtom0( PairList::AtmType const& atom0 ) { + q0_ = EW_.Charge(atom0.Idx()); + } + /// Call for atom 1 when looping over interaction atoms of this/other cell + void SetupAtom1( PairList::AtmType const& atom1 ) { + q1_ = EW_.Charge(atom1.Idx()); + } + /// Call when cutoff is satisfied + void CutoffSatisfied(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt( rij2 ); + T qiqj = q0_ * q1_; + //double erfc = erfc_func(ew_coeff_ * rij); + T erfcval = EW_.ErfcEW( rij ); + T e_elec = qiqj * erfcval / rij; + Eelec_ += e_elec; + + int nbindex = EW_.NbIndex(atom0.Idx(), atom1.Idx()); + if (nbindex > -1) { + double vswitch = EW_.Switch_Fn(rij2); + NonbondType const& LJ = EW_.GetLJ( nbindex ); + T e_vdw, e_pmevdw; + Cpptraj::Energy:: + Ene_LJPME_6_12( e_vdw, e_pmevdw, + rij2, LJ.A(), LJ.B(), EW_.LJ_EwaldCoeff(), + EW_.CalcCij(atom0.Idx(), atom1.Idx()) ); + Evdw_ += (e_vdw * vswitch); + Eljpme_correction_ += (e_pmevdw * vswitch); + } + } + /// Call when cutoff is not satisfied + void AtomPairExcluded(T const& rij2, + PairList::AtmType const& atom0, + PairList::AtmType const& atom1) + { + T rij = sqrt(rij2); + T erfcval = EW_.ErfcEW( rij ); + Eadjust_ += Cpptraj::Energy::Kernel_EwaldAdjust( q0_, q1_, rij, erfcval ); + // LJ PME direct space exclusion correction + Eljpme_correction_excl_ += Cpptraj::Energy:: + Kernel_LJPME_Adjust( rij2, EW_.LJ_EwaldCoeff(), + EW_.CalcCij(atom0.Idx(), atom1.Idx()) ); + } + // ------------------------------------------- + Cpptraj::Energy::EwaldParams_LJPME& ModifyEwaldParams() { return EW_; } + Cpptraj::Energy::EwaldParams_LJPME const& EwaldParams() const { return EW_; } + + T Evdw() const { return Evdw_ + Eljpme_correction_ + Eljpme_correction_excl_; } + T Eelec() const { return Eelec_; } + T Eadjust() const { return Eadjust_; } +# ifdef _OPENMP + /// To allow reduction of the energy terms + void operator+=(PairListEngine_Ewald_LJPME const& rhs) { + Evdw_ += rhs.Evdw_; + Eelec_ += rhs.Eelec_; + Eadjust_ += rhs.Eadjust_; + Eljpme_correction_ += rhs.Eljpme_correction_; + Eljpme_correction_excl_ += rhs.Eljpme_correction_excl_; + } +# endif + private: + T q0_; ///< Charge on atom 0 + T q1_; ///< Charge on atom 1 + T Evdw_; ///< VDW sum for current frame + T Eelec_; ///< Coulomb sum for current frame + T Eadjust_; ///< Adjust energy sum for current frame + T Eljpme_correction_; ///< LJ PME correction for VDW + T Eljpme_correction_excl_; ///< LJ PME correction for adjust + + Cpptraj::Energy::EwaldParams_LJPME EW_; ///< Hold Ewald parameters for LJPME +}; +#ifdef _OPENMP +#pragma omp declare reduction( + : PairListEngine_Ewald_LJPME : omp_out += omp_in ) initializer( omp_priv = omp_orig ) +#endif +} // END namespace Cpptraj +#endif diff --git a/src/PairListLoop.h b/src/PairListTemplate.h similarity index 65% rename from src/PairListLoop.h rename to src/PairListTemplate.h index 1508fd9889..d91baeb1aa 100644 --- a/src/PairListLoop.h +++ b/src/PairListTemplate.h @@ -1,3 +1,36 @@ +#ifndef INC_PAIRLISTTEMPLATE_H +#define INC_PAIRLISTTEMPLATE_H +#include "PairList.h" +#include "ExclusionArray.h" +namespace Cpptraj { +/// Template for doing pair list calculations +/** This template is designed to make it simpler to use the PairList class. + * It takes a PairList, an excluded atom array (ExclusionArray), a cutoff + * (squared), and an "Engine". + * The Engine determines what is done when the cutoff is satisfied vs + * when the interaction is excluded. It should also be a template and have + * the following functions: + * void FrameBeginCalc() : What to do at the beginning of each frame/calc. + * void SetupAtom0(int idx0) : What to do for the outer loop atom. + * void SetupAtom1(int idx1) : What to do for the inner loop atoms. + * void CutoffSatisfied(double rij2, int idx0, idx1) : What to do when the + * cutoff squared is satisfied for atom indices 0 and 1. + * void AtomPairExcluded(double rij2, int idx0, idx1) : What to do when the + * pair interaction between atom indices 0 and 1 is excluded. + * + */ +template class EngineClass> +void PairListTemplate(PairList const& PL, ExclusionArray const& Excluded, T cut2, + EngineClass& engine) +{ + engine.FrameBeginCalc(); + + int cidx; +# ifdef _OPENMP +# pragma omp parallel private(cidx) reduction(+: engine) + { +# pragma omp for +# endif for (cidx = 0; cidx < PL.NGridMax(); cidx++) { PairList::CellType const& thisCell = PL.Cell( cidx ); @@ -11,39 +44,38 @@ for (PairList::CellType::const_iterator it0 = thisCell.begin(); it0 != thisCell.end(); ++it0) { + engine.SetupAtom0( *it0 ); Vec3 const& xyz0 = it0->ImageCoords(); - double q0 = Charge_[it0->Idx()]; # ifdef DEBUG_PAIRLIST mprintf("DBG: Cell %6i (%6i atoms):\n", cidx, thisCell.NatomsInGrid()); # endif // Exclusion list for this atom - ExclusionArray::ExListType const& excluded = Excluded_[it0->Idx()]; + ExclusionArray::ExListType const& excluded = Excluded[it0->Idx()]; // Calc interaction of atom to all other atoms in thisCell. for (PairList::CellType::const_iterator it1 = it0 + 1; it1 != thisCell.end(); ++it1) { + engine.SetupAtom1( *it1 ); Vec3 const& xyz1 = it1->ImageCoords(); - double q1 = Charge_[it1->Idx()]; Vec3 dxyz = xyz1 - xyz0; - double rij2 = dxyz.Magnitude2(); + T rij2 = dxyz.Magnitude2(); # ifdef DEBUG_PAIRLIST mprintf("\tAtom %6i to atom %6i (%f)\n", it0->Idx()+1, it1->Idx()+1, sqrt(rij2)); # endif // If atom excluded, calc adjustment, otherwise calc elec. energy. if (excluded.find( it1->Idx() ) == excluded.end()) { - - if ( rij2 < cut2_ ) { + if ( rij2 < cut2 ) { # ifdef NBDBG if (it0->Idx() < it1->Idx()) mprintf("NBDBG %6i%6i\n", it0->Idx()+1, it1->Idx()+1); else mprintf("NBDBG %6i%6i\n", it1->Idx()+1, it0->Idx()+1); # endif -# include "EnergyKernel_Nonbond.h" + engine.CutoffSatisfied(rij2, *it0, *it1); } } else { -# include "EnergyKernel_Adjust.h" + engine.AtomPairExcluded(rij2, *it0, *it1); } } // END loop over other atoms in thisCell // Loop over all neighbor cells @@ -63,10 +95,10 @@ for (PairList::CellType::const_iterator it1 = nbrCell.begin(); it1 != nbrCell.end(); ++it1) { + engine.SetupAtom1( *it1 ); Vec3 const& xyz1 = it1->ImageCoords(); - double q1 = Charge_[it1->Idx()]; Vec3 dxyz = xyz1 + tVec - xyz0; - double rij2 = dxyz.Magnitude2(); + T rij2 = dxyz.Magnitude2(); //mprintf("\t\tAtom %6i {%f %f %f} to atom %6i {%f %f %f} = %f Ang\n", it0->Idx()+1, xyz0[0], xyz0[1], xyz0[2], it1->Idx()+1, xyz1[0], xyz1[1], xyz1[2], sqrt(rij2)); # ifdef DEBUG_PAIRLIST mprintf("\t\tAtom %6i to atom %6i (%f)\n", it0->Idx()+1, it1->Idx()+1, sqrt(rij2)); @@ -78,20 +110,26 @@ { //mprintf("\t\t\tdist= %f\n", sqrt(rij2)); - if ( rij2 < cut2_ ) { + if ( rij2 < cut2 ) { # ifdef NBDBG if (it0->Idx() < it1->Idx()) mprintf("NBDBG %6i%6i\n", it0->Idx()+1, it1->Idx()+1); else mprintf("NBDBG %6i%6i\n", it1->Idx()+1, it0->Idx()+1); # endif -# include "EnergyKernel_Nonbond.h" + engine.CutoffSatisfied(rij2, *it0, *it1); } } else { -# include "EnergyKernel_Adjust.h" + engine.AtomPairExcluded(rij2, *it0, *it1); } } // END loop over neighbor cell atoms } // END Loop over neighbor cells } // Loop over thisCell atoms } // END if thisCell is not empty } // Loop over cells +# ifdef _OPENMP + } // END pragma omp parallel +# endif +} // END PairListTemplate +} // END namespace Cpptraj +#endif diff --git a/src/PotentialTerm_Dihedral.cpp b/src/PotentialTerm_Dihedral.cpp index 5c92117498..5a8c578d01 100644 --- a/src/PotentialTerm_Dihedral.cpp +++ b/src/PotentialTerm_Dihedral.cpp @@ -65,8 +65,6 @@ void PotentialTerm_Dihedral::CalcForce(Frame& frameIn, CharMask const& maskIn) c double dr[13]; double dtx[7][13]; - double QFAC = Constants::ELECTOAMBER * Constants::ELECTOAMBER; - EnergyKernel_NonBond_Simple NB14; //mprintf("FCALC\n"); for (DihedralArray::const_iterator dih = activeDihs_.begin(); dih != activeDihs_.end(); ++dih) @@ -80,7 +78,7 @@ void PotentialTerm_Dihedral::CalcForce(Frame& frameIn, CharMask const& maskIn) c int nbindex = nonbond_->GetLJindex( A1.TypeIndex(), A4.TypeIndex() ); NonbondType const& LJ = nonbond_->NBarray( nbindex ); NB14.Calc_F_E( frameIn, dih->A1(), dih->A4(), LJ.A(), LJ.B(), - QFAC, A1.Charge(), A4.Charge(), + Constants::COULOMBFACTOR, A1.Charge(), A4.Charge(), 1.0/DP.SCNB(), 1.0/DP.SCEE(), maskIn, *Enb14_, *Eq14_); } diff --git a/src/Stats_Reduce.cpp b/src/Stats_Reduce.cpp new file mode 100644 index 0000000000..06c7890fc5 --- /dev/null +++ b/src/Stats_Reduce.cpp @@ -0,0 +1,58 @@ +#include "Stats_Reduce.h" +#ifdef MPI +/** Calculate overall average/stdev for array elements using the parallel + * form of the Online algorithm ( Chan, T.F.; Golub, G.H.; LeVeque, R.J. + * (1979), "Updating Formulae and a Pairwise Algorithm for Computing Sample + * Variances.", Technical Report STAN-CS-79-773, Department of Computer + * Science, Stanford University ). + */ +int Cpptraj::Stats_Reduce(Parallel::Comm const& trajComm_, + std::vector< Stats >& histogram_, + unsigned long& maxbin_) +{ + if (trajComm_.Size() < 2) return 0; + std::vector buffer; + unsigned long rank_size; + if (trajComm_.Master()) { + for (int rank = 1; rank < trajComm_.Size(); rank++) { + // 1. Get size of histogram on rank. + trajComm_.SendMaster(&rank_size, 1, rank, MPI_UNSIGNED_LONG); + // 2. Receive histogram from rank. + buffer.resize(3*rank_size, 0.0); // mean, m2, N + unsigned long master_size = (unsigned long)histogram_.size(); + trajComm_.SendMaster(&buffer[0], buffer.size(), rank, MPI_DOUBLE); + unsigned long idx = 0; // Index into buffer + // Only sum for bins where master and rank both have data + unsigned long Nbins = std::min( master_size, rank_size ); + for (unsigned long i = 0; i < Nbins; i++, idx += 3) { + double mB = buffer[idx ]; + double sB = buffer[idx+1]; + double nB = buffer[idx+2]; + histogram_[i].Combine( Stats(nB, mB, sB) ); + } + // If rank had more data than master, fill in data + if (rank_size > master_size) { + histogram_.resize( rank_size ); + maxbin_ = (unsigned long)histogram_.size() - 1; + idx = master_size * 3; + for (unsigned long i = master_size; i < rank_size; i++, idx += 3) + histogram_[i] = Stats( buffer[idx+2], buffer[idx], buffer[idx+1] ); + } + } + } else { + // 1. Send size of histogram on this rank to master. + rank_size = (unsigned long)histogram_.size(); + trajComm_.SendMaster(&rank_size, 1, trajComm_.Rank(), MPI_UNSIGNED_LONG); + // 2. Place histogram data into a buffer and send to master. + buffer.reserve(3*histogram_.size()); // mean, m2, N + for (unsigned long i = 0; i < histogram_.size(); i++) { + buffer.push_back( (double)histogram_[i].mean() ); + buffer.push_back( (double)histogram_[i].M2() ); + buffer.push_back( (double)histogram_[i].nData() ); + } + trajComm_.SendMaster(&buffer[0], buffer.size(), trajComm_.Rank(), MPI_DOUBLE); + } + + return 0; +} +#endif /* MPI */ diff --git a/src/Stats_Reduce.h b/src/Stats_Reduce.h new file mode 100644 index 0000000000..d4545222d3 --- /dev/null +++ b/src/Stats_Reduce.h @@ -0,0 +1,12 @@ +#ifndef INC_STATS_REDUCE_H +#define INC_STATS_REDUCE_H +#ifdef MPI +#include +#include "Parallel.h" +#include "OnlineVarT.h" +namespace Cpptraj { +/// Used to reduce an array of Stats down to master rank +int Stats_Reduce(Parallel::Comm const&, std::vector< Stats >&, unsigned long&); +} +#endif /* MPI */ +#endif diff --git a/src/Version.h b/src/Version.h index 2de71ea96e..7957c39291 100644 --- a/src/Version.h +++ b/src/Version.h @@ -12,7 +12,7 @@ * Whenever a number that precedes is incremented, all subsequent * numbers should be reset to 0. */ -#define CPPTRAJ_INTERNAL_VERSION "V6.29.3" +#define CPPTRAJ_INTERNAL_VERSION "V6.29.4" /// PYTRAJ relies on this #define CPPTRAJ_VERSION_STRING CPPTRAJ_INTERNAL_VERSION #endif diff --git a/src/cpptrajdepend b/src/cpptrajdepend index 300a19680d..f80b0a290f 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -31,12 +31,13 @@ Action_DihedralRMS.o : Action_DihedralRMS.cpp Action.h ActionState.h Action_Dihe Action_Dipole.o : Action_Dipole.cpp Action.h ActionState.h Action_Dipole.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Grid.h GridAction.h GridBin.h GridMover.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_DistRmsd.o : Action_DistRmsd.cpp Action.h ActionState.h Action_DistRmsd.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceAction.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Distance.o : Action_Distance.cpp Action.h ActionState.h Action_Distance.h ArgList.h AssociatedData.h AssociatedData_NOE.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Action_Energy.o : Action_Energy.cpp Action.h ActionState.h Action_Energy.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h Constraints.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h Energy.h EnergyArray.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h Ewald_Regular.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MdOpts.h MetaData.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PotentialFunction.h PotentialTerm.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h helpme_standalone.h +Action_EneDecomp.o : Action_EneDecomp.cpp Action.h ActionState.h Action_EneDecomp.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h Energy/Ecalc_Nonbond.h Energy/EnergyDecomposer.h EwaldOptions.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h +Action_Energy.o : Action_Energy.cpp Action.h ActionState.h Action_Energy.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h Constraints.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h Energy.h Energy/Ecalc_Nonbond.h EnergyArray.h EwaldOptions.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MdOpts.h MetaData.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PotentialFunction.h PotentialTerm.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Esander.o : Action_Esander.cpp Action.h ActionState.h Action_Esander.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h Energy_Sander.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_FilterByData.o : Action_FilterByData.cpp Action.h ActionState.h Action_FilterByData.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_FixAtomOrder.o : Action_FixAtomOrder.cpp Action.h ActionState.h ActionTopWriter.h Action_FixAtomOrder.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomTopType.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_FixImagedBonds.o : Action_FixImagedBonds.cpp Action.h ActionState.h Action_FixImagedBonds.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Action_GIST.o : Action_GIST.cpp Action.h ActionState.h Action_GIST.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridDbl.h DataSet_GridFlt.h DataSet_MatrixFlt.h Dimension.h DispatchObject.h DistRoutines.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h GIST_PME.h GistEntropyUtils.h Grid.h GridBin.h GridMover.h ImageOption.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h +Action_GIST.o : Action_GIST.cpp Action.h ActionState.h Action_GIST.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridDbl.h DataSet_GridFlt.h DataSet_MatrixFlt.h Dimension.h DispatchObject.h DistRoutines.h Energy/ErfcFxn.h Energy/EwaldParams.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h GIST_PME.h GistEntropyUtils.h Grid.h GridBin.h GridMover.h ImageOption.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h Action_Grid.o : Action_Grid.cpp Action.h ActionState.h Action_Grid.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Grid.h GridAction.h GridBin.h GridMover.h MaskArray.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PDBfile.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_GridFreeEnergy.o : Action_GridFreeEnergy.cpp Action.h ActionState.h Action_GridFreeEnergy.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Grid.h GridAction.h GridBin.h GridMover.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_HydrogenBond.o : Action_HydrogenBond.cpp Action.h ActionState.h Action_HydrogenBond.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h DataSet_integer.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h @@ -61,7 +62,7 @@ Action_NMRrst.o : Action_NMRrst.cpp Action.h ActionState.h Action_NMRrst.h ArgLi Action_NativeContacts.o : Action_NativeContacts.cpp Action.h ActionState.h Action_NativeContacts.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h DataSet_integer.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PDBfile.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_OrderParameter.o : Action_OrderParameter.cpp Action.h ActionState.h Action_OrderParameter.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Outtraj.o : Action_Outtraj.cpp Action.h ActionFrameCounter.h ActionState.h Action_Outtraj.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h -Action_PairDist.o : Action_PairDist.cpp Action.h ActionState.h Action_PairDist.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mesh.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h +Action_PairDist.o : Action_PairDist.cpp Action.h ActionState.h Action_PairDist.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mesh.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h Stats_Reduce.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Pairwise.o : Action_Pairwise.cpp Action.h ActionFrameCounter.h ActionState.h Action_Pairwise.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h Dimension.h DispatchObject.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OutputTrajCommon.h PDBfile.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h Action_Principal.o : Action_Principal.cpp Action.h ActionState.h Action_Principal.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mat3x3.h DataSet_Vector.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Projection.o : Action_Projection.cpp Action.h ActionFrameCounter.h ActionState.h Action_Projection.h ArgList.h Array1D.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Modes.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -189,7 +190,7 @@ ClusterMap.o : ClusterMap.cpp AssociatedData.h ClusterMap.h Constants.h CpptrajF Cmd.o : Cmd.cpp Cmd.h DispatchObject.h CmdInput.o : CmdInput.cpp CmdInput.h StringRoutines.h CmdList.o : CmdList.cpp Cmd.h CmdList.h DispatchObject.h -Command.o : Command.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h ActionTopWriter.h Action_AddAtom.h Action_Align.h Action_Angle.h Action_AreaPerMol.h Action_AtomMap.h Action_AtomicCorr.h Action_AtomicFluct.h Action_AutoImage.h Action_Average.h Action_AvgBox.h Action_Bounds.h Action_Box.h Action_Center.h Action_Channel.h Action_CheckChirality.h Action_CheckStructure.h Action_Closest.h Action_ClusterDihedral.h Action_Contacts.h Action_CreateCrd.h Action_CreateReservoir.h Action_DNAionTracker.h Action_DSSP.h Action_Density.h Action_Diffusion.h Action_Dihedral.h Action_DihedralRMS.h Action_Dipole.h Action_DistRmsd.h Action_Distance.h Action_Energy.h Action_Esander.h Action_FilterByData.h Action_FixAtomOrder.h Action_FixImagedBonds.h Action_GIST.h Action_Grid.h Action_GridFreeEnergy.h Action_HydrogenBond.h Action_Image.h Action_InfraredSpectrum.h Action_Jcoupling.h Action_Keep.h Action_LESsplit.h Action_LIE.h Action_LipidOrder.h Action_MakeStructure.h Action_Mask.h Action_Matrix.h Action_MinImage.h Action_MinMaxDist.h Action_Molsurf.h Action_MultiDihedral.h Action_MultiPucker.h Action_MultiVector.h Action_NAstruct.h Action_NMRrst.h Action_NativeContacts.h Action_OrderParameter.h Action_Outtraj.h Action_PairDist.h Action_Pairwise.h Action_Principal.h Action_Projection.h Action_Pucker.h Action_Radgyr.h Action_Radial.h Action_RandomizeIons.h Action_Remap.h Action_ReplicateCell.h Action_Rmsd.h Action_Rotate.h Action_RunningAvg.h Action_STFC_Diffusion.h Action_Scale.h Action_SetVelocity.h Action_Spam.h Action_Strip.h Action_Surf.h Action_SymmetricRmsd.h Action_Temperature.h Action_Time.h Action_ToroidalDiffusion.h Action_Translate.h Action_Unstrip.h Action_Unwrap.h Action_Vector.h Action_VelocityAutoCorr.h Action_Volmap.h Action_Volume.h Action_Watershell.h Action_XtalSymm.h Analysis.h AnalysisList.h AnalysisState.h Analysis_AmdBias.h Analysis_AutoCorr.h Analysis_Average.h Analysis_CalcDiffusion.h Analysis_Clustering.h Analysis_ConstantPHStats.h Analysis_Corr.h Analysis_CrankShaft.h Analysis_CrdFluct.h Analysis_CrossCorr.h Analysis_CurveFit.h Analysis_Divergence.h Analysis_EvalPlateau.h Analysis_FFT.h Analysis_HausdorffDistance.h Analysis_Hist.h Analysis_IRED.h Analysis_Integrate.h Analysis_KDE.h Analysis_Lifetime.h Analysis_LowestCurve.h Analysis_Matrix.h Analysis_MeltCurve.h Analysis_Modes.h Analysis_MultiHist.h Analysis_Multicurve.h Analysis_Overlap.h Analysis_PhiPsi.h Analysis_Project.h Analysis_Regression.h Analysis_RemLog.h Analysis_Rms2d.h Analysis_RmsAvgCorr.h Analysis_Rotdif.h Analysis_RunningAvg.h Analysis_Slope.h Analysis_Spline.h Analysis_State.h Analysis_Statistics.h Analysis_TI.h Analysis_TICA.h Analysis_Timecorr.h Analysis_VectorMath.h Analysis_Wavelet.h ArgList.h Array1D.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h AxisType.h BaseIOtype.h Box.h BoxArgs.h BufferedLine.h CharMask.h Cluster/Algorithm.h Cluster/BestReps.h Cluster/CentroidArray.h Cluster/Cframes.h Cluster/Control.h Cluster/DrawGraph.h Cluster/List.h Cluster/Metric.h Cluster/MetricArray.h Cluster/Node.h Cluster/Sieve.h Cluster/Silhouette.h ClusterMap.h Cmd.h CmdInput.h CmdList.h Command.h CompactFrameArray.h ComplexArray.h Constants.h Constraints.h ControlBlock.h ControlBlock_For.h CoordinateInfo.h Corr.h Cph.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_GridFlt.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_RemLog.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h Deprecated.h DiffusionResults.h DihedralSearch.h Dimension.h DispatchObject.h Energy.h Energy_Sander.h EnsembleIn.h EnsembleOutList.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h ExclusionArray.h Exec.h Exec_AddMissingRes.h Exec_Analyze.h Exec_Calc.h Exec_CatCrd.h Exec_Change.h Exec_ClusterMap.h Exec_CombineCoords.h Exec_Commands.h Exec_CompareClusters.h Exec_CompareEnergy.h Exec_CompareTop.h Exec_CrdAction.h Exec_CrdOut.h Exec_CrdTransform.h Exec_CreateSet.h Exec_DataFile.h Exec_DataFilter.h Exec_DataSetCmd.h Exec_Emin.h Exec_ExtendedComparison.h Exec_Flatten.h Exec_GenerateAmberRst.h Exec_Graft.h Exec_Help.h Exec_HmassRepartition.h Exec_LoadCrd.h Exec_LoadTraj.h Exec_ParallelAnalysis.h Exec_ParmBox.h Exec_ParmSolvent.h Exec_ParmStrip.h Exec_ParmWrite.h Exec_ParseTiming.h Exec_PermuteDihedrals.h Exec_Precision.h Exec_PrepareForLeap.h Exec_PrintData.h Exec_Random.h Exec_ReadData.h Exec_ReadEnsembleData.h Exec_ReadInput.h Exec_RotateDihedral.h Exec_RunAnalysis.h Exec_ScaleDihedralK.h Exec_Sequence.h Exec_SequenceAlign.h Exec_Set.h Exec_Show.h Exec_SortEnsembleData.h Exec_SplitCoords.h Exec_System.h Exec_Top.h Exec_Traj.h Exec_UpdateParameters.h Exec_ViewRst.h Exec_Zmatrix.h ExtendedSimilarity.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h GIST_PME.h Grid.h GridAction.h GridBin.h GridMover.h HistBin.h Hungarian.h ImageOption.h ImageTypes.h InputTrajCommon.h InteractionData.h MapAtom.h MaskArray.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Routines.h NameType.h NetcdfFile.h OnlineVarT.h OutputTrajCommon.h PDBfile.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PubFFT.h Pucker.h Pucker_PuckerMask.h Pucker_PuckerSearch.h Pucker_PuckerToken.h RPNcalc.h Random.h Range.h ReferenceAction.h ReferenceFrame.h RemdReservoirNC.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Spline.h SplineFxnTable.h StructureCheck.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h TrajoutList.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h molsurf.h +Command.o : Command.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h ActionTopWriter.h Action_AddAtom.h Action_Align.h Action_Angle.h Action_AreaPerMol.h Action_AtomMap.h Action_AtomicCorr.h Action_AtomicFluct.h Action_AutoImage.h Action_Average.h Action_AvgBox.h Action_Bounds.h Action_Box.h Action_Center.h Action_Channel.h Action_CheckChirality.h Action_CheckStructure.h Action_Closest.h Action_ClusterDihedral.h Action_Contacts.h Action_CreateCrd.h Action_CreateReservoir.h Action_DNAionTracker.h Action_DSSP.h Action_Density.h Action_Diffusion.h Action_Dihedral.h Action_DihedralRMS.h Action_Dipole.h Action_DistRmsd.h Action_Distance.h Action_EneDecomp.h Action_Energy.h Action_Esander.h Action_FilterByData.h Action_FixAtomOrder.h Action_FixImagedBonds.h Action_GIST.h Action_Grid.h Action_GridFreeEnergy.h Action_HydrogenBond.h Action_Image.h Action_InfraredSpectrum.h Action_Jcoupling.h Action_Keep.h Action_LESsplit.h Action_LIE.h Action_LipidOrder.h Action_MakeStructure.h Action_Mask.h Action_Matrix.h Action_MinImage.h Action_MinMaxDist.h Action_Molsurf.h Action_MultiDihedral.h Action_MultiPucker.h Action_MultiVector.h Action_NAstruct.h Action_NMRrst.h Action_NativeContacts.h Action_OrderParameter.h Action_Outtraj.h Action_PairDist.h Action_Pairwise.h Action_Principal.h Action_Projection.h Action_Pucker.h Action_Radgyr.h Action_Radial.h Action_RandomizeIons.h Action_Remap.h Action_ReplicateCell.h Action_Rmsd.h Action_Rotate.h Action_RunningAvg.h Action_STFC_Diffusion.h Action_Scale.h Action_SetVelocity.h Action_Spam.h Action_Strip.h Action_Surf.h Action_SymmetricRmsd.h Action_Temperature.h Action_Time.h Action_ToroidalDiffusion.h Action_Translate.h Action_Unstrip.h Action_Unwrap.h Action_Vector.h Action_VelocityAutoCorr.h Action_Volmap.h Action_Volume.h Action_Watershell.h Action_XtalSymm.h Analysis.h AnalysisList.h AnalysisState.h Analysis_AmdBias.h Analysis_AutoCorr.h Analysis_Average.h Analysis_CalcDiffusion.h Analysis_Clustering.h Analysis_ConstantPHStats.h Analysis_Corr.h Analysis_CrankShaft.h Analysis_CrdFluct.h Analysis_CrossCorr.h Analysis_CurveFit.h Analysis_Divergence.h Analysis_EvalPlateau.h Analysis_FFT.h Analysis_HausdorffDistance.h Analysis_Hist.h Analysis_IRED.h Analysis_Integrate.h Analysis_KDE.h Analysis_Lifetime.h Analysis_LowestCurve.h Analysis_Matrix.h Analysis_MeltCurve.h Analysis_Modes.h Analysis_MultiHist.h Analysis_Multicurve.h Analysis_Overlap.h Analysis_PhiPsi.h Analysis_Project.h Analysis_Regression.h Analysis_RemLog.h Analysis_Rms2d.h Analysis_RmsAvgCorr.h Analysis_Rotdif.h Analysis_RunningAvg.h Analysis_Slope.h Analysis_Spline.h Analysis_State.h Analysis_Statistics.h Analysis_TI.h Analysis_TICA.h Analysis_Timecorr.h Analysis_VectorMath.h Analysis_Wavelet.h ArgList.h Array1D.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h AxisType.h BaseIOtype.h Box.h BoxArgs.h BufferedLine.h CharMask.h Cluster/Algorithm.h Cluster/BestReps.h Cluster/CentroidArray.h Cluster/Cframes.h Cluster/Control.h Cluster/DrawGraph.h Cluster/List.h Cluster/Metric.h Cluster/MetricArray.h Cluster/Node.h Cluster/Sieve.h Cluster/Silhouette.h ClusterMap.h Cmd.h CmdInput.h CmdList.h Command.h CompactFrameArray.h ComplexArray.h Constants.h Constraints.h ControlBlock.h ControlBlock_For.h CoordinateInfo.h Corr.h Cph.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_GridFlt.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_RemLog.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h Deprecated.h DiffusionResults.h DihedralSearch.h Dimension.h DispatchObject.h Energy.h Energy/Ecalc_Nonbond.h Energy/EnergyDecomposer.h Energy/ErfcFxn.h Energy/EwaldParams.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h Energy_Sander.h EnsembleIn.h EnsembleOutList.h EwaldOptions.h ExclusionArray.h Exec.h Exec_AddMissingRes.h Exec_Analyze.h Exec_Calc.h Exec_CatCrd.h Exec_Change.h Exec_ClusterMap.h Exec_CombineCoords.h Exec_Commands.h Exec_CompareClusters.h Exec_CompareEnergy.h Exec_CompareTop.h Exec_CrdAction.h Exec_CrdOut.h Exec_CrdTransform.h Exec_CreateSet.h Exec_DataFile.h Exec_DataFilter.h Exec_DataSetCmd.h Exec_Emin.h Exec_ExtendedComparison.h Exec_Flatten.h Exec_GenerateAmberRst.h Exec_Graft.h Exec_Help.h Exec_HmassRepartition.h Exec_LoadCrd.h Exec_LoadTraj.h Exec_ParallelAnalysis.h Exec_ParmBox.h Exec_ParmSolvent.h Exec_ParmStrip.h Exec_ParmWrite.h Exec_ParseTiming.h Exec_PermuteDihedrals.h Exec_Precision.h Exec_PrepareForLeap.h Exec_PrintData.h Exec_Random.h Exec_ReadData.h Exec_ReadEnsembleData.h Exec_ReadInput.h Exec_RotateDihedral.h Exec_RunAnalysis.h Exec_ScaleDihedralK.h Exec_Sequence.h Exec_SequenceAlign.h Exec_Set.h Exec_Show.h Exec_SortEnsembleData.h Exec_SplitCoords.h Exec_System.h Exec_Top.h Exec_Traj.h Exec_UpdateParameters.h Exec_ViewRst.h Exec_Zmatrix.h ExtendedSimilarity.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h GIST_PME.h Grid.h GridAction.h GridBin.h GridMover.h HistBin.h Hungarian.h ImageOption.h ImageTypes.h InputTrajCommon.h InteractionData.h MapAtom.h MaskArray.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Routines.h NameType.h NetcdfFile.h OnlineVarT.h OutputTrajCommon.h PDBfile.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PubFFT.h Pucker.h Pucker_PuckerMask.h Pucker_PuckerSearch.h Pucker_PuckerToken.h RPNcalc.h Random.h Range.h ReferenceAction.h ReferenceFrame.h RemdReservoirNC.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Spline.h SplineFxnTable.h StructureCheck.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h TrajoutList.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h molsurf.h CompactFrameArray.o : CompactFrameArray.cpp Box.h CompactFrameArray.h CoordinateInfo.h CpptrajStdio.h Matrix_3x3.h Parallel.h ReplicaDimArray.h Vec3.h ComplexArray.o : ComplexArray.cpp ArrayIterator.h ComplexArray.h Constraints.o : Constraints.cpp ArgList.h Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h Constraints.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -274,7 +275,21 @@ Deprecated.o : Deprecated.cpp CpptrajStdio.h Deprecated.h DispatchObject.h DiffusionResults.o : DiffusionResults.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DiffusionResults.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DihedralSearch.o : DihedralSearch.cpp ArgList.h Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DihedralSearch.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h DistRoutines.o : DistRoutines.cpp Box.h DistRoutines.h ImageOption.h Matrix_3x3.h Parallel.h Vec3.h -Energy.o : Energy.cpp Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h Energy.h Energy/Ene_Angle.h Energy/Ene_Bond.h Energy/Kernel_Harmonic.h ExclusionArray.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h +Energy.o : Energy.cpp Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h Energy.h Energy/Ene_Angle.h Energy/Ene_Bond.h Energy/Ene_LJ_6_12.h Energy/Kernel_Harmonic.h ExclusionArray.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h +Energy/Ecalc_Nonbond.o : Energy/Ecalc_Nonbond.cpp Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ecalc_Nonbond.h Energy/Ene_Decomp_Nonbond.h Energy/Ene_LJPME_6_12.h Energy/Ene_LJ_6_12.h Energy/Ene_Nonbond.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_Decomp.h Energy/EwaldCalc_Decomp_LJPME.h Energy/EwaldCalc_Decomp_PME.h Energy/EwaldCalc_LJPME.h Energy/EwaldCalc_PME.h Energy/EwaldCalc_Regular.h Energy/EwaldParams.h Energy/EwaldParams_LJPME.h Energy/Ewald_Recip.h Energy/Kernel_EwaldAdjust.h Energy/Kernel_LJPME_Adjust.h Energy/PME_Recip.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_Decomp_LJLR.h PairListEngine_Ewald_Decomp_LJPME.h PairListEngine_Ewald_LJLR.h PairListEngine_Ewald_LJPME.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h helpme_standalone.h +Energy/EnergyDecomposer.o : Energy/EnergyDecomposer.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mesh.h Dimension.h DistRoutines.h Energy/Ecalc_Nonbond.h Energy/Ene_Angle.h Energy/Ene_Bond.h Energy/Ene_LJ_6_12.h Energy/EnergyDecomposer.h Energy/Kernel_Fourier.h Energy/Kernel_Harmonic.h EwaldOptions.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OnlineVarT.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h Stats_Reduce.h SymbolExporting.h TextFormat.h Timer.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h +Energy/ErfcFxn.o : Energy/ErfcFxn.cpp CpptrajStdio.h Energy/ErfcFxn.h SplineFxnTable.h +Energy/EwaldCalc_Decomp_LJPME.o : Energy/EwaldCalc_Decomp_LJPME.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ene_LJPME_6_12.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_Decomp.h Energy/EwaldCalc_Decomp_LJPME.h Energy/EwaldParams.h Energy/EwaldParams_LJPME.h Energy/Kernel_EwaldAdjust.h Energy/Kernel_LJPME_Adjust.h Energy/PME_Recip.h Energy/PME_RecipParams.h EwaldOptions.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_Decomp_LJPME.h PairListTemplate.h Parallel.h ParameterTypes.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h helpme_standalone.h +Energy/EwaldCalc_Decomp_PME.o : Energy/EwaldCalc_Decomp_PME.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ene_LJ_6_12.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_Decomp.h Energy/EwaldCalc_Decomp_PME.h Energy/EwaldParams.h Energy/Kernel_EwaldAdjust.h Energy/PME_Recip.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_Decomp_LJLR.h PairListTemplate.h Parallel.h ParameterTypes.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h helpme_standalone.h +Energy/EwaldCalc_LJPME.o : Energy/EwaldCalc_LJPME.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ene_LJPME_6_12.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_LJPME.h Energy/EwaldParams.h Energy/EwaldParams_LJPME.h Energy/Kernel_EwaldAdjust.h Energy/Kernel_LJPME_Adjust.h Energy/PME_Recip.h Energy/PME_RecipParams.h EwaldOptions.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_LJPME.h PairListTemplate.h Parallel.h ParameterTypes.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h helpme_standalone.h +Energy/EwaldCalc_PME.o : Energy/EwaldCalc_PME.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ene_LJ_6_12.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_PME.h Energy/EwaldParams.h Energy/Kernel_EwaldAdjust.h Energy/PME_Recip.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_LJLR.h PairListTemplate.h Parallel.h ParameterTypes.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h helpme_standalone.h +Energy/EwaldCalc_Regular.o : Energy/EwaldCalc_Regular.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/Ene_LJ_6_12.h Energy/ErfcFxn.h Energy/EwaldCalc.h Energy/EwaldCalc_Regular.h Energy/EwaldParams.h Energy/Ewald_Recip.h Energy/Kernel_EwaldAdjust.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListEngine_Ewald_LJLR.h PairListTemplate.h Parallel.h ParameterTypes.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h +Energy/EwaldParams.o : Energy/EwaldParams.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/ErfcFxn.h Energy/EwaldParams.h EwaldOptions.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h +Energy/EwaldParams_LJPME.o : Energy/EwaldParams_LJPME.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/ErfcFxn.h Energy/EwaldParams.h Energy/EwaldParams_LJPME.h EwaldOptions.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h +Energy/Ewald_Recip.o : Energy/Ewald_Recip.cpp Box.h Constants.h CpptrajStdio.h Energy/ErfcFxn.h Energy/EwaldParams.h Energy/Ewald_Recip.h EwaldOptions.h Matrix_3x3.h Parallel.h ParameterTypes.h SplineFxnTable.h StringRoutines.h Timer.h Vec3.h +Energy/PME_Recip.o : Energy/PME_Recip.cpp Box.h CpptrajStdio.h Energy/PME_Recip.h Energy/PME_RecipParams.h Matrix_3x3.h Parallel.h Timer.h Vec3.h helpme_standalone.h +Energy/PME_RecipParams.o : Energy/PME_RecipParams.cpp Box.h CpptrajStdio.h Energy/PME_RecipParams.h EwaldOptions.h Matrix_3x3.h Parallel.h Vec3.h +Energy/VDW_LongRange_Correction.o : Energy/VDW_LongRange_Correction.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/VDW_LongRange_Correction.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h EnergyArray.o : EnergyArray.cpp CpptrajFile.h CpptrajStdio.h EnergyArray.h FileIO.h FileName.h Parallel.h Energy_Sander.o : Energy_Sander.cpp ArgList.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy_Sander.h FileName.h FileTypes.h File_TempName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ParmFile.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h EnsembleIn.o : EnsembleIn.cpp Atom.h AtomMask.h Box.h CoordinateInfo.h CpptrajStdio.h EnsembleIn.h FileName.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h Timer.h TrajFrameCounter.h Unit.h Vec3.h @@ -285,10 +300,7 @@ EnsembleOut.o : EnsembleOut.cpp ActionFrameCounter.h BaseIOtype.h Box.h Coordina EnsembleOutList.o : EnsembleOutList.cpp ActionFrameCounter.h ArgList.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h EnsembleOut.h EnsembleOutList.h EnsembleOut_Multi.h EnsembleOut_Single.h FileName.h FileTypes.h Frame.h FramePtrArray.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TrajectoryFile.h TypeNameHolder.h Unit.h Vec3.h EnsembleOut_Multi.o : EnsembleOut_Multi.cpp ActionFrameCounter.h ArgList.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h EnsembleOut.h EnsembleOut_Multi.h FileName.h FileTypes.h Frame.h FramePtrArray.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Topology.h TrajectoryFile.h TrajectoryIO.h TypeNameHolder.h Unit.h Vec3.h EnsembleOut_Single.o : EnsembleOut_Single.cpp ActionFrameCounter.h ArgList.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h EnsembleOut.h EnsembleOut_Single.h FileName.h FileTypes.h Frame.h FramePtrArray.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TrajectoryFile.h TrajectoryIO.h TypeNameHolder.h Unit.h Vec3.h -Ewald.o : Ewald.cpp Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h EnergyKernel_Adjust.h EnergyKernel_Nonbond.h Ewald.h ExclusionArray.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h PairListLoop.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Spline.h SplineFxnTable.h StringRoutines.h SymbolExporting.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h EwaldOptions.o : EwaldOptions.cpp ArgList.h CpptrajStdio.h EwaldOptions.h -Ewald_ParticleMesh.o : Ewald_ParticleMesh.cpp Atom.h AtomMask.h Box.h CoordinateInfo.h CpptrajStdio.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h Parallel.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Unit.h Vec3.h helpme_standalone.h -Ewald_Regular.o : Ewald_Regular.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Ewald.h EwaldOptions.h Ewald_Regular.h ExclusionArray.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h Parallel.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h StringRoutines.h SymbolExporting.h Timer.h Unit.h Vec3.h ExclusionArray.o : ExclusionArray.cpp Atom.h AtomMask.h CharMask.h CpptrajStdio.h ExclusionArray.h MaskToken.h Molecule.h NameType.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Unit.h Exec_AddMissingRes.o : Exec_AddMissingRes.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h CharMask.h CompactFrameArray.h Constants.h Constraints.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnergyArray.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_AddMissingRes.h Exec_AddMissingRes_Pres.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MdOpts.h MetaData.h Minimize_SteepestDescent.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ParmFile.h PotentialFunction.h PotentialTerm.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h Trajin_Single.h TrajoutList.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h Exec_Analyze.o : Exec_Analyze.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Cmd.h CmdList.h Command.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_Analyze.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h @@ -365,7 +377,7 @@ ForLoop_list.o : ForLoop_list.cpp Action.h ActionList.h ActionState.h Analysis.h ForLoop_mask.o : ForLoop_mask.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h FileIO.h FileName.h FileTypes.h ForLoop.h ForLoop_mask.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h ForLoop_overSets.o : ForLoop_overSets.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h FileIO.h FileName.h FileTypes.h ForLoop.h ForLoop_overSets.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h Frame.o : Frame.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Unit.h Vec3.h -GIST_PME.o : GIST_PME.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h EnergyKernel_Adjust.h EnergyKernel_Nonbond.h Ewald.h Ewald_ParticleMesh.h ExclusionArray.h FileName.h Frame.h GIST_PME.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h helpme_standalone.h +GIST_PME.o : GIST_PME.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Energy/ErfcFxn.h Energy/EwaldParams.h Energy/Kernel_EwaldAdjust.h Energy/PME_RecipParams.h Energy/VDW_LongRange_Correction.h EwaldOptions.h ExclusionArray.h FileName.h Frame.h GIST_PME.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h helpme_standalone.h GistEntropyUtils.o : GistEntropyUtils.cpp CpptrajFile.h FileIO.h FileName.h GistEntropyUtils.h Parallel.h Vec3.h Gpu.o : Gpu.cpp Gpu.h GridAction.o : GridAction.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h FileIO.h FileName.h Frame.h Grid.h GridAction.h GridBin.h GridMover.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -442,6 +454,7 @@ SimplexMin.o : SimplexMin.cpp AssociatedData.h CpptrajFile.h CpptrajStdio.h Data SpaceGroup.o : SpaceGroup.cpp Matrix_3x3.h Parallel.h SpaceGroup.h Vec3.h Spline.o : Spline.cpp CpptrajStdio.h Spline.h SplineFxnTable.o : SplineFxnTable.cpp Constants.h CpptrajStdio.h Spline.h SplineFxnTable.h StringRoutines.h +Stats_Reduce.o : Stats_Reduce.cpp OnlineVarT.h Parallel.h Stats_Reduce.h StringRoutines.o : StringRoutines.cpp CpptrajStdio.h StringRoutines.h Structure/Builder.o : Structure/Builder.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/BuildAtom.h Structure/Builder.h Structure/Chirality.h Structure/InternalCoords.h Structure/StructureEnum.h Structure/Zmatrix.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h Structure/Chirality.o : Structure/Chirality.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/Chirality.h Structure/StructureEnum.h SymbolExporting.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h diff --git a/src/cpptrajfiles b/src/cpptrajfiles index 493089d055..ddfc01d3fe 100644 --- a/src/cpptrajfiles +++ b/src/cpptrajfiles @@ -35,6 +35,7 @@ COMMON_SOURCES= \ Action_Dipole.cpp \ Action_Distance.cpp \ Action_DistRmsd.cpp \ + Action_EneDecomp.cpp \ Action_Energy.cpp \ Action_FilterByData.cpp \ Action_FixAtomOrder.cpp \ @@ -255,9 +256,6 @@ COMMON_SOURCES= \ EnsembleOut_Multi.cpp \ EnsembleOut_Single.cpp \ EnsembleOutList.cpp \ - Ewald.cpp \ - Ewald_ParticleMesh.cpp \ - Ewald_Regular.cpp \ EwaldOptions.cpp \ ExclusionArray.cpp \ Exec_AddMissingRes.cpp \ @@ -411,6 +409,7 @@ COMMON_SOURCES= \ SimplexMin.cpp \ Spline.cpp \ SplineFxnTable.cpp \ + Stats_Reduce.cpp \ StringRoutines.cpp \ StructureCheck.cpp \ StructureMapper.cpp \ @@ -479,7 +478,7 @@ SOURCES=$(COMMON_SOURCES) \ # by libcpptraj. They MUST have the '.LIBCPPTRAJ.o' extension and will be # compiled with the '-DLIBCPPTRAJ' define. # NOTE: This variable MUST be in cpptrajfiles as the cmake build expects it. -LIBCPPTRAJ_OBJECTS=$(COMMON_SOURCES:.cpp=.o) $(CSOURCES:.c=.o) $(CLUSTER_SOURCEFILES:.cpp=.o) $(STRUCTURE_SOURCEFILES:.cpp=.o) \ +LIBCPPTRAJ_OBJECTS=$(COMMON_SOURCES:.cpp=.o) $(CSOURCES:.c=.o) $(CLUSTER_SOURCEFILES:.cpp=.o) $(STRUCTURE_SOURCEFILES:.cpp=.o) $(ENERGY_SOURCEFILES:.cpp=.o) \ Action_Esander.LIBCPPTRAJ.o \ Command.LIBCPPTRAJ.o \ Cpptraj.LIBCPPTRAJ.o \ diff --git a/test/Makefile b/test/Makefile index d518104090..2931fb985c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -542,6 +542,9 @@ test.sequence: test.tica: @-cd Test_TICA && ./RunTest.sh $(OPT) +test.enedecomp: + @-cd Test_EneDecomp && ./RunTest.sh $(OPT) + # Every test target should go here. COMPLETETESTS=test.general \ test.strip \ @@ -713,7 +716,8 @@ COMPLETETESTS=test.general \ test.zmatrix \ test.readoff \ test.sequence \ - test.tica + test.tica \ + test.enedecomp test.all: $(MAKE) test.complete summary diff --git a/test/Test_EneDecomp/AFV.rst7 b/test/Test_EneDecomp/AFV.rst7 new file mode 100644 index 0000000000..91b6d93235 --- /dev/null +++ b/test/Test_EneDecomp/AFV.rst7 @@ -0,0 +1,27 @@ +NALA + 49 + 3.3257700 1.5479090 -0.0000016 4.0461540 0.8399910 -0.0000029 + 2.8230940 1.4995080 -0.8746870 2.8230970 1.4995070 0.8746850 + 3.9700480 2.8457950 -0.0000001 3.6716630 3.4001290 -0.8898200 + 3.5769650 3.6538380 1.2321430 3.8774840 3.1157950 2.1311970 + 4.0750590 4.6230170 1.2057860 2.4969950 3.8010750 1.2413790 + 5.4855410 2.7052070 -0.0000044 6.0088240 1.5931750 -0.0000084 + 6.1910071 3.8385836 -0.0000051 5.7152868 4.7295323 -0.0000028 + 7.6400076 3.8385837 -0.0000074 8.0038585 3.3248391 0.8898118 + 8.1890012 3.1272109 -1.2321515 7.8406894 2.0944027 -1.2413883 + 7.8406911 3.6356234 -2.1312048 9.6955048 3.0758575 -1.3210964 + 10.3114182 2.4472435 -2.4099003 9.7034770 1.9948914 -3.1934084 + 11.7081764 2.3996298 -2.4923651 12.1877101 1.9102104 -3.3400779 + 12.4890227 2.9806305 -1.4860270 13.5764985 2.9435606 -1.5502317 + 11.8731121 3.6092454 -0.3972211 12.4810564 4.0615971 0.3862850 + 10.4763538 3.6568613 -0.3147532 9.9968237 4.1462834 0.5329595 + 8.1879242 5.2585384 -0.0000020 7.4245351 6.2216985 0.0000034 + 9.5167782 5.3864922 -0.0000020 10.1032885 4.5642362 -0.0000053 + 10.1610562 6.6843782 0.0000012 9.8626701 7.2387139 -0.8898172 + 9.7679746 7.4924189 1.2321464 8.6880046 7.6396559 1.2413839 + 10.1887231 6.7390615 2.4895434 11.2687041 6.5918435 2.4812439 + 9.9079841 7.3162048 3.3705609 9.6906411 5.7699014 2.5168342 + 10.4651956 8.8481830 1.1945821 10.1647895 9.3870427 0.2959785 + 10.1845696 9.4261643 2.0750855 11.5452806 8.7017590 1.1857916 + 11.6765492 6.5437902 -0.0000051 12.1998322 5.4317582 -0.0000119 + 12.3954632 7.5405862 -0.0000021 diff --git a/test/Test_EneDecomp/RunTest.sh b/test/Test_EneDecomp/RunTest.sh new file mode 100755 index 0000000000..0b67978de2 --- /dev/null +++ b/test/Test_EneDecomp/RunTest.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +. ../MasterTest.sh + +TESTNAME='Energy decomposition tests' + +CleanFiles enedecomp.in ene.*.dat decomp.*.dat Total.*.dat + +TESTNAME='Particle mesh Ewald tests' +#Requires maxthreads 1 + +INPUT='-i enedecomp.in' + +UNITNAME='NaCl box decomposition' +CheckFor libpme maxthreads 1 +if [ $? -eq 0 ] ; then + cat > enedecomp.in < enedecomp.in < enedecomp.in <