/** Set up the exclusion list based on the given mask and parm. * \return the total number of interactions, -1 on error. */ int Action_Pairwise::SetupNonbondParm(AtomMask const& maskIn, Topology const& ParmIn) { // Check if LJ parameters present - need at least 2 atoms for it to matter. if (ParmIn.Natom() > 1 && !ParmIn.Nonbond().HasNonbond()) { mprinterr("Error: Topology does not have LJ information.\n"); return -1; } // Determine the actual number of pairwise interactions that will be calcd. // This is ((N^2 - N) / 2) - SUM[ #excluded atoms] int N_interactions = ((maskIn.Nselected() * maskIn.Nselected()) - maskIn.Nselected()) / 2; for (AtomMask::const_iterator at = maskIn.begin(); at != maskIn.end(); ++at) N_interactions -= ParmIn[ *at ].Nexcluded(); // DEBUG - Print total number of interactions for this parm mprintf("\t%i interactions for this parm.\n",N_interactions); // DEBUG - Print exclusion list for each atom /*for (unsigned int atom = 0; atom < exclusionList.size(); atom++) { mprintf("\t%8u:",atom + 1); for (std::vector<int>::iterator eat = exclusionList[atom].begin(); eat != exclusionList[atom].end(); eat++) { mprintf(" %i",*eat + 1); } mprintf("\n"); }*/ return N_interactions; }
/** 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<NonbondParmType const*>( &(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. Iarray N_vdw_type( NB_->Ntypes(), 0 ); for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm) N_vdw_type[ 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++) { 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) Vdw_Recip_term_ += N_vdw_type[itype] * N_vdw_type[jtype] * NB_->NBarray()[ nbidx ].B(); } } }
// Action_Matrix::FillMassArray() Action_Matrix::Darray Action_Matrix::FillMassArray(Topology const& currentParm, AtomMask const& mask) const { Darray mass; mass.reserve( mask.Nselected() ); for (AtomMask::const_iterator atom = mask.begin(); atom != mask.end(); ++atom) mass.push_back( currentParm[ *atom ].Mass() ); return mass; }
/** Remove any selected solvent atoms from mask. */ static void removeSelectedSolvent( Topology const& parmIn, AtomMask& mask ) { AtomMask newMask = mask; newMask.ClearSelected(); for (AtomMask::const_iterator atom = mask.begin(); atom != mask.end(); ++atom) { int molnum = parmIn[*atom].MolNum(); if (!parmIn.Mol(molnum).IsSolvent()) newMask.AddSelectedAtom( *atom ); } mask = newMask; }
/** Set up atom/residue indices corresponding to atoms selected in mask. * This is done to make creating an atom/residue contact map easier. */ Action_NativeContacts::Iarray Action_NativeContacts::SetupContactIndices( AtomMask const& mask, Topology const& parmIn) { Iarray contactIdx; for (AtomMask::const_iterator atom = mask.begin(); atom != mask.end(); ++atom) if (byResidue_) contactIdx.push_back( parmIn[*atom].ResNum() ); else contactIdx.push_back( *atom ); return contactIdx; }
/** Check that all atoms in mask belong to same residue. */ int Action_NMRrst::CheckSameResidue(Topology const& top, AtomMask const& mask) const { if (mask.None()) return -1; int resnum = top[mask[0]].ResNum(); for (AtomMask::const_iterator at = mask.begin(); at != mask.end(); ++at) { int r = top[*at].ResNum(); if (r != resnum) { mprintf("Warning: Mask atom %i %s not in same residue as %i %s\n", *at + 1, top.AtomMaskName(*at).c_str(), mask[0] + 1, top.AtomMaskName(mask[0]).c_str()); } } return resnum; }
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); }
/** Place selected atoms into grid cells. Convert to fractional coords, wrap * into primary cell, then determine grid cell. */ void PairList::GridUnitCell(Frame const& frmIn, Matrix_3x3 const& ucell, Matrix_3x3 const& recip, AtomMask const& maskIn) { // Clear any existing atoms in cells. for (Carray::iterator cell = cells_.begin(); cell != cells_.end(); ++cell) cell->ClearAtoms(); Frac_.clear(); Frac_.reserve( maskIn.Nselected() ); if (frmIn.BoxCrd().Type() == Box::ORTHO) { // Orthogonal imaging for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) { const double* XYZ = frmIn.XYZ(*atom); Vec3 fc( XYZ[0]*recip[0], XYZ[1]*recip[4], XYZ[2]*recip[8] ); Vec3 fcw(fc[0]-floor(fc[0]), fc[1]-floor(fc[1]), fc[2]-floor(fc[2])); Vec3 ccw(fcw[0]*ucell[0], fcw[1]*ucell[4], fcw[2]*ucell[8] ); # ifdef DEBUG_PAIRLIST mprintf("DBG: o %6i fc=%7.3f%7.3f%7.3f fcw=%7.3f%7.3f%7.3f ccw=%7.3f%7.3f%7.3f\n", *atom+1, fc[0], fc[1], fc[2], fcw[0], fcw[1], fcw[2], ccw[0], ccw[1], ccw[2]); # endif GridAtom( atom-maskIn.begin(), fcw, ccw ); } } else { // Non-orthogonal imaging for (AtomMask::const_iterator atom = maskIn.begin(); atom != maskIn.end(); ++atom) { Vec3 fc = recip * Vec3(frmIn.XYZ(*atom)); Vec3 fcw(fc[0]-floor(fc[0]), fc[1]-floor(fc[1]), fc[2]-floor(fc[2])); Vec3 ccw = ucell.TransposeMult( fcw ); # ifdef DEBUG_PAIRLIST mprintf("DBG: n %6i fc=%7.3f%7.3f%7.3f fcw=%7.3f%7.3f%7.3f ccw=%7.3f%7.3f%7.3f\n", *atom+1, fc[0], fc[1], fc[2], fcw[0], fcw[1], fcw[2], ccw[0], ccw[1], ccw[2]); # endif GridAtom( atom-maskIn.begin(), fcw, ccw ); } } }
/** Calculate full nonbonded energy with PME */ double Ewald_ParticleMesh::CalcEnergy(Frame const& frameIn, AtomMask const& maskIn, double& e_vdw) { t_total_.Start(); Matrix_3x3 ucell, recip; double volume = frameIn.BoxCrd().ToRecip(ucell, recip); double e_self = Self( volume ); double e_vdw_lr_correction; pairList_.CreatePairList(frameIn, ucell, recip, maskIn); // 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_direct = Direct( pairList_, e_vdw ); if (debug_ > 0) mprintf("DEBUG: Eself= %20.10f Erecip= %20.10f Edirect= %20.10f Evdw= %20.10f\n", e_self, e_recip, e_direct, e_vdw); e_vdw += (e_vdw_lr_correction + e_vdw6self + e_vdw6recip); t_total_.Stop(); return e_self + e_recip + e_direct; }
/** 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 ); }
/** Set up masks. */ int Cpptraj::MaskArray::SetupMasks(AtomMask const& maskIn, Topology const& topIn) { if (type_ == BY_MOLECULE && topIn.Nmol() < 1) { mprintf("Warning: '%s' has no molecule information, cannot setup by molecule.\n", topIn.c_str()); return 1; } masks_.clear(); if ( maskIn.None() ) { mprintf("Warning: Nothing selected by mask '%s'\n", maskIn.MaskString()); return 0; } int last = -1; int current = 0; maxAtomsPerMask_ = 0; sameNumAtomsPerMask_ = true; for (AtomMask::const_iterator atm = maskIn.begin(); atm != maskIn.end(); ++atm) { switch (type_) { case BY_ATOM : current = *atm; break; case BY_RESIDUE : current = topIn[*atm].ResNum(); break; case BY_MOLECULE : current = topIn[*atm].MolNum(); break; } if (current != last) { if (!masks_.empty()) checkAtomsPerMask( masks_.back().Nselected() ); masks_.push_back( AtomMask() ); masks_.back().SetNatoms( topIn.Natom() ); } masks_.back().AddSelectedAtom( *atm ); last = current; } if (!masks_.empty()) checkAtomsPerMask( masks_.back().Nselected() ); return 0; }
/** Add the atoms in Mask to this mask starting at the specified positon. * Currently only used by Closest for modifying the original stripped * mask with the calculated closest waters. */ void AtomMask::AddMaskAtPosition(AtomMask const& maskIn, int idx) { // NOTE: NO BOUNDS CHECK! for (const_iterator atom = maskIn.begin(); atom != maskIn.end(); atom++) Selected_[idx++] = *atom; }
/** Set up each mask/integer loop. */ int ControlBlock_For::SetupBlock(CpptrajState& State, ArgList& argIn) { mprintf(" Setting up 'for' loop.\n"); Vars_.clear(); Topology* currentTop = 0; static const char* TypeStr[] = { "ATOMS ", "RESIDUES ", "MOLECULES ", "MOL_FIRST_RES ", "MOL_LAST_RES " }; static const char* OpStr[] = {"+=", "-=", "<", ">"}; description_.assign("for ("); int MaxIterations = -1; int iarg = 0; while (iarg < argIn.Nargs()) { // Advance to next unmarked argument. while (iarg < argIn.Nargs() && argIn.Marked(iarg)) iarg++; if (iarg == argIn.Nargs()) break; // Determine 'for' type ForType ftype = UNKNOWN; bool isMaskFor = true; int argToMark = iarg; if ( argIn[iarg] == "atoms" ) ftype = ATOMS; else if ( argIn[iarg] == "residues" ) ftype = RESIDUES; else if ( argIn[iarg] == "molecules" ) ftype = MOLECULES; else if ( argIn[iarg] == "molfirstres" ) ftype = MOLFIRSTRES; else if ( argIn[iarg] == "mollastres" ) ftype = MOLLASTRES; else if ( argIn[iarg].find(";") != std::string::npos ) { isMaskFor = false; ftype = INTEGER; } // If type is still unknown, check for list. if (ftype == UNKNOWN) { if (iarg+1 < argIn.Nargs() && argIn[iarg+1] == "in") { ftype = LIST; isMaskFor = false; argToMark = iarg+1; } } // Exit if type could not be determined. if (ftype == UNKNOWN) { mprinterr("Error: for loop type not specfied.\n"); return 1; } argIn.MarkArg(argToMark); Vars_.push_back( LoopVar() ); LoopVar& MH = Vars_.back(); int Niterations = -1; // Set up for specific type if (description_ != "for (") description_.append(", "); // ------------------------------------------- if (isMaskFor) { // {atoms|residues|molecules} <var> inmask <mask> [TOP KEYWORDS] if (argIn[iarg+2] != "inmask") { mprinterr("Error: Expected 'inmask', got %s\n", argIn[iarg+2].c_str()); return 1; } AtomMask currentMask; if (currentMask.SetMaskString( argIn.GetStringKey("inmask") )) return 1; MH.varType_ = ftype; Topology* top = State.DSL().GetTopByIndex( argIn ); if (top != 0) currentTop = top; if (currentTop == 0) return 1; MH.varname_ = argIn.GetStringNext(); if (MH.varname_.empty()) { mprinterr("Error: 'for inmask': missing variable name.\n"); return 1; } MH.varname_ = "$" + MH.varname_; // Set up mask if (currentTop->SetupIntegerMask( currentMask )) return 1; currentMask.MaskInfo(); if (currentMask.None()) return 1; // Set up indices if (MH.varType_ == ATOMS) MH.Idxs_ = currentMask.Selected(); else if (MH.varType_ == RESIDUES) { int curRes = -1; for (AtomMask::const_iterator at = currentMask.begin(); at != currentMask.end(); ++at) { int res = (*currentTop)[*at].ResNum(); if (res != curRes) { MH.Idxs_.push_back( res ); curRes = res; } } } else if (MH.varType_ == MOLECULES || MH.varType_ == MOLFIRSTRES || MH.varType_ == MOLLASTRES) { int curMol = -1; for (AtomMask::const_iterator at = currentMask.begin(); at != currentMask.end(); ++at) { int mol = (*currentTop)[*at].MolNum(); if (mol != curMol) { if (MH.varType_ == MOLECULES) MH.Idxs_.push_back( mol ); else { int res; if (MH.varType_ == MOLFIRSTRES) res = (*currentTop)[ currentTop->Mol( mol ).BeginAtom() ].ResNum(); else // MOLLASTRES res = (*currentTop)[ currentTop->Mol( mol ).EndAtom()-1 ].ResNum(); MH.Idxs_.push_back( res ); } curMol = mol; } } } Niterations = (int)MH.Idxs_.size(); description_.append(std::string(TypeStr[MH.varType_]) + MH.varname_ + " inmask " + currentMask.MaskExpression()); // ------------------------------------------- } else if (ftype == INTEGER) { // [<var>=<start>;[<var><OP><end>;]<var><OP>[<value>]] MH.varType_ = ftype; ArgList varArg( argIn[iarg], ";" ); if (varArg.Nargs() < 2 || varArg.Nargs() > 3) { mprinterr("Error: Malformed 'for' loop variable.\n" "Error: Expected '[<var>=<start>;[<var><OP><end>;]<var><OP>[<value>]]'\n" "Error: Got '%s'\n", argIn[iarg].c_str()); return 1; } // First argument: <var>=<start> ArgList startArg( varArg[0], "=" ); if (startArg.Nargs() != 2) { mprinterr("Error: Malformed 'start' argument.\n" "Error: Expected <var>=<start>, got '%s'\n", varArg[0].c_str()); return 1; } MH.varname_ = startArg[0]; if (!validInteger(startArg[1])) { // TODO allow variables mprinterr("Error: Start argument must be an integer.\n"); return 1; } else MH.start_ = convertToInteger(startArg[1]); // Second argument: <var><OP><end> size_t pos0 = MH.varname_.size(); size_t pos1 = pos0 + 1; MH.endOp_ = NO_OP; int iargIdx = 1; if (varArg.Nargs() == 3) { iargIdx = 2; if ( varArg[1][pos0] == '<' ) MH.endOp_ = LESS_THAN; else if (varArg[1][pos0] == '>') MH.endOp_ = GREATER_THAN; if (MH.endOp_ == NO_OP) { mprinterr("Error: Unrecognized end op: '%s'\n", varArg[1].substr(pos0, pos1-pos0).c_str()); return 1; } std::string endStr = varArg[1].substr(pos1); if (!validInteger(endStr)) { // TODO allow variables mprinterr("Error: End argument must be an integer.\n"); return 1; } else MH.end_ = convertToInteger(endStr); } // Third argument: <var><OP>[<value>] pos1 = pos0 + 2; MH.incOp_ = NO_OP; bool needValue = false; if ( varArg[iargIdx][pos0] == '+' ) { if (varArg[iargIdx][pos0+1] == '+') { MH.incOp_ = INCREMENT; MH.inc_ = 1; } else if (varArg[iargIdx][pos0+1] == '=') { MH.incOp_ = INCREMENT; needValue = true; } } else if ( varArg[iargIdx][pos0] == '-' ) { if (varArg[iargIdx][pos0+1] == '-' ) { MH.incOp_ = DECREMENT; MH.inc_ = 1; } else if (varArg[iargIdx][pos0+1] == '=') { MH.incOp_ = DECREMENT; needValue = true; } } if (MH.incOp_ == NO_OP) { mprinterr("Error: Unrecognized increment op: '%s'\n", varArg[iargIdx].substr(pos0, pos1-pos0).c_str()); return 1; } if (needValue) { std::string incStr = varArg[iargIdx].substr(pos1); if (!validInteger(incStr)) { mprinterr("Error: increment value is not a valid integer.\n"); return 1; } MH.inc_ = convertToInteger(incStr); if (MH.inc_ < 1) { mprinterr("Error: Extra '-' detected in increment.\n"); return 1; } } // Description MH.varname_ = "$" + MH.varname_; std::string sval = integerToString(MH.start_); description_.append("(" + MH.varname_ + "=" + sval + "; "); std::string eval; if (iargIdx == 2) { // End argument present eval = integerToString(MH.end_); description_.append(MH.varname_ + std::string(OpStr[MH.endOp_]) + eval + "; "); // Check end > start for increment, start > end for decrement int maxval, minval; if (MH.incOp_ == INCREMENT) { if (MH.start_ >= MH.end_) { mprinterr("Error: start must be less than end for increment.\n"); return 1; } minval = MH.start_; maxval = MH.end_; } else { if (MH.end_ >= MH.start_) { mprinterr("Error: end must be less than start for decrement.\n"); return 1; } minval = MH.end_; maxval = MH.start_; } // Figure out number of iterations Niterations = (maxval - minval) / MH.inc_; if (((maxval-minval) % MH.inc_) > 0) Niterations++; } description_.append( MH.varname_ + std::string(OpStr[MH.incOp_]) + integerToString(MH.inc_) + ")" ); // If decrementing just negate value if (MH.incOp_ == DECREMENT) MH.inc_ = -MH.inc_; // DEBUG //mprintf("DEBUG: start=%i endOp=%i end=%i incOp=%i val=%i startArg=%s endArg=%s\n", // MH.start_, (int)MH.endOp_, MH.end_, (int)MH.incOp_, MH.inc_, // MH.startArg_.c_str(), MH.endArg_.c_str()); // ------------------------------------------- } else if (ftype == LIST) { // <var> in <string0>[,<string1>...] MH.varType_ = ftype; // Variable name MH.varname_ = argIn.GetStringNext(); if (MH.varname_.empty()) { mprinterr("Error: 'for in': missing variable name.\n"); return 1; } MH.varname_ = "$" + MH.varname_; // Comma-separated list of strings std::string listArg = argIn.GetStringNext(); if (listArg.empty()) { mprinterr("Error: 'for in': missing comma-separated list of strings.\n"); return 1; } ArgList list(listArg, ","); if (list.Nargs() < 1) { mprinterr("Error: Could not parse '%s' for 'for in'\n", listArg.c_str()); return 1; } for (int il = 0; il != list.Nargs(); il++) { // Check if file name expansion should occur if (list[il].find_first_of("*?") != std::string::npos) { File::NameArray files = File::ExpandToFilenames( list[il] ); for (File::NameArray::const_iterator fn = files.begin(); fn != files.end(); ++fn) MH.List_.push_back( fn->Full() ); } else MH.List_.push_back( list[il] ); } Niterations = (int)MH.List_.size(); // Description description_.append( MH.varname_ + " in " + listArg ); } // Check number of values if (MaxIterations == -1) MaxIterations = Niterations; else if (Niterations != -1 && Niterations != MaxIterations) { mprintf("Warning: # iterations %i != previous # iterations %i\n", Niterations, MaxIterations); MaxIterations = std::min(Niterations, MaxIterations); } } mprintf("\tLoop will execute for %i iterations.\n", MaxIterations); if (MaxIterations < 1) { mprinterr("Error: Loop has less than 1 iteration.\n"); return 1; } description_.append(") do"); return 0; }
// DEBUG static void DebugContactList(AtomMask const& mask, Topology const& parmIn) { for (AtomMask::const_iterator atom = mask.begin(); atom != mask.end(); ++atom) mprintf("\tPotential Contact %li: %s\n", atom - mask.begin(), parmIn.AtomMaskName(*atom).c_str()); }
/** Calculate non-bonded energy using the nonbondParm array. The total * LJ (vdw) energy is put in ELJ, and the total Coulomb (elec) energy * is put in Eelec. Depending on the value of nb_calcType, each pair * energy is either compared to a reference, distributed over both atoms * evenly in the cumulative array, or reference values are set. If comparing * to a reference structure, pairs for which the energy difference exceeds * the cutoffs are printed. */ void Action_Pairwise::NonbondEnergy(Frame const& frameIn, Topology const& parmIn, AtomMask const& maskIn) { double delta2; NonbondEnergyType refE; ELJ_ = 0.0; Eelec_ = 0.0; std::vector<NonbondEnergyType>::const_iterator refpair = ref_nonbondEnergy_.begin(); // Loop over all atom pairs and set information // Outer loop for (AtomMask::const_iterator maskatom1 = maskIn.begin(); maskatom1 != maskIn.end(); ++maskatom1) { // Get coordinates for first atom. Vec3 coord1 = frameIn.XYZ( *maskatom1 ); // Set up exclusion list for this atom Atom::excluded_iterator excluded_atom = parmIn[*maskatom1].excludedbegin(); // Inner loop for (AtomMask::const_iterator maskatom2 = maskatom1 + 1; maskatom2 != maskIn.end(); ++maskatom2) { // If atom is excluded, just increment to next excluded atom; // otherwise perform energy calc. if ( excluded_atom != parmIn[*maskatom1].excludedend() && *maskatom2 == *excluded_atom ) ++excluded_atom; else { // Calculate the vector pointing from atom2 to atom1 Vec3 JI = coord1 - Vec3(frameIn.XYZ( *maskatom2 )); double rij2 = JI.Magnitude2(); // Normalize double rij = sqrt(rij2); JI /= rij; // LJ energy NonbondType const& LJ = parmIn.GetLJparam(*maskatom1, *maskatom2); 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) ELJ_ += e_vdw; // LJ Force //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 e_elec = qiqj / rij; Eelec_ += e_elec; // Coulomb Force //force=e_elec/rij; // kes_*(qiqj/r)*(1/r) //scalarmult(f,JI,F); // ---------------------------------------- int atom1 = *maskatom1; int atom2 = *maskatom2; if (nb_calcType_ == COMPARE_REF) { // 1 - Comparison to reference, cumulative dEnergy on atoms // dEvdw double delta_vdw = refpair->evdw - e_vdw; // dEelec double delta_eelec = refpair->eelec - e_elec; // Output if (Eout_ != 0) WriteEnergies(parmIn, atom1, atom2, delta_vdw, delta_eelec, "d"); vdwMat_->Element(atom1, atom2) += delta_vdw; eleMat_->Element(atom1, atom2) += delta_eelec; // Divide the total pair dEvdw between both atoms. delta2 = delta_vdw * 0.5; atom_evdw_[atom1] += delta2; atom_evdw_[atom2] += delta2; // Divide the total pair dEelec between both atoms. delta2 = delta_eelec * 0.5; atom_eelec_[atom1] += delta2; atom_eelec_[atom2] += delta2; } else if (nb_calcType_ == NORMAL) { // 2 - No reference, just cumulative Energy on atoms if (Eout_ != 0) WriteEnergies(parmIn, atom1, atom2, e_vdw, e_elec, ""); vdwMat_->Element(atom1, atom2) += e_vdw; eleMat_->Element(atom1, atom2) += e_elec; // Cumulative evdw - divide between both atoms delta2 = e_vdw * 0.5; atom_evdw_[atom1] += delta2; atom_evdw_[atom2] += delta2; // Cumulative eelec - divide between both atoms delta2 = e_elec * 0.5; atom_eelec_[atom1] += delta2; atom_eelec_[atom2] += delta2; } else { // if nb_calcType_ == SET_REF // 3 - Store the reference nonbond energy for this pair refE.evdw = e_vdw; refE.eelec = e_elec; ref_nonbondEnergy_.push_back( refE ); } ++refpair; // ---------------------------------------- } // END pair not excluded } // END Inner loop } // END Outer loop }