1 #include "buildISGTopology.h" 2 3 #include "ExclusionTable.h" 4 #include "ExclusionType.h" 5 #include "GenericTopology.h" 6 #include "iSGPAR.h" 7 #include "PSF.h" 8 #include "Report.h" 9 #include "pmconstants.h" 10 #include "mathutilities.h" 11 #include "stringutilities.h" 12 #include "topologyutilities.h" 13 14 #include <algorithm> 15 #include <list> 16 #include <map> 17 #include <set> 18 #include <string> 19 #include <vector> 20 21 using std::list; 22 using std::map; 23 using std::set; 24 using std::pair; 25 using std::string; 26 using std::vector; 27 28 using namespace ProtoMol::Report; 29 30 //#define DEBUG_PRINT_MOLECULETABLE 31 32 namespace ProtoMol { 33 34 static void findNextNeighbor(int a, vector<int>& v, vector<PairInt>& p, vector<bool>& unused, const vector<vector<int> >& graph, set<PairInt>& pairs); 35 // bool cmpSize(const vector<int>& m1, const vector<int>& m2); 36 37 38 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 // 40 // buildISGTopology 41 // 42 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 buildISGTopology(GenericTopology * topo,const PSF & psf,const iSGPAR & par)44 void buildISGTopology(GenericTopology* topo,const PSF& psf, const iSGPAR& par) { 45 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 46 // First, generate the array of atomtypes 47 // Each time a new atom comes up, we need to check if it is 48 // already in the vector.... 49 // NOTE: this may take a while for large systems; however, it will cut 50 // down on the size of the atomTypes vector, and therefore, the amount 51 // access time in the back end. 52 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 54 topo->atoms.clear(); 55 topo->atomTypes.clear(); 56 topo->bonds.clear(); 57 topo->angles.clear(); 58 topo->dihedrals.clear(); 59 topo->impropers.clear(); 60 61 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 // Get the atoms 63 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 64 65 map<string,int> atomLookUpTable; 66 67 // loop over all atoms in the PSF object 68 for (vector<PSF::Atom>::const_iterator atom = psf.atoms.begin(); 69 atom != psf.atoms.end(); ++atom) { 70 71 // store the atom_type name for this atom 72 AtomType tempatomtype; 73 tempatomtype.name = atom->atom_type; 74 tempatomtype.symbolName = atomTypeToSymbolName(atom->atom_type); 75 76 // Now check if this already exists (same name) 77 if (atomLookUpTable.find(tempatomtype.name) == atomLookUpTable.end()) { 78 79 // this is a new atom type, add to the atomTypes list 80 atomLookUpTable[tempatomtype.name] = topo->atomTypes.size(); 81 topo->atomTypes.push_back(tempatomtype); 82 } 83 84 85 Atom tempatom; 86 // First, we need to find the index. (an integer corresponding 87 // to the type of the atom 88 tempatom.type = atomLookUpTable[tempatomtype.name]; 89 90 // Now, the mass and scaled charge. These are straightforward. 91 tempatom.scaledCharge = (atom->charge)*Constant::SQRTCOULOMBCONSTANT; 92 tempatom.scaledMass = atom->mass; 93 94 // Now we need the size of the group for heavy atom ordering 95 // We need to parse the name for any H's then any numbers following 96 // First, if the atom is an H then this is 0 97 if (atom->atom_type == "H"){ 98 tempatom.hvyAtom = 0; 99 } 100 else{ 101 // Otherwise, we need to parse.. 102 // Initialize to 1 103 tempatom.hvyAtom = 1; 104 for (unsigned int pos = 0; pos < atom->atom_type.size(); ++pos){ 105 if (atom->atom_type[pos] == 'H'){ 106 string number = ""; 107 while (isdigit(atom->atom_type[++pos])) { 108 number += atom->atom_type[pos]; 109 } 110 if (number == "") // never entered loop, default is 1 111 number = "1"; 112 tempatom.hvyAtom += atoi(number.c_str()); 113 } 114 } 115 } 116 // C/C++ starts at 0, where PSF/PDB at 1 117 tempatom.atomNum = atom->number-1; 118 // Also the molecule - using residue sequence for now 119 topo->atoms.push_back(tempatom); 120 121 } // end loop over atoms 122 123 // calculate the # of degrees of freedom, if there are any bond constraints 124 // they will be subtracted later by ModifierShake 125 topo->degreesOfFreedom = 3 * topo->atoms.size() - 3; 126 127 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 128 // Get the bonds 129 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 131 // First create look-up-table (into PAR object bonds) 132 map<string,vector<iSGPAR::Bond>::const_iterator> bondLookUpTable; 133 134 // take the bonds from the PAR object and put then into the map/look-up-table 135 for (vector<iSGPAR::Bond>::const_iterator bond = par.bonds.begin(); 136 bond != par.bonds.end(); ++bond){ 137 bondLookUpTable[bond->atom1+","+bond->atom2] = bond; 138 //report << (*bond)<< ", " << bond->atom1 << ", " << bond->atom2 <<endr; 139 } 140 141 142 // Find the parameters from PAR 143 int ignoredBonds = 0; 144 145 // loop over the bond list in the PSF object 146 for (vector<PSF::Bond>::const_iterator bond = psf.bonds.begin(); 147 bond != psf.bonds.end(); ++bond){ 148 149 // store the ID numbers of the bonded atoms 150 int atom1 = bond->atom1-1; 151 int atom2 = bond->atom2-1; 152 153 // store the type names of the bonded atoms 154 string bond1(topo->atomTypes[topo->atoms[atom1].type].name); 155 string bond2(topo->atomTypes[topo->atoms[atom2].type].name); 156 157 // look into the bond table and see if this bond type was stored in the PAR file 158 map<string,vector<iSGPAR::Bond>::const_iterator>::const_iterator currentbond = bondLookUpTable.find(bond1+","+bond2); 159 160 // if this bond type has not been found, try reversing the order of the atom types 161 if(currentbond == bondLookUpTable.end()){ 162 currentbond = bondLookUpTable.find(bond2+","+bond1);} 163 164 // if we still have not found this bond type in the PAR object, report an error 165 if(currentbond == bondLookUpTable.end()){ 166 report << error << "Could not find bond \'"<<bond1<<"\'-\'"<<bond2<<"\'."<<std::endl; 167 for (map<string,vector<iSGPAR::Bond>::const_iterator>::const_iterator i = bondLookUpTable.begin(); 168 i != bondLookUpTable.end(); 169 ++i){ 170 report << plain << i->first<<std::endl; 171 } 172 report << endr; 173 } // end if statement 174 175 // if we have found this bond type then copy the bond parameters 176 // into the topology 177 Bond tempbond; 178 179 // store the time-zero identity of this bond 180 int bondIdentity = psf.atoms[atom1].identity; 181 tempbond.springConstant = currentbond->second->forceConstant[bondIdentity]; 182 tempbond.restLength = currentbond->second->distance[bondIdentity]; 183 tempbond.atom1 = atom1; 184 tempbond.atom2 = atom2; 185 topo->bonds.push_back(tempbond); 186 if(tempbond.springConstant == 0.0) 187 ++ignoredBonds; 188 } 189 190 if(ignoredBonds > 0) 191 report << hint << "Systems contains "<<ignoredBonds<<" bonds with zero force constants."<<endr; 192 193 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 // Get the angles 195 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 196 197 // First create look-up-table (into PAR object angles) 198 map<string,vector<iSGPAR::Angle>::const_iterator> angleLookUpTable; 199 200 // take the angles from the PAR object and put them into the map 201 for (vector<iSGPAR::Angle>::const_iterator angle = par.angles.begin(); 202 angle != par.angles.end(); ++angle){ 203 angleLookUpTable[angle->atom1+","+angle->atom2+","+angle->atom3] = angle; 204 //report << (*angle)<<endr; 205 } 206 207 // Find the parameters from PAR 208 int ignoredAngles = 0; 209 210 // loop over the angle list in the PSF object 211 for (vector<PSF::Angle>::const_iterator angle = psf.angles.begin(); 212 angle != psf.angles.end(); ++angle){ 213 214 // store the ID numbers of the atoms in this angle 215 int atom1 = angle->atom1-1; 216 int atom2 = angle->atom2-1; 217 int atom3 = angle->atom3-1; 218 219 // store the type names of the atoms in this angle 220 string angle1(topo->atomTypes[topo->atoms[atom1].type].name); 221 string angle2(topo->atomTypes[topo->atoms[atom2].type].name); 222 string angle3(topo->atomTypes[topo->atoms[atom3].type].name); 223 224 // look into the angle table and see if this angle type was stored in the PAR file 225 map<string,vector<iSGPAR::Angle>::const_iterator>::const_iterator currentangle = angleLookUpTable.find(angle1+","+angle2+","+angle3); 226 227 // if this angle type has not been found, try reversing the order of the atom types 228 if(currentangle == angleLookUpTable.end()) 229 currentangle = angleLookUpTable.find(angle3+","+angle2+","+angle1); 230 231 // if we still have not found this angle type in the PAR object, report an error 232 if(currentangle == angleLookUpTable.end()) 233 report << error << "Could not find angle \'"<<angle1<<"\'-\'"<<angle2<<"\'-\'"<<angle3<<"\'."<<endr; 234 235 // if we have found this angle type then copy the angle parameters 236 // into the topology 237 Angle tempangle; 238 239 // store the time-zero identity of this angle 240 int angleIdentity = psf.atoms[atom1].identity; 241 tempangle.atom1 = atom1; 242 tempangle.atom2 = atom2; 243 tempangle.atom3 = atom3; 244 tempangle.forceConstant = currentangle->second->forceConstant[angleIdentity]; 245 tempangle.restAngle = dtor(currentangle->second->angleval[angleIdentity]); 246 247 // check to see if a Urey-Bradley term has been specified 248 if (currentangle->second->ub_flag){ // do we want defaults for these 249 tempangle.ureyBradleyConstant = currentangle->second->k_ub[angleIdentity]; 250 tempangle.ureyBradleyRestLength = currentangle->second->r_ub[angleIdentity]; 251 } 252 // no Urey-Bradley term specified 253 else{ 254 tempangle.ureyBradleyConstant = 0.0; 255 tempangle.ureyBradleyRestLength = 0.0; 256 } 257 topo->angles.push_back(tempangle); 258 if(tempangle.forceConstant == 0.0) 259 ++ignoredAngles; 260 } 261 262 if(ignoredAngles > 0) 263 report << hint << "Systems contains "<<ignoredAngles<<" angles with zero force constants."<<endr; 264 265 266 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 267 // Get the dihedrals 268 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 269 // 270 // One change I made was to assume that a dihedral will only appear 271 // once in the .psf file regardless of it's multiplicity. The 272 // multiplicity should be handled in the .par file. 273 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 274 275 276 // First create look-up-table (into PAR object) 277 map<string,vector<iSGPAR::Dihedral>::const_iterator> dihedralLookUpTable; 278 279 // take the dihedrals from the PAR object and put them into the map 280 for (vector<iSGPAR::Dihedral>::const_iterator dihedral = par.dihedrals.begin(); 281 dihedral != par.dihedrals.end(); ++dihedral){ 282 dihedralLookUpTable[dihedral->atom1+","+dihedral->atom2+","+dihedral->atom3+","+dihedral->atom4] = dihedral; 283 //report << (*dihedral)<<endr; 284 } 285 286 // Find the parameters from PAR 287 // loop over the dihedral list in the PSF object 288 for(vector<PSF::Dihedral>::const_iterator dihedral = psf.dihedrals.begin(); 289 dihedral != psf.dihedrals.end(); ++dihedral) { 290 291 // store the ID numbers of the atoms in this dihedral 292 int atom1 = dihedral->atom1 - 1; 293 int atom2 = dihedral->atom2 - 1; 294 int atom3 = dihedral->atom3 - 1; 295 int atom4 = dihedral->atom4 - 1; 296 297 // store the type names of the atoms in this dihedral 298 string dihedral1 = topo->atomTypes[topo->atoms[atom1].type].name; 299 string dihedral2 = topo->atomTypes[topo->atoms[atom2].type].name; 300 string dihedral3 = topo->atomTypes[topo->atoms[atom3].type].name; 301 string dihedral4 = topo->atomTypes[topo->atoms[atom4].type].name; 302 303 // look into the dihedral table and see if this dihedral type was stored in the PAR file 304 map<string,vector<iSGPAR::Dihedral>::const_iterator>::const_iterator currentdihedral = 305 dihedralLookUpTable.find(dihedral1+","+dihedral2+","+dihedral3+","+dihedral4); 306 307 // if this dihedral type has not been found, try reversing the order of the atom types 308 if(currentdihedral == dihedralLookUpTable.end()) 309 currentdihedral = dihedralLookUpTable.find(dihedral4+","+dihedral3+","+dihedral2+","+dihedral1); 310 311 // Try wildcards if necessary 312 if(currentdihedral == dihedralLookUpTable.end()){ 313 currentdihedral = dihedralLookUpTable.find("X,"+dihedral2+","+dihedral3+",X"); 314 if(currentdihedral == dihedralLookUpTable.end()) 315 currentdihedral = dihedralLookUpTable.find("X,"+dihedral3+","+dihedral2+",X"); 316 } 317 318 // if we still have not found this dihedral type in the PAR object, report an error 319 if(currentdihedral == dihedralLookUpTable.end()) 320 report << error << "Could not find dihedral \'"<<dihedral1<<"\'-\'"<<dihedral2<<"\'-\'"<<dihedral3<<"\'-\'"<<dihedral4<<"\'."<<endr; 321 322 // if we have found this dihedral type then copy the 323 // dihedral parameters into the topology 324 Torsion torsion; 325 326 // store the time-zero identity of this torsion 327 int torsionIdentity = psf.atoms[atom1].identity; 328 torsion.atom1 = atom1; 329 torsion.atom2 = atom2; 330 torsion.atom3 = atom3; 331 torsion.atom4 = atom4; 332 torsion.periodicity = currentdihedral->second->periodicity[torsionIdentity]; 333 torsion.forceConstant = currentdihedral->second->forceConstant[torsionIdentity]; 334 torsion.phaseShift = dtor(currentdihedral->second->phaseShift[torsionIdentity]); 335 torsion.multiplicity = currentdihedral->second->multiplicity[torsionIdentity]; 336 torsion.DeltaK.resize(torsion.multiplicity); 337 torsion.DeltaPhase.resize(torsion.multiplicity); 338 339 //report << plain 340 // << dihedral1 <<"," 341 // << dihedral2 <<"," 342 // << dihedral3 <<"," 343 // << dihedral4 <<"," 344 // << torsion.atom1 <<"," 345 // << torsion.atom2 <<"," 346 // << torsion.atom3 <<"," 347 // << torsion.atom4 <<"," 348 // << torsion.periodicity.size() <<","; 349 //for (unsigned int tors=0; tors<torsion.periodicity.size(); tors++) { 350 // report << torsion.periodicity[tors] <<"," 351 // << torsion.forceConstant[tors] <<"," 352 // << torsion.phaseShift[tors] <<","; } 353 //report << torsion.multiplicity << endr; 354 355 if(topo->dihedrals.size() == 0 || 356 topo->dihedrals[topo->dihedrals.size()-1].atom1 != atom1 || 357 topo->dihedrals[topo->dihedrals.size()-1].atom2 != atom2 || 358 topo->dihedrals[topo->dihedrals.size()-1].atom3 != atom3 || 359 topo->dihedrals[topo->dihedrals.size()-1].atom4 != atom4){ 360 topo->dihedrals.push_back(torsion); 361 //report << plain //<< (wildcard ? "#":"") 362 // << dihedral1 <<"," 363 // << dihedral2 <<"," 364 // << dihedral3 <<"," 365 // << dihedral4 <<"," 366 // << torsion.atom1 <<"," 367 // << torsion.atom2 <<"," 368 // << torsion.atom3 <<"," 369 // << torsion.atom4 <<"," 370 // << torsion.periodicity[0] <<"," 371 // << torsion.periodicity.size() <<"," 372 // << torsion.forceConstant[0] <<"," 373 // << torsion.phaseShift[0] <<"," 374 // << torsion.multiplicity << endr; 375 } 376 } 377 378 379 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 380 // Get the impropers 381 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 382 // 383 // One change I made was to assume that a improper will only appear 384 // once in the .psf file regardless of it's multiplicity. The 385 // multiplicity should be handled in the .par file. 386 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 387 388 // No wildcard usage is allowed for bonds and angles. For dihedrals, 389 // two types are allowed; A - B - C - D (all four atoms specified) and 390 // X - A - B - X (only middle two atoms specified). Double dihedral 391 // specifications may be specified for the four atom type by listing a 392 // given set twice. When specifying this type in the topology file, specify 393 // a dihedral twice (with nothing intervening) and both forms will be used. 394 // 395 // There are five choices for wildcard usage for improper dihedrals; 396 // 1) A - B - C - D (all four atoms, double specification allowed) 397 // 2) A - X - X - B 398 // 3) X - A - B - C 399 // 4) X - A - B - X 400 // 5) X - X - A - B 401 // When classifying an improper dihedral, the first acceptable match (from 402 // the above order) is chosen. The match may be made in either direction 403 // ( A - B - C - D = D - C - B - A). 404 // 405 // The periodicity value for dihedrals and improper dihedral terms 406 // must be an integer. If it is positive, then a cosine functional form is used. 407 // Only positive values of 1,2,3,4,5 and 6 are allowed for the vector, parallel 408 // vector and cray routines. Slow and scalar routines can use any positive 409 // integer and thus dihedral constrains can be of any periodicity. 410 // Reference angle 0.0 and 180.0 degree correspond to minimum in staggered 411 // and eclipsed respectively. Any reference angle is allowed. The value 412 // 180 should be prefered over -180 since it is parsed faster and more 413 // accuratly. When the periodicity is given as zero, for OTHER THAN THE 414 // FIRST dihdral in a multiple dihedral set, then a the amplitude is a 415 // constant added to the energy. This is needed to effect the 416 // Ryckaert-Bellemans potential for hydrocarbons (see below). 417 418 419 // First create look-up-table into PAR object 420 map<string,vector<iSGPAR::Improper>::const_iterator> improperLookUpTable; 421 422 // take the impropers from the PAR object and put them into the map 423 for (vector<iSGPAR::Improper>::const_iterator improper = par.impropers.begin(); 424 improper != par.impropers.end(); ++improper){ 425 improperLookUpTable[improper->atom1+","+improper->atom2+","+improper->atom3+","+improper->atom4] = improper; 426 //report << (*improper)<<endr; 427 } 428 429 // Find the parameters from PAR 430 // loop over the improper list in the PSF object 431 for(vector<PSF::Improper>::const_iterator improper = psf.impropers.begin(); 432 improper != psf.impropers.end(); ++improper) { 433 434 // store the ID numbers of the atoms in this improper 435 int atom1 = improper->atom1 - 1; 436 int atom2 = improper->atom2 - 1; 437 int atom3 = improper->atom3 - 1; 438 int atom4 = improper->atom4 - 1; 439 440 // store the type names of the atoms in this improper 441 string improper1 = topo->atomTypes[topo->atoms[atom1].type].name; 442 string improper2 = topo->atomTypes[topo->atoms[atom2].type].name; 443 string improper3 = topo->atomTypes[topo->atoms[atom3].type].name; 444 string improper4 = topo->atomTypes[topo->atoms[atom4].type].name; 445 446 // look into the improper table and see if this improper type was stored in the PAR file 447 map<string,vector<iSGPAR::Improper>::const_iterator>::const_iterator currentimproper = 448 improperLookUpTable.find(improper1+","+improper2+","+improper3+","+improper4); 449 450 // if this dihedral type has not been found, try reversing the order of the atom types 451 if(currentimproper == improperLookUpTable.end()) 452 currentimproper = improperLookUpTable.find(improper4+","+improper3+","+improper2+","+improper1); 453 454 // Try wildcards if necessary 455 // 2) A - X - X - B 456 if(currentimproper == improperLookUpTable.end()){ 457 currentimproper = improperLookUpTable.find(improper1+",X,X,"+improper4); 458 if(currentimproper == improperLookUpTable.end()) 459 currentimproper = improperLookUpTable.find(improper4+",X,X,"+improper1); 460 461 } 462 // 3) X - A - B - C 463 if(currentimproper == improperLookUpTable.end()){ 464 currentimproper = improperLookUpTable.find("X,"+improper2+","+improper3+","+improper4); 465 if(currentimproper == improperLookUpTable.end()) 466 currentimproper = improperLookUpTable.find(improper4+","+improper3+","+improper2+",X"); 467 } 468 469 // 4) X - A - B - X 470 if(currentimproper == improperLookUpTable.end()){ 471 currentimproper = improperLookUpTable.find("X,"+improper2+","+improper3+",X"); 472 if(currentimproper == improperLookUpTable.end()) 473 currentimproper = improperLookUpTable.find("X,"+improper3+","+improper2+",X"); 474 } 475 476 // 5) X - X - A - B 477 if(currentimproper == improperLookUpTable.end()){ 478 currentimproper = improperLookUpTable.find("X,X,"+improper3+","+improper4); 479 if(currentimproper == improperLookUpTable.end()) 480 currentimproper = improperLookUpTable.find(improper4+","+improper3+",X,X"); 481 } 482 483 // if we still have not found this improper type in the PAR object, report an error 484 if(currentimproper == improperLookUpTable.end()) 485 report << error << "Could not find improper."<<endr; 486 487 // if we have found this improper type then copy the 488 // improper parameters into the topology 489 Torsion torsion; 490 491 // store the time-zero identity of this improper 492 int improperIdentity = psf.atoms[atom1].identity; 493 torsion.atom1 = atom1; 494 torsion.atom2 = atom2; 495 torsion.atom3 = atom3; 496 torsion.atom4 = atom4; 497 torsion.periodicity.push_back(currentimproper->second->periodicity[improperIdentity]); 498 torsion.forceConstant.push_back(currentimproper->second->forceConstant[improperIdentity]); 499 torsion.phaseShift.push_back(dtor(currentimproper->second->phaseShift[improperIdentity])); 500 torsion.multiplicity = 1; 501 topo->impropers.push_back(torsion); 502 // report << plain<< (wildcard ? "#":"") 503 // << improper1 <<"," 504 // << improper2 <<"," 505 // << improper3 <<"," 506 // << improper4 <<"," 507 // << torsion.atom1 <<"," 508 // << torsion.atom2 <<"," 509 // << torsion.atom3 <<"," 510 // << torsion.atom4 <<"," 511 // << torsion.periodicity[0] <<"," 512 // << torsion.periodicity.size() <<"," 513 // << torsion.forceConstant[0] <<"," 514 // << torsion.phaseShift[0] <<"," 515 // << torsion.multiplicity << endr; 516 } 517 518 519 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 520 // LennardJonesParameters 521 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 522 523 // get some array sizes 524 unsigned int sizeAtomTypes = topo->atomTypes.size(); 525 unsigned int sizeNonbondeds = par.nonbondeds.size(); 526 unsigned int sizeNbfixs = par.nbfixs.size(); 527 unsigned int sizeLJbank = par.nonbondeds[0].epsilon.size(); 528 529 // create the bank of Lennard-Jones parameter tables 530 topo->isgLJParms.createTables(sizeLJbank,sizeAtomTypes); 531 532 533 // loop over all atom types 534 for(unsigned int i=0;i<sizeAtomTypes;++i) { 535 536 // sentinel 537 int foundI = 0; 538 unsigned int AtomI = sizeNonbondeds; 539 540 // loop over all nonbonded types in the PAR object 541 for(unsigned int k=0;k<sizeNonbondeds;++k) { 542 543 // determine if this PAR nonbonded type is the same as the current atom type (i) 544 int ok = equalWildcard(par.nonbondeds[k].atom,topo->atomTypes[i].name); 545 546 // if we have found the current atom type in the PAR object the record its index (k) 547 if(ok > foundI){ 548 AtomI = k; 549 foundI = ok; 550 } 551 552 // if we have found the current atom type then exit the loop 553 if(foundI > 1) 554 break; 555 } // end loop over k 556 557 // report an error if we could not find atom type (i) in the PAR object 558 if(foundI <= 0) 559 report << error <<"Could not find matching parameter nonbonded of atom \'"<<topo->atomTypes[i].name<<"\'."<<endr; 560 561 // loop over all other (i != j) atom types 562 for(unsigned int j=i;j<sizeAtomTypes;++j) { 563 564 // sentinel 565 int foundJ = 0; 566 unsigned int AtomJ = sizeNonbondeds; 567 568 // loop over all nonbonded types in the PAR object 569 for(unsigned int k=0;k<sizeNonbondeds;++k) { 570 571 // determine if this PAR nonbonded type is the same as the current atom type (j) 572 int ok = equalWildcard(par.nonbondeds[k].atom,topo->atomTypes[j].name); 573 574 // if we have found the current atom type in the PAR object the record its index (k) 575 if(ok > foundJ){ 576 AtomJ = k; 577 foundJ = ok; 578 } 579 580 // if we have found the current atom type then exit the loop 581 if(foundJ > 1) 582 break; 583 } 584 585 // report an error if we could not find atom type (j) in the PAR object 586 if(foundJ<=0) 587 report << error <<"Could not find matching parameter nonbonded of atom \'"<<topo->atomTypes[j].name<<"\'."<<endr; 588 589 // initialize a set of LJ parameters 590 LennardJonesParameters paramsij; 591 592 // loop over all possible identities of atom i 593 for (unsigned int identity_I=0; identity_I < sizeLJbank; identity_I++) { 594 595 // loop over all possible identities for atom j 596 for (unsigned int identity_J = 0; identity_J < sizeLJbank; identity_J++) { 597 598 // calculate the (Charmm28) minimum energy distances 599 Real sigma_i = par.nonbondeds[AtomI].sigma[identity_I]; 600 Real sigma_j = par.nonbondeds[AtomJ].sigma[identity_J]; 601 Real sigma14_i = par.nonbondeds[AtomI].sigma14[identity_I]; 602 Real sigma14_j = par.nonbondeds[AtomJ].sigma14[identity_J]; 603 604 // calculate the minimum LJ pair energy 605 Real epsilon_i = par.nonbondeds[AtomI].epsilon[identity_I]; 606 Real epsilon_j = par.nonbondeds[AtomJ].epsilon[identity_J]; 607 Real epsilon14_i = par.nonbondeds[AtomI].epsilon14[identity_I]; 608 Real epsilon14_j = par.nonbondeds[AtomJ].epsilon14[identity_J]; 609 610 // calculate the ij pair minimum distances and energies 611 Real r_ij = sigma_i + sigma_j; 612 Real e_ij = sqrt(epsilon_i * epsilon_j); 613 Real r14_ij = sigma14_i + sigma14_j; 614 Real e14_ij = sqrt(epsilon14_i * epsilon14_j); 615 616 // stores these numbers into the paramsij object 617 paramsij.A = power<12>(r_ij) * e_ij; 618 paramsij.B = 2 * power<6>(r_ij) * e_ij; 619 paramsij.A14 = power<12>(r14_ij) * e14_ij; 620 paramsij.B14 = 2 * power<6>(r14_ij) * e14_ij; 621 622 topo->isgLJParms.set(identity_I,identity_J, i, j, paramsij); 623 624 } // end loop over identity_J 625 } // end loop over identity_I 626 } // end loop over atom types (j) 627 } // end loop over atom types (i) 628 629 630 // NbFix 631 // loop over all Nbfix types 632 for(unsigned int k=0;k<sizeNbfixs;++k) { 633 634 //report << par.nbfixs[k].atom1 << ","<<par.nbfixs[k].atom2<<endr; 635 636 int ti = 0; 637 int tj = 0; 638 unsigned int bi = sizeNbfixs; 639 unsigned int bj = sizeNbfixs; 640 641 for(unsigned int i=0;i<sizeAtomTypes;++i){ 642 int ok = equalWildcard(par.nbfixs[k].atom1,topo->atomTypes[i].name); 643 if(ok > ti){ 644 bi = i; 645 ti = ok; 646 } 647 if(ti > 1) 648 break; 649 } 650 651 if(ti <=0) // ??? 652 continue; 653 654 for(unsigned int j=0;j<sizeAtomTypes;++j){ 655 int ok = equalWildcard(par.nbfixs[k].atom2,topo->atomTypes[j].name); 656 if(ok > tj){ 657 bj = j; 658 tj = ok; 659 } 660 if(tj > 1) 661 break; 662 } 663 664 if(tj<=0) 665 report << error <<"Could not find matching parameter nbfix of atoms \'"<<par.nbfixs[k].atom1<<"\' - '"<<par.nbfixs[k].atom2<<"\'."<<endr; 666 667 LennardJonesParameters paramsij; 668 669 paramsij.A = par.nbfixs[k].a; 670 paramsij.B = par.nbfixs[k].b; 671 paramsij.A14 = par.nbfixs[k].a14; 672 paramsij.B14 = par.nbfixs[k].b14; 673 topo->lennardJonesParameters.set(bi, bj, paramsij); 674 675 } // end loop over NbFix types 676 677 // store the molecule information 678 buildMoleculeTable(topo); 679 680 // build the nonbonded exclusion table 681 buildExclusionTable(topo,topo->exclude); 682 683 // build the list of bonds, angles, etc. belonging to each molecule 684 buildMoleculeBondingLists(topo); 685 686 // determine the time-zero identity of each molecule 687 for(unsigned int i=0; i<topo->molecules.size(); i++) { 688 689 // the ID# of the first atom in this molecule 690 int firstAtom = topo->molecules[i][0]; 691 692 // get the identity number from the psf file 693 topo->molecules[i].type = psf.atoms[firstAtom].identity; 694 topo->molecules[i].newtype = psf.atoms[firstAtom].identity; 695 } 696 697 } // end build topology function 698 699 700 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 701 // 702 // buildMoleculeTable 703 // 704 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 705 buildMoleculeTable(GenericTopology * topo)706 void buildMoleculeTable(GenericTopology *topo){ 707 708 // *** First we clear all molecules *** 709 topo->molecules.clear(); 710 711 const unsigned int numAtoms = topo->atoms.size(); 712 713 // *** Collecting all possible connections, building the graph *** 714 vector<vector<int> > graph(numAtoms,vector<int>()); 715 set<pair<int,int> > pairs; 716 // *** Bonds *** 717 for(unsigned int i=0;i<topo->bonds.size();++i){ 718 int a1 = topo->bonds[i].atom1; 719 int a2 = topo->bonds[i].atom2; 720 graph[a1].push_back(a2); 721 graph[a2].push_back(a1); 722 pairs.insert(pair<int,int>(std::min(a1,a2),std::max(a1,a2))); 723 } 724 unsigned int count = pairs.size(); 725 726 // *** Angles *** 727 for(unsigned int i=0;i<topo->angles.size();++i){ 728 int a1 = topo->angles[i].atom1; 729 int a2 = topo->angles[i].atom2; 730 int a3 = topo->angles[i].atom3; 731 graph[a1].push_back(a2); 732 graph[a1].push_back(a3); 733 graph[a2].push_back(a1); 734 graph[a2].push_back(a3); 735 graph[a3].push_back(a1); 736 graph[a3].push_back(a2); 737 pairs.insert(pair<int,int>(std::min(a1,a2),std::max(a1,a2))); 738 pairs.insert(pair<int,int>(std::min(a3,a2),std::max(a3,a2))); 739 } 740 741 if(count < pairs.size()) 742 report << hint << "Angles added "<<pairs.size()-count<<" new bond(s)." <<endr; 743 count = pairs.size(); 744 745 // *** Dihedrals *** 746 for(unsigned int i=0;i<topo->dihedrals.size();++i){ 747 int a1 = topo->dihedrals[i].atom1; 748 int a2 = topo->dihedrals[i].atom2; 749 int a3 = topo->dihedrals[i].atom3; 750 int a4 = topo->dihedrals[i].atom4; 751 graph[a1].push_back(a2); 752 graph[a1].push_back(a3); 753 graph[a1].push_back(a4); 754 graph[a2].push_back(a1); 755 graph[a2].push_back(a3); 756 graph[a2].push_back(a4); 757 graph[a3].push_back(a1); 758 graph[a3].push_back(a2); 759 graph[a3].push_back(a4); 760 graph[a4].push_back(a1); 761 graph[a4].push_back(a2); 762 graph[a4].push_back(a3); 763 pairs.insert(pair<int,int>(std::min(a1,a2),std::max(a1,a2))); 764 pairs.insert(pair<int,int>(std::min(a3,a2),std::max(a3,a2))); 765 pairs.insert(pair<int,int>(std::min(a3,a4),std::max(a3,a4))); 766 } 767 if(count < pairs.size()) 768 report << hint << "Dihedrals added "<<pairs.size()-count<<" new bond(s)." <<endr; 769 count = pairs.size(); 770 771 // *** Impropers *** 772 set<pair<int,int> > pairsAddImpropers; 773 // Impropers are defined over the bonds 1-2,1-3,1-4 or 4-1,4-3,4-2 774 // but MTorsionSystemForce computes distances betweeen 1-2,2-3,3-4 775 // we have to take care about these differences ... 776 for(unsigned int i=0;i<topo->impropers.size();++i){ 777 int a1 = topo->impropers[i].atom1; 778 int a2 = topo->impropers[i].atom2; 779 int a3 = topo->impropers[i].atom3; 780 int a4 = topo->impropers[i].atom4; 781 graph[a1].push_back(a2); 782 graph[a1].push_back(a3); 783 graph[a1].push_back(a4); 784 graph[a2].push_back(a1); 785 graph[a2].push_back(a3); 786 graph[a2].push_back(a4); 787 graph[a3].push_back(a1); 788 graph[a3].push_back(a2); 789 graph[a3].push_back(a4); 790 graph[a4].push_back(a1); 791 graph[a4].push_back(a2); 792 graph[a4].push_back(a3); 793 pair<int,int> p0(std::min(a1,a2),std::max(a1,a2)); 794 pair<int,int> p1(std::min(a1,a3),std::max(a1,a3)); 795 pair<int,int> p2(std::min(a1,a4),std::max(a1,a4)); 796 pair<int,int> p3(std::min(a2,a3),std::max(a2,a3)); 797 pair<int,int> p4(std::min(a2,a4),std::max(a2,a4)); 798 pair<int,int> p5(std::min(a3,a4),std::max(a3,a4)); 799 int j0 = 0; 800 int j1 = 0; 801 int j2 = 0; 802 int j3 = 0; 803 int j4 = 0; 804 int j5 = 0; 805 if(pairs.find(p0) != pairs.end()) j0++; 806 if(pairs.find(p1) != pairs.end()) j1++; 807 if(pairs.find(p2) != pairs.end()) j2++; 808 if(pairs.find(p3) != pairs.end()) j3++; 809 if(pairs.find(p4) != pairs.end()) j4++; 810 if(pairs.find(p5) != pairs.end()) j5++; 811 if(j0+j1+j2+j3+j4+j5 < 3){ 812 pairs.insert(p0); 813 pairs.insert(p1); 814 pairs.insert(p2); 815 } 816 pairsAddImpropers.insert(p0); 817 pairsAddImpropers.insert(p3); 818 pairsAddImpropers.insert(p5); 819 } 820 if(count < pairs.size()) 821 report << hint << "Impropers added "<<pairs.size()-count<<" new bond(s)." <<endr; 822 823 // Now add the improper pairs 824 for(set<pair<int,int> >::const_iterator i= pairsAddImpropers.begin();i != pairsAddImpropers.end();++i) 825 pairs.insert(*i); 826 827 828 count = pairs.size(); 829 //report << hint << count << endr; 830 // To keep track which atoms already have been added 831 // to molecules. 832 vector<bool> unused(numAtoms,true); 833 834 835 // Recursively finding the atoms beloning to a molecule 836 for(unsigned int i=0;i<numAtoms;++i){ 837 vector<int> v; 838 vector<PairInt> p; 839 findNextNeighbor(i,v,p,unused,graph,pairs); 840 if(v.size()>0){ 841 // sort(v.begin(),v.end()); 842 // add this atom list to the molecules array 843 Molecule mol; 844 mol.atoms = v; 845 mol.pairs = p; 846 topo->molecules.push_back(mol); 847 } 848 } 849 850 // Uncomment to sort descending after size() 851 // sort(topo->molecules.begin(),topo->molecules.end(),cmpSize); 852 853 // Look up table for atoms 854 const string h("H"); 855 const string o("O"); 856 for(unsigned int i=0;i<topo->molecules.size();++i){ 857 Real mass = 0.0; 858 const vector<int>& mol = topo->molecules[i].atoms; 859 for(unsigned int j=0;j<mol.size();++j){ 860 int k = mol[j]; 861 topo->atoms[k].molecule = i; 862 mass += topo->atoms[k].scaledMass; 863 } 864 topo->molecules[i].mass = mass; 865 topo->molecules[i].water = (mol.size() == 3 && 866 ((topo->atomTypes[topo->atoms[mol[0]].type].symbolName == h && 867 topo->atomTypes[topo->atoms[mol[1]].type].symbolName == h && 868 topo->atomTypes[topo->atoms[mol[2]].type].symbolName == o) || 869 (topo->atomTypes[topo->atoms[mol[0]].type].symbolName == h && 870 topo->atomTypes[topo->atoms[mol[1]].type].symbolName == o && 871 topo->atomTypes[topo->atoms[mol[2]].type].symbolName == h) || 872 (topo->atomTypes[topo->atoms[mol[0]].type].symbolName == o && 873 topo->atomTypes[topo->atoms[mol[1]].type].symbolName == h && 874 topo->atomTypes[topo->atoms[mol[2]].type].symbolName == h))); 875 876 } 877 878 #if defined(DEBUG_PRINT_MOLECULETABLE) 879 report<< plain << endl << "[buildMoleculeTable]: molecule table printout:" << endl; 880 for(int i=0;i<topo->molecules.size();++i){ 881 for(int j=0;j<topo->molecules[i].size();++j){ 882 report << topo->molecules[i][j]<<" "; 883 } 884 report << endl; 885 } 886 report << endr; 887 #endif 888 } 889 890 891 //____________________________________________________________findNextNeighbor findNextNeighbor(int a,vector<int> & v,vector<PairInt> & p,vector<bool> & unused,const vector<vector<int>> & graph,set<PairInt> & pairs)892 void findNextNeighbor(int a, vector<int>& v, vector<PairInt>& p, vector<bool>& unused, 893 const vector<vector<int> >& graph, set<PairInt>& pairs){ 894 if(unused[a]){ 895 v.push_back(a); 896 unused[a] = false; 897 for(unsigned int i=0;i<graph[a].size();++i){ 898 set<PairInt>::iterator itr = pairs.find(PairInt(std::min(a,graph[a][i]),std::max(a,graph[a][i]))); 899 if(itr != pairs.end()){ 900 p.push_back(PairInt(a,graph[a][i])); 901 pairs.erase(itr); 902 } 903 findNextNeighbor(graph[a][i],v,p,unused,graph,pairs); 904 } 905 } 906 } 907 908 909 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 910 // 911 // buildExclusionTable 912 // 913 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 914 buildExclusionTable(GenericTopology * topo,const ExclusionType & exclusionType)915 void buildExclusionTable(GenericTopology* topo, const ExclusionType& exclusionType) { 916 917 if(!exclusionType.valid()) 918 report << error <<"[buildExclusionTable()] Exclusion type not defined/valid."<<endr; 919 920 topo->exclude = exclusionType; 921 922 const int numBonds = topo->bonds.size(); 923 const int numAtoms = topo->atoms.size(); 924 int a1,a2,a3; 925 926 // *** Reformatting bond list *** 927 vector< set<int> > bondsParsed(numAtoms); 928 for (int i = 0; i < numBonds; ++i) { 929 a1=topo->bonds[i].atom1; 930 a2=topo->bonds[i].atom2; 931 bondsParsed[a1].insert(a2); 932 bondsParsed[a2].insert(a1); 933 } 934 935 // *** Building exclusion list *** 936 topo->exclusions.resize(numAtoms); 937 topo->exclusions.clear(); 938 list<ExclusionPair> one3s; 939 int exclusionsInserted = 0; 940 if(exclusionType!=ExclusionType::NONE) { 941 for(a2 = 0; a2 < numAtoms; ++a2) { 942 for(set<int>::iterator i=bondsParsed[a2].begin();i!=bondsParsed[a2].end();++i) { 943 a1=*i; 944 if(a1<a2) { 945 topo->exclusions.add(a1,a2,EXCLUSION_FULL); 946 ++exclusionsInserted; 947 } 948 if(exclusionType==ExclusionType::ONE3||exclusionType==ExclusionType::ONE4||exclusionType==ExclusionType::ONE4MODIFIED) { 949 for(set<int>::iterator j=i; j!=bondsParsed[a2].end();++j) { 950 a3=*j; 951 topo->exclusions.add(a1,a3,EXCLUSION_FULL); 952 ++exclusionsInserted; 953 one3s.push_front(ExclusionPair(a1,a3)); 954 one3s.push_front(ExclusionPair(a3,a1)); 955 } 956 } 957 } 958 } 959 if(exclusionType==ExclusionType::ONE4||exclusionType==ExclusionType::ONE4MODIFIED) { 960 ExclusionClass currentType = EXCLUSION_NONE; 961 if(exclusionType==ExclusionType::ONE4) 962 currentType=EXCLUSION_FULL; 963 if(exclusionType==ExclusionType::ONE4MODIFIED) 964 currentType=EXCLUSION_MODIFIED; 965 int curSrc=0; 966 for(list<ExclusionPair>::iterator i=one3s.begin(); i!=one3s.end(); ++i,++curSrc) { 967 a1=i->a1; 968 a2=i->a2; 969 for(set<int>::iterator j=bondsParsed[a2].lower_bound(a1);j!=bondsParsed[a2].end();++j) { 970 a3=*j; 971 if(!topo->exclusions.check(a1,a3)) { 972 topo->exclusions.add(a1,a3,currentType); 973 ++exclusionsInserted; 974 } 975 } 976 } 977 } 978 } 979 } 980 981 982 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 983 // 984 // buildMoleculeBondingLists 985 // 986 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 987 buildMoleculeBondingLists(GenericTopology * topo)988 void buildMoleculeBondingLists(GenericTopology* topo) { 989 990 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 991 // bond lists 992 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 993 // loop over all bonds in the topology 994 for (unsigned int i=0; i<topo->bonds.size(); i++) { 995 996 // get the ID#s of the two atoms in this bond 997 int atom1 = topo->bonds[i].atom1; 998 int atom2 = topo->bonds[i].atom2; 999 1000 // loop sentinels 1001 bool found1 = false; 1002 bool found2 = false; 1003 unsigned int m; 1004 1005 // loop over all molecules 1006 for (m=0; m<topo->molecules.size(); m++) { 1007 1008 // loop over all atoms in the atom list for this molecule 1009 for (unsigned int a=0; a<topo->molecules[m].atoms.size(); a++) { 1010 1011 if (atom1 == topo->molecules[m].atoms[a]) {found1 = true;} 1012 else if (atom2 == topo->molecules[m].atoms[a]) {found2 = true;} 1013 1014 if (found1 && found2) {break;} 1015 } // end atom list loop 1016 1017 if (found1 && found2) {break;} 1018 } // end loop over molecules 1019 1020 // store this bond index number in the molecule's bond list 1021 topo->molecules[m].bondList.push_back(i); 1022 } // end loop over bonds 1023 1024 1025 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1026 // angle lists 1027 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1028 // loop over all angles in the topology 1029 for (unsigned int i=0; i<topo->angles.size(); i++) { 1030 1031 // get the ID#s of the three atoms in this angle 1032 int atom1 = topo->angles[i].atom1; 1033 int atom2 = topo->angles[i].atom2; 1034 int atom3 = topo->angles[i].atom3; 1035 1036 // loop sentinels 1037 bool found1 = false; 1038 bool found2 = false; 1039 bool found3 = false; 1040 unsigned int m; 1041 1042 // loop over all molecules 1043 for (m=0; m<topo->molecules.size(); m++) { 1044 1045 // loop over all atoms in the atom list for this molecule 1046 for (unsigned int a=0; a<topo->molecules[m].atoms.size(); a++) { 1047 1048 if (atom1 == topo->molecules[m].atoms[a]) {found1 = true;} 1049 else if (atom2 == topo->molecules[m].atoms[a]) {found2 = true;} 1050 else if (atom3 == topo->molecules[m].atoms[a]) {found3 = true;} 1051 1052 if (found1 && found2 && found3) {break;} 1053 } // end atom list loop 1054 1055 if (found1 && found2 && found3) {break;} 1056 } // end loop over molecules 1057 1058 // store this angle index number in the molecule's angle list 1059 topo->molecules[m].angleList.push_back(i); 1060 } // end loop over angles 1061 1062 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1063 // dihedral lists 1064 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1065 // loop over all diherals in the topology 1066 for (unsigned int i=0; i<topo->dihedrals.size(); i++) { 1067 1068 // get the ID#s of the four atoms in this dihedral 1069 int atom1 = topo->dihedrals[i].atom1; 1070 int atom2 = topo->dihedrals[i].atom2; 1071 int atom3 = topo->dihedrals[i].atom3; 1072 int atom4 = topo->dihedrals[i].atom4; 1073 1074 // loop sentinels 1075 bool found1 = false; 1076 bool found2 = false; 1077 bool found3 = false; 1078 bool found4 = false; 1079 unsigned int m; 1080 1081 // loop over all molecules 1082 for (m=0; m<topo->molecules.size(); m++) { 1083 1084 // loop over all atoms in the atom list for this molecule 1085 for (unsigned int a=0; a<topo->molecules[m].atoms.size(); a++) { 1086 1087 if (atom1 == topo->molecules[m].atoms[a]) {found1 = true;} 1088 else if (atom2 == topo->molecules[m].atoms[a]) {found2 = true;} 1089 else if (atom3 == topo->molecules[m].atoms[a]) {found3 = true;} 1090 else if (atom4 == topo->molecules[m].atoms[a]) {found4 = true;} 1091 1092 if (found1 && found2 && found3 && found4) {break;} 1093 } // end atom list loop 1094 1095 if (found1 && found2 && found3 && found4) {break;} 1096 } // end loop over molecules 1097 1098 // store this dihedral index number in the molecule's dihderal list 1099 topo->molecules[m].dihedralList.push_back(i); 1100 } // end loop over dihedrals 1101 1102 1103 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1104 // improper lists 1105 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1106 // loop over all impropers in the topology 1107 for (unsigned int i=0; i<topo->impropers.size(); i++) { 1108 1109 // get the ID#s of the four atoms in this improper 1110 int atom1 = topo->impropers[i].atom1; 1111 int atom2 = topo->impropers[i].atom2; 1112 int atom3 = topo->impropers[i].atom3; 1113 int atom4 = topo->impropers[i].atom4; 1114 1115 // loop sentinels 1116 bool found1 = false; 1117 bool found2 = false; 1118 bool found3 = false; 1119 bool found4 = false; 1120 unsigned int m; 1121 1122 // loop over all molecules 1123 for (m=0; m<topo->molecules.size(); m++) { 1124 1125 // loop over all atoms in the atom list for this molecule 1126 for (unsigned int a=0; a<topo->molecules[m].atoms.size(); a++) { 1127 1128 if (atom1 == topo->molecules[m].atoms[a]) {found1 = true;} 1129 else if (atom2 == topo->molecules[m].atoms[a]) {found2 = true;} 1130 else if (atom3 == topo->molecules[m].atoms[a]) {found3 = true;} 1131 else if (atom4 == topo->molecules[m].atoms[a]) {found4 = true;} 1132 1133 if (found1 && found2 && found3 && found4) {break;} 1134 } // end atom list loop 1135 1136 if (found1 && found2 && found4) {break;} 1137 } // end loop over molecules 1138 1139 // store this bond index number in the molecule's improper list 1140 topo->molecules[m].improperList.push_back(i); 1141 } // end loop over impropers 1142 } // end function buildMoleculeBonding Lists 1143 1144 } // end class 1145 1146