NAMD
Molecule.C
Go to the documentation of this file.
1 
7 // Molecule.C is compiled twice!
8 // MOLECULE2_C undefined only compiles first half of file
9 // MOLECULE2_C defined only compiles second half of file
10 // This is shameful but it works. Molecule needs refactoring badly.
11 
12 /*
13  The class Molecule is used to hold all of the structural information
14  for a simulation. This information is read in from a .psf file and
15  cross checked with the Parameters object passed in. All of the structural
16  information is then stored in arrays for use.
17 */
18 
19 #include "largefiles.h" // must be first!
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 
26 #include "InfoStream.h"
27 #include "Molecule.h"
28 #include "strlib.h"
29 #include "MStream.h"
30 #include "Communicate.h"
31 #include "Node.h"
32 #include "ObjectArena.h"
33 #include "Parameters.h"
34 #include "PDB.h"
35 #include "SimParameters.h"
36 #include "Hydrogen.h"
37 #include "UniqueSetIter.h"
38 #include "charm++.h"
39 /* BEGIN gf */
40 #include "ComputeGridForce.h"
41 #include "GridForceGrid.h"
42 
43 #include "MGridforceParams.h"
44 /* END gf */
45 
46 #define MIN_DEBUG_LEVEL 3
47 //#define DEBUGM
48 #include "Debug.h"
49 
50 #include "CompressPsf.h"
51 #include "ParallelIOMgr.h"
52 #include <deque>
53 #include <algorithm>
54 
55 #ifndef M_PI
56 #define M_PI 3.14159265358979323846
57 #endif
58 
59 #ifndef GROMACS_PAIR
60 #define GROMACS_PAIR 1
61 #endif
62 
63 #ifndef GROMACS_EXCLUSIONS
64 #define GROMACS_EXCLUSIONS 1
65 #endif
66 
67 using namespace std;
68 
69 #ifndef MOLECULE2_C // first object file
70 
71 #ifdef MEM_OPT_VERSION
72 template int lookupCstPool<AtomSignature>(const vector<AtomSignature>&, const AtomSignature&);
73 template int lookupCstPool<ExclusionSignature>(const vector<ExclusionSignature>&, const ExclusionSignature&);
74 #endif
75 
77  const char *segid, int resid, int *begin, int *end) const {
78  const ResidueLookupElem *elem = this;
79  int rval = -1; // error
80  while ( elem && strcasecmp(elem->mySegid,segid) ) elem = elem->next;
81  if ( elem && (resid >= elem->firstResid) && (resid <= elem->lastResid) ) {
82  *begin = elem->atomIndex[resid - elem->firstResid];
83  *end = elem->atomIndex[resid - elem->firstResid + 1];
84  rval = 0; // no error
85  }
86  return rval;
87 }
88 
90  const char *segid, int resid, int aid) {
91  ResidueLookupElem *rval = this;
92  if ( firstResid == -1 ) { // nothing added yet
93  strcpy(mySegid,segid);
94  firstResid = resid;
95  lastResid = resid;
96  atomIndex.add(aid);
97  atomIndex.add(aid+1);
98  } else if ( ! strcasecmp(mySegid,segid) ) { // same segid
99  if ( resid == lastResid ) { // same resid
100  atomIndex[lastResid - firstResid + 1] = aid + 1;
101  } else if ( resid < lastResid ) { // error
102  // We can work around this by creating a new segment.
103  iout << iWARN << "Residue " << resid <<
104  " out of order in segment " << segid <<
105  ", lookup for additional residues in this segment disabled.\n" << endi;
106  rval = next = new ResidueLookupElem;
107  next->append(segid,resid,aid);
108  } else { // new resid
109  for ( ; lastResid < resid; ++lastResid ) atomIndex.add(aid);
110  atomIndex[lastResid - firstResid + 1] = aid + 1;
111  }
112  } else { // new segid
113  rval = next = new ResidueLookupElem;
114  next->append(segid,resid,aid);
115  }
116  return rval;
117 }
118 
119 
120 // Lookup atom id from segment, residue, and name
122  const char *segid, int resid, const char *aname) const {
123 
124  if (atomNames == NULL || resLookup == NULL)
125  {
126  NAMD_die("Tried to find atom from name on node other than node 0");
127  }
128 
129  int i = 0;
130  int end = 0;
131  if ( resLookup->lookup(segid,resid,&i,&end) ) return -1;
132  for ( ; i < end; ++i ) {
133  #ifdef MEM_OPT_VERSION
134  Index idx = atomNames[i].atomnameIdx;
135  if(!strcasecmp(aname, atomNamePool[idx])) return i;
136  #else
137  if ( ! strcasecmp(aname,atomNames[i].atomname) ) return i;
138  #endif
139  }
140  return -1;
141 }
142 
143 // Lookup number of atoms in residue from segment and residue
145  const char *segid, int resid) const {
146 
147  if (atomNames == NULL || resLookup == NULL)
148  {
149  NAMD_die("Tried to find atom from name on node other than node 0");
150  }
151  int i = 0;
152  int end = 0;
153  if ( resLookup->lookup(segid,resid,&i,&end) ) return 0;
154  return ( end - i );
155 }
156 
157 // Lookup atom id from segment, residue, and index in residue
159  const char *segid, int resid, int index) const {
160 
161  if (atomNames == NULL || resLookup == NULL)
162  {
163  NAMD_die("Tried to find atom from name on node other than node 0");
164  }
165  int i = 0;
166  int end = 0;
167  if ( resLookup->lookup(segid,resid,&i,&end) ) return -1;
168  if ( index >= 0 && index < ( end - i ) ) return ( index + i );
169  return -1;
170 }
171 
172 /************************************************************************/
173 /* */
174 /* FUNCTION initialize */
175 /* */
176 /* This is the initializer for the Molecule class. It simply sets */
177 /* the counts for all the various parameters to 0 and sets the pointers*/
178 /* to the arrays that will store these parameters to NULL, since they */
179 /* have not been allocated yet. */
180 /* */
181 /************************************************************************/
182 
184 {
185  if ( sizeof(int32) != 4 ) { NAMD_bug("sizeof(int32) != 4"); }
186  this->simParams = simParams;
187  this->params = param;
188 
189  /* Initialize array pointers to NULL */
190  atoms=NULL;
191  atomNames=NULL;
192  resLookup=NULL;
193 
194  // DRUDE
195  is_lonepairs_psf = 1; // anticipate having lone pair hosts
196  is_drude_psf = 0; // assume not Drude model
197  drudeConsts=NULL;
198  lphosts=NULL; // might have lone pair hosts without Drude!
199  anisos=NULL;
200  tholes=NULL;
201  lphostIndexes=NULL;
202  // DRUDE
203 
204  //LCPO
205  lcpoParamType = NULL;
206 
207  //for compressing molecule info
208  atomSegResids=NULL;
209 
210  if ( simParams->globalForcesOn ) {
211  resLookup = new ResidueLookupElem;
212  }
213 
214  #ifdef MEM_OPT_VERSION
215  eachAtomSig = NULL;
216  atomSigPoolSize = 0;
217  atomSigPool = NULL;
218  massPoolSize = 0;
219  atomMassPool = NULL;
220  eachAtomMass = NULL;
221  chargePoolSize = 0;
222  atomChargePool = NULL;
223  eachAtomCharge = NULL;
224  #else
225  bonds=NULL;
226  angles=NULL;
227  dihedrals=NULL;
228  impropers=NULL;
229  crossterms=NULL;
230  #endif
231 
232  donors=NULL;
233  acceptors=NULL;
234 
235 
236  #ifndef MEM_OPT_VERSION
237  tmpArena=NULL;
238  exclusions=NULL;
239  bondsWithAtom=NULL;
240  bondsByAtom=NULL;
241  anglesByAtom=NULL;
242  dihedralsByAtom=NULL;
243  impropersByAtom=NULL;
244  crosstermsByAtom=NULL;
245  // JLai
246  gromacsPairByAtom=NULL;
247  // End of JLai
248  // DRUDE
249  tholesByAtom=NULL;
250  anisosByAtom=NULL;
251  // DRUDE
252  #endif
253 
254  #ifdef MEM_OPT_VERSION
255  exclSigPool = NULL;
256  exclChkSigPool = NULL;
257  exclSigPoolSize = 0;
258  eachAtomExclSig = NULL;
259 
260  fixedAtomsSet = NULL;
261  constrainedAtomsSet = NULL;
262  #else
263  exclusionsByAtom=NULL;
264  fullExclusionsByAtom=NULL;
265  modExclusionsByAtom=NULL;
266  all_exclusions=NULL;
267  #endif
268 
269  langevinParams=NULL;
270  fixedAtomFlags=NULL;
271 
272  #ifdef MEM_OPT_VERSION
273  clusterSigs=NULL;
274  #else
275  cluster=NULL;
276  #endif
277  clusterSize=NULL;
278 
279  exPressureAtomFlags=NULL;
280  rigidBondLengths=NULL;
281  consIndexes=NULL;
282  consParams=NULL;
283  /* BEGIN gf */
284  gridfrcIndexes=NULL;
285  gridfrcParams=NULL;
286  gridfrcGrid=NULL;
287  numGridforces=NULL;
288  /* END gf */
289  stirIndexes=NULL;
290  stirParams=NULL;
291  movDragIndexes=NULL;
292  movDragParams=NULL;
293  rotDragIndexes=NULL;
294  rotDragParams=NULL;
295  consTorqueIndexes=NULL;
296  consTorqueParams=NULL;
297  consForceIndexes=NULL;
298  consForce=NULL;
299 //fepb
300  fepAtomFlags=NULL;
301  alch_unpert_bonds = NULL;
302  alch_unpert_angles = NULL;
303  alch_unpert_dihedrals = NULL;
304 //fepe
305 //soluteScaling
306  ssAtomFlags=NULL;
307  ss_vdw_type=NULL;
308  ss_index=NULL;
309 //soluteScaling
310  nameArena = new ObjectArena<char>;
311  // nameArena->setAlignment(8);
312  // arena->setAlignment(32);
313  #ifndef MEM_OPT_VERSION
314  arena = new ObjectArena<int32>;
315  exclArena = new ObjectArena<char>;
316  #endif
317  // exclArena->setAlignment(32);
318 
319  /* Initialize counts to 0 */
320  numAtoms=0;
321  numRealBonds=0;
322  numBonds=0;
323  numAngles=0;
324  numDihedrals=0;
325  numImpropers=0;
326  numCrossterms=0;
327  // JLai
328  numLJPair=0;
329  // End of JLai
330  numDonors=0;
331  numAcceptors=0;
332  numExclusions=0;
333 
334  // DRUDE
335  numLonepairs=0;
336  numDrudeAtoms=0;
337  numTholes=0;
338  numAnisos=0;
339  numLphosts=0;
340  numZeroMassAtoms=0;
341  // DRUDE
342 
343  numConstraints=0;
344  numStirredAtoms=0;
345  numMovDrag=0;
346  numRotDrag=0;
347  numConsTorque=0;
348  numConsForce=0;
349  numFixedAtoms=0;
350  numFixedGroups=0;
351  numExPressureAtoms=0;
352  numRigidBonds=0;
353  numFixedRigidBonds=0;
354  numMultipleDihedrals=0;
355  numMultipleImpropers=0;
356  numCalcBonds=0;
357  numCalcAngles=0;
358  numCalcDihedrals=0;
359  numCalcImpropers=0;
360  numCalcTholes=0;
361  numCalcAnisos=0;
362  numCalcCrossterms=0;
363  numCalcExclusions=0;
364  numCalcFullExclusions=0;
365  // JLai
366  numCalcLJPair=0;
367  // End of JLai
368 
369 //fepb
370  numFepInitial = 0;
371  numFepFinal = 0;
372  num_alch_unpert_Bonds = 0;
373  num_alch_unpert_Angles = 0;
374  num_alch_unpert_Dihedrals = 0;
375 //fepe
376 
377  //fields related with pluginIO-based loading molecule structure
378  occupancy = NULL;
379  bfactor = NULL;
380 
381  qmElementArray=0;
382  qmDummyElement=0;
383  qmGrpSizes=0;
384  qmAtomGroup=0;
385  qmAtmChrg=0;
386  qmAtmIndx=0;
387  qmGrpID=0;
388  qmGrpChrg=0;
389  qmGrpMult=0;
390  qmGrpNumBonds=0;
391  qmMMBond=0;
392  qmGrpBonds=0;
393  qmMMBondedIndx=0;
394  qmMMChargeTarget=0;
395  qmMMNumTargs=0;
396  qmDummyBondVal=0;
397  qmMeMMindx=0;
398  qmMeQMGrp=0;
399  qmCustomPCIdxs=0;
400  qmCustPCSizes=0;
401  qmLSSSize=0;
402  qmLSSIdxs=0;
403  qmLSSMass=0;
404  qmLSSRefIDs=0;
405  qmLSSRefMass=0;
406  qmLSSRefSize=0;
407  qmNumBonds=0;
408  cSMDindex=0;
409  cSMDindxLen=0;
410  cSMDpairs=0;
411  cSMDKs=0;
412  cSMDVels=0;
413  cSMDcoffs=0;
414  cSMDnumInst=0;
415 
416  goInit();
417 }
418 
419 /* END OF FUNCTION initialize */
420 
421 /************************************************************************/
422 /* */
423 /* FUNCTION Molecule */
424 /* */
425 /* This is the constructor for the Molecule class. */
426 /* */
427 /************************************************************************/
428 
430 {
431  initialize(simParams,param);
432 }
433 
434 /************************************************************************/
435 /* */
436 /* FUNCTION Molecule */
437 /* */
438 /* This is the constructor for the Molecule class from CHARMM/XPLOR files. */
439 /* */
440 /************************************************************************/
441 
442 Molecule::Molecule(SimParameters *simParams, Parameters *param, char *filename, ConfigList *cfgList)
443 {
444  initialize(simParams,param);
445 
446 #ifdef MEM_OPT_VERSION
447  if(simParams->useCompressedPsf)
448  read_mol_signatures(filename, param, cfgList);
449 #else
450  read_psf_file(filename, param);
451  //LCPO
452  if (simParams->LCPOOn)
453  assignLCPOTypes( 0 );
454 #endif
455  }
456 
457 /************************************************************************/
458 /* */
459 /* FUNCTION Molecule */
460 /* */
461 /* This is the constructor for the Molecule class from plugin IO. */
462 /* */
463 /************************************************************************/
464 Molecule::Molecule(SimParameters *simParams, Parameters *param, molfile_plugin_t *pIOHdl, void *pIOFileHdl, int natoms)
465 {
466 #ifdef MEM_OPT_VERSION
467  NAMD_die("Sorry, plugin IO is not supported in the memory optimized version.");
468 #else
469  initialize(simParams, param);
470  numAtoms = natoms;
471  int optflags = MOLFILE_BADOPTIONS;
472  molfile_atom_t *atomarray = (molfile_atom_t *) malloc(natoms*sizeof(molfile_atom_t));
473  memset(atomarray, 0, natoms*sizeof(molfile_atom_t));
474 
475  //1a. read basic atoms information
476  int rc = pIOHdl->read_structure(pIOFileHdl, &optflags, atomarray);
477  if (rc != MOLFILE_SUCCESS && rc != MOLFILE_NOSTRUCTUREDATA) {
478  free(atomarray);
479  NAMD_die("ERROR: plugin failed reading structure data");
480  }
481  if(optflags == MOLFILE_BADOPTIONS) {
482  free(atomarray);
483  NAMD_die("ERROR: plugin didn't initialize optional data flags");
484  }
485  if(optflags & MOLFILE_OCCUPANCY) {
486  setOccupancyData(atomarray);
487  }
488  if(optflags & MOLFILE_BFACTOR) {
489  setBFactorData(atomarray);
490  }
491  //1b. load basic atoms information to the molecule object
492  plgLoadAtomBasics(atomarray);
493  free(atomarray);
494 
495  //2a. read bonds
496  //indices are one-based in read_bonds
497  int *from, *to;
498  float *bondorder;
499  int *bondtype, nbondtypes;
500  char **bondtypename;
501  if(pIOHdl->read_bonds!=NULL) {
502  if(pIOHdl->read_bonds(pIOFileHdl, &numBonds, &from, &to, &bondorder,
503  &bondtype, &nbondtypes, &bondtypename)){
504  NAMD_die("ERROR: failed reading bond information.");
505  }
506  }
507  //2b. load bonds information to the molecule object
508  if(numBonds!=0) {
509  plgLoadBonds(from,to);
510  }
511 
512  //3a. read other bonded structures
513  int *plgAngles, *plgDihedrals, *plgImpropers, *plgCterms;
514  int ctermcols, ctermrows;
515  int *angletypes, numangletypes, *dihedraltypes, numdihedraltypes;
516  int *impropertypes, numimpropertypes;
517  char **angletypenames, **dihedraltypenames, **impropertypenames;
518 
519  plgAngles=plgDihedrals=plgImpropers=plgCterms=NULL;
520  if(pIOHdl->read_angles!=NULL) {
521  if(pIOHdl->read_angles(pIOFileHdl,
522  &numAngles, &plgAngles,
523  &angletypes, &numangletypes, &angletypenames,
524  &numDihedrals, &plgDihedrals,
525  &dihedraltypes, &numdihedraltypes, &dihedraltypenames,
526  &numImpropers, &plgImpropers,
527  &impropertypes, &numimpropertypes, &impropertypenames,
528  &numCrossterms, &plgCterms, &ctermcols, &ctermrows)) {
529  NAMD_die("ERROR: failed reading angle information.");
530  }
531  }
532  //3b. load other bonded structures to the molecule object
533  if(numAngles!=0) plgLoadAngles(plgAngles);
534  if(numDihedrals!=0) plgLoadDihedrals(plgDihedrals);
535  if(numImpropers!=0) plgLoadImpropers(plgImpropers);
536  if(numCrossterms!=0) plgLoadCrossterms(plgCterms);
537 
538  numRealBonds = numBonds;
539  build_atom_status();
540  //LCPO
541  if (simParams->LCPOOn)
542  assignLCPOTypes( 2 );
543 #endif
544 }
545 
546 /* END OF FUNCTION Molecule */
547 
548 /************************************************************************/
549 /* */
550 /* FUNCTION Molecule */
551 /* */
552 /* This is the destructor for the class Molecule. It simply frees */
553 /* the memory allocated for each of the arrays used to store the */
554 /* structure information. */
555 /* */
556 /************************************************************************/
557 
559 {
560  /* Check to see if each array was ever allocated. If it was */
561  /* then free it */
562  if (atoms != NULL)
563  delete [] atoms;
564 
565  if (atomNames != NULL)
566  {
567  // subarrarys allocated from arena - automatically deleted
568  delete [] atomNames;
569  }
570  delete nameArena;
571 
572  if (resLookup != NULL)
573  delete resLookup;
574 
575  // DRUDE: free arrays read from PSF
576  if (drudeConsts != NULL) delete [] drudeConsts;
577  if (lphosts != NULL) delete [] lphosts;
578  if (anisos != NULL) delete [] anisos;
579  if (tholes != NULL) delete [] tholes;
580  if (lphostIndexes != NULL) delete [] lphostIndexes;
581  // DRUDE
582 
583  //LCPO
584  if (lcpoParamType != NULL) delete [] lcpoParamType;
585 
586  #ifdef MEM_OPT_VERSION
587  if(eachAtomSig) delete [] eachAtomSig;
588  if(atomSigPool) delete [] atomSigPool;
589  #else
590  if (bonds != NULL)
591  delete [] bonds;
592 
593  if (angles != NULL)
594  delete [] angles;
595 
596  if (dihedrals != NULL)
597  delete [] dihedrals;
598 
599  if (impropers != NULL)
600  delete [] impropers;
601 
602  if (crossterms != NULL)
603  delete [] crossterms;
604 
605  if (exclusions != NULL)
606  delete [] exclusions;
607  #endif
608 
609  if (donors != NULL)
610  delete [] donors;
611 
612  if (acceptors != NULL)
613  delete [] acceptors;
614 
615  #ifdef MEM_OPT_VERSION
616  if(exclSigPool) delete [] exclSigPool;
617  if(exclChkSigPool) delete [] exclChkSigPool;
618  if(eachAtomExclSig) delete [] eachAtomExclSig;
619  if(fixedAtomsSet) delete fixedAtomsSet;
620  if(constrainedAtomsSet) delete constrainedAtomsSet;
621  #else
622  if (bondsByAtom != NULL)
623  delete [] bondsByAtom;
624 
625  if (anglesByAtom != NULL)
626  delete [] anglesByAtom;
627 
628  if (dihedralsByAtom != NULL)
629  delete [] dihedralsByAtom;
630 
631  if (impropersByAtom != NULL)
632  delete [] impropersByAtom;
633 
634  if (crosstermsByAtom != NULL)
635  delete [] crosstermsByAtom;
636 
637  if (exclusionsByAtom != NULL)
638  delete [] exclusionsByAtom;
639 
640  if (fullExclusionsByAtom != NULL)
641  delete [] fullExclusionsByAtom;
642 
643  if (modExclusionsByAtom != NULL)
644  delete [] modExclusionsByAtom;
645 
646  if (all_exclusions != NULL)
647  delete [] all_exclusions;
648 
649  // JLai
650  if (gromacsPairByAtom != NULL)
651  delete [] gromacsPairByAtom;
652  // End of JLai
653 
654  // DRUDE
655  if (tholesByAtom != NULL)
656  delete [] tholesByAtom;
657  if (anisosByAtom != NULL)
658  delete [] anisosByAtom;
659  // DRUDE
660  #endif
661 
662  //LCPO
663  if (lcpoParamType != NULL)
664  delete [] lcpoParamType;
665 
666  if (fixedAtomFlags != NULL)
667  delete [] fixedAtomFlags;
668 
669  if (stirIndexes != NULL)
670  delete [] stirIndexes;
671 
672 
673  #ifdef MEM_OPT_VERSION
674  if(clusterSigs != NULL){
675  delete [] clusterSigs;
676  }
677  #else
678  if (cluster != NULL)
679  delete [] cluster;
680  #endif
681  if (clusterSize != NULL)
682  delete [] clusterSize;
683 
684  if (exPressureAtomFlags != NULL)
685  delete [] exPressureAtomFlags;
686 
687  if (rigidBondLengths != NULL)
688  delete [] rigidBondLengths;
689 
690 //fepb
691  if (fepAtomFlags != NULL)
692  delete [] fepAtomFlags;
693  if (alch_unpert_bonds != NULL)
694  delete [] alch_unpert_bonds;
695  if (alch_unpert_angles != NULL)
696  delete [] alch_unpert_angles;
697  if (alch_unpert_dihedrals != NULL)
698  delete [] alch_unpert_dihedrals;
699 //fepe
700 
701 //soluteScaling
702  if (ssAtomFlags != NULL)
703  delete [] ssAtomFlags;
704  if (ss_vdw_type != NULL)
705  delete [] ss_vdw_type;
706  if (ss_index != NULL)
707  delete [] ss_index;
708 //soluteScaling
709 
710  if (qmAtomGroup != NULL)
711  delete [] qmAtomGroup;
712 
713  if (qmAtmIndx != NULL)
714  delete [] qmAtmIndx;
715 
716  if (qmAtmChrg != NULL)
717  delete [] qmAtmChrg;
718 
719 
720  if (qmGrpNumBonds != NULL)
721  delete [] qmGrpNumBonds;
722 
723  if (qmGrpSizes != NULL)
724  delete [] qmGrpSizes;
725 
726  if (qmDummyBondVal != NULL)
727  delete [] qmDummyBondVal;
728 
729  if (qmMMNumTargs != NULL)
730  delete [] qmMMNumTargs;
731 
732  if (qmGrpID != NULL)
733  delete [] qmGrpID;
734 
735  if (qmGrpChrg != NULL)
736  delete [] qmGrpChrg;
737 
738  if (qmGrpMult != NULL)
739  delete [] qmGrpMult;
740 
741  if (qmMeMMindx != NULL)
742  delete [] qmMeMMindx;
743 
744  if (qmMeQMGrp != NULL)
745  delete [] qmMeQMGrp;
746 
747  if (qmLSSSize != NULL)
748  delete [] qmLSSSize;
749 
750  if (qmLSSIdxs != NULL)
751  delete [] qmLSSIdxs;
752 
753  if (qmLSSMass != NULL)
754  delete [] qmLSSMass;
755 
756  if (qmLSSRefSize != NULL)
757  delete [] qmLSSRefSize;
758 
759  if (qmLSSRefIDs != NULL)
760  delete [] qmLSSRefIDs;
761 
762  if (qmLSSRefMass != NULL)
763  delete [] qmLSSRefMass;
764 
765  if (qmMMBond != NULL) {
766  for(int grpIndx = 0 ; grpIndx < qmNumBonds; grpIndx++) {
767  if (qmMMBond[grpIndx] != NULL)
768  delete [] qmMMBond[grpIndx];
769  }
770  delete [] qmMMBond;
771  }
772 
773  if (qmGrpBonds != NULL) {
774  for(int grpIndx = 0 ; grpIndx < qmNumGrps; grpIndx++) {
775  if (qmGrpBonds[grpIndx] != NULL)
776  delete [] qmGrpBonds[grpIndx];
777  }
778  delete [] qmGrpBonds;
779  }
780 
781  if (qmMMBondedIndx != NULL) {
782  for(int grpIndx = 0 ; grpIndx < qmNumGrps; grpIndx++) {
783  if (qmMMBondedIndx[grpIndx] != NULL)
784  delete [] qmMMBondedIndx[grpIndx];
785  }
786  delete [] qmMMBondedIndx;
787  }
788 
789  if (qmMMChargeTarget != NULL) {
790  for(int grpIndx = 0 ; grpIndx < qmNumBonds; grpIndx++) {
791  if (qmMMChargeTarget[grpIndx] != NULL)
792  delete [] qmMMChargeTarget[grpIndx];
793  }
794  delete [] qmMMChargeTarget;
795  }
796 
797  if (qmElementArray != NULL){
798  for(int atmInd = 0 ; atmInd < numAtoms; atmInd++) {
799  if (qmElementArray[atmInd] != NULL)
800  delete [] qmElementArray[atmInd];
801  }
802  delete [] qmElementArray;
803  }
804 
805  if (qmDummyElement != NULL){
806  for(int atmInd = 0 ; atmInd < numAtoms; atmInd++) {
807  if (qmDummyElement[atmInd] != NULL)
808  delete [] qmDummyElement[atmInd];
809  }
810  delete [] qmDummyElement;
811  }
812 
813  if (qmCustPCSizes != NULL){
814  delete [] qmCustPCSizes;
815  }
816 
817  if (qmCustomPCIdxs != NULL){
818  delete [] qmCustomPCIdxs;
819  }
820 
821  if (cSMDindex != NULL) {
822  for(int grpIndx = 0 ; grpIndx < qmNumGrps; grpIndx++) {
823  if (cSMDindex[grpIndx] != NULL)
824  delete [] cSMDindex[grpIndx];
825  }
826  delete [] cSMDindex;
827  }
828 
829  if (cSMDpairs != NULL) {
830  for(int instIndx = 0 ; instIndx < cSMDnumInst; instIndx++) {
831  if (cSMDpairs[instIndx] != NULL)
832  delete [] cSMDpairs[instIndx];
833  }
834  delete [] cSMDpairs;
835  }
836 
837  if (cSMDindxLen != NULL)
838  delete [] cSMDindxLen;
839  if (cSMDKs != NULL)
840  delete [] cSMDKs;
841  if (cSMDVels != NULL)
842  delete [] cSMDVels;
843  if (cSMDcoffs != NULL)
844  delete [] cSMDcoffs;
845 
846  #ifndef MEM_OPT_VERSION
847  delete arena;
848  delete exclArena;
849  #endif
850 }
851 /* END OF FUNCTION Molecule */
852 
853 #ifndef MEM_OPT_VERSION
854 
855 //===Non-memory optimized version of functions that read Molecule file===//
856 
857 /************************************************************************/
858 /* */
859 /* FUNCTION read_psf_file */
860 /* */
861 /* INPUTS: */
862 /* fname - Name of the .psf file to read */
863 /* params - pointer to Parameters object to use to obtain */
864 /* parameters for vdWs, bonds, etc. */
865 /* */
866 /* This function reads a .psf file in. This is where just about */
867 /* all of the structural information for this class comes from. The */
868 /* .psf file contains descriptions of the atom, bonds, angles, */
869 /* dihedrals, impropers, and exclusions. The parameter object is */
870 /* used to look up parameters for each of these entities. */
871 /* */
872 /************************************************************************/
873 
874 void Molecule::read_psf_file(char *fname, Parameters *params)
875 {
876  char err_msg[512]; // Error message for NAMD_die
877  char buffer[512]; // Buffer for file reading
878  int i; // Loop counter
879  int NumTitle; // Number of Title lines in .psf file
880  FILE *psf_file; // pointer to .psf file
881  int ret_code; // ret_code from NAMD_read_line calls
882 
883  /* Try and open the .psf file */
884  if ( (psf_file = Fopen(fname, "r")) == NULL)
885  {
886  sprintf(err_msg, "UNABLE TO OPEN .psf FILE %s", fname);
887  NAMD_die(err_msg);
888  }
889 
890  /* Read till we have the first non-blank line of file */
891  ret_code = NAMD_read_line(psf_file, buffer);
892 
893  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
894  {
895  ret_code = NAMD_read_line(psf_file, buffer);
896  }
897 
898  /* Check to see if we dropped out of the loop because of a */
899  /* read error. This shouldn't happen unless the file is empty */
900  if (ret_code!=0)
901  {
902  sprintf(err_msg, "EMPTY .psf FILE %s", fname);
903  NAMD_die(err_msg);
904  }
905 
906  /* The first non-blank line should contain the word "psf". */
907  /* If we can't find it, die. */
908  if (!NAMD_find_word(buffer, "psf"))
909  {
910  sprintf(err_msg, "UNABLE TO FIND \"PSF\" STRING IN PSF FILE %s",
911  fname);
912  NAMD_die(err_msg);
913  }
914 
915  // DRUDE: set flag if we discover Drude PSF
916  if (NAMD_find_word(buffer, "drude"))
917  {
918  if ( ! simParams->drudeOn ) {
919  iout << iWARN << "Reading PSF supporting DRUDE without "
920  "enabling the Drude model in the simulation config file\n" << endi;
921  }
922  is_drude_psf = 1;
923  }
924  // DRUDE
925 
926  /* Read until we find the next non-blank line */
927  ret_code = NAMD_read_line(psf_file, buffer);
928 
929  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
930  {
931  ret_code = NAMD_read_line(psf_file, buffer);
932  }
933 
934  /* Check to see if we dropped out of the loop because of a */
935  /* read error. This shouldn't happen unless there is nothing */
936  /* but the PSF line in the file */
937  if (ret_code!=0)
938  {
939  sprintf(err_msg, "MISSING EVERYTHING BUT PSF FROM %s", fname);
940  NAMD_die(err_msg);
941  }
942 
943  /* This line should have the word "NTITLE" in it specifying */
944  /* how many title lines there are */
945  if (!NAMD_find_word(buffer, "NTITLE"))
946  {
947  sprintf(err_msg,"CAN NOT FIND \"NTITLE\" STRING IN PSF FILE %s",
948  fname);
949  NAMD_die(err_msg);
950  }
951 
952  sscanf(buffer, "%d", &NumTitle);
953 
954  /* Now skip the next NTITLE non-blank lines and then read in the*/
955  /* line which should contain NATOM */
956  i=0;
957 
958  while ( ((ret_code=NAMD_read_line(psf_file, buffer)) == 0) &&
959  (i<NumTitle) )
960  {
961  if (!NAMD_blank_string(buffer))
962  i++;
963  }
964 
965  /* Make sure we didn't exit because of a read error */
966  if (ret_code!=0)
967  {
968  sprintf(err_msg, "FOUND EOF INSTEAD OF NATOM IN PSF FILE %s",
969  fname);
970  NAMD_die(err_msg);
971  }
972 
973  while (NAMD_blank_string(buffer))
974  {
975  NAMD_read_line(psf_file, buffer);
976  }
977 
978  /* Check to make sure we have the line we want */
979  if (!NAMD_find_word(buffer, "NATOM"))
980  {
981  sprintf(err_msg, "DIDN'T FIND \"NATOM\" IN PSF FILE %s",
982  fname);
983  NAMD_die(err_msg);
984  }
985 
986  /* Read in the number of atoms, and then the atoms themselves */
987  sscanf(buffer, "%d", &numAtoms);
988 
989  read_atoms(psf_file, params);
990 
991  /* Read until we find the next non-blank line */
992  ret_code = NAMD_read_line(psf_file, buffer);
993 
994  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
995  {
996  ret_code = NAMD_read_line(psf_file, buffer);
997  }
998 
999  /* Check to make sure we didn't hit the EOF */
1000  if (ret_code != 0)
1001  {
1002  NAMD_die("EOF ENCOUNTERED LOOKING FOR NBONDS IN PSF");
1003  }
1004 
1005  /* Look for the string "NBOND" */
1006  if (!NAMD_find_word(buffer, "NBOND"))
1007  {
1008  NAMD_die("DID NOT FIND NBOND AFTER ATOM LIST IN PSF");
1009  }
1010 
1011  /* Read in the number of bonds and then the bonds themselves */
1012  sscanf(buffer, "%d", &numBonds);
1013 
1014  if (numBonds)
1015  read_bonds(psf_file);
1016 
1017  /* Read until we find the next non-blank line */
1018  ret_code = NAMD_read_line(psf_file, buffer);
1019 
1020  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
1021  {
1022  ret_code = NAMD_read_line(psf_file, buffer);
1023  }
1024 
1025  /* Check to make sure we didn't hit the EOF */
1026  if (ret_code != 0)
1027  {
1028  NAMD_die("EOF ENCOUNTERED LOOKING FOR NTHETA IN PSF");
1029  }
1030 
1031  /* Look for the string "NTHETA" */
1032  if (!NAMD_find_word(buffer, "NTHETA"))
1033  {
1034  NAMD_die("DID NOT FIND NTHETA AFTER BOND LIST IN PSF");
1035  }
1036 
1037  /* Read in the number of angles and then the angles themselves */
1038  sscanf(buffer, "%d", &numAngles);
1039 
1040  if (numAngles)
1041  read_angles(psf_file, params);
1042 
1043  /* Read until we find the next non-blank line */
1044  ret_code = NAMD_read_line(psf_file, buffer);
1045 
1046  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
1047  {
1048  ret_code = NAMD_read_line(psf_file, buffer);
1049  }
1050 
1051  /* Check to make sure we didn't hit the EOF */
1052  if (ret_code != 0)
1053  {
1054  NAMD_die("EOF ENCOUNTERED LOOKING FOR NPHI IN PSF");
1055  }
1056 
1057  /* Look for the string "NPHI" */
1058  if (!NAMD_find_word(buffer, "NPHI"))
1059  {
1060  NAMD_die("DID NOT FIND NPHI AFTER ANGLE LIST IN PSF");
1061  }
1062 
1063  /* Read in the number of dihedrals and then the dihedrals */
1064  sscanf(buffer, "%d", &numDihedrals);
1065 
1066  if (numDihedrals)
1067  read_dihedrals(psf_file, params);
1068 
1069  /* Read until we find the next non-blank line */
1070  ret_code = NAMD_read_line(psf_file, buffer);
1071 
1072  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
1073  {
1074  ret_code = NAMD_read_line(psf_file, buffer);
1075  }
1076 
1077  /* Check to make sure we didn't hit the EOF */
1078  if (ret_code != 0)
1079  {
1080  NAMD_die("EOF ENCOUNTERED LOOKING FOR NIMPHI IN PSF");
1081  }
1082 
1083  /* Look for the string "NIMPHI" */
1084  if (!NAMD_find_word(buffer, "NIMPHI"))
1085  {
1086  NAMD_die("DID NOT FIND NIMPHI AFTER ATOM LIST IN PSF");
1087  }
1088 
1089  /* Read in the number of Impropers and then the impropers */
1090  sscanf(buffer, "%d", &numImpropers);
1091 
1092  if (numImpropers)
1093  read_impropers(psf_file, params);
1094 
1095  /* Read until we find the next non-blank line */
1096  ret_code = NAMD_read_line(psf_file, buffer);
1097 
1098  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
1099  {
1100  ret_code = NAMD_read_line(psf_file, buffer);
1101  }
1102 
1103  /* Check to make sure we didn't hit the EOF */
1104  if (ret_code != 0)
1105  {
1106  NAMD_die("EOF ENCOUNTERED LOOKING FOR NDON IN PSF");
1107  }
1108 
1109  /* Look for the string "NDON" */
1110  if (!NAMD_find_word(buffer, "NDON"))
1111  {
1112  NAMD_die("DID NOT FIND NDON AFTER ATOM LIST IN PSF");
1113  }
1114 
1115  /* Read in the number of hydrogen bond donors and then the donors */
1116  sscanf(buffer, "%d", &numDonors);
1117 
1118  if (numDonors)
1119  read_donors(psf_file);
1120 
1121  /* Read until we find the next non-blank line */
1122  ret_code = NAMD_read_line(psf_file, buffer);
1123 
1124  while ( (ret_code==0) && (NAMD_blank_string(buffer)) )
1125  {
1126  ret_code = NAMD_read_line(psf_file, buffer);
1127  }
1128 
1129  /* Check to make sure we didn't hit the EOF */
1130  if (ret_code != 0)
1131  {
1132  NAMD_die("EOF ENCOUNTERED LOOKING FOR NACC IN PSF");
1133  }
1134 
1135  /* Look for the string "NACC" */
1136  if (!NAMD_find_word(buffer, "NACC"))
1137  {
1138  NAMD_die("DID NOT FIND NACC AFTER ATOM LIST IN PSF");
1139  }
1140 
1141  /* Read in the number of hydrogen bond donors and then the donors */
1142  sscanf(buffer, "%d", &numAcceptors);
1143 
1144  if (numAcceptors)
1145  read_acceptors(psf_file);
1146 
1147  /* look for the explicit non-bonded exclusion section. */
1148  while (!NAMD_find_word(buffer, "NNB"))
1149  {
1150  ret_code = NAMD_read_line(psf_file, buffer);
1151 
1152  if (ret_code != 0)
1153  {
1154  NAMD_die("EOF ENCOUNTERED LOOKING FOR NNB IN PSF FILE");
1155  }
1156  }
1157 
1158  /* Read in the number of exclusions and then the exclusions */
1159  sscanf(buffer, "%d", &numExclusions);
1160 
1161  if (numExclusions)
1162  read_exclusions(psf_file);
1163 
1164  //
1165  // The remaining sections that we can read might be optional to the PSF.
1166  //
1167  // Possibilities are:
1168  // - Drude simulation:
1169  // + NUMLP (probably, but necessarily?)
1170  // + NUMANISO (required)
1171  // + NCRTERM (optional)
1172  // - non-Drude simulation
1173  // + NUMLP (optional)
1174  // + NCRTERM (optional)
1175  //
1176  // Also, there might be unrecognized PSF sections that we should skip.
1177  //
1178 
1179  // Keep reading until we recognize another section of PSF or find EOF.
1180  int is_found = 0;
1181  int is_found_numlp = 0;
1182  int is_found_numaniso = 0;
1183  int is_found_ncrterm = 0;
1184  while ( ! is_found ) {
1185  // Read until we find the next non-blank line
1186  do {
1187  ret_code = NAMD_read_line(psf_file, buffer);
1188  } while (ret_code == 0 && NAMD_blank_string(buffer) != 0 );
1189  // we either found EOF or we will try to match word in buffer
1190  if (ret_code != 0) {
1191  is_found = -1; // found end of file
1192  }
1193  else if ( (is_found_numlp = NAMD_find_word(buffer, "NUMLP")) > 0) {
1194  is_found = is_found_numlp;
1195  }
1196  else if ( (is_found_numaniso = NAMD_find_word(buffer, "NUMANISO")) > 0) {
1197  is_found = is_found_numaniso;
1198  }
1199  else if ( (is_found_ncrterm = NAMD_find_word(buffer, "NCRTERM")) > 0) {
1200  is_found = is_found_ncrterm;
1201  }
1202  }
1203 
1204  if (is_found_numlp) {
1205  // We found lone pair hosts.
1206  // Read the number and then read the lone pair hosts.
1207  sscanf(buffer, "%d", &numLphosts);
1208  }
1209 
1210  if (numLphosts == 0) {
1211  // We either had no NUMLP section or we did and zero were listed.
1212  // Nevertheless, we have no lone pair hosts
1213  // so reset the simparams flag before simulation
1214  simParams->lonepairs = FALSE;
1215  is_lonepairs_psf = 0;
1216  }
1217  else if (simParams->lonepairs == FALSE /* but numLphosts > 0 */) {
1218  // Config file "lonepairs" option is (now) enabled by default.
1219  // Bad things will happen when lone pair hosts exist but "lonepairs"
1220  // in simparams is disabled. In this event, terminate with an error.
1221  NAMD_die("FOUND LONE PAIR HOSTS IN PSF WITH \"LONEPAIRS\" DISABLED IN CONFIG FILE");
1222  }
1223 
1224  // Process previously read bonds now that we know if lonepairs for TIP4 are explicit
1225  if (numBonds) process_bonds(params);
1226 
1227  if (is_found_numlp) {
1228  // Must follow process_bonds() since lone pairs are placed at end of bonds array
1229  if (numLphosts > 0) read_lphosts(psf_file);
1230 
1231  // Keep reading for next keyword.
1232  is_found = 0;
1233  is_found_numaniso = 0;
1234  is_found_ncrterm = 0;
1235  while ( ! is_found ) {
1236  // Read until we find the next non-blank line
1237  do {
1238  ret_code = NAMD_read_line(psf_file, buffer);
1239  } while (ret_code == 0 && NAMD_blank_string(buffer) != 0 );
1240  // we either found EOF or we will try to match word in buffer
1241  if (ret_code != 0) {
1242  is_found = -1; // found end of file
1243  }
1244  else if ( (is_found_numaniso = NAMD_find_word(buffer, "NUMANISO")) > 0) {
1245  is_found = is_found_numaniso;
1246  }
1247  else if ( (is_found_ncrterm = NAMD_find_word(buffer, "NCRTERM")) > 0) {
1248  is_found = is_found_ncrterm;
1249  }
1250  }
1251  }
1252 
1253  if (is_found_numaniso && is_drude_psf) {
1254  // We are reading a Drude PSF and found the anisotropic terms.
1255  // Read the number and then read those terms.
1256  sscanf(buffer, "%d", &numAnisos);
1257  if (numAnisos > 0) read_anisos(psf_file);
1258 
1259  // Keep reading for next keyword.
1260  is_found = 0;
1261  is_found_ncrterm = 0;
1262  while ( ! is_found ) {
1263  // Read until we find the next non-blank line
1264  do {
1265  ret_code = NAMD_read_line(psf_file, buffer);
1266  } while (ret_code == 0 && NAMD_blank_string(buffer) != 0 );
1267  // we either found EOF or we will try to match word in buffer
1268  if (ret_code != 0) {
1269  is_found = -1; // found end of file
1270  }
1271  else if ( (is_found_ncrterm = NAMD_find_word(buffer, "NCRTERM")) > 0) {
1272  is_found = is_found_ncrterm;
1273  }
1274  }
1275  }
1276  else if (is_drude_psf /* but not is_found_numaniso */) {
1277  NAMD_die("DID NOT FIND REQUIRED NUMANISO IN DRUDE PSF FILE");
1278  }
1279  else if (is_found_numaniso /* but not is_drude_file */) {
1280  NAMD_die("FOUND NUMANISO IN PSF FILE MISSING DRUDE DESIGNATION");
1281  }
1282 
1283  if (is_found_ncrterm) {
1284  // We found crossterms section of PSF.
1285  // Read the number and then read the crossterms.
1286  sscanf(buffer, "%d", &numCrossterms);
1287  if (numCrossterms > 0) read_crossterms(psf_file, params);
1288  }
1289 
1290  // Nothing else for us to read.
1291 
1292  /* Close the .psf file. */
1293  Fclose(psf_file);
1294 
1295  if (is_drude_psf && numDrudeAtoms) {
1296  // Automatically build Drude bonds that were previously ignored.
1297  Bond *newbonds = new Bond[numBonds+numDrudeAtoms];
1298  memcpy(newbonds, bonds, numBonds*sizeof(Bond));
1299  delete [] bonds;
1300  bonds = newbonds;
1301  int origNumBonds = numBonds;
1302  for (i=0; i < numAtoms; i++) {
1303  if (!is_drude(i)) continue;
1304  Bond *b = &(bonds[numBonds++]);
1305  b->atom1 = i-1;
1306  b->atom2 = i;
1307  params->assign_bond_index(
1308  atomNames[i-1].atomtype, atomNames[i].atomtype, b
1309  );
1310  }
1311  if (numBonds-origNumBonds != numDrudeAtoms) {
1312  NAMD_die("must have same number of Drude particles and parents");
1313  }
1314  }
1315 
1316  // analyze the data and find the status of each atom
1317  numRealBonds = numBonds;
1318  build_atom_status();
1319  return;
1320 }
1321 
1322 /************************************************************************/
1323 /* */
1324 /* FUNCTION read_atoms */
1325 /* */
1326 /* INPUTS: */
1327 /* fd - file pointer to the .psf file */
1328 /* params - Parameters object to use for parameters */
1329 /* */
1330 /* this function reads in the Atoms section of the .psf file. */
1331 /* This section consists of numAtoms lines that are of the form: */
1332 /* <atom#> <mol> <seg#> <res> <atomname> <atomtype> <charge> <mass> */
1333 /* Each line is read into the appropriate entry in the atoms array. */
1334 /* The parameters object is then used to determine the vdW constants */
1335 /* for this atom. */
1336 /* */
1337 /************************************************************************/
1338 
1339 void Molecule::read_atoms(FILE *fd, Parameters *params)
1340 
1341 {
1342  char buffer[512]; // Buffer for reading from file
1343  int atom_number=0; // Atom number
1344  int last_atom_number=0; // Last atom number, used to assure
1345  // atoms are in order
1346  char segment_name[11]; // Segment name
1347  char residue_number[11]; // Residue number
1348  char residue_name[11]; // Residue name
1349  char atom_name[11]; // Atom name
1350  char atom_type[11]; // Atom type
1351  Real charge; // Charge for the current atom
1352  Real mass; // Mass for the current atom
1353  int read_count; // Number of fields read by sscanf
1354 
1355  /* Allocate the atom arrays */
1356  atoms = new Atom[numAtoms];
1357  atomNames = new AtomNameInfo[numAtoms];
1358  if(simParams->genCompressedPsf) {
1359  atomSegResids = new AtomSegResInfo[numAtoms];
1360  }
1361 
1362  // DRUDE: supplement Atom data
1363  if (is_drude_psf) {
1364  drudeConsts = new DrudeConst[numAtoms];
1365  }
1366  // DRUDE
1367 
1368  hydrogenGroup.resize(0);
1369 
1370  if (atoms == NULL || atomNames == NULL )
1371  {
1372  NAMD_die("memory allocation failed in Molecule::read_atoms");
1373  }
1374 
1375  ResidueLookupElem *tmpResLookup = resLookup;
1376 
1377  /* Loop and read in numAtoms atom lines. */
1378  while (atom_number < numAtoms)
1379  {
1380  // Standard PSF format has 8 columns:
1381  // ATOMNUM SEGNAME RESIDUE RESNAME ATOMNAME ATOMTYPE CHARGE MASS
1382 
1383  /* Get the line from the file */
1384  NAMD_read_line(fd, buffer);
1385 
1386  /* If its blank or a comment, skip it */
1387  if ( (NAMD_blank_string(buffer)) || (buffer[0] == '!') )
1388  continue;
1389 
1390  /* Parse up the line */
1391  read_count=sscanf(buffer, "%d %s %s %s %s %s %f %f",
1392  &atom_number, segment_name, residue_number,
1393  residue_name, atom_name, atom_type, &charge, &mass);
1394  if (mass <= 0.05) ++numZeroMassAtoms;
1395 
1396  /* Check to make sure we found what we were expecting */
1397  if (read_count != 8)
1398  {
1399  char err_msg[128];
1400 
1401  sprintf(err_msg, "BAD ATOM LINE FORMAT IN PSF FILE IN ATOM LINE %d\nLINE=%s",
1402  last_atom_number+1, buffer);
1403  NAMD_die(err_msg);
1404  }
1405 
1406  // DRUDE: read alpha and thole parameters from atom line
1407  if (is_drude_psf)
1408  {
1409  // Drude model PSF format has 11 columns, the 8 above plus 3 more:
1410  // (unknown integer) ALPHA THOLE
1411  // These constants are used for the Thole interactions
1412  // (dipole interactions occurring between excluded non-bonded terms).
1413 
1414  Real alpha, thole;
1415  read_count=sscanf(buffer,
1416 // "%*d %*s %*s %*s %*s %*s %*f %*f %*d %*f %*f %f %f", &alpha, &thole);
1417  // the two columns preceding alpha and thole will disappear
1418  "%*d %*s %*s %*s %*s %*s %*f %*f %*d %f %f", &alpha, &thole);
1419  if (read_count != 2)
1420  {
1421  char err_msg[128];
1422 
1423  sprintf(err_msg, "BAD ATOM LINE FORMAT IN PSF FILE "
1424  "IN ATOM LINE %d\nLINE=%s", last_atom_number+1, buffer);
1425  NAMD_die(err_msg);
1426  }
1427  drudeConsts[atom_number-1].alpha = alpha;
1428  drudeConsts[atom_number-1].thole = thole;
1429  if (fabs(alpha) >= 1e-6) ++numDrudeAtoms;
1430  }
1431  // DRUDE
1432 
1433  /* Check if this is in XPLOR format */
1434  int atom_type_num;
1435  if ( sscanf(atom_type, "%d", &atom_type_num) > 0 )
1436  {
1437  NAMD_die("Structure (psf) file is either in CHARMM format (with numbers for atoms types, the X-PLOR format using names is required) or the segment name field is empty.");
1438  }
1439 
1440  /* Make sure the atoms were in sequence */
1441  if (atom_number != last_atom_number+1)
1442  {
1443  char err_msg[128];
1444 
1445  sprintf(err_msg, "ATOM NUMBERS OUT OF ORDER AT ATOM #%d OF PSF FILE",
1446  last_atom_number+1);
1447  NAMD_die(err_msg);
1448  }
1449 
1450  last_atom_number++;
1451 
1452  /* Dynamically allocate strings for atom name, atom */
1453  /* type, etc so that we only allocate as much space */
1454  /* for these strings as we really need */
1455  int reslength = strlen(residue_name)+1;
1456  int namelength = strlen(atom_name)+1;
1457  int typelength = strlen(atom_type)+1;
1458 
1459  atomNames[atom_number-1].resname = nameArena->getNewArray(reslength);
1460  atomNames[atom_number-1].atomname = nameArena->getNewArray(namelength);
1461  atomNames[atom_number-1].atomtype = nameArena->getNewArray(typelength);
1462 
1463  if (atomNames[atom_number-1].resname == NULL)
1464  {
1465  NAMD_die("memory allocation failed in Molecule::read_atoms");
1466  }
1467 
1468  /* Put the values from this atom into the atoms array */
1469  strcpy(atomNames[atom_number-1].resname, residue_name);
1470  strcpy(atomNames[atom_number-1].atomname, atom_name);
1471  strcpy(atomNames[atom_number-1].atomtype, atom_type);
1472  atoms[atom_number-1].mass = mass;
1473  atoms[atom_number-1].charge = charge;
1474  atoms[atom_number-1].status = UnknownAtom;
1475 
1476  /* Add this atom to residue lookup table */
1477  if ( tmpResLookup ) tmpResLookup =
1478  tmpResLookup->append(segment_name, atoi(residue_number), atom_number-1);
1479 
1480  if(atomSegResids) { //for compressing molecule information
1481  AtomSegResInfo *one = atomSegResids + (atom_number - 1);
1482  memcpy(one->segname, segment_name, strlen(segment_name)+1);
1483  one->resid = atoi(residue_number);
1484  }
1485 
1486  /* Determine the type of the atom (H or O) */
1487  if ( simParams->ignoreMass ) {
1488  } else if (atoms[atom_number-1].mass <= 0.05) {
1489  atoms[atom_number-1].status |= LonepairAtom;
1490  } else if (atoms[atom_number-1].mass < 1.0) {
1491  atoms[atom_number-1].status |= DrudeAtom;
1492  } else if (atoms[atom_number-1].mass <=3.5) {
1493  atoms[atom_number-1].status |= HydrogenAtom;
1494  } else if ((atomNames[atom_number-1].atomname[0] == 'O') &&
1495  (atoms[atom_number-1].mass >= 14.0) &&
1496  (atoms[atom_number-1].mass <= 18.0)) {
1497  atoms[atom_number-1].status |= OxygenAtom;
1498  }
1499 
1500  /* Look up the vdw constants for this atom */
1501  params->assign_vdw_index(atomNames[atom_number-1].atomtype,
1502  &(atoms[atom_number-1]));
1503  }
1504 
1505  return;
1506 }
1507 /* END OF FUNCTION read_atoms */
1508 
1509 /************************************************************************/
1510 /* */
1511 /* FUNCTION read_bonds */
1512 /* */
1513 /* read_bonds reads in the bond section of the .psf file. This */
1514 /* section contains a list of pairs of numbers where each pair is */
1515 /* represents two atoms that are bonded together. Each atom pair is */
1516 /* read in. Then that parameter object is queried to determine the */
1517 /* force constant and rest distance for the bond. */
1518 /* */
1519 /************************************************************************/
1520 
1521 void Molecule::read_bonds(FILE *fd)
1522 
1523 {
1524  int atom_nums[2]; // Atom indexes for the bonded atoms
1525  register int j; // Loop counter
1526  int num_read=0; // Number of bonds read so far
1527 
1528  /* Allocate the array to hold the bonds */
1529  bonds=new Bond[numBonds];
1530 
1531  if (bonds == NULL)
1532  {
1533  NAMD_die("memory allocations failed in Molecule::read_bonds");
1534  }
1535 
1536  /* Loop through and read in all the bonds */
1537  while (num_read < numBonds)
1538  {
1539  /* Loop and read in the two atom indexes */
1540  for (j=0; j<2; j++)
1541  {
1542  /* Read the atom number from the file. */
1543  /* Subtract 1 to convert the index from the */
1544  /* 1 to NumAtoms used in the file to the */
1545  /* 0 to NumAtoms-1 that we need */
1546  atom_nums[j]=NAMD_read_int(fd, "BONDS")-1;
1547 
1548  /* Check to make sure the index isn't too big */
1549  if (atom_nums[j] >= numAtoms)
1550  {
1551  char err_msg[128];
1552 
1553  sprintf(err_msg, "BOND INDEX %d GREATER THAN NATOM %d IN BOND # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1554  NAMD_die(err_msg);
1555  }
1556  }
1557 
1558  /* Assign the atom indexes to the array element */
1559  Bond *b = &(bonds[num_read]);
1560  b->atom1=atom_nums[0];
1561  b->atom2=atom_nums[1];
1562 
1563  ++num_read;
1564  }
1565 
1566 }
1567 /* END OF FUNCTION read_bonds */
1568 
1569 /************************************************************************/
1570 void Molecule::process_bonds(Parameters *params) {
1571 
1572  int atom_nums[2]; // Atom indexes for the bonded atoms
1573  int origNumBonds = numBonds; // number of bonds in file header
1574  int num_read=0; // Number of bonds read so far
1575  int numZeroFrcBonds = 0;
1576  int numLPBonds = 0;
1577  int numDrudeBonds = 0;
1578 
1579  for (int old_read=0; old_read < origNumBonds; ++old_read)
1580  {
1581  /* Assign the atom indexes to the new array element */
1582  Bond *b = &(bonds[num_read]);
1583  *b = bonds[old_read];
1584  atom_nums[0] = b->atom1;
1585  atom_nums[1] = b->atom2;
1586 
1587  /* Query the parameter object for the constants for */
1588  /* this bond */
1589  params->assign_bond_index(
1590  atomNames[atom_nums[0]].atomtype,
1591  atomNames[atom_nums[1]].atomtype,
1592  b);
1593 
1594  /* Make sure this isn't a fake bond meant for shake in x-plor. */
1595  Real k, x0;
1596  params->get_bond_params(&k,&x0,b->bond_type);
1597 
1598  Bool is_lp_bond = (is_lp(b->atom1) || is_lp(b->atom2));
1599  Bool is_drude_bond = (is_drude(b->atom1) || is_drude(b->atom2));
1600  numZeroFrcBonds += (k == 0.);
1601  numLPBonds += is_lp_bond;
1602  numDrudeBonds += is_drude_bond;
1603  /* haochuan: bonds involving lone pairs are still explicitly
1604  * defined in the parameter files of TIP4 water model (2020-06-29),
1605  * so we need to revert to the old behavior for including them in
1606  * numBonds.
1607  */
1608  switch (simParams->watmodel) {
1609  case WAT_TIP4: {
1610  // Drude force field does not use TIP4 water
1611  // so we can ignore is_drude_bond here
1612  if ( is_lonepairs_psf ) { // new format, has NUMLP section in psf, numLphosts > 0
1613  if (k == 0. || is_lp_bond) --numBonds; // fake bond
1614  else ++num_read; // real bond
1615  } else { // old format, no NUMLP section in psf
1616  numLPBonds -= is_lp_bond;
1617  if (k == 0. && !is_lp_bond) --numBonds; // fake bond
1618  else ++num_read; // real bond
1619  }
1620  break;
1621  }
1622  case WAT_SWM4:
1623  // intentionally fall through
1624  default: {
1625  // should be this the default behavior?
1626  if (k == 0. || is_lp_bond || is_drude_bond) --numBonds; // fake bond
1627  else ++num_read; // real bond
1628  }
1629  }
1630  }
1631 
1632  if ( num_read != numBonds ) {
1633  NAMD_bug("num_read != numBonds in Molecule::process_bonds()");
1634  }
1635 
1636  /* Tell user about our subterfuge */
1637  if ( numBonds != origNumBonds ) {
1638  if (numZeroFrcBonds) {
1639  iout << iWARN << "Ignored " << numZeroFrcBonds <<
1640  " bonds with zero force constants.\n" <<
1641  iWARN << "Will get H-H distance in rigid H2O from H-O-H angle.\n" <<
1642  endi;
1643  }
1644  if (numLPBonds) {
1645  iout << iWARN << "Ignored " << numLPBonds <<
1646  " bonds with lone pairs.\n" <<
1647  iWARN << "Will infer lonepair bonds from LPhost entries.\n" << endi;
1648  }
1649  if (numDrudeBonds) {
1650  iout << iWARN << "Ignored " << numDrudeBonds <<
1651  " bonds with Drude particles.\n" <<
1652  iWARN << "Will use polarizability to assign Drude bonds.\n" << endi;
1653  }
1654  }
1655 
1656 }
1657 /* END OF FUNCTION process_bonds */
1658 
1659 /************************************************************************/
1661  int atom_nums[2]; // Atom indexes for the bonded atoms
1662  register int j; // Loop counter
1663  int num_read=0; // Number of bonds read so far
1664 
1665  alch_unpert_bonds=new Bond[num_alch_unpert_Bonds];
1666 
1667  if (alch_unpert_bonds == NULL) {
1668  NAMD_die("memory allocations failed in Molecule::read_alch_unpert_bonds");
1669  }
1670 
1671  while (num_read < num_alch_unpert_Bonds) {
1672  for (j=0; j<2; j++) {
1673  atom_nums[j]=NAMD_read_int(fd, "BONDS")-1;
1674 
1675  if (atom_nums[j] >= numAtoms) {
1676  char err_msg[128];
1677 
1678  sprintf(err_msg, "BOND INDEX %d GREATER THAN NATOM %d IN BOND # %d IN ALCH PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1679  NAMD_die(err_msg);
1680  }
1681  }
1682 
1683  Bond *b = &(alch_unpert_bonds[num_read]);
1684  b->atom1=atom_nums[0];
1685  b->atom2=atom_nums[1];
1686 
1687  ++num_read;
1688  }
1689  return;
1690 }
1691 /* END OF FUNCTION read_alch_unpert_bonds */
1692 
1693 /************************************************************************/
1694 /* */
1695 /* FUNCTION read_angles */
1696 /* */
1697 /* INPUTS: */
1698 /* fd - File descriptor for .psf file */
1699 /* params - Parameters object to query for parameters */
1700 /* */
1701 /* read_angles reads the angle parameters from the .psf file. */
1702 /* This section of the .psf file consists of a list of triplets of */
1703 /* atom indexes. Each triplet represents three atoms connected via */
1704 /* an angle bond. The parameter object is queried to obtain the */
1705 /* constants for each bond. */
1706 /* */
1707 /************************************************************************/
1708 
1709 void Molecule::read_angles(FILE *fd, Parameters *params)
1710 
1711 {
1712  int atom_nums[3]; // Atom numbers for the three atoms
1713  register int j; // Loop counter
1714  int num_read=0; // Number of angles read so far
1715  int origNumAngles = numAngles; // Number of angles in file
1716  /* Alloc the array of angles */
1717  angles=new Angle[numAngles];
1718 
1719  if (angles == NULL)
1720  {
1721  NAMD_die("memory allocation failed in Molecule::read_angles");
1722  }
1723 
1724  /* Loop through and read all the angles */
1725  while (num_read < numAngles)
1726  {
1727  /* Loop through the 3 atom indexes in the current angle*/
1728  for (j=0; j<3; j++)
1729  {
1730  /* Read the atom number from the file. */
1731  /* Subtract 1 to convert the index from the */
1732  /* 1 to NumAtoms used in the file to the */
1733  /* 0 to NumAtoms-1 that we need */
1734  atom_nums[j]=NAMD_read_int(fd, "ANGLES")-1;
1735 
1736  /* Check to make sure the atom index doesn't */
1737  /* exceed the Number of Atoms */
1738  if (atom_nums[j] >= numAtoms)
1739  {
1740  char err_msg[128];
1741 
1742  sprintf(err_msg, "ANGLES INDEX %d GREATER THAN NATOM %d IN ANGLES # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1743  NAMD_die(err_msg);
1744  }
1745  }
1746 
1747  /* Assign the three atom indices */
1748  angles[num_read].atom1=atom_nums[0];
1749  angles[num_read].atom2=atom_nums[1];
1750  angles[num_read].atom3=atom_nums[2];
1751 
1752  /* Get the constant values for this bond from the */
1753  /* parameter object */
1754  params->assign_angle_index(
1755  atomNames[atom_nums[0]].atomtype,
1756  atomNames[atom_nums[1]].atomtype,
1757  atomNames[atom_nums[2]].atomtype,
1758  &(angles[num_read]), simParams->alchOn ? -1 : 0);
1759  if ( angles[num_read].angle_type == -1 ) {
1760  iout << iWARN << "ALCHEMY MODULE WILL REMOVE ANGLE OR RAISE ERROR\n"
1761  << endi;
1762  }
1763 
1764  /* Make sure this isn't a fake angle meant for shake in x-plor. */
1765  Real k, t0, k_ub, r_ub;
1766  if ( angles[num_read].angle_type == -1 ) { k = -1.; k_ub = -1.; } else
1767  params->get_angle_params(&k,&t0,&k_ub,&r_ub,angles[num_read].angle_type);
1768  if ( k == 0. && k_ub == 0. ) --numAngles; // fake angle
1769  else ++num_read; // real angle
1770  }
1771 
1772  /* Tell user about our subterfuge */
1773  if ( numAngles != origNumAngles ) {
1774  iout << iWARN << "Ignored " << origNumAngles - numAngles <<
1775  " angles with zero force constants.\n" << endi;
1776  }
1777 
1778  return;
1779 }
1780 /* END OF FUNCTION read_angles */
1781 
1782 /************************************************************************/
1784  int atom_nums[3]; // Atom numbers for the three atoms
1785  register int j; // Loop counter
1786  int num_read=0; // Number of angles read so far
1787 
1788  alch_unpert_angles=new Angle[num_alch_unpert_Angles];
1789 
1790  if (alch_unpert_angles == NULL) {
1791  NAMD_die("memory allocation failed in Molecule::read_alch_unpert_angles");
1792  }
1793 
1794  while (num_read < num_alch_unpert_Angles) {
1795  for (j=0; j<3; j++) {
1796  atom_nums[j]=NAMD_read_int(fd, "ANGLES")-1;
1797 
1798  if (atom_nums[j] >= numAtoms) {
1799  char err_msg[128];
1800  sprintf(err_msg, "ANGLES INDEX %d GREATER THAN NATOM %d IN ANGLES # %d IN ALCH UNPERT PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1801  NAMD_die(err_msg);
1802  }
1803  }
1804 
1805  alch_unpert_angles[num_read].atom1=atom_nums[0];
1806  alch_unpert_angles[num_read].atom2=atom_nums[1];
1807  alch_unpert_angles[num_read].atom3=atom_nums[2];
1808 
1809  ++num_read;
1810  }
1811  return;
1812 }
1813 /* END OF FUNCTION read_alch_unpert_angles */
1814 
1815 /************************************************************************/
1816 /* */
1817 /* FUNCTION read_dihedrals */
1818 /* */
1819 /* INPUTS: */
1820 /* fd - file descriptor for the .psf file */
1821 /* params - pointer to parameter object */
1822 /* */
1823 /* read_dihedreals reads the dihedral section of the .psf file. */
1824 /* This section of the file contains a list of quartets of atom */
1825 /* numbers. Each quartet represents a group of atoms that form a */
1826 /* dihedral bond. */
1827 /* */
1828 /************************************************************************/
1829 
1830 void Molecule::read_dihedrals(FILE *fd, Parameters *params)
1831 {
1832  int atom_nums[4]; // The 4 atom indexes
1833  int last_atom_nums[4]; // Atom numbers from previous bond
1834  register int j; // loop counter
1835  int num_read=0; // number of dihedrals read so far
1836  int multiplicity=1; // multiplicity of the current bond
1837  Bool duplicate_bond; // Is this a duplicate of the last bond
1838  int num_unique=0; // Number of unique dihedral bonds
1839 
1840  // Initialize the array used to check for duplicate dihedrals
1841  for (j=0; j<4; j++)
1842  last_atom_nums[j] = -1;
1843 
1844  /* Allocate an array to hold the Dihedrals */
1845  dihedrals = new Dihedral[numDihedrals];
1846 
1847  if (dihedrals == NULL)
1848  {
1849  NAMD_die("memory allocation failed in Molecule::read_dihedrals");
1850  }
1851 
1852  /* Loop through and read all the dihedrals */
1853  while (num_read < numDihedrals)
1854  {
1855  duplicate_bond = TRUE;
1856 
1857  /* Loop through and read the 4 indexes for this bond */
1858  for (j=0; j<4; j++)
1859  {
1860  /* Read the atom number from the file. */
1861  /* Subtract 1 to convert the index from the */
1862  /* 1 to NumAtoms used in the file to the */
1863  /* 0 to NumAtoms-1 that we need */
1864  atom_nums[j]=NAMD_read_int(fd, "DIHEDRALS")-1;
1865 
1866  /* Check for an atom index that is too large */
1867  if (atom_nums[j] >= numAtoms)
1868  {
1869  char err_msg[128];
1870 
1871  sprintf(err_msg, "DIHEDRALS INDEX %d GREATER THAN NATOM %d IN DIHEDRALS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1872  NAMD_die(err_msg);
1873  }
1874 
1875  // Check to see if this atom matches the last bond
1876  if (atom_nums[j] != last_atom_nums[j])
1877  {
1878  duplicate_bond = FALSE;
1879  }
1880 
1881  last_atom_nums[j] = atom_nums[j];
1882  }
1883 
1884  // Check to see if this is really a new bond or just
1885  // a repeat of the last one
1886  if (duplicate_bond)
1887  {
1888  // This is a duplicate, so increase the multiplicity
1889  multiplicity++;
1890 
1891  if (multiplicity == 2)
1892  {
1893  numMultipleDihedrals++;
1894  }
1895  }
1896  else
1897  {
1898  multiplicity=1;
1899  num_unique++;
1900  }
1901 
1902  /* Assign the atom indexes */
1903  dihedrals[num_unique-1].atom1=atom_nums[0];
1904  dihedrals[num_unique-1].atom2=atom_nums[1];
1905  dihedrals[num_unique-1].atom3=atom_nums[2];
1906  dihedrals[num_unique-1].atom4=atom_nums[3];
1907 
1908  /* Get the constants for this dihedral bond */
1909  params->assign_dihedral_index(
1910  atomNames[atom_nums[0]].atomtype,
1911  atomNames[atom_nums[1]].atomtype,
1912  atomNames[atom_nums[2]].atomtype,
1913  atomNames[atom_nums[3]].atomtype,
1914  &(dihedrals[num_unique-1]),
1915  multiplicity, simParams->alchOn ? -1 : 0);
1916  if ( dihedrals[num_unique-1].dihedral_type == -1 ) {
1917  iout << iWARN << "ALCHEMY MODULE WILL REMOVE DIHEDRAL OR RAISE ERROR\n"
1918  << endi;
1919  }
1920 
1921  num_read++;
1922  }
1923 
1924  numDihedrals = num_unique;
1925 
1926  return;
1927 }
1928 /* END OF FUNCTION read_dihedral */
1929 
1930 /*************************************************************************/
1932  int atom_nums[4]; // The 4 atom indexes
1933  int num_read=0; // number of dihedrals read so far
1934  register int j; // loop counter
1935 
1936  alch_unpert_dihedrals = new Dihedral[num_alch_unpert_Dihedrals];
1937 
1938  if (alch_unpert_dihedrals == NULL) {
1939  NAMD_die("memory allocation failed in Molecule::read_alch_unpert_dihedrals");
1940  }
1941 
1942  while (num_read < num_alch_unpert_Dihedrals) {
1943  for (j=0; j<4; j++) {
1944  atom_nums[j]=NAMD_read_int(fd, "DIHEDRALS")-1;
1945 
1946  if (atom_nums[j] >= numAtoms) {
1947  char err_msg[128];
1948 
1949  sprintf(err_msg, "DIHEDRALS INDEX %d GREATER THAN NATOM %d IN DIHEDRALS # %d IN ALCH UNPERT PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
1950  NAMD_die(err_msg);
1951  }
1952  }
1953 
1954  alch_unpert_dihedrals[num_read].atom1=atom_nums[0];
1955  alch_unpert_dihedrals[num_read].atom2=atom_nums[1];
1956  alch_unpert_dihedrals[num_read].atom3=atom_nums[2];
1957  alch_unpert_dihedrals[num_read].atom4=atom_nums[3];
1958 
1959  num_read++;
1960  }
1961  return;
1962 }
1963 /* END OF FUNCTION read_alch_unpert_dihedral */
1964 
1965 /************************************************************************/
1966 /* */
1967 /* FUNCTION read_impropers */
1968 /* */
1969 /* INPUTS: */
1970 /* fd - file descriptor for .psf file */
1971 /* params - parameter object */
1972 /* */
1973 /* read_impropers reads the improper section of the .psf file. */
1974 /* This section is identical to the dihedral section in that it is */
1975 /* made up of a list of quartets of atom indexes that define the */
1976 /* atoms that are bonded together. */
1977 /* */
1978 /************************************************************************/
1979 
1980 void Molecule::read_impropers(FILE *fd, Parameters *params)
1981 {
1982  int atom_nums[4]; // Atom indexes for the 4 atoms
1983  int last_atom_nums[4]; // Atom indexes from previous bond
1984  register int j; // Loop counter
1985  int num_read=0; // Number of impropers read so far
1986  int multiplicity=1; // multiplicity of the current bond
1987  Bool duplicate_bond; // Is this a duplicate of the last bond
1988  int num_unique=0; // Number of unique dihedral bonds
1989 
1990  // Initialize the array used to look for duplicate improper
1991  // entries. Set them all to -1 so we know nothing will match
1992  for (j=0; j<4; j++)
1993  last_atom_nums[j] = -1;
1994 
1995  /* Allocate the array to hold the impropers */
1996  impropers=new Improper[numImpropers];
1997 
1998  if (impropers == NULL)
1999  {
2000  NAMD_die("memory allocation failed in Molecule::read_impropers");
2001  }
2002 
2003  /* Loop through and read all the impropers */
2004  while (num_read < numImpropers)
2005  {
2006  duplicate_bond = TRUE;
2007 
2008  /* Loop through the 4 indexes for this improper */
2009  for (j=0; j<4; j++)
2010  {
2011  /* Read the atom number from the file. */
2012  /* Subtract 1 to convert the index from the */
2013  /* 1 to NumAtoms used in the file to the */
2014  /* 0 to NumAtoms-1 that we need */
2015  atom_nums[j]=NAMD_read_int(fd, "IMPROPERS")-1;
2016 
2017  /* Check to make sure the index isn't too big */
2018  if (atom_nums[j] >= numAtoms)
2019  {
2020  char err_msg[128];
2021 
2022  sprintf(err_msg, "IMPROPERS INDEX %d GREATER THAN NATOM %d IN IMPROPERS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
2023  NAMD_die(err_msg);
2024  }
2025 
2026  if (atom_nums[j] != last_atom_nums[j])
2027  {
2028  duplicate_bond = FALSE;
2029  }
2030 
2031  last_atom_nums[j] = atom_nums[j];
2032  }
2033 
2034  // Check to see if this is a duplicate improper
2035  if (duplicate_bond)
2036  {
2037  // This is a duplicate improper. So we don't
2038  // really count this entry, we just update
2039  // the parameters object
2040  multiplicity++;
2041 
2042  if (multiplicity == 2)
2043  {
2044  // Count the number of multiples.
2045  numMultipleImpropers++;
2046  }
2047  }
2048  else
2049  {
2050  // Not a duplicate
2051  multiplicity = 1;
2052  num_unique++;
2053  }
2054 
2055  /* Assign the atom indexes */
2056  impropers[num_unique-1].atom1=atom_nums[0];
2057  impropers[num_unique-1].atom2=atom_nums[1];
2058  impropers[num_unique-1].atom3=atom_nums[2];
2059  impropers[num_unique-1].atom4=atom_nums[3];
2060 
2061  /* Look up the constants for this bond */
2062  params->assign_improper_index(
2063  atomNames[atom_nums[0]].atomtype,
2064  atomNames[atom_nums[1]].atomtype,
2065  atomNames[atom_nums[2]].atomtype,
2066  atomNames[atom_nums[3]].atomtype,
2067  &(impropers[num_unique-1]),
2068  multiplicity);
2069 
2070  num_read++;
2071  }
2072 
2073  // Now reset the numImpropers value to the number of UNIQUE
2074  // impropers. Sure, we waste a few entries in the improper_array
2075  // on the master node, but it is very little space . . .
2076  numImpropers = num_unique;
2077 
2078  return;
2079 }
2080 /* END OF FUNCTION read_impropers */
2081 
2082 /************************************************************************/
2083 /* */
2084 /* FUNCTION read_crossterms */
2085 /* */
2086 /* INPUTS: */
2087 /* fd - file descriptor for .psf file */
2088 /* params - parameter object */
2089 /* */
2090 /* This section is identical to the dihedral section in that it is */
2091 /* made up of a list of quartets of atom indexes that define the */
2092 /* atoms that are bonded together. */
2093 /* */
2094 /************************************************************************/
2095 
2096 void Molecule::read_crossterms(FILE *fd, Parameters *params)
2097 
2098 {
2099  int atom_nums[8]; // Atom indexes for the 4 atoms
2100  int last_atom_nums[8]; // Atom indexes from previous bond
2101  register int j; // Loop counter
2102  int num_read=0; // Number of items read so far
2103  Bool duplicate_bond; // Is this a duplicate of the last bond
2104 
2105  // Initialize the array used to look for duplicate crossterm
2106  // entries. Set them all to -1 so we know nothing will match
2107  for (j=0; j<8; j++)
2108  last_atom_nums[j] = -1;
2109 
2110  /* Allocate the array to hold the cross-terms */
2111  crossterms=new Crossterm[numCrossterms];
2112 
2113  if (crossterms == NULL)
2114  {
2115  NAMD_die("memory allocation failed in Molecule::read_crossterms");
2116  }
2117 
2118  /* Loop through and read all the cross-terms */
2119  while (num_read < numCrossterms)
2120  {
2121  duplicate_bond = TRUE;
2122 
2123  /* Loop through the 8 indexes for this cross-term */
2124  for (j=0; j<8; j++)
2125  {
2126  /* Read the atom number from the file. */
2127  /* Subtract 1 to convert the index from the */
2128  /* 1 to NumAtoms used in the file to the */
2129  /* 0 to NumAtoms-1 that we need */
2130  atom_nums[j]=NAMD_read_int(fd, "CROSS-TERMS")-1;
2131 
2132  /* Check to make sure the index isn't too big */
2133  if (atom_nums[j] >= numAtoms)
2134  {
2135  char err_msg[128];
2136 
2137  sprintf(err_msg, "CROSS-TERM INDEX %d GREATER THAN NATOM %d IN CROSS-TERMS # %d IN PSF FILE", atom_nums[j]+1, numAtoms, num_read+1);
2138  NAMD_die(err_msg);
2139  }
2140 
2141  if (atom_nums[j] != last_atom_nums[j])
2142  {
2143  duplicate_bond = FALSE;
2144  }
2145 
2146  last_atom_nums[j] = atom_nums[j];
2147  }
2148 
2149  // Check to see if this is a duplicate term
2150  if (duplicate_bond)
2151  {
2152  iout << iWARN << "Duplicate cross-term detected.\n" << endi;
2153  }
2154 
2155  /* Assign the atom indexes */
2156  crossterms[num_read].atom1=atom_nums[0];
2157  crossterms[num_read].atom2=atom_nums[1];
2158  crossterms[num_read].atom3=atom_nums[2];
2159  crossterms[num_read].atom4=atom_nums[3];
2160  crossterms[num_read].atom5=atom_nums[4];
2161  crossterms[num_read].atom6=atom_nums[5];
2162  crossterms[num_read].atom7=atom_nums[6];
2163  crossterms[num_read].atom8=atom_nums[7];
2164 
2165  /* Look up the constants for this bond */
2166  params->assign_crossterm_index(
2167  atomNames[atom_nums[0]].atomtype,
2168  atomNames[atom_nums[1]].atomtype,
2169  atomNames[atom_nums[2]].atomtype,
2170  atomNames[atom_nums[3]].atomtype,
2171  atomNames[atom_nums[4]].atomtype,
2172  atomNames[atom_nums[5]].atomtype,
2173  atomNames[atom_nums[6]].atomtype,
2174  atomNames[atom_nums[7]].atomtype,
2175  &(crossterms[num_read]));
2176 
2177  if(!duplicate_bond) num_read++;
2178  }
2179 
2180  numCrossterms = num_read;
2181 
2182  return;
2183 }
2184 /* END OF FUNCTION read_impropers */
2185 
2186 /************************************************************************/
2187 /* */
2188 /* FUNCTION read_donors */
2189 /* */
2190 /* read_donors reads in the bond section of the .psf file. This */
2191 /* section contains a list of pairs of numbers where each pair is */
2192 /* represents two atoms that are part of an H-bond. Each atom pair is */
2193 /* read in. */
2194 /* */
2195 /* Donor atoms are the heavy atoms to which hydrogens are bonded. */
2196 /* There will always be a donor atom for each donor pair. However, */
2197 /* for a united-atom model there may not be an explicit hydrogen */
2198 /* present, in which case the second atom index in the pair will be */
2199 /* given as 0 in the PSF (and stored as -1 in this program's internal */
2200 /* storage). */
2201 /************************************************************************/
2202 
2203 void Molecule::read_donors(FILE *fd)
2204 {
2205  int d[2]; // temporary storage of donor atom index
2206  register int j; // Loop counter
2207  int num_read=0; // Number of bonds read so far
2208  int num_no_hydr=0; // Number of bonds with no hydrogen given
2209 
2210  /* Allocate the array to hold the bonds */
2211  donors=new Bond[numDonors];
2212 
2213  if (donors == NULL)
2214  {
2215  NAMD_die("memory allocations failed in Molecule::read_donors");
2216  }
2217 
2218  /* Loop through and read in all the donors */
2219  while (num_read < numDonors)
2220  {
2221  /* Loop and read in the two atom indexes */
2222  for (j=0; j<2; j++)
2223  {
2224  /* Read the atom number from the file. */
2225  /* Subtract 1 to convert the index from the */
2226  /* 1 to NumAtoms used in the file to the */
2227  /* 0 to NumAtoms-1 that we need */
2228  d[j]=NAMD_read_int(fd, "DONORS")-1;
2229 
2230  /* Check to make sure the index isn't too big */
2231  if (d[j] >= numAtoms)
2232  {
2233  char err_msg[128];
2234 
2235  sprintf(err_msg,
2236  "DONOR INDEX %d GREATER THAN NATOM %d IN DONOR # %d IN PSF FILE",
2237  d[j]+1, numAtoms, num_read+1);
2238  NAMD_die(err_msg);
2239  }
2240 
2241  /* Check if there is a hydrogen given */
2242  if (d[j] < 0)
2243  num_no_hydr++;
2244  }
2245 
2246  /* Assign the atom indexes to the array element */
2247  Bond *b = &(donors[num_read]);
2248  b->atom1=d[0];
2249  b->atom2=d[1];
2250 
2251  num_read++;
2252  }
2253 
2254  return;
2255 }
2256 /* END OF FUNCTION read_donors */
2257 
2258 
2259 /************************************************************************/
2260 /* */
2261 /* FUNCTION read_acceptors */
2262 /* */
2263 /* read_acceptors reads in the bond section of the .psf file. */
2264 /* This section contains a list of pairs of numbers where each pair is */
2265 /* represents two atoms that are part of an H-bond. Each atom pair is */
2266 /* read in. */
2267 /* */
2268 /* Acceptor atoms are the heavy atoms to which hydrogens directly */
2269 /* orient in a hydrogen bond interaction. There will always be an */
2270 /* acceptor atom for each acceptor pair. The antecedent atom, to */
2271 /* which the acceptor is bound, may not be given in the structure, */
2272 /* however, in which case the second atom index in the pair will be */
2273 /* given as 0 in the PSF (and stored as -1 in this program's internal */
2274 /* storage). */
2275 /************************************************************************/
2276 
2277 void Molecule::read_acceptors(FILE *fd)
2278 {
2279  int d[2]; // temporary storage of atom index
2280  register int j; // Loop counter
2281  int num_read=0; // Number of bonds read so far
2282  int num_no_ante=0; // number of pairs with no antecedent
2283 
2284  /* Allocate the array to hold the bonds */
2285  acceptors=new Bond[numAcceptors];
2286 
2287  if (acceptors == NULL)
2288  {
2289  NAMD_die("memory allocations failed in Molecule::read_acceptors");
2290  }
2291 
2292  /* Loop through and read in all the acceptors */
2293  while (num_read < numAcceptors)
2294  {
2295  /* Loop and read in the two atom indexes */
2296  for (j=0; j<2; j++)
2297  {
2298  /* Read the atom number from the file. */
2299  /* Subtract 1 to convert the index from the */
2300  /* 1 to NumAtoms used in the file to the */
2301  /* 0 to NumAtoms-1 that we need */
2302  d[j]=NAMD_read_int(fd, "ACCEPTORS")-1;
2303 
2304  /* Check to make sure the index isn't too big */
2305  if (d[j] >= numAtoms)
2306  {
2307  char err_msg[128];
2308 
2309  sprintf(err_msg, "ACCEPTOR INDEX %d GREATER THAN NATOM %d IN DONOR # %d IN PSF FILE", d[j]+1, numAtoms, num_read+1);
2310  NAMD_die(err_msg);
2311  }
2312 
2313  /* Check if there is an antecedent given */
2314  if (d[j] < 0)
2315  num_no_ante++;
2316  }
2317 
2318  /* Assign the atom indexes to the array element */
2319  Bond *b = &(acceptors[num_read]);
2320  b->atom1=d[0];
2321  b->atom2=d[1];
2322 
2323  num_read++;
2324  }
2325 
2326  return;
2327 }
2328 /* END OF FUNCTION read_acceptors */
2329 
2330 
2331 /************************************************************************/
2332 /* */
2333 /* FUNCTION read_exclusions */
2334 /* */
2335 /* INPUTS: */
2336 /* fd - file descriptor for .psf file */
2337 /* */
2338 /* read_exclusions reads in the explicit non-bonded exclusions */
2339 /* from the .psf file. This section is a little funky, so hang on. */
2340 /* Ok, first there is a list of atom indexes that is NumExclusions */
2341 /* long. These are in some sense the atoms that will be exlcuded. */
2342 /* Following this list is a list of NumAtoms length that is a list */
2343 /* of indexes into the list of excluded atoms. So an example. Suppose*/
2344 /* we have a 5 atom simulation with 3 explicit exclusions. The .psf */
2345 /* file could look like: */
2346 /* */
2347 /* 3!NNB */
2348 /* 3 4 5 */
2349 /* 0 1 3 3 3 */
2350 /* */
2351 /* This would mean that atom 1 has no explicit exclusions. Atom 2 */
2352 /* has an explicit exclusion with atom 3. Atom 3 has an explicit */
2353 /* exclusion with atoms 4 AND 5. And atoms 4 and 5 have no explicit */
2354 /* exclusions. Got it!?! I'm not sure who dreamed this up . . . */
2355 /* */
2356 /************************************************************************/
2357 
2358 void Molecule::read_exclusions(FILE *fd)
2359 
2360 {
2361  int *exclusion_atoms; // Array of indexes of excluded atoms
2362  register int num_read=0; // Number fo exclusions read in
2363  int current_index; // Current index value
2364  int last_index; // the previous index value
2365  register int insert_index=0; // index of where we are in exlcusions array
2366 
2367  /* Allocate the array of exclusion structures and the array of */
2368  /* exlcuded atom indexes */
2369  exclusions = new Exclusion[numExclusions];
2370  exclusion_atoms = new int[numExclusions];
2371 
2372  if ( (exclusions == NULL) || (exclusion_atoms == NULL) )
2373  {
2374  NAMD_die("memory allocation failed in Molecule::read_exclusions");
2375  }
2376 
2377  /* First, read in the excluded atoms list */
2378  for (num_read=0; num_read<numExclusions; num_read++)
2379  {
2380  /* Read the atom number from the file. Subtract 1 to */
2381  /* convert the index from the 1 to NumAtoms used in the*/
2382  /* file to the 0 to NumAtoms-1 that we need */
2383  exclusion_atoms[num_read]=NAMD_read_int(fd, "IMPROPERS")-1;
2384 
2385  /* Check for an illegal index */
2386  if (exclusion_atoms[num_read] >= numAtoms)
2387  {
2388  char err_msg[128];
2389 
2390  sprintf(err_msg, "EXCLUSION INDEX %d GREATER THAN NATOM %d IN EXCLUSION # %d IN PSF FILE", exclusion_atoms[num_read]+1, numAtoms, num_read+1);
2391  NAMD_die(err_msg);
2392  }
2393  }
2394 
2395  /* Now, go through and read the list of NumAtoms pointers into */
2396  /* the array that we just read in */
2397  last_index=0;
2398 
2399  for (num_read=0; num_read<numAtoms; num_read++)
2400  {
2401  /* Read in the current index value */
2402  current_index=NAMD_read_int(fd, "EXCLUSIONS");
2403 
2404  /* Check for an illegal pointer */
2405  if (current_index>numExclusions)
2406  {
2407  char err_msg[128];
2408 
2409  sprintf(err_msg, "EXCLUSION INDEX %d LARGER THAN NUMBER OF EXLCUSIONS %d IN PSF FILE, EXCLUSION #%d\n",
2410  current_index+1, numExclusions, num_read);
2411  NAMD_die(err_msg);
2412  }
2413 
2414  /* Check to see if it matches the last index. If so */
2415  /* than this atom has no exclusions. If not, then */
2416  /* we have to build some exclusions */
2417  if (current_index != last_index)
2418  {
2419  /* This atom has some exclusions. Loop from */
2420  /* the last_index to the current index. This */
2421  /* will include how ever many exclusions this */
2422  /* atom has */
2423  for (insert_index=last_index;
2424  insert_index<current_index; insert_index++)
2425  {
2426  /* Assign the two atoms involved. */
2427  /* The first one is our position in */
2428  /* the list, the second is based on */
2429  /* the pointer into the index list */
2430  int a1 = num_read;
2431  int a2 = exclusion_atoms[insert_index];
2432  if ( a1 < a2 ) {
2433  exclusions[insert_index].atom1 = a1;
2434  exclusions[insert_index].atom2 = a2;
2435  } else if ( a2 < a1 ) {
2436  exclusions[insert_index].atom1 = a2;
2437  exclusions[insert_index].atom2 = a1;
2438  } else {
2439  char err_msg[128];
2440  sprintf(err_msg, "ATOM %d EXCLUDED FROM ITSELF IN PSF FILE\n", a1+1);
2441  NAMD_die(err_msg);
2442  }
2443  }
2444 
2445  last_index=current_index;
2446  }
2447  }
2448 
2449  /* Free our temporary list of indexes */
2450  delete [] exclusion_atoms;
2451 
2452  return;
2453 }
2454 /* END OF FUNCTION read_exclusions */
2455 
2456 /************************************************************************/
2457 /* FUNCTION read_exclusions */
2458 /* */
2459 /* INPUTS: */
2460 /* int* atom_i - array of atom i indices */
2461 /* int* atom_j - array of atom j indices */
2462 /* int num_exclusion - length of array */
2463 /* */
2464 /* JLai August 16th, 2012 */
2465 /************************************************************************/
2466 void Molecule::read_exclusions(int* atom_i, int* atom_j, int num_exclusion)
2467 {
2468  /* Allocate the array of exclusion structures and the array of */
2469  /* exlcuded atom indexes */
2470  exclusions = new Exclusion[num_exclusion];
2471  int loop_counter = 0;
2472  int a=0;
2473  int b=0;
2474 
2475  if ( (exclusions == NULL) )
2476  {
2477  NAMD_die("memory allocation failed in Molecule::read_exclusions");
2478  }
2479 
2480  /* The following code only guarantees that exclusion.atom1 is < exclusion.atom2 */
2481  for (loop_counter = 0; loop_counter < num_exclusion; loop_counter++) {
2482 
2483  if ( (atom_i == NULL) || (atom_j == NULL) ) {
2484  NAMD_die("null pointer expection in Molecule::read_exclusions");
2485  }
2486 
2487  a = atom_i[loop_counter];
2488  b = atom_j[loop_counter];
2489  if(a < b) {
2490  exclusions[loop_counter].atom1 = a;
2491  exclusions[loop_counter].atom2 = b;
2492  } else {
2493  exclusions[loop_counter].atom1 = b;
2494  exclusions[loop_counter].atom2 = a;
2495  }
2496  exclusionSet.add(Exclusion(exclusions[loop_counter].atom1,exclusions[loop_counter].atom2));
2497  }
2498 
2499  if ( ! CkMyPe() ) {
2500  iout << iINFO << "ADDED " << num_exclusion << " EXPLICIT EXCLUSIONS: THIS VALUE WILL *NOT* BE ADDED TO THE STRUCTURE SUMMARY\n" << endi;
2501  }
2502 
2503  return;
2504 }
2505 /* END OF FUNCTION read_exclusions */
2506 
2507 /************************************************************************
2508  *
2509  * FUNCTION read_lphosts
2510  *
2511  * INPUTS:
2512  * fd - file pointer to the .psf file
2513  *
2514  * This function reads in the lone pair host section of the .psf file.
2515  * Each lone pair is supported by 2 or 3 host atoms.
2516  *
2517  * All lonepair specifications in a PSF are expected to have three
2518  * associated values. However, the meaning of these values depends
2519  * on the lonepair type. Nonetheless, for simplicity with the old
2520  * code, the struct values are still called "distance", "angle",
2521  * and "dihedral", even when this is not what the value signifies.
2522  *
2523  ************************************************************************/
2524 void Molecule::read_lphosts(FILE *fd)
2525 {
2526  char buffer[512]; // Buffer for reading from file
2527  char weight[8]; // Weighting type identified by string --
2528  // unused/unsupported outside of CHARMM RTF
2529  // so we read it, but ignore it.
2530  int numhosts; // Refers to the number of atoms that support the
2531  // given lone pair, either 2 or 3.
2532  int index; // 1-based index into the stream of numbers (8 per line)
2533  // that indicates the start of each LP host record.
2534  int next_index = 1; // Forecast next index value as an error check.
2535  int i, read_count;
2536  Real value1, value2, value3;
2537 
2538  // called only if numLphosts > 0
2539  lphosts = new Lphost[numLphosts];
2540  if (lphosts == NULL) {
2541  NAMD_die("memory allocation failed in Molecule::read_lphosts");
2542  }
2543  for (i = 0; i < numLphosts; i++) {
2544  NAMD_read_line(fd, buffer);
2545  if ( (NAMD_blank_string(buffer)) || (buffer[0] == '!') ) continue;
2546  read_count=sscanf(buffer, "%d %d %6s %f %f %f",
2547  &numhosts, &index, weight, &value1, &value2, &value3);
2548  // The "weight" specification in PSF remains hardcoded as "F"
2549  // (for false) inside NAMD. Again, no extant force field uses
2550  // lonepairs with weighted placement, so this can really only be
2551  // specified inside an RTF, which NAMD never reads anyway.
2552  if (read_count != 6 || index != next_index ||
2553  strcmp(weight,"F") != 0 || numhosts < 2 || 3 < numhosts) {
2554  char err_msg[128];
2555  sprintf(err_msg, "BAD FORMAT FOR LPHOST LINE %d IN PSF FILE LINE\n"
2556  "LINE=%s\n", i+1, buffer);
2557  NAMD_die(err_msg);
2558  }
2559  lphosts[i].numhosts = numhosts; // currently must be 2 or 3
2560  next_index += numhosts + 1; // add 1 to account for LP index
2561  if (numhosts == 2) {
2562  lphosts[i].distance = value1;
2563  lphosts[i].angle = value2;
2564  lphosts[i].dihedral = 0.0; // ignore value3
2565  }
2566  else { // numhosts == 3
2567  lphosts[i].distance = value1;
2568  lphosts[i].angle = value2 * (M_PI/180); // convert to radians
2569  lphosts[i].dihedral = value3 * (M_PI/180); // convert to radians
2570  }
2571  }
2572  // Resize bonds to accommodate the lonepairs.
2573  Bond *newbonds = new Bond[numBonds+numLphosts];
2574  memcpy(newbonds, bonds, numBonds*sizeof(Bond));
2575  delete [] bonds;
2576  bonds = newbonds;
2577  for (i = 0; i < numLphosts; i++) {
2578  // Subtract 1 to get 0-based atom index
2579  lphosts[i].atom1 = NAMD_read_int(fd, "LPHOSTS")-1;
2580  lphosts[i].atom2 = NAMD_read_int(fd, "LPHOSTS")-1;
2581  lphosts[i].atom3 = NAMD_read_int(fd, "LPHOSTS")-1;
2582  // For numhosts==2, set unused atom4 to atom1
2583  lphosts[i].atom4 = ( lphosts[i].numhosts == 3 ?
2584  NAMD_read_int(fd, "LPHOSTS")-1 : lphosts[i].atom1 );
2585  // Add dummy bond entry for connectivity.
2586  Bond *b = &(bonds[numBonds++]);
2587  b->atom1 = lphosts[i].atom1;
2588  b->atom2 = lphosts[i].atom2;
2589  b->bond_type = -1; // dummy index, never used
2590  }
2591 }
2592 /* END OF FUNCTION read_lphosts */
2593 
2594 /************************************************************************/
2595 /* */
2596 /* FUNCTION read_anisos */
2597 /* */
2598 /* INPUTS: */
2599 /* fd - file pointer to the .psf file */
2600 /* */
2601 /* this function reads in the anisotropic terms section of .psf file. */
2602 /* */
2603 void Molecule::read_anisos(FILE *fd)
2604 {
2605  char buffer[512]; // Buffer for reading from file
2606  int numhosts, index, i, read_count;
2607  Real k11, k22, k33;
2608 
2609  anisos = new Aniso[numAnisos];
2610  if (anisos == NULL)
2611  {
2612  NAMD_die("memory allocation failed in Molecule::read_anisos");
2613  }
2614  for (i = 0; i < numAnisos; i++)
2615  {
2616  NAMD_read_line(fd, buffer);
2617  if ( (NAMD_blank_string(buffer)) || (buffer[0] == '!') ) continue;
2618  read_count=sscanf(buffer, "%f %f %f", &k11, &k22, &k33);
2619  if (read_count != 3)
2620  {
2621  char err_msg[128];
2622  sprintf(err_msg, "BAD FORMAT FOR ANISO LINE %d IN PSF FILE LINE\n"
2623  "LINE=%s\n", i+1, buffer);
2624  NAMD_die(err_msg);
2625  }
2626  anisos[i].k11 = k11;
2627  anisos[i].k22 = k22;
2628  anisos[i].k33 = k33;
2629  }
2630  for (i = 0; i < numAnisos; i++) {
2631  anisos[i].atom1 = NAMD_read_int(fd, "ANISOS")-1;
2632  anisos[i].atom2 = NAMD_read_int(fd, "ANISOS")-1;
2633  anisos[i].atom3 = NAMD_read_int(fd, "ANISOS")-1;
2634  anisos[i].atom4 = NAMD_read_int(fd, "ANISOS")-1;
2635  }
2636 }
2637 /* END OF FUNCTION read_anisos */
2638 
2639 //LCPO
2640 inline int getLCPOTypeAmber(char atomType[11], int numBonds) {
2641 
2642  //Hydrogen
2643  if (atomType[0] == 'H' || atomType[0] == 'h') {
2644  return 0;
2645 
2646  //Carbon
2647  } else if (atomType[0] == 'C' || atomType[0] == 'c') {
2648  if (//Sp3 Carbon
2649  //atomType[1] == 'T')// ||
2650  strcmp(atomType, "CT" )==0 )
2651  //strcmp(atomType, "CP1" )==0 ||
2652  //strcmp(atomType, "CP2" )==0 ||
2653  //strcmp(atomType, "CP3" )==0 ||
2654  //strcmp(atomType, "CS" )==0 )
2655  {
2656  if (numBonds == 1)
2657  return 1;
2658  else if (numBonds == 2)
2659  return 2;
2660  else if (numBonds == 3)
2661  return 3;
2662  else if (numBonds == 4)
2663  return 4;
2664  else
2665  return 1;
2666 
2667  } else {//Sp2 or other
2668  if (numBonds == 2)
2669  return 5;
2670  else if (numBonds == 3)
2671  return 6;
2672  else
2673  return 1;
2674  }
2675 
2676  //Nitrogen
2677  } else if (atomType[0] == 'N' || atomType[0] == 'n') {
2678  if ( strcmp(atomType, "N3" ) == 0 ) { //Sp3 Nitrogen
2679  if (numBonds == 1)
2680  return 11;
2681  else if (numBonds == 2)
2682  return 12;
2683  else if (numBonds == 3)
2684  return 13;
2685  else
2686  return 11;
2687 
2688  } else {//SP2 Nitrogen
2689  if (numBonds == 1)
2690  return 14;
2691  else if (numBonds == 2)
2692  return 15;
2693  else if (numBonds == 3)
2694  return 16;
2695  else
2696  return 11;
2697  }
2698 
2699  //Oxygen
2700  } else if (atomType[0] == 'O' || atomType[0] == 'o') {
2701 
2702  if ( strcmp(atomType, "O" )==0) {//Sp2 Oxygen
2703  return 9;
2704  } else if (strcmp(atomType, "O2" )==0) {//Carboxylate Oxygen
2705  return 10;
2706  } else { // Sp3 Oxygen
2707  if (numBonds == 1)
2708  return 7;
2709  else if (numBonds == 2)
2710  return 8;
2711  else
2712  return 7;
2713  }
2714 
2715  //Sulfur
2716  } else if (atomType[0] == 'S' || atomType[0] == 's') {
2717  if ( strcmp(atomType, "SH" )==0) { //Sulfur 1 neighbor
2718  return 17;
2719  } else {
2720  return 18;
2721  }
2722 
2723  //Phosphorus
2724  } else if (atomType[0] == 'P' || atomType[0] == 'p') {
2725  if (numBonds == 3)
2726  return 19;
2727  else if (numBonds == 4)
2728  return 20;
2729  else
2730  return 19;
2731  } else if (atomType[0] == 'Z') { // ? just to agree with Amber mdread.f
2732  return 0;
2733  } else if ( strcmp(atomType, "MG" )==0) { //Mg
2734  return 22;
2735  } else { // unknown atom type
2736  return 5;
2737  }
2738  return 5;
2739 } // getLCPOTypeAmber
2740 
2741 inline int getLCPOTypeCharmm(char atomType[11], int numBonds) {
2742 
2743  //Hydrogen
2744  if (atomType[0] == 'H') {
2745  return 0;
2746 
2747  //Carbon
2748  } else if (atomType[0] == 'C') {
2749  if (//Sp3 Carbon
2750  atomType[1] == 'T' ||
2751  strcmp(atomType, "CP1" )==0 ||
2752  strcmp(atomType, "CP2" )==0 ||
2753  strcmp(atomType, "CP3" )==0 ||
2754  strcmp(atomType, "CS" )==0 ) {
2755  if (numBonds == 1)
2756  return 1;
2757  else if (numBonds == 2)
2758  return 2;
2759  else if (numBonds == 3)
2760  return 3;
2761  else if (numBonds == 4)
2762  return 4;
2763  else
2764  return 1;
2765 
2766  } else if (//Sp2
2767  strcmp(atomType, "C" )==0 ||
2768  strcmp(atomType, "CA" )==0 ||
2769  strcmp(atomType, "CC" )==0 ||
2770  strcmp(atomType, "CD" )==0 ||
2771  strcmp(atomType, "CN" )==0 ||
2772  strcmp(atomType, "CY" )==0 ||
2773  strcmp(atomType, "C3" )==0 ||
2774  strcmp(atomType, "CE1" )==0 ||
2775  strcmp(atomType, "CE2" )==0 ||
2776  strcmp(atomType, "CST" )==0 ||
2777  strcmp(atomType, "CAP" )==0 ||
2778  strcmp(atomType, "COA" )==0 ||
2779  strcmp(atomType, "CPT" )==0 ||
2780  strcmp(atomType, "CPH1")==0 ||
2781  strcmp(atomType, "CPH2")==0
2782  ) {
2783  if (numBonds == 2)
2784  return 5;
2785  else if (numBonds == 3)
2786  return 6;
2787  else
2788  return 1;
2789  } else { // other Carbon
2790  return 1;
2791  }
2792 
2793  //Nitrogen
2794  } else if (atomType[0] == 'N') {
2795  if (//Sp3 Nitrogen
2796  //strcmp(atomType, "N" )==0 ||
2797  //strcmp(atomType, "NH1" )==0 ||
2798  //strcmp(atomType, "NH2" )==0 ||
2799  strcmp(atomType, "NH3" )==0 ||
2800  //strcmp(atomType, "NC2" )==0 ||
2801  //strcmp(atomType, "NY" )==0 ||
2802  strcmp(atomType, "NP" )==0
2803  ) {
2804  if (numBonds == 1)
2805  return 11;
2806  else if (numBonds == 2)
2807  return 12;
2808  else if (numBonds == 3)
2809  return 13;
2810  else
2811  return 11;
2812 
2813  } else if (//SP2 Nitrogen
2814  strcmp(atomType, "NY" )==0 || //
2815  strcmp(atomType, "NC2" )==0 || //
2816  strcmp(atomType, "N" )==0 || //
2817  strcmp(atomType, "NH1" )==0 || //
2818  strcmp(atomType, "NH2" )==0 || //
2819  strcmp(atomType, "NR1" )==0 ||
2820  strcmp(atomType, "NR2" )==0 ||
2821  strcmp(atomType, "NR3" )==0 ||
2822  strcmp(atomType, "NPH" )==0 ||
2823  strcmp(atomType, "NC" )==0
2824  ) {
2825  if (numBonds == 1)
2826  return 14;
2827  else if (numBonds == 2)
2828  return 15;
2829  else if (numBonds == 3)
2830  return 16;
2831  else
2832  return 11;
2833  } else { // other Nitrogen
2834  return 11;
2835  }
2836 
2837  //Oxygen
2838  } else if (atomType[0] == 'O') {
2839  if (//Sp3 Oxygen
2840  strcmp(atomType, "OH1" )==0 ||
2841  strcmp(atomType, "OS" )==0 ||
2842  strcmp(atomType, "OC" )==0 || //
2843  strcmp(atomType, "OT" )==0
2844  ) {
2845  if (numBonds == 1)
2846  return 7;
2847  else if (numBonds == 2)
2848  return 8;
2849  else
2850  return 7;
2851  } else if ( // Sp2 Oxygen
2852  strcmp(atomType, "O" )==0 ||
2853  strcmp(atomType, "OB" )==0 ||
2854  strcmp(atomType, "OST" )==0 ||
2855  strcmp(atomType, "OCA" )==0 ||
2856  strcmp(atomType, "OM" )==0
2857  ) {
2858  return 9;
2859  } else if ( // SP1 Oxygen
2860  strcmp(atomType, "OC" )==0
2861  ) {
2862  return 10;
2863  } else { // other Oxygen
2864  return 7;
2865  }
2866 
2867  //Sulfur
2868  } else if (atomType[0] == 'S') {
2869  if (numBonds == 1)
2870  return 17;
2871  else
2872  return 18;
2873 
2874  //Phosphorus
2875  } else if (atomType[0] == 'P') {
2876  if (numBonds == 3)
2877  return 19;
2878  else if (numBonds == 4)
2879  return 20;
2880  else
2881  return 19;
2882  } else { // unknown atom type
2883  return 5;
2884  }
2885  return 5;
2886 } // getLCPOTypeCharmm
2887 
2888 //input type is Charmm/Amber/other
2889 //0 - Charmm/Xplor
2890 //1 - Amber
2891 //2 - Plugin
2892 //3 - Gromacs
2893 void Molecule::assignLCPOTypes(int inputType) {
2894  int *heavyBonds = new int[numAtoms];
2895  for (int i = 0; i < numAtoms; i++)
2896  heavyBonds[i] = 0;
2897  for (int i = 0; i < numBonds; i++ ) {
2898  Bond curBond = bonds[i];
2899  int a1 = bonds[i].atom1;
2900  int a2 = bonds[i].atom2;
2901  if (atoms[a1].mass > 2.f && atoms[a2].mass > 2.f) {
2902  heavyBonds[a1]++;
2903  heavyBonds[a2]++;
2904  }
2905  }
2906 
2907  lcpoParamType = new int[numAtoms];
2908 
2909  int warning = 0;
2910  for (int i = 0; i < numAtoms; i++) {
2911  //print vdw_type and numbonds
2912 
2913  if (inputType == 1) { // Amber
2914  lcpoParamType[i] = getLCPOTypeAmber(atomNames[i].atomtype, heavyBonds[i]);
2915  } else { // Charmm
2916  lcpoParamType[i] = getLCPOTypeCharmm(atomNames[i].atomtype, heavyBonds[i]);
2917  }
2918 /*
2919  CkPrintf("%d MOL: ATOM[%05d] = { %4s %d } : %d\n",
2920  inputType,
2921  i+1,
2922  atomNames[i].atomtype,
2923  heavyBonds[i],
2924  lcpoParamType[i]
2925  );
2926 */
2927  if ( atoms[i].mass < 1.5 && lcpoParamType[i] != 0 ) {
2928  if (atoms[i].status & LonepairAtom) {
2929  warning |= LonepairAtom;
2930  lcpoParamType[i] = 0; // reset LCPO type for LP
2931  }
2932  else if (atoms[i].status & DrudeAtom) {
2933  warning |= DrudeAtom;
2934  lcpoParamType[i] = 0; // reset LCPO type for Drude
2935  }
2936  else {
2937  CkPrintf("ERROR in Molecule::assignLCPOTypes(): "
2938  "Light atom given heavy atom LCPO type.\n");
2939  }
2940  }
2941 
2942  //CkPrintf("VDW_TYPE %02d %4s\n", atoms[i].vdw_type, atomNames[i].atomtype);
2943  } // for atoms
2944 
2945  if (warning & LonepairAtom) {
2946  iout << iWARN << "LONE PAIRS TO BE IGNORED BY SASA\n" << endi;
2947  }
2948  if (warning & DrudeAtom) {
2949  iout << iWARN << "DRUDE PARTICLES TO BE IGNORED BY SASA\n" << endi;
2950  }
2951 
2952  delete [] heavyBonds;
2953 
2954 } // buildLCPOTable
2955 
2956 void Molecule::plgLoadAtomBasics(molfile_atom_t *atomarray){
2957  atoms = new Atom[numAtoms];
2958  atomNames = new AtomNameInfo[numAtoms];
2959  if(simParams->genCompressedPsf) {
2960  atomSegResids = new AtomSegResInfo[numAtoms];
2961  }
2962  hydrogenGroup.resize(0);
2963 
2964  ResidueLookupElem *tmpResLookup = resLookup;
2965 
2966  for(int i=0; i<numAtoms; i++) {
2967  int reslength = strlen(atomarray[i].resname)+1;
2968  int namelength = strlen(atomarray[i].name)+1;
2969  int typelength = strlen(atomarray[i].type)+1;
2970  atomNames[i].resname = nameArena->getNewArray(reslength);
2971  atomNames[i].atomname = nameArena->getNewArray(namelength);
2972  atomNames[i].atomtype = nameArena->getNewArray(typelength);
2973  strcpy(atomNames[i].resname, atomarray[i].resname);
2974  strcpy(atomNames[i].atomname, atomarray[i].name);
2975  strcpy(atomNames[i].atomtype, atomarray[i].type);
2976 
2977  atoms[i].mass = atomarray[i].mass;
2978  atoms[i].charge = atomarray[i].charge;
2979  atoms[i].status = UnknownAtom;
2980 
2981  //add this atom to residue lookup table
2982  if(tmpResLookup) {
2983  tmpResLookup = tmpResLookup->append(atomarray[i].segid, atomarray[i].resid, i);
2984  }
2985 
2986  if(atomSegResids) { //for compressing molecule information
2987  AtomSegResInfo *one = atomSegResids + i;
2988  memcpy(one->segname, atomarray[i].segid, strlen(atomarray[i].segid)+1);
2989  one->resid = atomarray[i].resid;
2990  }
2991  //Determine the type of the atom
2992  if ( simParams->ignoreMass ) {
2993  }else if(atoms[i].mass <= 0.05) {
2994  atoms[i].status |= LonepairAtom;
2995  }else if(atoms[i].mass < 1.0) {
2996  atoms[i].status |= DrudeAtom;
2997  }else if(atoms[i].mass <= 3.5) {
2998  atoms[i].status |= HydrogenAtom;
2999  }else if((atomNames[i].atomname[0] == 'O') &&
3000  (atoms[i].mass>=14.0) && (atoms[i].mass<=18.0)){
3001  atoms[i].status |= OxygenAtom;
3002  }
3003  //Look up the vdw constants for this atom
3004  params->assign_vdw_index(atomNames[i].atomtype, &atoms[i]);
3005  }
3006 }
3007 
3008 void Molecule::plgLoadBonds(int *from, int *to){
3009  bonds = new Bond[numBonds];
3010  int realNumBonds = 0;
3011  for(int i=0; i<numBonds; i++) {
3012  Bond *thisBond = bonds+realNumBonds;
3013  thisBond->atom1 = from[i]-1;
3014  thisBond->atom2 = to[i]-1;
3015 
3016  params->assign_bond_index(
3017  atomNames[thisBond->atom1].atomtype,
3018  atomNames[thisBond->atom2].atomtype,
3019  thisBond);
3020 
3021  //Make sure this isn't a fake bond meant for shake in x-plor
3022  Real k, x0;
3023  params->get_bond_params(&k, &x0, thisBond->bond_type);
3024  if (is_lonepairs_psf) {
3025  //need to retain Lonepair bonds for Drude
3026  if(k!=0. || is_lp(thisBond->atom1) ||
3027  is_lp(thisBond->atom2)) {
3028  realNumBonds++;
3029  }
3030  }else{
3031  if(k != 0.) realNumBonds++;
3032  }
3033  }
3034 
3035  if(numBonds != realNumBonds) {
3036  iout << iWARN << "Ignored" << numBonds-realNumBonds <<
3037  "bonds with zero force constants.\n" <<endi;
3038  iout << iWARN << "Will get H-H distance in rigid H20 from H-O-H angle.\n" <<endi;
3039  }
3040  numBonds = realNumBonds;
3041 }
3042 
3043 void Molecule::plgLoadAngles(int *plgAngles)
3044 {
3045  angles=new Angle[numAngles];
3046  int *atomid = plgAngles;
3047  int numRealAngles = 0;
3048  for(int i=0; i<numAngles; i++) {
3049  Angle *thisAngle = angles+numRealAngles;
3050  thisAngle->atom1 = atomid[0]-1;
3051  thisAngle->atom2 = atomid[1]-1;
3052  thisAngle->atom3 = atomid[2]-1;
3053  atomid += 3;
3054 
3055  params->assign_angle_index(
3056  atomNames[thisAngle->atom1].atomtype,
3057  atomNames[thisAngle->atom2].atomtype,
3058  atomNames[thisAngle->atom3].atomtype,
3059  thisAngle, simParams->alchOn ? -1 : 0);
3060  if ( thisAngle->angle_type == -1 ) {
3061  iout << iWARN << "ALCHEMY MODULE WILL REMOVE ANGLE OR RAISE ERROR\n"
3062  << endi;
3063  }
3064 
3065  Real k, t0, k_ub, r_ub;
3066  if ( thisAngle->angle_type == -1 ) { k = -1.; k_ub = -1.; } else
3067  params->get_angle_params(&k, &t0, &k_ub, &r_ub, thisAngle->angle_type);
3068  if(k!=0. || k_ub!=0.) numRealAngles++;
3069  }
3070 
3071  if(numAngles != numRealAngles) {
3072  iout << iWARN << "Ignored" << numAngles-numRealAngles <<
3073  " angles with zero force constants.\n" << endi;
3074  }
3075  numAngles = numRealAngles;
3076 }
3077 
3078 void Molecule::plgLoadDihedrals(int *plgDihedrals)
3079 {
3080  std::map< std::string, int > cache;
3081 
3082  int lastAtomIds[4];
3083  int multiplicity = 1; //multiplicity of the current bond
3084 
3085  lastAtomIds[0]=lastAtomIds[1]=lastAtomIds[2]=lastAtomIds[3]=-1;
3086  dihedrals = new Dihedral[numDihedrals];
3087  int numRealDihedrals = 0;
3088  int *atomid = plgDihedrals;
3089  for(int i=0; i<numDihedrals; i++, atomid+=4) {
3090  Dihedral *thisDihedral = dihedrals + numRealDihedrals;
3091  Bool duplicate_bond = TRUE;
3092  for(int j=0; j<4; j++) {
3093  if(atomid[j] != lastAtomIds[j]) {
3094  duplicate_bond = FALSE;
3095  }
3096  lastAtomIds[j] = atomid[j];
3097  }
3098 
3099  if(duplicate_bond) {
3100  multiplicity++;
3101  if(multiplicity==2) {
3102  numMultipleDihedrals++;
3103  }
3104  }else{
3105  multiplicity=1;
3106  numRealDihedrals++;
3107  }
3108 
3109  thisDihedral->atom1 = atomid[0]-1;
3110  thisDihedral->atom2 = atomid[1]-1;
3111  thisDihedral->atom3 = atomid[2]-1;
3112  thisDihedral->atom4 = atomid[3]-1;
3113 
3114  char query[128];
3115  sprintf(query,"%10s :: %10s :: %10s :: %10s :: %d",
3116  atomNames[atomid[0]-1].atomtype,
3117  atomNames[atomid[1]-1].atomtype,
3118  atomNames[atomid[2]-1].atomtype,
3119  atomNames[atomid[3]-1].atomtype,
3120  multiplicity);
3121  auto search = cache.find(query);
3122  if ( search != cache.end() ) {
3123  thisDihedral->dihedral_type = search->second;
3124  } else {
3125  params->assign_dihedral_index(
3126  atomNames[atomid[0]-1].atomtype,
3127  atomNames[atomid[1]-1].atomtype,
3128  atomNames[atomid[2]-1].atomtype,
3129  atomNames[atomid[3]-1].atomtype,
3130  thisDihedral, multiplicity, simParams->alchOn ? -1 : 0);
3131  if ( thisDihedral->dihedral_type == -1 ) {
3132  iout << iWARN << "ALCHEMY MODULE WILL REMOVE DIHEDRAL OR RAISE ERROR\n"
3133  << endi;
3134  }
3135  cache[query] = thisDihedral->dihedral_type;
3136  }
3137  }
3138 
3139  numDihedrals = numRealDihedrals;
3140 }
3141 
3142 void Molecule::plgLoadImpropers(int *plgImpropers)
3143 {
3144  int lastAtomIds[4];
3145  int multiplicity = 1; //multiplicity of the current bond
3146 
3147  lastAtomIds[0]=lastAtomIds[1]=lastAtomIds[2]=lastAtomIds[3]=-1;
3148  impropers = new Improper[numImpropers];
3149  int numRealImpropers = 0;
3150  int *atomid = plgImpropers;
3151  for(int i=0; i<numImpropers; i++, atomid+=4) {
3152  Improper *thisImproper = impropers + numRealImpropers;
3153  Bool duplicate_bond = TRUE;
3154  for(int j=0; j<4; j++) {
3155  if(atomid[j] != lastAtomIds[j]) {
3156  duplicate_bond = FALSE;
3157  }
3158  lastAtomIds[j] = atomid[j];
3159  }
3160 
3161  if(duplicate_bond) {
3162  multiplicity++;
3163  if(multiplicity==2) {
3164  numMultipleImpropers++;
3165  }
3166  }else{
3167  multiplicity=1;
3168  numRealImpropers++;
3169  }
3170 
3171  thisImproper->atom1 = atomid[0]-1;
3172  thisImproper->atom2 = atomid[1]-1;
3173  thisImproper->atom3 = atomid[2]-1;
3174  thisImproper->atom4 = atomid[3]-1;
3175 
3176  params->assign_improper_index(
3177  atomNames[atomid[0]-1].atomtype,
3178  atomNames[atomid[1]-1].atomtype,
3179  atomNames[atomid[2]-1].atomtype,
3180  atomNames[atomid[3]-1].atomtype,
3181  thisImproper, multiplicity);
3182  }
3183 
3184  numImpropers = numRealImpropers;
3185 }
3186 
3187 void Molecule::plgLoadCrossterms(int *plgCterms)
3188 {
3189  int lastAtomIds[8];
3190 
3191  for(int i=0; i<8; i++)
3192  lastAtomIds[i]=-1;
3193 
3194  crossterms = new Crossterm[numCrossterms];
3195  int numRealCrossterms = 0;
3196  int *atomid = plgCterms;
3197  for(int i=0; i<numCrossterms; i++, atomid+=8) {
3198  Crossterm *thisCrossterm = crossterms + numRealCrossterms;
3199  Bool duplicate_bond = TRUE;
3200  for(int j=0; j<8; j++) {
3201  if(atomid[j] != lastAtomIds[j]) {
3202  duplicate_bond = FALSE;
3203  }
3204  lastAtomIds[j] = atomid[j];
3205  }
3206 
3207  if(duplicate_bond) {
3208  iout << iWARN <<"Duplicate cross-term detected.\n" << endi;
3209  } else
3210  numRealCrossterms++;
3211 
3212  thisCrossterm->atom1 = atomid[0]-1;
3213  thisCrossterm->atom2 = atomid[1]-1;
3214  thisCrossterm->atom3 = atomid[2]-1;
3215  thisCrossterm->atom4 = atomid[3]-1;
3216  thisCrossterm->atom5 = atomid[4]-1;
3217  thisCrossterm->atom6 = atomid[5]-1;
3218  thisCrossterm->atom7 = atomid[6]-1;
3219  thisCrossterm->atom8 = atomid[7]-1;
3220 
3221  params->assign_crossterm_index(
3222  atomNames[atomid[0]-1].atomtype,
3223  atomNames[atomid[1]-1].atomtype,
3224  atomNames[atomid[2]-1].atomtype,
3225  atomNames[atomid[3]-1].atomtype,
3226  atomNames[atomid[4]-1].atomtype,
3227  atomNames[atomid[5]-1].atomtype,
3228  atomNames[atomid[6]-1].atomtype,
3229  atomNames[atomid[7]-1].atomtype,
3230  thisCrossterm);
3231  }
3232 
3233  numCrossterms = numRealCrossterms;
3234 }
3235 
3236 void Molecule::setOccupancyData(molfile_atom_t *atomarray){
3237  occupancy = new float[numAtoms];
3238  for(int i=0; i<numAtoms; i++) {
3239  occupancy[i] = atomarray[i].occupancy;
3240  }
3241 }
3242 
3243 void Molecule::setBFactorData(molfile_atom_t *atomarray){
3244  bfactor = new float[numAtoms];
3245  for(int i=0; i<numAtoms; i++) {
3246  bfactor[i] = atomarray[i].bfactor;
3247  }
3248 }
3249 
3250  /************************************************************************/
3251  /* */
3252  /* FUNCTION build_lists_by_atom */
3253  /* */
3254  /* This function builds O(NumAtoms) arrays that store the bonds, */
3255  /* angles, dihedrals, and impropers, that each atom is involved in. */
3256  /* This is a space hog, but VERY fast. This will certainly have to */
3257  /* change to make things scalable in memory, but for now, speed is the */
3258  /* thing! */
3259  /* */
3260  /************************************************************************/
3261  void Molecule::build_lists_by_atom()
3262  {
3263  register int i; // Loop counter
3264 
3265  register int numFixedAtoms = this->numFixedAtoms;
3266  // if we want forces on fixed atoms then just pretend
3267  // there are none for the purposes of this routine;
3268  if ( simParams->fixedAtomsForces ) numFixedAtoms = 0;
3269 
3270 //fepb
3271 // int numFepInitial = this->numFepInitial;
3272 // int numFepFinal = this->numFepFinal;
3273 //fepe
3274  tmpArena = new ObjectArena<int32>;
3275  bondsWithAtom = new int32 *[numAtoms];
3276  cluster = new int32 [numAtoms];
3277  clusterSize = new int32 [numAtoms];
3278 
3279  bondsByAtom = new int32 *[numAtoms];
3280  anglesByAtom = new int32 *[numAtoms];
3281  dihedralsByAtom = new int32 *[numAtoms];
3282  impropersByAtom = new int32 *[numAtoms];
3283  crosstermsByAtom = new int32 *[numAtoms];
3284 
3285  exclusionsByAtom = new int32 *[numAtoms];
3286  fullExclusionsByAtom = new int32 *[numAtoms];
3287  modExclusionsByAtom = new int32 *[numAtoms];
3288 
3289  // JLai
3290  gromacsPairByAtom = new int32 *[numAtoms];
3291  // End of JLai
3292 
3293  int32 *byAtomSize = new int32[numAtoms];
3294 
3295  const int pair_self =
3296  simParams->pairInteractionOn ? simParams->pairInteractionSelf : 0;
3297 
3298  DebugM(3,"Building bond lists.\n");
3299 
3300  // Build the bond lists
3301  for (i=0; i<numAtoms; i++)
3302  {
3303  byAtomSize[i] = 0;
3304  }
3305  for (i=0; i<numRealBonds; i++)
3306  {
3307  byAtomSize[bonds[i].atom1]++;
3308  byAtomSize[bonds[i].atom2]++;
3309  }
3310  for (i=0; i<numAtoms; i++)
3311  {
3312  bondsWithAtom[i] = tmpArena->getNewArray(byAtomSize[i]+1);
3313  bondsWithAtom[i][byAtomSize[i]] = -1;
3314  byAtomSize[i] = 0;
3315  }
3316  for (i=0; i<numRealBonds; i++)
3317  {
3318  int a1 = bonds[i].atom1;
3319  int a2 = bonds[i].atom2;
3320  bondsWithAtom[a1][byAtomSize[a1]++] = i;
3321  bondsWithAtom[a2][byAtomSize[a2]++] = i;
3322  }
3323 
3324 
3325  // Updates all bond, angle, dihedral, improper and crossterm
3326  // to reflect the QM region (which can't have any of there terms)
3327  if (simParams->qmForcesOn) {
3328 
3329  DebugM(3,"Calculating exclusions for QM simulation.\n");
3330  build_exclusions();
3331 
3332  delete_qm_bonded() ;
3333 
3334  DebugM(3,"Re-Building bond lists.\n");
3335 
3336  // We re-calculate the bondsWithAtom list for cluster
3337  // info calculation below.
3338  for (i=0; i<numAtoms; i++)
3339  {
3340  byAtomSize[i] = 0;
3341  }
3342  for (i=0; i<numRealBonds; i++)
3343  {
3344  byAtomSize[bonds[i].atom1]++;
3345  byAtomSize[bonds[i].atom2]++;
3346  }
3347  for (i=0; i<numAtoms; i++)
3348  {
3349  bondsWithAtom[i][byAtomSize[i]] = -1;
3350  byAtomSize[i] = 0;
3351  }
3352  for (i=0; i<numRealBonds; i++)
3353  {
3354  int a1 = bonds[i].atom1;
3355  int a2 = bonds[i].atom2;
3356  bondsWithAtom[a1][byAtomSize[a1]++] = i;
3357  bondsWithAtom[a2][byAtomSize[a2]++] = i;
3358  }
3359  }
3360 
3361  // Build cluster information (contiguous clusters)
3362  for (i=0; i<numAtoms; i++) {
3363  cluster[i] = i;
3364  }
3365  for (i=0; i<numAtoms; i++) {
3366  int ci = i;
3367  while ( cluster[ci] != ci ) ci = cluster[ci];
3368  for ( int32 *b = bondsWithAtom[i]; *b != -1; ++b ) {
3369  int a = bonds[*b].atom1;
3370  if ( a == i ) a = bonds[*b].atom2;
3371  if ( a > i ) {
3372  int ca = a;
3373  while ( cluster[ca] != ca ) ca = cluster[ca];
3374  if ( ca > ci ) cluster[ca] = cluster[ci];
3375  else cluster[ci] = cluster[ca];
3376  }
3377  }
3378  }
3379  while ( 1 ) {
3380  int allok = 1;
3381  for (i=0; i<numAtoms; i++) {
3382  int ci = cluster[i];
3383  if ( cluster[ci] != ci ) {
3384  allok = 0;
3385  cluster[i] = cluster[ci];
3386  }
3387  }
3388  if ( allok ) break;
3389  }
3390 
3391  for (i=0; i<numAtoms; i++) {
3392  clusterSize[i] = 0;
3393  }
3394  for (i=0; i<numAtoms; i++) {
3395  clusterSize[cluster[i]] += 1;
3396  }
3397 
3398 /*
3399  //Getting number of clusters for debugging
3400  int numClusters=0;
3401  for(int i=0; i<numAtoms; i++){
3402  if(clusterSize[i]!=0) numClusters++;
3403  }
3404  printf("Num of clusters: %d\n", numClusters);
3405 */
3406 
3407  // Build the bond lists
3408  for (i=0; i<numAtoms; i++)
3409  {
3410  byAtomSize[i] = 0;
3411  }
3412  numCalcBonds = 0;
3413  for (i=0; i<numBonds; i++)
3414  {
3415  if ( numFixedAtoms && fixedAtomFlags[bonds[i].atom1]
3416  && fixedAtomFlags[bonds[i].atom2] ) continue;
3417 
3418  if ( pair_self && fepAtomFlags[bonds[i].atom1] != 1) continue;
3419  byAtomSize[bonds[i].atom1]++;
3420  numCalcBonds++;
3421  }
3422  for (i=0; i<numAtoms; i++)
3423  {
3424  bondsByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3425  bondsByAtom[i][byAtomSize[i]] = -1;
3426  byAtomSize[i] = 0;
3427  }
3428  for (i=0; i<numBonds; i++)
3429  {
3430  if ( numFixedAtoms && fixedAtomFlags[bonds[i].atom1]
3431  && fixedAtomFlags[bonds[i].atom2] ) continue;
3432  if ( pair_self && fepAtomFlags[bonds[i].atom1] != 1) continue;
3433  int a1 = bonds[i].atom1;
3434  bondsByAtom[a1][byAtomSize[a1]++] = i;
3435  }
3436  for (i=0; i<numBonds; ++i) {
3437  int a1 = bonds[i].atom1;
3438  int a2 = bonds[i].atom2;
3439  int j;
3440  if ( a1 == a2 ) {
3441  char buff[512];
3442  sprintf(buff,"Atom %d is bonded to itself", a1+1);
3443  NAMD_die(buff);
3444  }
3445  for ( j = 0; j < byAtomSize[a1]; ++j ) {
3446  int b = bondsByAtom[a1][j];
3447  int ba1 = bonds[b].atom1;
3448  int ba2 = bonds[b].atom2;
3449  if ( b != i && ( (ba1==a1 && ba2==a2) || (ba1==a2 && ba2==a1) ) ) {
3450  char buff[512];
3451  sprintf(buff,"Duplicate bond from atom %d to atom %d", a1+1, a2+1);
3452  NAMD_die(buff);
3453  }
3454  }
3455  for ( j = 0; j < byAtomSize[a2]; ++j ) {
3456  int b = bondsByAtom[a2][j];
3457  int ba1 = bonds[b].atom1;
3458  int ba2 = bonds[b].atom2;
3459  if ( b != i && ( (ba1==a1 && ba2==a2) || (ba1==a2 && ba2==a1) ) ) {
3460  char buff[512];
3461  sprintf(buff,"Duplicate bond from atom %d to atom %d", a1+1, a2+1);
3462  NAMD_die(buff);
3463  }
3464  }
3465  }
3466 
3467  DebugM(3,"Building angle lists.\n");
3468 
3469  // Build the angle lists
3470  for (i=0; i<numAtoms; i++)
3471  {
3472  byAtomSize[i] = 0;
3473  }
3474  numCalcAngles = 0;
3475  for (i=0; i<numAngles; i++)
3476  {
3477  if ( numFixedAtoms && fixedAtomFlags[angles[i].atom1]
3478  && fixedAtomFlags[angles[i].atom2]
3479  && fixedAtomFlags[angles[i].atom3] ) continue;
3480  if ( pair_self && fepAtomFlags[angles[i].atom1] != 1) continue;
3481  byAtomSize[angles[i].atom1]++;
3482  numCalcAngles++;
3483  }
3484  for (i=0; i<numAtoms; i++)
3485  {
3486  anglesByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3487  anglesByAtom[i][byAtomSize[i]] = -1;
3488  byAtomSize[i] = 0;
3489  }
3490  for (i=0; i<numAngles; i++)
3491  {
3492  if ( pair_self && fepAtomFlags[angles[i].atom1] != 1) continue;
3493  if ( numFixedAtoms && fixedAtomFlags[angles[i].atom1]
3494  && fixedAtomFlags[angles[i].atom2]
3495  && fixedAtomFlags[angles[i].atom3] ) continue;
3496  int a1 = angles[i].atom1;
3497  anglesByAtom[a1][byAtomSize[a1]++] = i;
3498  }
3499 
3500  DebugM(3,"Building improper lists.\n");
3501 
3502  // Build the improper lists
3503  for (i=0; i<numAtoms; i++)
3504  {
3505  byAtomSize[i] = 0;
3506  }
3507  numCalcImpropers = 0;
3508  for (i=0; i<numImpropers; i++)
3509  {
3510  if ( numFixedAtoms && fixedAtomFlags[impropers[i].atom1]
3511  && fixedAtomFlags[impropers[i].atom2]
3512  && fixedAtomFlags[impropers[i].atom3]
3513  && fixedAtomFlags[impropers[i].atom4] ) continue;
3514  if ( pair_self && fepAtomFlags[impropers[i].atom1] != 1) continue;
3515  byAtomSize[impropers[i].atom1]++;
3516  numCalcImpropers++;
3517  }
3518  for (i=0; i<numAtoms; i++)
3519  {
3520  impropersByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3521  impropersByAtom[i][byAtomSize[i]] = -1;
3522  byAtomSize[i] = 0;
3523  }
3524  for (i=0; i<numImpropers; i++)
3525  {
3526  if ( numFixedAtoms && fixedAtomFlags[impropers[i].atom1]
3527  && fixedAtomFlags[impropers[i].atom2]
3528  && fixedAtomFlags[impropers[i].atom3]
3529  && fixedAtomFlags[impropers[i].atom4] ) continue;
3530  if ( pair_self && fepAtomFlags[impropers[i].atom1] != 1) continue;
3531  int a1 = impropers[i].atom1;
3532  impropersByAtom[a1][byAtomSize[a1]++] = i;
3533  }
3534 
3535  DebugM(3,"Building dihedral lists.\n");
3536 
3537  // Build the dihedral lists
3538  for (i=0; i<numAtoms; i++)
3539  {
3540  byAtomSize[i] = 0;
3541  }
3542  numCalcDihedrals = 0;
3543  for (i=0; i<numDihedrals; i++)
3544  {
3545  if ( numFixedAtoms && fixedAtomFlags[dihedrals[i].atom1]
3546  && fixedAtomFlags[dihedrals[i].atom2]
3547  && fixedAtomFlags[dihedrals[i].atom3]
3548  && fixedAtomFlags[dihedrals[i].atom4] ) continue;
3549  if ( pair_self && fepAtomFlags[dihedrals[i].atom1] != 1) continue;
3550  byAtomSize[dihedrals[i].atom1]++;
3551  numCalcDihedrals++;
3552  }
3553  for (i=0; i<numAtoms; i++)
3554  {
3555  dihedralsByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3556  dihedralsByAtom[i][byAtomSize[i]] = -1;
3557  byAtomSize[i] = 0;
3558  }
3559  for (i=0; i<numDihedrals; i++)
3560  {
3561  if ( numFixedAtoms && fixedAtomFlags[dihedrals[i].atom1]
3562  && fixedAtomFlags[dihedrals[i].atom2]
3563  && fixedAtomFlags[dihedrals[i].atom3]
3564  && fixedAtomFlags[dihedrals[i].atom4] ) continue;
3565  if ( pair_self && fepAtomFlags[dihedrals[i].atom1] != 1) continue;
3566  int a1 = dihedrals[i].atom1;
3567  dihedralsByAtom[a1][byAtomSize[a1]++] = i;
3568  }
3569 
3570  DebugM(3,"Building crossterm lists.\n");
3571 
3572  // Build the crossterm lists
3573  for (i=0; i<numAtoms; i++)
3574  {
3575  byAtomSize[i] = 0;
3576  }
3577  numCalcCrossterms = 0;
3578  for (i=0; i<numCrossterms; i++)
3579  {
3580  if ( numFixedAtoms && fixedAtomFlags[crossterms[i].atom1]
3581  && fixedAtomFlags[crossterms[i].atom2]
3582  && fixedAtomFlags[crossterms[i].atom3]
3583  && fixedAtomFlags[crossterms[i].atom4]
3584  && fixedAtomFlags[crossterms[i].atom5]
3585  && fixedAtomFlags[crossterms[i].atom6]
3586  && fixedAtomFlags[crossterms[i].atom7]
3587  && fixedAtomFlags[crossterms[i].atom8] ) continue;
3588  if ( pair_self && fepAtomFlags[crossterms[i].atom1] != 1) continue;
3589  byAtomSize[crossterms[i].atom1]++;
3590  numCalcCrossterms++;
3591  }
3592  for (i=0; i<numAtoms; i++)
3593  {
3594  crosstermsByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3595  crosstermsByAtom[i][byAtomSize[i]] = -1;
3596  byAtomSize[i] = 0;
3597  }
3598  for (i=0; i<numCrossterms; i++)
3599  {
3600  if ( numFixedAtoms && fixedAtomFlags[crossterms[i].atom1]
3601  && fixedAtomFlags[crossterms[i].atom2]
3602  && fixedAtomFlags[crossterms[i].atom3]
3603  && fixedAtomFlags[crossterms[i].atom4]
3604  && fixedAtomFlags[crossterms[i].atom5]
3605  && fixedAtomFlags[crossterms[i].atom6]
3606  && fixedAtomFlags[crossterms[i].atom7]
3607  && fixedAtomFlags[crossterms[i].atom8] ) continue;
3608  if ( pair_self && fepAtomFlags[crossterms[i].atom1] != 1) continue;
3609  int a1 = crossterms[i].atom1;
3610  crosstermsByAtom[a1][byAtomSize[a1]++] = i;
3611  }
3612 
3613  // DRUDE: init lphostIndexes array
3614  if (is_lonepairs_psf) {
3615  // allocate lone pair host index array only if we need it!
3616  DebugM(3,"Initializing lone pair host index array.\n");
3617  lphostIndexes = new int32[numAtoms];
3618  for (i = 0; i < numAtoms; i++) {
3619  lphostIndexes[i] = -1;
3620  }
3621  for (i = 0; i < numLphosts; i++) {
3622  int32 index = lphosts[i].atom1;
3623  lphostIndexes[index] = i;
3624  }
3625  }
3626  // DRUDE
3627 
3628  // JLai
3629  DebugM(3,"Building gromacsPair lists.\n");
3630 
3631  // Build the gromacsPair lists
3632  for (i=0; i<numAtoms; i++)
3633  {
3634  byAtomSize[i] = 0;
3635  }
3636  numCalcLJPair = 0;
3637  for (i=0; i<numLJPair; i++)
3638  {
3639  if ( numFixedAtoms && fixedAtomFlags[gromacsPair[i].atom1]
3640  && fixedAtomFlags[gromacsPair[i].atom2] ) continue;
3641  if ( pair_self && fepAtomFlags[gromacsPair[i].atom1] != 1) continue;
3642  byAtomSize[gromacsPair[i].atom1]++;
3643  numCalcLJPair++;
3644  }
3645  for (i=0; i<numAtoms; i++)
3646  {
3647  gromacsPairByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3648  gromacsPairByAtom[i][byAtomSize[i]] = -1;
3649  byAtomSize[i] = 0;
3650  }
3651  for (i=0; i<numLJPair; i++)
3652  {
3653  if ( numFixedAtoms && fixedAtomFlags[gromacsPair[i].atom1]
3654  && fixedAtomFlags[gromacsPair[i].atom2] ) continue;
3655  if ( pair_self && fepAtomFlags[gromacsPair[i].atom1] != 1) continue;
3656  int a1 = gromacsPair[i].atom1;
3657  gromacsPairByAtom[a1][byAtomSize[a1]++] = i;
3658  }
3659 
3660  // End of JLai
3661 
3662  DebugM(3,"Building exclusion data.\n");
3663 
3664  // Build the arrays of exclusions for each atom
3665  if (! simParams->qmForcesOn)
3666  build_exclusions();
3667 
3668  // Remove temporary structures
3669  delete [] bondsWithAtom; bondsWithAtom = 0;
3670  delete tmpArena; tmpArena = 0;
3671 
3672  if (exclusions != NULL)
3673  delete [] exclusions;
3674 
3675  // 1-4 exclusions which are also fully excluded were eliminated by hash table
3676  numTotalExclusions = exclusionSet.size();
3677  if ( ! CkMyPe() ) {
3678  iout << iINFO << "ADDED " << (numTotalExclusions - numExclusions) << " IMPLICIT EXCLUSIONS\n" << endi;
3679  }
3680  exclusions = new Exclusion[numTotalExclusions];
3681  UniqueSetIter<Exclusion> exclIter(exclusionSet);
3682  for ( exclIter=exclIter.begin(),i=0; exclIter != exclIter.end(); exclIter++,i++ )
3683  {
3684  exclusions[i] = *exclIter;
3685  }
3686  // Free exclusionSet storage
3687  // exclusionSet.clear(1);
3688  exclusionSet.clear();
3689 
3690  DebugM(3,"Building exclusion lists.\n");
3691 
3692  for (i=0; i<numAtoms; i++)
3693  {
3694  byAtomSize[i] = 0;
3695  }
3696  numCalcExclusions = 0;
3697  numCalcFullExclusions = 0;
3698  for (i=0; i<numTotalExclusions; i++)
3699  {
3700  if ( numFixedAtoms && fixedAtomFlags[exclusions[i].atom1]
3701  && fixedAtomFlags[exclusions[i].atom2] ) continue;
3702  byAtomSize[exclusions[i].atom1]++;
3703  numCalcExclusions++;
3704  if ( ! exclusions[i].modified ) numCalcFullExclusions++;
3705  }
3706 
3707  for (i=0; i<numAtoms; i++)
3708  {
3709  exclusionsByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3710  exclusionsByAtom[i][byAtomSize[i]] = -1;
3711  byAtomSize[i] = 0;
3712  }
3713  for (i=0; i<numTotalExclusions; i++)
3714  {
3715  if ( numFixedAtoms && fixedAtomFlags[exclusions[i].atom1]
3716  && fixedAtomFlags[exclusions[i].atom2] ) continue;
3717  int a1 = exclusions[i].atom1;
3718  exclusionsByAtom[a1][byAtomSize[a1]++] = i;
3719  }
3720 
3721  int32 *byAtomSize2 = new int32[numAtoms];
3722 
3723  for (i=0; i<numAtoms; i++)
3724  {
3725  byAtomSize[i] = 0;
3726  byAtomSize2[i] = 0;
3727  }
3728 
3729  for (i=0; i<numTotalExclusions; i++)
3730  {
3731  if ( numFixedAtoms && fixedAtomFlags[exclusions[i].atom1]
3732  && fixedAtomFlags[exclusions[i].atom2] ) continue;
3733  if ( exclusions[i].modified ) {
3734  byAtomSize2[exclusions[i].atom1]++;
3735  byAtomSize2[exclusions[i].atom2]++;
3736  } else {
3737  byAtomSize[exclusions[i].atom1]++;
3738  byAtomSize[exclusions[i].atom2]++;
3739  }
3740  }
3741 
3742  for (i=0; i<numAtoms; i++)
3743  {
3744  fullExclusionsByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3745  fullExclusionsByAtom[i][0] = 0;
3746  modExclusionsByAtom[i] = arena->getNewArray(byAtomSize2[i]+1);
3747  modExclusionsByAtom[i][0] = 0;
3748  }
3749 
3750  for (i=0; i<numTotalExclusions; i++)
3751  {
3752  int a1 = exclusions[i].atom1;
3753  int a2 = exclusions[i].atom2;
3754  if ( numFixedAtoms && fixedAtomFlags[a1]
3755  && fixedAtomFlags[a2] ) continue;
3756  int32 *l1, *l2;
3757  if ( exclusions[i].modified ) {
3758  l1 = modExclusionsByAtom[a1];
3759  l2 = modExclusionsByAtom[a2];
3760  } else {
3761  l1 = fullExclusionsByAtom[a1];
3762  l2 = fullExclusionsByAtom[a2];
3763  }
3764  l1[++(*l1)] = a2;
3765  l2[++(*l2)] = a1;
3766  }
3767 
3768  if ( ! CkMyPe() && simParams->printExclusions ) {
3769  for (i=0; i<numAtoms; i++) {
3770  int32 *lf = fullExclusionsByAtom[i];
3771  iout << "EXCL " << i << " FULL";
3772  int nf = *(lf++);
3773  for ( int j = 0; j < nf; ++j ) {
3774  iout << " " << *(lf++);
3775  }
3776  iout << "\n";
3777  int32 *lm = modExclusionsByAtom[i];
3778  iout << "EXCL " << i << " MOD";
3779  int nm = *(lm++);
3780  for ( int j = 0; j < nm; ++j ) {
3781  iout << " " << *(lm++);
3782  }
3783  iout << "\n" << endi;
3784  }
3785  }
3786 
3787  // DRUDE
3788  if (is_drude_psf || simParams->drudeOn) {
3789 
3790  // build Thole (screened Coulomb) correction terms;
3791  // they are constructed implicitly from exclusions
3792 
3793  // free the previous Thole array if already allocated
3794  if (tholes != NULL) delete[] tholes;
3795  numTholes = 0;
3796 
3797  // count the number of Thole terms
3798  for (i = 0; i < numTotalExclusions; i++) {
3799  /* skip over the modified exclusions */
3800  if (exclusions[i].modified) continue;
3801  int a1 = exclusions[i].atom1;
3802  int a2 = exclusions[i].atom2;
3803  if (a2 < numAtoms-1 && is_drude(a1+1) && is_drude(a2+1)) {
3804  numTholes++;
3805  }
3806  }
3807 
3808  // allocate space for Thole terms
3809  if (numTholes != 0) tholes = new Thole[numTholes];
3810  else tholes = NULL;
3811  int nt = 0;
3812 
3813  Real c = COULOMB*simParams->nonbondedScaling/simParams->dielectric;
3814 
3815  // store Thole terms
3816  for (i = 0; i < numTotalExclusions; i++) {
3817  /* skip over the modified exclusions */
3818  if (exclusions[i].modified) continue;
3819  int a1 = exclusions[i].atom1;
3820  int a2 = exclusions[i].atom2;
3821  // exclusions are stored with a1 < a2
3822  if (a2 < numAtoms-1 && is_drude(a1+1) && is_drude(a2+1)) {
3823  Real thsum = drudeConsts[a1].thole + drudeConsts[a2].thole;
3824  Real aprod = drudeConsts[a1].alpha * drudeConsts[a2].alpha;
3825  // guard against having alpha==0
3826  Real apower = (aprod <= 0 ? 0 : powf(aprod, -1.f/6));
3827  tholes[nt].atom1 = a1;
3828  tholes[nt].atom2 = a1+1;
3829  tholes[nt].atom3 = a2;
3830  tholes[nt].atom4 = a2+1;
3831  tholes[nt].aa = apower * thsum;
3832  tholes[nt].qq = c * atoms[a1+1].charge * atoms[a2+1].charge;
3833  nt++;
3834  }
3835  }
3836 
3837  // build Thole lists by atom
3838  DebugM(3, "Building Thole correction term lists.\n");
3839  tholesByAtom = new int32 *[numAtoms];
3840 
3841  for (i = 0; i < numAtoms; i++) {
3842  byAtomSize[i] = 0;
3843  }
3844  numCalcTholes = 0;
3845  for (i = 0; i < numTholes; i++) {
3846  if ( numFixedAtoms && fixedAtomFlags[tholes[i].atom1]
3847  && fixedAtomFlags[tholes[i].atom2]
3848  && fixedAtomFlags[tholes[i].atom3]
3849  && fixedAtomFlags[tholes[i].atom4] ) continue;
3850  if ( pair_self && fepAtomFlags[tholes[i].atom1] != 1) continue;
3851  byAtomSize[tholes[i].atom1]++;
3852  numCalcTholes++;
3853  }
3854  for (i = 0; i < numAtoms; i++) {
3855  tholesByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3856  tholesByAtom[i][byAtomSize[i]] = -1;
3857  byAtomSize[i] = 0;
3858  }
3859  for (i = 0; i < numTholes; i++) {
3860  if ( numFixedAtoms && fixedAtomFlags[tholes[i].atom1]
3861  && fixedAtomFlags[tholes[i].atom2]
3862  && fixedAtomFlags[tholes[i].atom3]
3863  && fixedAtomFlags[tholes[i].atom4] ) continue;
3864  if ( pair_self && fepAtomFlags[tholes[i].atom1] != 1) continue;
3865  int a1 = tholes[i].atom1;
3866  tholesByAtom[a1][byAtomSize[a1]++] = i;
3867  }
3868 
3869  // build anisotropic lists by atom
3870  DebugM(3, "Building anisotropic term lists.\n");
3871  anisosByAtom = new int32 *[numAtoms];
3872 
3873  for (i = 0; i < numAtoms; i++) {
3874  byAtomSize[i] = 0;
3875  }
3876  numCalcAnisos = 0;
3877  for (i = 0; i < numAnisos; i++) {
3878  if ( numFixedAtoms && fixedAtomFlags[anisos[i].atom1]
3879  && fixedAtomFlags[anisos[i].atom2]
3880  && fixedAtomFlags[anisos[i].atom3]
3881  && fixedAtomFlags[anisos[i].atom4] ) continue;
3882  if ( pair_self && fepAtomFlags[anisos[i].atom1] != 1) continue;
3883  byAtomSize[anisos[i].atom1]++;
3884  numCalcAnisos++;
3885  }
3886  for (i = 0; i < numAtoms; i++) {
3887  anisosByAtom[i] = arena->getNewArray(byAtomSize[i]+1);
3888  anisosByAtom[i][byAtomSize[i]] = -1;
3889  byAtomSize[i] = 0;
3890  }
3891  for (i = 0; i < numAnisos; i++) {
3892  if ( numFixedAtoms && fixedAtomFlags[anisos[i].atom1]
3893  && fixedAtomFlags[anisos[i].atom2]
3894  && fixedAtomFlags[anisos[i].atom3]
3895  && fixedAtomFlags[anisos[i].atom4] ) continue;
3896  if ( pair_self && fepAtomFlags[anisos[i].atom1] != 1) continue;
3897  int a1 = anisos[i].atom1;
3898  anisosByAtom[a1][byAtomSize[a1]++] = i;
3899  }
3900 
3901  }
3902  // DRUDE
3903 
3904  delete [] byAtomSize; byAtomSize = 0;
3905  delete [] byAtomSize2; byAtomSize2 = 0;
3906 
3907 
3908  // Allocate an array to hold the exclusions for each atom
3909  all_exclusions = new ExclusionCheck[numAtoms];
3910 
3911  for (i=0; i<numAtoms; i++)
3912  {
3913  all_exclusions[i].min = numAtoms;
3914  all_exclusions[i].max = -1;
3915  }
3916  for (i=0; i<numTotalExclusions; i++)
3917  {
3918  // first atom should alway have lower number!
3919  int a1 = exclusions[i].atom1;
3920  int a2 = exclusions[i].atom2;
3921  if ( numFixedAtoms && fixedAtomFlags[a1]
3922  && fixedAtomFlags[a2] ) continue;
3923  if ( all_exclusions[a1].min > a2 ) all_exclusions[a1].min = a2;
3924  if ( all_exclusions[a2].min > a1 ) all_exclusions[a2].min = a1;
3925  if ( a2 > all_exclusions[a1].max ) all_exclusions[a1].max = a2;
3926  if ( a1 > all_exclusions[a2].max ) all_exclusions[a2].max = a1;
3927  }
3928 
3929  // build array of all full exclusions for water etc.
3930  int maxDenseAllFull = 0;
3931  int numDenseAllFull = 0;
3932  for (i=0; i<numAtoms; i++) {
3933  int iInMiddle = ( i < all_exclusions[i].max &&
3934  i > all_exclusions[i].min ) ? 1 : 0;
3935  int s = all_exclusions[i].max - all_exclusions[i].min + 1;
3936  if ( s == fullExclusionsByAtom[i][0] + iInMiddle ) {
3937  if ( s > maxDenseAllFull ) maxDenseAllFull = s;
3938  all_exclusions[i].flags = (char*)-1; // shared array
3939  } else {
3940  all_exclusions[i].flags = 0; // individual array
3941  }
3942  }
3943  char *denseFullArray = exclArena->getNewArray(maxDenseAllFull);
3944  for ( i=0; i<maxDenseAllFull; ++i ) denseFullArray[i] = EXCHCK_FULL;
3945 
3946  int exclmem = maxDenseAllFull;
3947  int maxExclusionFlags = simParams->maxExclusionFlags;
3948  for (i=0; i<numAtoms; i++) {
3949  int s = all_exclusions[i].max - all_exclusions[i].min + 1;
3950  if ( all_exclusions[i].max != -1 ) {
3951  if ( all_exclusions[i].flags ) {
3952  all_exclusions[i].flags = denseFullArray;
3953  ++numDenseAllFull;
3954  } else if ( s < maxExclusionFlags ) {
3955  char *f = all_exclusions[i].flags = exclArena->getNewArray(s);
3956  for ( int k=0; k<s; ++k ) f[k] = 0;
3957  exclmem += s;
3958  } else {
3959  all_exclusions[i].flags = 0; // need to build on the fly
3960  }
3961  } else {
3962  all_exclusions[i].flags = (char*)-1; // should never dereference
3963  }
3964  }
3965  if ( 0 ) {
3966  iout << iINFO << numTotalExclusions << " exclusions consume "
3967  << exclmem << " bytes.\n" << endi;
3968  iout << iINFO << numDenseAllFull
3969  << " atoms sharing one array.\n" << endi;
3970  }
3971  for (i=0; i<numTotalExclusions; i++)
3972  {
3973  int a1 = exclusions[i].atom1;
3974  int a2 = exclusions[i].atom2;
3975  if ( numFixedAtoms && fixedAtomFlags[a1]
3976  && fixedAtomFlags[a2] ) continue;
3977  if ( exclusions[i].modified ) {
3978  if ( all_exclusions[a1].flags )
3979  all_exclusions[a1].flags[a2-all_exclusions[a1].min] = EXCHCK_MOD;
3980  if ( all_exclusions[a2].flags )
3981  all_exclusions[a2].flags[a1-all_exclusions[a2].min] = EXCHCK_MOD;
3982  } else {
3983  if ( all_exclusions[a1].flags )
3984  all_exclusions[a1].flags[a2-all_exclusions[a1].min] = EXCHCK_FULL;
3985  if ( all_exclusions[a2].flags )
3986  all_exclusions[a2].flags[a1-all_exclusions[a2].min] = EXCHCK_FULL;
3987  }
3988  }
3989  }
3990 
3991  /* END OF FUNCTION build_lists_by_atom */
3992 
3993  /****************************************************************/
3994  /* */
3995  /* FUNCTION build_exclusions */
3996  /* */
3997  /* This function builds a list of all the exlcusions */
3998  /* atoms. These lists include explicit exclusions as well as */
3999  /* exclusions that are calculated based on the bonded structure*/
4000  /* and the exclusion flag. For each pair of atoms that are */
4001  /* excluded, the larger of the 2 atom indexes is stored in the */
4002  /* array of the smaller index. All the arrays are not sorted. */
4003  /* Then to determine if two atoms have an exclusion, a linear */
4004  /* search is done on the array of the atom with the smaller */
4005  /* index for the larger index. */
4006  /* If the exclusion policy is set to scaled1-4, there are */
4007  /* actually two lists built. One contains the pairs of atoms */
4008  /* that are to be exlcuded (i.e., explicit exclusions, 1-2, */
4009  /* and 1-3 interactions) and the other contains just the 1-4 */
4010  /* interactions, since they will need to be determined */
4011  /* independantly of the other exclusions. */
4012  /* */
4013  /****************************************************************/
4014 
4015  void Molecule::build_exclusions()
4016  {
4017  register int i; // Loop counter
4018  ExclusionSettings exclude_flag; // Exclusion policy
4019 
4020  exclude_flag = simParams->exclude;
4021 
4022  // Go through the explicit exclusions and add them to the arrays
4023  for (i=0; i<numExclusions; i++)
4024  {
4025  exclusionSet.add(exclusions[i]);
4026  }
4027 
4028  // If this is AMBER force field, and readExclusions is TRUE,
4029  // then all the exclusions were read from parm file, and we
4030  // shouldn't generate any of them.
4031  if (!simParams->amberOn || !simParams->readExclusions)
4032  { // Now calculate the bonded exlcusions based on the exclusion policy
4033  switch (exclude_flag)
4034  {
4035  case NONE:
4036  break;
4037  case ONETWO:
4038  build12excl();
4039  break;
4040  case ONETHREE:
4041  build12excl();
4042  build13excl();
4043  break;
4044  case ONEFOUR:
4045  build12excl();
4046  build13excl();
4047  build14excl(0);
4048  break;
4049  case SCALED14:
4050  build12excl();
4051  build13excl();
4052  build14excl(1);
4053  break;
4054  }
4055  }
4056 
4057  stripFepExcl();
4058 
4059  // DRUDE
4060  if (is_lonepairs_psf || is_drude_psf) {
4061  build_inherited_excl(SCALED14 == exclude_flag);
4062  }
4063  }
4064  /* END OF FUNCTION build_exclusions */
4065 
4066 
4067  // Extend exclusions for the Drude model. The Drude model is generally
4068  // used with the 1-3 exclusion policy, although the code below also
4069  // supports the 1-2 exclusion policy. The use of light (or massless)
4070  // pseudo-atoms requires the introduction of extra exclusions.
4071  //
4072  // Here is the algorithm for determining Drude model exclusions:
4073  // (1) Each Drude particle and each lone pair has a single parent atom.
4074  // The parent atom must be a heavy atom.
4075  // (2) Each Drude particle and lone pair inherit the exclusions of its
4076  // parent atom.
4077  // (3) If two heavy atoms are excluded and they both have either a
4078  // Drude particle or a lone pair, the these light (or massless)
4079  // particles are also excluded from interacting with each other.
4080  void Molecule::build_inherited_excl(int modified) {
4081  ExclusionSettings exclude_flag = simParams->exclude;
4082  int32 *bond1, *bond2, *bond3, *bond4, *bond5;
4083  int32 i, j, mid1, mid2, mid3, mid4;
4084 
4085  // validate that each Drude or lone pair particle
4086  // has a unique parent that is a heavy atom
4087  for (i = 0; i < numAtoms; i++) {
4088 
4089  if (!is_drude(i) && !is_lp(i)) continue;
4090  // make sure that i is either Drude or LP
4091 
4092  // find parent (heavy) atom of particle i
4093  bond1 = bondsWithAtom[i];
4094 
4095  if (-1 == *bond1) { // i must have one bond
4096  char err_msg[512];
4097  const char *idescrip = (is_drude(i) ? "DRUDE" : "LONE PAIR");
4098  sprintf(err_msg, "FOUND ISOLATED %s PARTICLE %d", idescrip, i+1);
4099  NAMD_die(err_msg);
4100  }
4101  if (-1 != *(bond1+1)) { // and only one bond
4102  char err_msg[512];
4103  const char *idescrip = (is_drude(i) ? "DRUDE" : "LONE PAIR");
4104  sprintf(err_msg, "FOUND MULTIPLY LINKED %s PARTICLE %d",
4105  idescrip, i+1);
4106  NAMD_die(err_msg);
4107  }
4108 
4109  // mid1 is parent of particle i
4110  mid1 = bonds[*bond1].atom1;
4111  if (mid1 == i) mid1 = bonds[*bond1].atom2;
4112 
4113  // make sure that mid1 is a heavy atom
4114  if (is_drude(mid1) || is_lp(mid1) || is_hydrogen(mid1)) {
4115  char err_msg[512];
4116  const char *idescrip = (is_drude(i) ? "DRUDE" : "LONE PAIR");
4117  sprintf(err_msg, "PARENT ATOM %d of %s PARTICLE %d "
4118  "IS NOT HEAVY ATOM", mid1+1, idescrip, i+1);
4119  NAMD_die(err_msg);
4120  }
4121 
4122  if (exclude_flag == NONE) {
4123  // add (i,mid1) as an exclusion
4124  if (i < mid1) {
4125  exclusionSet.add(Exclusion(i, mid1));
4126  }
4127  else {
4128  exclusionSet.add(Exclusion(mid1, i));
4129  }
4130 
4131  // also exclude any Drude particles or LPs bonded to mid1
4132  bond2 = bondsWithAtom[mid1];
4133  while (*bond2 != -1) {
4134  j = bonds[*bond2].atom1;
4135  if ((is_drude(j) || is_lp(j)) && j != mid1) {
4136  if (i < j) exclusionSet.add(Exclusion(i, j));
4137  else if (j < i) exclusionSet.add(Exclusion(j, i));
4138  }
4139  j = bonds[*bond2].atom2;
4140  if ((is_drude(j) || is_lp(j)) && j != mid1) {
4141  if (i < j) exclusionSet.add(Exclusion(i, j));
4142  else if (j < i) exclusionSet.add(Exclusion(j, i));
4143  }
4144  bond2++;
4145  }
4146  }
4147  else { // if ONETWO or ONETHREE or ONEFOUR or SCALED14
4148 
4149  // find the next link
4150  bond2 = bondsWithAtom[mid1];
4151 
4152  // loop through all the bonds connected to atom mid1
4153  while (*bond2 != -1) {
4154  if (bonds[*bond2].atom1 == mid1) {
4155  mid2 = bonds[*bond2].atom2;
4156  }
4157  else {
4158  mid2 = bonds[*bond2].atom1;
4159  }
4160 
4161  // Make sure that we don't double back to where we started from.
4162  // Doing so causes strange behavior.
4163  if (mid2 == i) {
4164  bond2++;
4165  continue;
4166  }
4167 
4168  if (exclude_flag == ONETWO) {
4169  // add (i,mid2) as an exclusion
4170  if (i < mid2) {
4171  exclusionSet.add(Exclusion(i, mid2));
4172  }
4173  else {
4174  exclusionSet.add(Exclusion(mid2, i));
4175  }
4176 
4177  // also exclude any Drude particles or LPs bonded to mid2
4178  bond3 = bondsWithAtom[mid2];
4179  while (*bond3 != -1) {
4180  j = bonds[*bond3].atom1;
4181  if ((is_drude(j) || is_lp(j)) && j != mid2) {
4182  if (i < j) exclusionSet.add(Exclusion(i, j));
4183  else if (j < i) exclusionSet.add(Exclusion(j, i));
4184  }
4185  j = bonds[*bond3].atom2;
4186  if ((is_drude(j) || is_lp(j)) && j != mid2) {
4187  if (i < j) exclusionSet.add(Exclusion(i, j));
4188  else if (j < i) exclusionSet.add(Exclusion(j, i));
4189  }
4190  bond3++;
4191  }
4192  }
4193  else { // if ONETHREE or ONEFOUR or SCALED14
4194 
4195  // find the next link
4196  bond3 = bondsWithAtom[mid2];
4197 
4198  // loop through all the bonds connected to mid2
4199  while (*bond3 != -1) {
4200 
4201  if (bonds[*bond3].atom1 == mid2) {
4202  mid3 = bonds[*bond3].atom2;
4203  }
4204  else {
4205  mid3 = bonds[*bond3].atom1;
4206  }
4207 
4208  // Make sure we don't double back to where we started.
4209  // Doing so causes strange behavior.
4210  if (mid3 == mid1) {
4211  bond3++;
4212  continue;
4213  }
4214 
4215  // add (i,mid3) as an exclusion
4216  if (i < mid3) {
4217  exclusionSet.add(Exclusion(i, mid3));
4218  }
4219  else if (mid3 < i) {
4220  exclusionSet.add(Exclusion(mid3, i));
4221  }
4222 
4223  if (exclude_flag == ONETHREE) {
4224  // also exclude any Drude particles or LPs bonded to mid3
4225  bond4 = bondsWithAtom[mid3];
4226  while (*bond4 != -1) {
4227  j = bonds[*bond4].atom1;
4228  if ((is_drude(j) || is_lp(j)) && j != mid3) {
4229  if (i < j) exclusionSet.add(Exclusion(i, j));
4230  else if (j < i) exclusionSet.add(Exclusion(j, i));
4231  }
4232  j = bonds[*bond4].atom2;
4233  if ((is_drude(j) || is_lp(j)) && j != mid3) {
4234  if (i < j) exclusionSet.add(Exclusion(i, j));
4235  else if (j < i) exclusionSet.add(Exclusion(j, i));
4236  }
4237  bond4++;
4238  }
4239  }
4240  else { // if ONEFOUR or SCALED14
4241 
4242  // find next link
4243  bond4 = bondsWithAtom[mid3];
4244 
4245  // loop through all the bonds connected to mid3
4246  while (*bond4 != -1) {
4247 
4248  if (bonds[*bond4].atom1 == mid3) {
4249  mid4 = bonds[*bond4].atom2;
4250  }
4251  else {
4252  mid4 = bonds[*bond4].atom1;
4253  }
4254 
4255  // Make sure we don't double back to where we started.
4256  // Doing so causes strange behavior.
4257  if (mid4 == mid2) {
4258  bond4++;
4259  continue;
4260  }
4261 
4262  if (is_drude(mid4) || is_lp(mid4)) {
4263  // (i,mid4) is 1-3 excl
4264  if (i < mid4) {
4265  exclusionSet.add(Exclusion(i, mid4));
4266  }
4267  else if (mid4 < i) {
4268  exclusionSet.add(Exclusion(mid4, i));
4269  }
4270  bond4++;
4271  continue;
4272  }
4273 
4274  // (mid1,mid4) is an existing heavy atom exclusion
4275  // if we have modified 1-4 exclusions, make sure
4276  // that (mid1,mid4) is modified 1-4 exclusion
4277  // rather than something closer due to a ring
4278  int modi = modified;
4279  if (modified) {
4280  int amin = (mid1 < mid4 ? mid1 : mid4);
4281  int amax = (mid1 >= mid4 ? mid1 : mid4);
4282  Exclusion *pe = exclusionSet.find(Exclusion(amin,amax));
4283  if (pe==0) {
4284  // since there is not an existing exclusion
4285  // between (mid1,mid4), don't inherit!
4286  bond4++;
4287  continue;
4288  }
4289  modi = pe->modified;
4290  }
4291 
4292  if (i < mid4) {
4293  exclusionSet.add(Exclusion(i, mid4, modi));
4294  }
4295  else if (mid4 < i) {
4296  exclusionSet.add(Exclusion(mid4, i, modi));
4297  }
4298 
4299  // also exclude any Drude particles or LPs bonded to mid4
4300  // using the "modi" setting of (mid1,mid4) exclusion
4301  bond5 = bondsWithAtom[mid4];
4302  while (*bond5 != -1) {
4303  j = bonds[*bond5].atom1;
4304  if ((is_drude(j) || is_lp(j)) && j != mid4) {
4305  if (i<j) exclusionSet.add(Exclusion(i,j,modi));
4306  else if (j<i) exclusionSet.add(Exclusion(j,i,modi));
4307  }
4308  j = bonds[*bond5].atom2;
4309  if ((is_drude(j) || is_lp(j)) && j != mid4) {
4310  if (i<j) exclusionSet.add(Exclusion(i,j,modi));
4311  else if (j<i) exclusionSet.add(Exclusion(j,i,modi));
4312  }
4313  bond5++;
4314  }
4315  ++bond4;
4316  } // while bond4
4317 
4318  } // else (if ONEFOUR or SCALED14)
4319 
4320  ++bond3;
4321  } // while bond3
4322 
4323  } // else (if ONETHREE or ONEFOUR or SCALED14)
4324 
4325  ++bond2;
4326  } // while bond2
4327 
4328  } // else (if ONETWO or ONETHREE or ONEFOUR or SCALED14)
4329 
4330  } // for i
4331  }
4332  // DRUDE
4333 
4334 
4335  /************************************************************************/
4336  /* */
4337  /* FUNCTION build12excl */
4338  /* */
4339  /************************************************************************/
4340 
4341  void Molecule::build12excl(void)
4342  {
4343  int32 *current_val; // Current value to check
4344  register int i; // Loop counter to loop through all atoms
4345 
4346  // Loop through all the atoms marking the bonded interactions for each one
4347  for (i=0; i<numAtoms; i++)
4348  {
4349  current_val = bondsWithAtom[i];
4350 
4351  // Loop through all the bonds for this atom
4352  while (*current_val != -1)
4353  {
4354  if (bonds[*current_val].atom1 == i)
4355  {
4356  if (i<bonds[*current_val].atom2)
4357  {
4358  exclusionSet.add(Exclusion(i,bonds[*current_val].atom2));
4359  }
4360  }
4361  else
4362  {
4363  if (i<bonds[*current_val].atom1)
4364  {
4365  exclusionSet.add(Exclusion(i,bonds[*current_val].atom1));
4366  }
4367  }
4368 
4369  ++current_val;
4370  }
4371  }
4372  }
4373  /* END OF FUNCTION build12excl */
4374 
4375  /************************************************************************/
4376  /* */
4377  /* FUNCTION build13excl */
4378  /* */
4379  /************************************************************************/
4380 
4381  void Molecule::build13excl(void)
4382  {
4383  int32 *bond1, *bond2; // The two bonds being checked
4384  int middle_atom; // Common third atom
4385  register int i; // Loop counter to loop through all atoms
4386 
4387  // Loop through all the atoms looking at the bonded connections
4388  // for each one
4389  for (i=0; i<numAtoms; i++)
4390  {
4391  bond1 = bondsWithAtom[i];
4392 
4393  // Loop through all the bonds directly connect to atom i
4394  while (*bond1 != -1)
4395  {
4396  if (bonds[*bond1].atom1 == i)
4397  {
4398  middle_atom=bonds[*bond1].atom2;
4399  }
4400  else
4401  {
4402  middle_atom=bonds[*bond1].atom1;
4403  }
4404 
4405  bond2 = bondsWithAtom[middle_atom];
4406 
4407  // Now loop through all the bonds connect to the
4408  // middle atom
4409  while (*bond2 != -1)
4410  {
4411  if (bonds[*bond2].atom1 == middle_atom)
4412  {
4413  if (i < bonds[*bond2].atom2)
4414  {
4415  exclusionSet.add(Exclusion(i,bonds[*bond2].atom2));
4416  }
4417  }
4418  else
4419  {
4420  if (i < bonds[*bond2].atom1)
4421  {
4422  exclusionSet.add(Exclusion(i,bonds[*bond2].atom1));
4423  }
4424  }
4425 
4426  ++bond2;
4427  }
4428 
4429  ++bond1;
4430  }
4431  }
4432  }
4433  /* END OF FUNCTION build13excl */
4434 
4435  /************************************************************************/
4436  /* */
4437  /* FUNCTION build14excl */
4438  /* */
4439  /************************************************************************/
4440 
4441 
4442  void Molecule::build14excl(int modified)
4443  {
4444  int32 *bond1, *bond2, *bond3; // The two bonds being checked
4445  int mid1, mid2; // Middle atoms
4446  register int i; // Counter to loop through all atoms
4447 
4448  // Loop through all the atoms
4449  for (i=0; i<numAtoms; i++)
4450  {
4451  if (is_drude(i) || is_lp(i)) continue; // skip Drude and LP for now
4452 
4453  // Get all the bonds connect directly to atom i
4454  bond1 = bondsWithAtom[i];
4455 
4456  while (*bond1 != -1)
4457  {
4458  if (bonds[*bond1].atom1 == i)
4459  {
4460  mid1=bonds[*bond1].atom2;
4461  }
4462  else
4463  {
4464  mid1=bonds[*bond1].atom1;
4465  }
4466 
4467  bond2 = bondsWithAtom[mid1];
4468 
4469  // Loop through all the bonds connected to atom mid1
4470  while (*bond2 != -1)
4471  {
4472  if (bonds[*bond2].atom1 == mid1)
4473  {
4474  mid2 = bonds[*bond2].atom2;
4475  }
4476  else
4477  {
4478  mid2 = bonds[*bond2].atom1;
4479  }
4480 
4481  // Make sure that we don't double back to where
4482  // we started from. This causes strange behavior.
4483  // Trust me, I've been there . . .
4484  if (mid2 == i)
4485  {
4486  ++bond2;
4487  continue;
4488  }
4489 
4490  bond3=bondsWithAtom[mid2];
4491 
4492  // Loop through all the bonds connected to mid2
4493  while (*bond3 != -1)
4494  {
4495  if (bonds[*bond3].atom1 == mid2)
4496  {
4497  int j = bonds[*bond3].atom2;
4498  // Make sure that we don't double back to where
4499  // we started from. This causes strange behavior.
4500  // Trust me, I've been there . . .
4501  // I added this!!! Why wasn't it there before? -JCP
4502  if (j != mid1)
4503  if (i < j && !is_drude(j) && !is_lp(j)) // skip Drude and LP
4504  {
4505  exclusionSet.add(Exclusion(i,j,modified));
4506  }
4507  }
4508  else
4509  {
4510  int j = bonds[*bond3].atom1;
4511  // Make sure that we don't double back to where
4512  // we started from. This causes strange behavior.
4513  // Trust me, I've been there . . .
4514  // I added this!!! Why wasn't it there before? -JCP
4515  if (j != mid1)
4516  if (i < j && !is_drude(j) && !is_lp(j)) // skip Drude and LP
4517  {
4518  exclusionSet.add(Exclusion(i,j,modified));
4519  }
4520  }
4521 
4522  ++bond3;
4523  }
4524 
4525  ++bond2;
4526  }
4527 
4528  ++bond1;
4529  }
4530  }
4531  }
4532  /* END OF FUNCTION build14excl */
4533 
4534 
4535  /************************************************************************/
4536  /* */
4537  /* FUNCTION stripFepExcl */
4538  /* */
4539  /************************************************************************/
4540  void Molecule::stripFepExcl(void)
4541  {
4542  UniqueSet<Exclusion> fepExclusionSet;
4543  UniqueSetIter<Exclusion> exclIter(exclusionSet);
4544 
4545  if ( simParams->alchOn || simParams->lesOn ) {
4546  for ( exclIter=exclIter.begin(); exclIter != exclIter.end(); exclIter++ )
4547  {
4548  int t1 = get_fep_type(exclIter->atom1);
4549  int t2 = get_fep_type(exclIter->atom2);
4550  if (t1 && t2 && t1 !=t2 && abs(t1-t2) != 2) {
4551  fepExclusionSet.add(*exclIter);
4552  }
4553  }
4554  } else if ( simParams->pairInteractionOn ) {
4555  for ( exclIter=exclIter.begin(); exclIter != exclIter.end(); exclIter++ )
4556  {
4557  int ifep_type = get_fep_type(exclIter->atom1);
4558  int jfep_type = get_fep_type(exclIter->atom2);
4559  if ( simParams->pairInteractionSelf ) {
4560  // for pair-self, both atoms must be in group 1.
4561  if (ifep_type != 1 || jfep_type != 1) {
4562  fepExclusionSet.add(*exclIter);
4563  }
4564  } else {
4565 
4566  // for pair, must have one from each group.
4567  if (!(ifep_type == 1 && jfep_type == 2) &&
4568  !(ifep_type == 2 && jfep_type == 1)) {
4569  fepExclusionSet.add(*exclIter);
4570  }
4571  }
4572  }
4573  }
4574 
4575  UniqueSetIter<Exclusion> fepIter(fepExclusionSet);
4576  for ( fepIter=fepIter.begin(); fepIter != fepIter.end(); fepIter++ )
4577  {
4578  exclusionSet.del(*fepIter);
4579  }
4580  }
4581  /* END OF FUNCTION stripFepExcl */
4582 
4583 #else
4584 
4585 //===Memory optimized version of functions that read Molecule file===//
4586 void Molecule::read_mol_signatures(char *fname, Parameters *params, ConfigList *cfgList){
4587  FILE *psf_file; // pointer to .psf file
4588  int ret_code; // ret_code from NAMD_read_line calls
4589  char buffer[512];
4590 
4591 
4592  if ( (psf_file = Fopen(fname, "r")) == NULL)
4593  {
4594  char err_msg[512];
4595  sprintf(err_msg, "UNABLE TO OPEN THE COMPRESSED .psf FILE %s", fname);
4596  NAMD_die(err_msg);
4597  }
4598 
4599  char strBuf[12];
4600 
4601 
4602  NAMD_read_line(psf_file, buffer);
4603  if(!NAMD_find_word(buffer, "FORMAT VERSION")) {
4604  NAMD_die("The compressed psf file format is incorrect, please re-generate!\n");
4605  }
4606  float psfVer = 0.0f;
4607  sscanf(buffer, "FORMAT VERSION: %f\n", &psfVer);
4608  if(fabs(psfVer - COMPRESSED_PSF_VER)>1e-6) {
4609  NAMD_die("The compressed psf file format is incorrect, please re-generate!\n");
4610  }
4611 
4612  NAMD_read_line(psf_file, buffer);
4613  if(!NAMD_find_word(buffer, "NSEGMENTNAMES"))
4614  NAMD_die("UNABLE TO FIND NSEGMENTNAMES");
4615  sscanf(buffer, "%d", &segNamePoolSize);
4616 #if 0
4617  if(segNamePoolSize!=0)
4618  segNamePool = new char *[segNamePoolSize];
4619  for(int i=0; i<segNamePoolSize; i++){
4620  NAMD_read_line(psf_file, buffer);
4621  sscanf(buffer, "%s", strBuf);
4622  segNamePool[i] = nameArena->getNewArray(strlen(strBuf)+1);
4623  strcpy(segNamePool[i], strBuf);
4624  }
4625 #else
4626  for(int i=0; i<segNamePoolSize; i++) NAMD_read_line(psf_file, buffer);
4627 #endif
4628 
4629  NAMD_read_line(psf_file, buffer);
4630  if(!NAMD_find_word(buffer, "NRESIDUENAMES"))
4631  NAMD_die("UNABLE TO FIND NRESIDUENAMES");
4632  sscanf(buffer, "%d", &resNamePoolSize);
4633 #if 0
4634  if(resNamePoolSize!=0)
4635  resNamePool = new char *[resNamePoolSize];
4636  for(int i=0; i<resNamePoolSize; i++){
4637  NAMD_read_line(psf_file, buffer);
4638  sscanf(buffer, "%s", strBuf);
4639  resNamePool[i] = nameArena->getNewArray(strlen(strBuf)+1);
4640  strcpy(resNamePool[i], strBuf);
4641  }
4642 #else
4643  for(int i=0; i<resNamePoolSize; i++) NAMD_read_line(psf_file, buffer);
4644 #endif
4645 
4646  NAMD_read_line(psf_file, buffer);
4647  if(!NAMD_find_word(buffer, "NATOMNAMES"))
4648  NAMD_die("UNABLE TO FIND NATOMNAMES");
4649  sscanf(buffer, "%d", &atomNamePoolSize);
4650  if(atomNamePoolSize!=0)
4651  atomNamePool = new char *[atomNamePoolSize];
4652  for(int i=0; i<atomNamePoolSize; i++){
4653  NAMD_read_line(psf_file, buffer);
4654  sscanf(buffer, "%s", strBuf);
4655  atomNamePool[i] = nameArena->getNewArray(strlen(strBuf)+1);
4656  strcpy(atomNamePool[i], strBuf);
4657  }
4658 
4659  NAMD_read_line(psf_file, buffer);
4660  if(!NAMD_find_word(buffer, "NATOMTYPES"))
4661  NAMD_die("UNABLE TO FIND NATOMTYPES");
4662  sscanf(buffer, "%d", &atomTypePoolSize);
4663 #if 0
4664  if(atomTypePoolSize!=0)
4665  atomTypePool = new char *[atomTypePoolSize];
4666  for(int i=0; i<atomTypePoolSize; i++){
4667  NAMD_read_line(psf_file, buffer);
4668  sscanf(buffer, "%s", strBuf);
4669  atomTypePool[i] = nameArena->getNewArray(strlen(strBuf)+1);
4670  strcpy(atomTypePool[i], strBuf);
4671  }
4672 #else
4673  for(int i=0; i<atomTypePoolSize; i++) NAMD_read_line(psf_file, buffer);
4674 #endif
4675 
4676  NAMD_read_line(psf_file, buffer);
4677  if(!NAMD_find_word(buffer, "NCHARGES"))
4678  NAMD_die("UNABLE TO FIND NCHARGES");
4679  sscanf(buffer, "%d", &chargePoolSize);
4680  if(chargePoolSize!=0)
4681  atomChargePool = new Real[chargePoolSize];
4682  for(int i=0; i<chargePoolSize; i++){
4683  NAMD_read_line(psf_file, buffer);
4684  sscanf(buffer, "%f", atomChargePool+i);
4685  }
4686 
4687  NAMD_read_line(psf_file, buffer);
4688  if(!NAMD_find_word(buffer, "NMASSES"))
4689  NAMD_die("UNABLE TO FIND NMASSES");
4690  sscanf(buffer, "%d", &massPoolSize);
4691  if(massPoolSize!=0)
4692  atomMassPool = new Real[massPoolSize];
4693  for(int i=0; i<massPoolSize; i++){
4694  NAMD_read_line(psf_file, buffer);
4695  sscanf(buffer, "%f", atomMassPool+i);
4696  }
4697 
4698  NAMD_read_line(psf_file, buffer);
4699  if(!NAMD_find_word(buffer, "ATOMSIGS"))
4700  NAMD_die("UNABLE TO FIND ATOMSIGS");
4701  sscanf(buffer, "%d", &atomSigPoolSize);
4702  atomSigPool = new AtomSignature[atomSigPoolSize];
4703  int typeCnt;
4704  int tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
4705  int tisReal;
4706  int ttype;
4707  for(int i=0; i<atomSigPoolSize; i++){
4708 
4709  NAMD_read_line(psf_file, buffer);
4710  if(!NAMD_find_word(buffer, "NBONDSIGS"))
4711  NAMD_die("UNABLE TO FIND NBONDSIGS");
4712  sscanf(buffer, "%d", &typeCnt);
4713  if(typeCnt!=0){
4714  atomSigPool[i].bondCnt = typeCnt;
4715  atomSigPool[i].bondSigs = new TupleSignature[typeCnt];
4716  }
4717  for(int j=0; j<typeCnt; j++){
4718  NAMD_read_line(psf_file, buffer);
4719  sscanf(buffer, "%d | %d | %d", &tmp1, &ttype, &tisReal);
4720  TupleSignature oneSig(1, BOND, (Index)ttype, (char)tisReal);
4721  oneSig.offset[0] = tmp1;
4722  atomSigPool[i].bondSigs[j]=oneSig;
4723  if(tisReal) numRealBonds++;
4724  }
4725 
4726 
4727  NAMD_read_line(psf_file, buffer);
4728  if(!NAMD_find_word(buffer, "NTHETASIGS"))
4729  NAMD_die("UNABLE TO FIND NTHETASIGS");
4730  sscanf(buffer, "%d", &typeCnt);
4731  if(typeCnt!=0){
4732  atomSigPool[i].angleCnt = typeCnt;
4733  atomSigPool[i].angleSigs = new TupleSignature[typeCnt];
4734  }
4735  for(int j=0; j<typeCnt; j++){
4736  NAMD_read_line(psf_file, buffer);
4737  sscanf(buffer, "%d %d | %d | %d", &tmp1, &tmp2, &ttype, &tisReal);
4738  TupleSignature oneSig(2,ANGLE,(Index)ttype, (char)tisReal);
4739  oneSig.offset[0] = tmp1;
4740  oneSig.offset[1] = tmp2;
4741  atomSigPool[i].angleSigs[j] = oneSig;
4742  }
4743 
4744  NAMD_read_line(psf_file, buffer);
4745  if(!NAMD_find_word(buffer, "NPHISIGS"))
4746  NAMD_die("UNABLE TO FIND NPHISIGS");
4747  sscanf(buffer, "%d", &typeCnt);
4748  if(typeCnt!=0){
4749  atomSigPool[i].dihedralCnt = typeCnt;
4750  atomSigPool[i].dihedralSigs = new TupleSignature[typeCnt];
4751  }
4752  for(int j=0; j<typeCnt; j++){
4753  NAMD_read_line(psf_file, buffer);
4754  sscanf(buffer, "%d %d %d | %d | %d", &tmp1, &tmp2, &tmp3, &ttype, &tisReal);
4755  TupleSignature oneSig(3,DIHEDRAL,(Index)ttype, (char)tisReal);
4756  oneSig.offset[0] = tmp1;
4757  oneSig.offset[1] = tmp2;
4758  oneSig.offset[2] = tmp3;
4759  atomSigPool[i].dihedralSigs[j] = oneSig;
4760  }
4761 
4762  NAMD_read_line(psf_file, buffer);
4763  if(!NAMD_find_word(buffer, "NIMPHISIGS"))
4764  NAMD_die("UNABLE TO FIND NIMPHISIGS");
4765  sscanf(buffer, "%d", &typeCnt);
4766  if(typeCnt!=0){
4767  atomSigPool[i].improperCnt = typeCnt;
4768  atomSigPool[i].improperSigs = new TupleSignature[typeCnt];
4769  }
4770  for(int j=0; j<typeCnt; j++){
4771  NAMD_read_line(psf_file, buffer);
4772  sscanf(buffer, "%d %d %d | %d | %d", &tmp1, &tmp2, &tmp3, &ttype, &tisReal);
4773  TupleSignature oneSig(3,IMPROPER,(Index)ttype, (char)tisReal);
4774  oneSig.offset[0] = tmp1;
4775  oneSig.offset[1] = tmp2;
4776  oneSig.offset[2] = tmp3;
4777  atomSigPool[i].improperSigs[j] = oneSig;
4778  }
4779 
4780  NAMD_read_line(psf_file, buffer);
4781  if(!NAMD_find_word(buffer, "NCRTERMSIGS"))
4782  NAMD_die("UNABLE TO FIND NCRTERMSIGS");
4783  sscanf(buffer, "%d", &typeCnt);
4784  if(typeCnt!=0){
4785  atomSigPool[i].crosstermCnt = typeCnt;
4786  atomSigPool[i].crosstermSigs = new TupleSignature[typeCnt];
4787  }
4788  for(int j=0; j<typeCnt; j++){
4789  NAMD_read_line(psf_file, buffer);
4790  sscanf(buffer, "%d %d %d %d %d %d %d | %d | %d", &tmp1, &tmp2, &tmp3, &tmp4, &tmp5, &tmp6, &tmp7, &ttype, &tisReal);
4791  TupleSignature oneSig(7,CROSSTERM,(Index)ttype, (char)tisReal);
4792  oneSig.offset[0] = tmp1;
4793  oneSig.offset[1] = tmp2;
4794  oneSig.offset[2] = tmp3;
4795  oneSig.offset[3] = tmp4;
4796  oneSig.offset[4] = tmp5;
4797  oneSig.offset[5] = tmp6;
4798  oneSig.offset[6] = tmp7;
4799  atomSigPool[i].crosstermSigs[j] = oneSig;
4800  }
4801  }
4802 
4803 
4804  NAMD_read_line(psf_file, buffer);
4805  if(!NAMD_find_word(buffer, "NEXCLSIGS")){
4806  NAMD_die("UNABLE TO FIND NEXCLSIGS");
4807  }
4808  sscanf(buffer, "%d", &exclSigPoolSize);
4809  if(exclSigPoolSize>0) exclSigPool = new ExclusionSignature[exclSigPoolSize];
4810  vector<int> fullExcls;
4811  vector<int> modExcls;
4812  for(int i=0; i<exclSigPoolSize; i++){
4813  int fullExclCnt = NAMD_read_int(psf_file, buffer);
4814  for(int j=0; j<fullExclCnt; j++)
4815  fullExcls.push_back(NAMD_read_int(psf_file, buffer));
4816  int modExclCnt = NAMD_read_int(psf_file, buffer);
4817  for(int j=0; j<modExclCnt; j++)
4818  modExcls.push_back(NAMD_read_int(psf_file, buffer));
4819 
4820 
4821  exclSigPool[i].setOffsets(fullExcls, modExcls);
4822 
4823  fullExcls.clear();
4824  modExcls.clear();
4825  }
4826 
4827 
4828  NAMD_read_line(psf_file, buffer);
4829  if(!NAMD_find_word(buffer, "NCLUSTERS")) {
4830  NAMD_die("UNABLE TO FIND NCLUSTERS");
4831  }
4832  sscanf(buffer, "%d", &numClusters);
4833 
4834  NAMD_read_line(psf_file, buffer);
4835  if(!NAMD_find_word(buffer, "NATOM"))
4836  NAMD_die("UNABLE TO FIND NATOM");
4837  sscanf(buffer, "%d", &numAtoms);
4838 
4839  NAMD_read_line(psf_file, buffer);
4840  if(!NAMD_find_word(buffer, "NHYDROGENGROUP"))
4841  NAMD_die("UNABLE TO FIND NHYDROGENGROUP");
4842  sscanf(buffer, "%d", &numHydrogenGroups);
4843 
4844  NAMD_read_line(psf_file, buffer);
4845  if(!NAMD_find_word(buffer, "MAXHYDROGENGROUPSIZE"))
4846  NAMD_die("UNABLE TO FIND MAXHYDROGENGROUPSIZE");
4847  sscanf(buffer, "%d", &maxHydrogenGroupSize);
4848  NAMD_read_line(psf_file, buffer);
4849  if(!NAMD_find_word(buffer, "NMIGRATIONGROUP"))
4850  NAMD_die("UNABLE TO FIND NMIGRATIONGROUP");
4851  sscanf(buffer, "%d", &numMigrationGroups);
4852  NAMD_read_line(psf_file, buffer);
4853  if(!NAMD_find_word(buffer, "MAXMIGRATIONGROUPSIZE"))
4854  NAMD_die("UNABLE TO FIND MAXMIGRATIONGROUPSIZE");
4855  sscanf(buffer, "%d", &maxMigrationGroupSize);
4856 
4857  int inputRigidType = -1;
4858  NAMD_read_line(psf_file, buffer);
4859  if(!NAMD_find_word(buffer, "RIGIDBONDTYPE"))
4860  NAMD_die("UNABLE TO FIND RIGIDBONDTYPE");
4861  sscanf(buffer, "%d", &inputRigidType);
4862  if(simParams->rigidBonds != RIGID_NONE){
4863  //check whether the input rigid bond type matches
4864  if(simParams->rigidBonds != inputRigidType){
4865  const char *tmpstr[]={"RIGID_NONE", "RIGID_ALL", "RIGID_WATER"};
4866  char errmsg[125];
4867  sprintf(errmsg, "RIGIDBOND TYPE MISMATCH BETWEEN INPUT (%s) AND CURRENT RUN (%s)",
4868  tmpstr[inputRigidType], tmpstr[simParams->rigidBonds]);
4869  NAMD_die(errmsg);
4870  }
4871  }
4872 #if 0
4873 // int isOccupancyValid, isBFactorValid;
4874  NAMD_read_line(psf_file, buffer);
4875  if(!NAMD_find_word(buffer, "OCCUPANCYVALID"))
4876  NAMD_die("UNABLE TO FIND OCCUPANCYVALID");
4877  sscanf(buffer, "%d", &isOccupancyValid);
4878  NAMD_read_line(psf_file, buffer);
4879  if(!NAMD_find_word(buffer, "TEMPFACTORVALID"))
4880  NAMD_die("UNABLE TO FIND TEMPFACTORVALID");
4881  sscanf(buffer, "%d", &isBFactorValid);
4882 #endif
4883 
4884  //Just reading for the parameters values; extra Bonds, Dihedrals etc.
4885  //have been taken into account when compressing the molecule object.
4886  //The actual number of Bonds, Dihedrals etc. will be calculated based
4887  //on atom signatures.
4888  if(cfgList && simParams->extraBondsOn)
4889  build_extra_bonds(params, cfgList->find("extraBondsFile"));
4890 
4891  NAMD_read_line(psf_file, buffer);
4892  if(!NAMD_find_word(buffer, "DIHEDRALPARAMARRAY"))
4893  NAMD_die("UNABLE TO FIND DIHEDRALPARAMARRAY");
4894  for(int i=0; i<params->NumDihedralParams; i++){
4895  params->dihedral_array[i].multiplicity = NAMD_read_int(psf_file, buffer);
4896  }
4897 
4898 
4899  NAMD_read_line(psf_file, buffer); //to read a simple single '\n' line
4900  NAMD_read_line(psf_file, buffer);
4901  if(!NAMD_find_word(buffer, "IMPROPERPARAMARRAY"))
4902  NAMD_die("UNABLE TO FIND IMPROPERPARAMARRAY");
4903  for(int i=0; i<params->NumImproperParams; i++){
4904  params->improper_array[i].multiplicity = NAMD_read_int(psf_file, buffer);
4905  }
4906 
4907  Fclose(psf_file);
4908 }
4909 
4910 /*
4911  * The following method is called on every input processors. However, in SMP mode, two
4912  * input procs are likely to be inside the same SMP node. Additionally, there's only one
4913  * Molecule object per SMP node. Therefore, if there are any assignments to the molecule
4914  * object in this function, there's going to be DATA RACE !! That's why the calculation of
4915  * numTupes(Bonds, Angles, etc) and numExclusions has to be done in ParallelIOMgr, and
4916  * then reduce those values.
4917  * -Chao Mei
4918  */
4919 void Molecule::read_binary_atom_info(int fromAtomID, int toAtomID, InputAtomList& inAtoms){
4920  int numAtomsPar = toAtomID-fromAtomID+1;
4921  CmiAssert(numAtomsPar > 0);
4922  CmiAssert(inAtoms.size() == numAtomsPar);
4923 
4924  /*
4925  //all the following vars are not needed as the
4926  //atom info is loaded into inAtoms.
4927  atoms = new AtomCstInfo[numAtomsPar];
4928  atomNames = new AtomNameIdx[numAtomsPar];
4929  eachAtomMass = new Index[numAtomsPar];
4930  eachAtomCharge = new Index[numAtomsPar];
4931  eachAtomSig = new Index[numAtomsPar];
4932  eachAtomExclSig = new Index[numAtomsPar];
4933  */
4934  /*
4935  atoms = new AtomCstInfo[numAtomsPar];
4936  atomNames = new AtomNameIdx[numAtomsPar];
4937  */
4938 
4939  atoms = NULL;
4940  atomNames = NULL;
4941  eachAtomMass = NULL;
4942  eachAtomCharge = NULL;
4943  eachAtomSig = NULL;
4944  eachAtomExclSig = NULL;
4945  clusterSigs = NULL;
4946 
4947  /* HydrogenGroup is not needed here anymore
4948  hydrogenGroup.resize(numAtomsPar);
4949  ResidueLookupElem *tmpResLookup = resLookup;
4950  */
4951 /*
4952  if (isOccupancyValid) {
4953  occupancy = new float[numAtomsPar];
4954  }
4955  if (isBFactorValid) {
4956  bfactor = new float[numAtomsPar];
4957  }
4958 */
4959  occupancy = NULL;
4960  bfactor = NULL;
4961 
4962  char *segment_name;
4963 
4964  //use "fopen" instead of "Fopen" because "stat" call inside Fopen may
4965  //fail on some platforms (such as BG/P) for very large file because of
4966  //EOVERFLOW, say a 2GB file. -Chao Mei
4967  FILE *perAtomFile = fopen(simParams->binAtomFile, "rb");
4968  if (perAtomFile==NULL) {
4969  char err_msg[512];
4970  sprintf(err_msg, "UNABLE TO OPEN THE ASSOCIATED PER-ATOM FILE FOR THE COMPRESSED .psf FILE %s", simParams->binAtomFile);
4971  NAMD_die(err_msg);
4972  }
4973  int needFlip = 0;
4974  int magicNum = COMPRESSED_PSF_MAGICNUM;
4975  int rMagicNum = COMPRESSED_PSF_MAGICNUM;
4976  flipNum((char *)&rMagicNum, sizeof(int), 1);
4977  int fMagicNum;
4978  fread(&fMagicNum, sizeof(int), 1, perAtomFile);
4979  if (fMagicNum==magicNum) {
4980  needFlip = 0;
4981  } else if (fMagicNum==rMagicNum) {
4982  needFlip = 1;
4983  } else {
4984  char err_msg[512];
4985  sprintf(err_msg, "THE ASSOCIATED PER-ATOM FILE FOR THE COMPRESSED .psf FILE %s IS CORRUPTED", simParams->binAtomFile);
4986  NAMD_die(err_msg);
4987  }
4988 
4989  float verNum = 0.0f;
4990  fread(&verNum, sizeof(float), 1, perAtomFile);
4991  if (needFlip) flipNum((char *)&verNum, sizeof(float), 1);
4992  if (fabs(verNum - COMPRESSED_PSF_VER)>1e-6) {
4993  char err_msg[512];
4994  sprintf(err_msg, "THE ASSOCIATED PER-ATOM FILE FOR THE COMPRESSED .psf FILE %s IS INCORRECT, PLEASE RE-GENERATE!\n", simParams->binAtomFile);
4995  NAMD_die(err_msg);
4996  }
4997 
4998  int recSize = 0;
4999  fread(&recSize, sizeof(int), 1, perAtomFile);
5000  if(needFlip) flipNum((char *)&recSize, sizeof(int), 1);
5001  if(recSize != sizeof(OutputAtomRecord)){
5002  char err_msg[512];
5003  sprintf(err_msg, "THE ASSOCIATED PER-ATOM RECORD SIZE FOR THE COMPRESSED .psf FILE %s IS INCORRECT, PLEASE RE-GENERATE!\n", simParams->binAtomFile);
5004  NAMD_die(err_msg);
5005  }
5006 
5007  const int BUFELEMS = 32*1024; //32K elems
5008 
5009  //remember to convert to long in case of int overflow!
5010  int64 startbyte=((int64)fromAtomID)*sizeof(OutputAtomRecord);
5011 #ifdef WIN32
5012  if ( _fseeki64(perAtomFile,startbyte,SEEK_CUR) )
5013 #else
5014  if ( fseeko(perAtomFile,startbyte,SEEK_CUR) )
5015 #endif
5016  {
5017  char errmsg[512];
5018  sprintf(errmsg, "Error on seeking binary file %s", simParams->binAtomFile);
5019  NAMD_err(errmsg);
5020  }
5021 
5022  //reduce the number of fread calls as file I/O is expensive.
5023  OutputAtomRecord *elemsBuf = new OutputAtomRecord[BUFELEMS];
5024  int atomsCnt = numAtomsPar;
5025  int curIdx=0;
5026  OutputAtomRecord *oneRec = NULL;
5027  while(atomsCnt >= BUFELEMS) {
5028  if ( fread((char *)elemsBuf, sizeof(OutputAtomRecord), BUFELEMS, perAtomFile) != BUFELEMS ) {
5029  char errmsg[512];
5030  sprintf(errmsg, "Error on reading binary file %s", simParams->binAtomFile);
5031  NAMD_err(errmsg);
5032  }
5033  oneRec = elemsBuf;
5034  for(int i=0; i<BUFELEMS; i++, curIdx++, oneRec++) {
5035  InputAtom *fAtom = &(inAtoms[curIdx]);
5036  int aid = curIdx+fromAtomID;
5037  if(needFlip) oneRec->flip();
5038  load_one_inputatom(aid, oneRec, fAtom);
5039  }
5040  atomsCnt -= BUFELEMS;
5041  }
5042 
5043  if ( fread(elemsBuf, sizeof(OutputAtomRecord), atomsCnt, perAtomFile) != atomsCnt ) {
5044  char errmsg[512];
5045  sprintf(errmsg, "Error on reading binary file %s", simParams->binAtomFile);
5046  NAMD_err(errmsg);
5047  }
5048  oneRec = elemsBuf;
5049  for(int i=curIdx; i<numAtomsPar; i++, oneRec++) {
5050  InputAtom *fAtom = &(inAtoms[i]);
5051  int aid = i+fromAtomID;
5052  if(needFlip) oneRec->flip();
5053  load_one_inputatom(aid,oneRec,fAtom);
5054  }
5055 
5056  if ( fclose(perAtomFile) ) {
5057  char errmsg[512];
5058  sprintf(errmsg, "Error on closing binary file %s", simParams->binAtomFile);
5059  NAMD_err(errmsg);
5060  }
5061 
5062  delete [] elemsBuf;
5063 
5064  //deal with fixed atoms info
5065  if(simParams->fixedAtomsOn){
5066  int listIdx=0;
5067  is_atom_fixed(fromAtomID, &listIdx);
5068  for(int i=listIdx; i<fixedAtomsSet->size(); i++){
5069  const AtomSet one = fixedAtomsSet->item(i);
5070  //set the atoms in this range to be fixed
5071  int sAtomId = one.aid1>fromAtomID ? one.aid1:fromAtomID;
5072  int eAtomId = one.aid2>toAtomID? toAtomID:one.aid2;
5073  for(int j=sAtomId; j<=eAtomId; j++)
5074  inAtoms[j-fromAtomID].atomFixed = 1;
5075  }
5076  }
5077 }
5078 
5079 void Molecule::load_one_inputatom(int aid, OutputAtomRecord *one, InputAtom *fAtom){
5080 
5081  char *thisAtomName = NULL;
5082  fAtom->isValid=true;
5083 
5084  //segment_name = segNamePool[sIdx[0]];
5085  /*
5086  atomNames[i].resnameIdx = sIdx[1];
5087  atomNames[i].atomnameIdx = sIdx[2];
5088  atomNames[i].atomtypeIdx = sIdx[3];
5089  */
5090  thisAtomName = atomNamePool[one->sSet.atomNameIdx];
5091 
5092  fAtom->charge = atomChargePool[one->sSet.chargeIdx];
5093  fAtom->mass = atomMassPool[one->sSet.massIdx];
5094  // Using double precision division for reciprocal mass.
5095  fAtom->recipMass = ( fAtom->mass > 0 ? (1. / fAtom->mass) : 0 );
5096  fAtom->sigId = one->iSet.atomSigIdx;
5097  fAtom->exclId = one->iSet.exclSigIdx;
5098  fAtom->vdwType = one->sSet.vdw_type;
5099 
5100  //atoms[i].vdw_type = sIdx[8];
5101 
5102  int residue_number; //for residue number
5103  residue_number = one->iSet.resID;
5104 
5105  /*
5106  atoms[i].partner = iIdx[2];
5107  atoms[i].hydrogenList= iIdx[3];
5108  */
5109 
5110  fAtom->id=aid;
5111  fAtom->atomFixed = 0;
5112  fAtom->hydList = one->iSet.hydrogenList;
5113  fAtom->hydrogenGroupSize=one->iSet.atomsInGroup;
5114  fAtom->GPID=one->iSet.GPID;
5115  //fAtom->waterVal=one->waterVal;
5117  fAtom->MPID=one->iSet.MPID;
5118  fAtom->isGP=(fAtom->hydrogenGroupSize ? 1 : 0);
5119  fAtom->isMP=( fAtom->migrationGroupSize ? 1 : 0 );
5120 
5121  if(simParams->rigidBonds) {
5122  fAtom->rigidBondLength = one->fSet.rigidBondLength;
5123  }else{
5124  fAtom->rigidBondLength = 0.0;
5125  }
5126 
5127  //Node::Object()->ioMgr->maxAtom=fAtom.id;
5128 
5129  /*if (isOccupancyValid)
5130  occupancy[i] = tmpf[0];
5131  if (isBFactorValid)
5132  bfactor[i] = tmpf[1];*/
5133 
5134  /*
5136  if (tmpResLookup) tmpResLookup =
5137  tmpResLookup->append(segment_name, residue_number, i);
5138  */
5139 
5140  Real thisAtomMass = fAtom->mass;
5141 
5142  if ( simParams->ignoreMass ) {
5143  } else if (thisAtomMass <= 0.05) {
5144  fAtom->status |= LonepairAtom;
5145  } else if (thisAtomMass < 1.0) {
5146  fAtom->status |= DrudeAtom;
5147  } else if (thisAtomMass <= 3.5) {
5148  fAtom->status = HydrogenAtom;
5149  } else if (thisAtomName[0]=='O' &&
5150  (thisAtomMass >= 14.0) && (thisAtomMass <= 18.0)) {
5151  fAtom->status = OxygenAtom;
5152  }
5153 
5154  //Move the langevinParam setting which depends on atom's status
5155  //to the time when each home patch is filled with their atoms
5156  //(WorkDistrib::fillAtomListForOnePatch so that "langevinParam"
5157  //could be shared with the "hydVal".
5158  //--Chao Mei
5159 }
5160 
5161 //Well, the exclusion check signatures could also done on PE0 and
5162 //sent to other processors through send_Molecule/receive_Molecule
5163 //two procedures.
5164 void Molecule::build_excl_check_signatures(){
5165  exclChkSigPool = new ExclusionCheck[exclSigPoolSize];
5166  for(int i=0; i<exclSigPoolSize; i++){
5167  ExclusionSignature *sig = &exclSigPool[i];
5168  ExclusionCheck *sigChk = &exclChkSigPool[i];
5169  if(sig->fullExclCnt){
5170  if(!sig->modExclCnt){ //only having fullExclusion
5171  sigChk->min = sig->fullOffset[0];
5172  sigChk->max = sig->fullOffset[sig->fullExclCnt-1];
5173  }else{ //have both full and modified exclusion
5174  int fullMin, fullMax, modMin, modMax;
5175 
5176  fullMin = sig->fullOffset[0];
5177  fullMax = sig->fullOffset[sig->fullExclCnt-1];
5178 
5179  modMin = sig->modOffset[0];
5180  modMax = sig->modOffset[sig->modExclCnt-1];
5181 
5182  if(fullMin < modMin)
5183  sigChk->min = fullMin;
5184  else
5185  sigChk->min = modMin;
5186  if(fullMax < modMax)
5187  sigChk->max = modMax;
5188  else
5189  sigChk->max = fullMax;
5190  }
5191  }else{
5192  if(sig->modExclCnt){
5193  sigChk->min = sig->modOffset[0];
5194  sigChk->max = sig->modOffset[sig->modExclCnt-1];
5195  }else{ //both count are 0
5196  if(CkMyPe()==0)
5197  iout << iWARN << "an empty exclusion signature with index "
5198  << i << "!\n" << endi;
5199  continue;
5200  }
5201  }
5202 
5203  sigChk->flags = new char[sigChk->max-sigChk->min+1];
5204  memset(sigChk->flags, 0, sizeof(char)*(sigChk->max-sigChk->min+1));
5205  for(int j=0; j<sig->fullExclCnt; j++){
5206  int dist = sig->fullOffset[j] - sigChk->min;
5207  sigChk->flags[dist] = EXCHCK_FULL;
5208  }
5209  for(int j=0; j<sig->modExclCnt; j++){
5210  int dist = sig->modOffset[j] - sigChk->min;
5211  sigChk->flags[dist] = EXCHCK_MOD;
5212  }
5213  }
5214 }
5215 
5225 void Molecule::load_atom_set(StringList *setfile, const char *setname,
5226  int *numAtomsInSet, AtomSetList **atomsSet) const {
5227  if(setfile == NULL) {
5228  char errmsg[128];
5229  sprintf(errmsg,"The text input file for %s atoms is not found!", setname);
5230  NAMD_die(errmsg);
5231  }
5232  FILE *ifp = fopen(setfile->data, "r");
5233 
5234  if(ifp==NULL){
5235  char errmsg[128];
5236  sprintf(errmsg, "ERROR IN OPENING %s ATOMS FILE: %s\n", setname, setfile->data);
5237  NAMD_die(errmsg);
5238  }
5239 
5240  char oneline[128];
5241  int numLocalAtoms = 0;
5242  AtomSet one;
5243  AtomSetList *localAtomsSet = new AtomSetList();
5244  while(1) {
5245  int ret = NAMD_read_line(ifp, oneline, 128);
5246  if(ret!=0) break;
5247  if(NAMD_blank_string(oneline)) continue;
5248  bool hasDash = false;
5249  for(int i=0; oneline[i] && i<128; i++){
5250  if(oneline[i]=='-') {
5251  hasDash = true;
5252  break;
5253  }
5254  }
5255  if(hasDash) {
5256  sscanf(oneline,"%d-%d", &(one.aid1), &(one.aid2));
5257  if(one.aid1>one.aid2 || one.aid1<0 || one.aid2<0) {
5258  char errmsg[512];
5259  sprintf(errmsg, "The input for %s atoms is wrong: %s\n", setname, oneline);
5260  NAMD_die(errmsg);
5261  }
5262  numLocalAtoms += (one.aid2-one.aid1+1);
5263  }else{
5264  sscanf(oneline, "%d", &(one.aid1));
5265  if(one.aid1<0) {
5266  char errmsg[512];
5267  sprintf(errmsg, "The input for %s atoms is wrong: %s\n", setname, oneline);
5268  NAMD_die(errmsg);
5269  }
5270  one.aid2 = one.aid1;
5271  numLocalAtoms++;
5272  }
5273  localAtomsSet->add(one);
5274  }
5275  //sort the localAtomsSet for binary search to decide
5276  //whether an atom is in the set or not
5277  std::sort(localAtomsSet->begin(), localAtomsSet->end());
5278 
5279  *numAtomsInSet = numLocalAtoms;
5280  *atomsSet = localAtomsSet;
5281 }
5282 
5283 void Molecule::load_fixed_atoms(StringList *fixedfile){
5284  load_atom_set(fixedfile, "FIXED", &numFixedAtoms, &fixedAtomsSet);
5285 }
5286 
5287 void Molecule::load_constrained_atoms(StringList *constrainedfile){
5288  load_atom_set(constrainedfile, "CONSTRAINED", &numConstraints, &constrainedAtomsSet);
5289 }
5290 
5291 Bool Molecule::is_atom_in_set(AtomSetList *localAtomsSet, int aid, int *listIdx) const {
5292  int idx = localAtomsSet->size();
5293  int rIdx = 0;
5294  int lIdx = localAtomsSet->size()-1;
5295 
5296  while(rIdx <= lIdx){
5297  int mIdx = (rIdx+lIdx)/2;
5298  const AtomSet one = localAtomsSet->item(mIdx);
5299 
5300  if(aid < one.aid1){
5301  //aid could be in [rIdx, mIdx);
5302  idx = mIdx;
5303  lIdx = mIdx-1;
5304  }else if(aid > one.aid1){
5305  //aid could be inside the atom set "one" or in (mIdx, lIdx];
5306  if(aid<=one.aid2){
5307  //found, aid in the atom set "one"
5308  if(listIdx) *listIdx = mIdx;
5309  return 1;
5310  }else{
5311  rIdx = mIdx+1;
5312  }
5313  }else{
5314  //found, aid is exactly same with one.aid1
5315  if(listIdx) *listIdx = mIdx;
5316  return 1;
5317  }
5318  }
5319 
5320  //not found
5321  if(listIdx) *listIdx = idx;
5322  return 0;
5323 }
5324 
5325 #endif
5326 
5327 
5328 /************************************************************************/
5329 /* */
5330 /* FUNCTION print_atoms */
5331 /* */
5332 /* print_atoms prints out the list of atoms stored in this object. */
5333 /* It is inteded mainly for debugging purposes. */
5334 /* */
5335 /************************************************************************/
5336 
5338 {
5339 #ifdef MEM_OPT_VERSION
5340  DebugM(2, "WARNING: this function is not availabe in memory optimized version!\n" << endi);
5341 #else
5342  register int i;
5343  Real sigma;
5344  Real epsilon;
5345  Real sigma14;
5346  Real epsilon14;
5347 
5348  DebugM(2,"ATOM LIST\n" \
5349  << "******************************************\n" \
5350  << "NUM NAME TYPE RES MASS CHARGE CHARGE FEP-CHARGE" \
5351  << "SIGMA EPSILON SIGMA14 EPSILON14\n" \
5352  << endi);
5353 
5354  for (i=0; i<numAtoms; i++)
5355  {
5356  params->get_vdw_params(&sigma, &epsilon, &sigma14, &epsilon14,
5357  atoms[i].vdw_type);
5358 
5359  DebugM(2,i+1 << " " << atomNames[i].atomname \
5360  << " " << atomNames[i].atomtype << " " \
5361  << atomNames[i].resname << " " << atoms[i].mass \
5362  << " " << atoms[i].charge << " " << sigma \
5363  << " " << epsilon << " " << sigma14 \
5364  << " " << epsilon14 << "\n" \
5365  << endi);
5366  }
5367 #endif
5368 }
5369 /* END OF FUNCTION print_atoms */
5370 
5371 /************************************************************************/
5372 /* */
5373 /* FUNCTION print_bonds */
5374 /* */
5375 /* print_bonds prints out the list of bonds stored in this object. */
5376 /* It is inteded mainly for debugging purposes. */
5377 /* */
5378 /************************************************************************/
5379 
5381 {
5382 #ifdef MEM_OPT_VERSION
5383  DebugM(2, "WARNING: this function is not availabe in memory optimized version!\n" << endi);
5384 #else
5385  register int i;
5386  Real k;
5387  Real x0;
5388 
5389  DebugM(2,"BOND LIST\n" << "********************************\n" \
5390  << "ATOM1 ATOM2 TYPE1 TYPE2 k x0" \
5391  << endi);
5392 
5393  for (i=0; i<numBonds; i++)
5394  {
5395  params->get_bond_params(&k, &x0, bonds[i].bond_type);
5396 
5397  DebugM(2,bonds[i].atom1+1 << " " \
5398  << bonds[i].atom2+1 << " " \
5399  << atomNames[bonds[i].atom1].atomtype << " " \
5400  << atomNames[bonds[i].atom2].atomtype << " " << k \
5401  << " " << x0 << endi);
5402  }
5403 
5404 #endif
5405 }
5406 /* END OF FUNCTION print_bonds */
5407 
5408 /************************************************************************/
5409 /* */
5410 /* FUNCTION print_exclusions */
5411 /* */
5412 /* print_exlcusions prints out the list of exlcusions stored in */
5413 /* this object. It is inteded mainly for debugging purposes. */
5414 /* */
5415 /************************************************************************/
5416 
5418 {
5419 #ifdef MEM_OPT_VERSION
5420  DebugM(2, "WARNING: this function is not availabe in memory optimized version!\n" << endi);
5421 #else
5422  register int i;
5423 
5424  DebugM(2,"EXPLICIT EXCLUSION LIST\n" \
5425  << "********************************\n" \
5426  << "ATOM1 ATOM2 " \
5427  << endi);
5428 
5429  for (i=0; i<numExclusions; i++)
5430  {
5431  DebugM(2,exclusions[i].atom1+1 << " " \
5432  << exclusions[i].atom2+1 << endi);
5433  }
5434 #endif
5435 }
5436 /* END OF FUNCTION print_exclusions */
5437 
5438 /************************************************************************/
5439 /* */
5440 /* FUNCTION send_Molecule */
5441 /* */
5442 /* send_Molecule is used by the Master node to distribute the */
5443 /* structural information to all the client nodes. It is NEVER called*/
5444 /* by the client nodes. */
5445 /* */
5446 /************************************************************************/
5447 
5449 #ifdef MEM_OPT_VERSION
5450 //in the memory optimized version, only the atom signatures are broadcast
5451 //to other Nodes. --Chao Mei
5452 
5453  msg->put(numAtoms);
5454 
5455  msg->put(massPoolSize);
5456  msg->put(massPoolSize, atomMassPool);
5457 
5458  msg->put(chargePoolSize);
5459  msg->put(chargePoolSize, atomChargePool);
5460 
5461  //put atoms' signatures
5462  msg->put(atomSigPoolSize);
5463  for(int i=0; i<atomSigPoolSize; i++)
5464  atomSigPool[i].pack(msg);
5465 
5466  //put atom's exclusion signatures
5467  msg->put(exclSigPoolSize);
5468  for(int i=0; i<exclSigPoolSize; i++)
5469  exclSigPool[i].pack(msg);
5470 
5471  msg->put(numHydrogenGroups);
5472  msg->put(maxHydrogenGroupSize);
5473  msg->put(numMigrationGroups);
5474  msg->put(maxMigrationGroupSize);
5475  msg->put(isOccupancyValid);
5476  msg->put(isBFactorValid);
5477 
5478  //put names for atoms
5479  msg->put(atomNamePoolSize);
5480  for(int i=0; i<atomNamePoolSize;i++) {
5481  int len = strlen(atomNamePool[i]);
5482  msg->put(len);
5483  msg->put(len*sizeof(char), atomNamePool[i]);
5484  }
5485 
5486  if(simParams->fixedAtomsOn){
5487  int numFixedAtomsSet = fixedAtomsSet->size();
5488  msg->put(numFixedAtoms);
5489  msg->put(numFixedAtomsSet);
5490  msg->put(numFixedAtomsSet*sizeof(AtomSet), (char *)(fixedAtomsSet->begin()));
5491  }
5492 
5493  if (simParams->constraintsOn) {
5494  int numConstrainedAtomsSet = constrainedAtomsSet->size();
5495  msg->put(numConstraints);
5496  msg->put(numConstrainedAtomsSet);
5497  msg->put(numConstrainedAtomsSet*sizeof(AtomSet), (char *)(constrainedAtomsSet->begin()));
5498  }
5499 
5500 #else
5501  msg->put(numAtoms);
5502  msg->put(numAtoms*sizeof(Atom), (char*)atoms);
5503 
5504  // Send the bond information
5505  msg->put(numRealBonds);
5506  msg->put(numBonds);
5507 
5508  if (numBonds)
5509  {
5510  msg->put(numBonds*sizeof(Bond), (char*)bonds);
5511  }
5512 
5513  // Send the angle information
5514  msg->put(numAngles);
5515  if (numAngles)
5516  {
5517  msg->put(numAngles*sizeof(Angle), (char*)angles);
5518  }
5519 
5520  // Send the dihedral information
5521  msg->put(numDihedrals);
5522  if (numDihedrals)
5523  {
5524  msg->put(numDihedrals*sizeof(Dihedral), (char*)dihedrals);
5525  }
5526 
5527  if (simParams->sdScaling) {
5528  msg->put(num_alch_unpert_Bonds);
5529  msg->put(num_alch_unpert_Bonds*sizeof(Bond), (char*)alch_unpert_bonds);
5530 
5531  msg->put(num_alch_unpert_Angles);
5532  msg->put(num_alch_unpert_Angles*sizeof(Angle), (char*)alch_unpert_angles);
5533 
5534  msg->put(num_alch_unpert_Dihedrals);
5535  msg->put(num_alch_unpert_Dihedrals*sizeof(Dihedral), (char*)alch_unpert_dihedrals);
5536  }
5537 
5538  // Send the improper information
5539  msg->put(numImpropers);
5540  if (numImpropers)
5541  {
5542  msg->put(numImpropers*sizeof(Improper), (char*)impropers);
5543  }
5544 
5545  // Send the crossterm information
5546  msg->put(numCrossterms);
5547  if (numCrossterms)
5548  {
5549  msg->put(numCrossterms*sizeof(Crossterm), (char*)crossterms);
5550  }
5551 
5552  // send the hydrogen bond donor information
5553  msg->put(numDonors);
5554  if(numDonors)
5555  {
5556  msg->put(numDonors*sizeof(Bond), (char*)donors);
5557  }
5558 
5559  // send the hydrogen bond acceptor information
5560  msg->put(numAcceptors);
5561  if(numAcceptors)
5562  {
5563  msg->put(numAcceptors*sizeof(Bond), (char*)acceptors);
5564  }
5565 
5566  // Send the exclusion information
5567  msg->put(numExclusions);
5568  if (numExclusions)
5569  {
5570  msg->put(numExclusions*sizeof(Exclusion), (char*)exclusions);
5571  }
5572  // Send the constraint information, if used
5573  if (simParams->constraintsOn)
5574  {
5575  msg->put(numConstraints);
5576 
5577  msg->put(numAtoms, consIndexes);
5578 
5579  if (numConstraints)
5580  {
5581  msg->put(numConstraints*sizeof(ConstraintParams), (char*)consParams);
5582  }
5583  }
5584 #endif
5585 
5586  /* BEGIN gf */
5587  // Send the gridforce information, if used
5588  if (simParams->mgridforceOn)
5589  {
5590  DebugM(3, "Sending gridforce info\n" << endi);
5591  msg->put(numGridforceGrids);
5592 
5593  for (int gridnum = 0; gridnum < numGridforceGrids; gridnum++) {
5594  msg->put(numGridforces[gridnum]);
5595  msg->put(numAtoms, gridfrcIndexes[gridnum]);
5596  if (numGridforces[gridnum])
5597  {
5598  msg->put(numGridforces[gridnum]*sizeof(GridforceParams), (char*)gridfrcParams[gridnum]);
5599  }
5600  GridforceGrid::pack_grid(gridfrcGrid[gridnum], msg);
5601  }
5602  }
5603  /* END gf */
5604 
5605  // Send the stirring information, if used
5606  if (simParams->stirOn)
5607  {
5608  //CkPrintf ("DEBUG: putting numStirredAtoms..\n");
5609  msg->put(numStirredAtoms);
5610  //CkPrintf ("DEBUG: putting numAtoms,stirIndexes.. numAtoms=%d\n",numStirredAtoms);
5611  msg->put(numAtoms, stirIndexes);
5612  //CkPrintf ("DEBUG: if numStirredAtoms..\n");
5613  if (numStirredAtoms)
5614  {
5615  //CkPrintf ("DEBUG: big put, with (char*)stirParams\n");
5616  msg->put(numStirredAtoms*sizeof(StirParams), (char*)stirParams);
5617  }
5618  }
5619 
5620 
5621  // Send the moving drag information, if used
5622  if (simParams->movDragOn) {
5623  msg->put(numMovDrag);
5624  msg->put(numAtoms, movDragIndexes);
5625  if (numMovDrag)
5626  {
5627  msg->put(numMovDrag*sizeof(MovDragParams), (char*)movDragParams);
5628  }
5629  }
5630 
5631  // Send the rotating drag information, if used
5632  if (simParams->rotDragOn) {
5633  msg->put(numRotDrag);
5634  msg->put(numAtoms, rotDragIndexes);
5635  if (numRotDrag)
5636  {
5637  msg->put(numRotDrag*sizeof(RotDragParams), (char*)rotDragParams);
5638  }
5639  }
5640 
5641  // Send the "constant" torque information, if used
5642  if (simParams->consTorqueOn) {
5643  msg->put(numConsTorque);
5644  msg->put(numAtoms, consTorqueIndexes);
5645  if (numConsTorque)
5646  {
5647  msg->put(numConsTorque*sizeof(ConsTorqueParams), (char*)consTorqueParams);
5648  }
5649  }
5650 
5651  // Send the constant force information, if used
5652  if (simParams->consForceOn)
5653  { msg->put(numConsForce);
5654  msg->put(numAtoms, consForceIndexes);
5655  if (numConsForce)
5656  msg->put(numConsForce*sizeof(Vector), (char*)consForce);
5657  }
5658 
5659  if (simParams->excludeFromPressure) {
5660  msg->put(numExPressureAtoms);
5661  msg->put(numAtoms, exPressureAtomFlags);
5662  }
5663 
5664 #ifndef MEM_OPT_VERSION
5665  // Send the langevin parameters, if active
5666  if (simParams->langevinOn || simParams->tCoupleOn)
5667  {
5668  msg->put(numAtoms, langevinParams);
5669  }
5670 
5671  // Send fixed atoms, if active
5672  if (simParams->fixedAtomsOn)
5673  {
5674  msg->put(numFixedAtoms);
5675  msg->put(numAtoms, fixedAtomFlags);
5676  msg->put(numFixedRigidBonds);
5677  }
5678 
5679  if (simParams->qmForcesOn)
5680  {
5681  msg->put(numAtoms, qmAtomGroup);
5682  msg->put(qmNumQMAtoms);
5683  msg->put(qmNumQMAtoms, qmAtmChrg);
5684  msg->put(qmNumQMAtoms, qmAtmIndx);
5685  msg->put(qmNoPC);
5686  msg->put(qmNumBonds);
5687  msg->put(qmMeNumBonds);
5688  msg->put(qmMeNumBonds, qmMeMMindx);
5689  msg->put(qmMeNumBonds, qmMeQMGrp);
5690  msg->put(qmPCFreq);
5691  msg->put(qmNumGrps);
5692  msg->put(qmNumGrps, qmGrpID);
5693  msg->put(qmNumGrps, qmCustPCSizes);
5694  msg->put(qmTotCustPCs);
5695  msg->put(qmTotCustPCs, qmCustomPCIdxs);
5696  }
5697 
5698  //fepb
5699  // send fep atom info
5700  if (simParams->alchOn || simParams->lesOn || simParams->pairInteractionOn) {
5701  msg->put(numFepInitial);
5702  msg->put(numFepFinal);
5703  msg->put(numAtoms*sizeof(char), (char*)fepAtomFlags);
5704  }
5705  //fepe
5706 
5707  if (simParams->soluteScalingOn) {
5708  msg->put(numAtoms*sizeof(char), (char*)ssAtomFlags);
5709  msg->put(ss_num_vdw_params);
5710  msg->put(params->get_num_vdw_params()*sizeof(int), (char*)ss_vdw_type);
5711  msg->put(numAtoms*sizeof(int), (char*)ss_index);
5712  }
5713 
5714  #ifdef OPENATOM_VERSION
5715  // needs to be refactored into its own openatom version
5716  if (simParams->openatomOn ) {
5717  msg->put(numFepInitial);
5718  msg->put(numAtoms*sizeof(char), (char*)fepAtomFlags);
5719  }
5720  #endif //OPENATOM_VERSION
5721 
5722  // DRUDE: send data read from PSF
5723  msg->put(is_lonepairs_psf);
5724  if (is_lonepairs_psf) {
5725  msg->put(numLphosts);
5726  msg->put(numLphosts*sizeof(Lphost), (char*)lphosts);
5727  }
5728  msg->put(is_drude_psf);
5729  if (is_drude_psf) {
5730  msg->put(numAtoms*sizeof(DrudeConst), (char*)drudeConsts);
5731  msg->put(numTholes);
5732  msg->put(numTholes*sizeof(Thole), (char*)tholes);
5733  msg->put(numAnisos);
5734  msg->put(numAnisos*sizeof(Aniso), (char*)anisos);
5735  }
5736  msg->put(numZeroMassAtoms);
5737  // DRUDE
5738 
5739  //LCPO
5740  if (simParams->LCPOOn) {
5741  msg->put(numAtoms, (int*)lcpoParamType);
5742  }
5743 
5744  //Send GromacsPairStuff -- JLai
5745  if (simParams->goGroPair) {
5746  msg->put(numLJPair);
5747  msg->put(numLJPair,indxLJA);
5748  msg->put(numLJPair,indxLJB);
5749  msg->put(numLJPair,pairC6);
5750  msg->put(numLJPair,pairC12);
5751  msg->put(numLJPair,gromacsPair_type);
5752  msg->put((numAtoms),pointerToLJBeg);
5753  msg->put((numAtoms),pointerToLJEnd);
5754  msg->put(numGaussPair);
5755  msg->put(numGaussPair,indxGaussA);
5756  msg->put(numGaussPair,indxGaussB);
5757  msg->put(numGaussPair,gA);
5758  msg->put(numGaussPair,gMu1);
5759  msg->put(numGaussPair,giSigma1);
5760  msg->put(numGaussPair,gMu2);
5761  msg->put(numGaussPair,giSigma2);
5762  msg->put(numGaussPair,gRepulsive);
5763  msg->put((numAtoms),pointerToGaussBeg);
5764  msg->put((numAtoms),pointerToGaussEnd);
5765  }
5766 #endif
5767 
5768  // Broadcast the message to the other nodes
5769  msg->end();
5770  delete msg;
5771 
5772 #ifdef MEM_OPT_VERSION
5773 
5774  build_excl_check_signatures();
5775 
5776  //set num{Calc}Tuples(Bonds,...,Impropers) to 0
5777  numBonds = numCalcBonds = 0;
5778  numAngles = numCalcAngles = 0;
5779  numDihedrals = numCalcDihedrals = 0;
5780  numImpropers = numCalcImpropers = 0;
5781  numCrossterms = numCalcCrossterms = 0;
5782  numTotalExclusions = numCalcExclusions = numCalcFullExclusions = 0;
5783  // JLai
5784  numLJPair = numCalcLJPair = 0;
5785  // End of JLai
5786 
5787 #else
5788 
5789  // Now build arrays of indexes into these arrays by atom
5790  build_lists_by_atom();
5791 
5792 #endif
5793 }
5794  /* END OF FUNCTION send_Molecule */
5795 
5796  /************************************************************************/
5797  /* */
5798  /* FUNCTION receive_Molecule */
5799  /* */
5800  /* receive_Molecule is used by all the clients to receive the */
5801  /* structural data sent out by the master node. It is NEVER called */
5802  /* by the Master node. */
5803  /* */
5804  /************************************************************************/
5805 
5807  // Get the atom information
5808  msg->get(numAtoms);
5809 
5810 #ifdef MEM_OPT_VERSION
5811 //in the memory optimized version, only the atom signatures are recved
5812 //from the master Node. --Chao Mei
5813 
5814  msg->get(massPoolSize);
5815  if(atomMassPool) delete [] atomMassPool;
5816  atomMassPool = new Real[massPoolSize];
5817  msg->get(massPoolSize, atomMassPool);
5818 
5819  msg->get(chargePoolSize);
5820  if(atomChargePool) delete [] atomChargePool;
5821  atomChargePool = new Real[chargePoolSize];
5822  msg->get(chargePoolSize, atomChargePool);
5823 
5824  //get atoms' signatures
5825  msg->get(atomSigPoolSize);
5826  if(atomSigPool) delete [] atomSigPool;
5827  atomSigPool = new AtomSignature[atomSigPoolSize];
5828  for(int i=0; i<atomSigPoolSize; i++)
5829  atomSigPool[i].unpack(msg);
5830 
5831  //get exclusions' signatures
5832  msg->get(exclSigPoolSize);
5833  if(exclSigPool) delete [] exclSigPool;
5834  exclSigPool = new ExclusionSignature[exclSigPoolSize];
5835  for(int i=0; i<exclSigPoolSize; i++)
5836  exclSigPool[i].unpack(msg);
5837 
5838  msg->get(numHydrogenGroups);
5839  msg->get(maxHydrogenGroupSize);
5840  msg->get(numMigrationGroups);
5841  msg->get(maxMigrationGroupSize);
5842  msg->get(isOccupancyValid);
5843  msg->get(isBFactorValid);
5844 
5845  //get names for atoms
5846  msg->get(atomNamePoolSize);
5847  atomNamePool = new char *[atomNamePoolSize];
5848  for(int i=0; i<atomNamePoolSize;i++) {
5849  int len;
5850  msg->get(len);
5851  atomNamePool[i] = nameArena->getNewArray(len+1);
5852  msg->get(len, atomNamePool[i]);
5853  }
5854 
5855  if(simParams->fixedAtomsOn){
5856  int numFixedAtomsSet;
5857  msg->get(numFixedAtoms);
5858  msg->get(numFixedAtomsSet);
5859  fixedAtomsSet = new AtomSetList(numFixedAtomsSet);
5860  msg->get(numFixedAtomsSet*sizeof(AtomSet), (char *)(fixedAtomsSet->begin()));
5861  }
5862 
5863  if(simParams->constraintsOn){
5864  int numConstrainedAtomsSet;
5865  msg->get(numConstraints);
5866  msg->get(numConstrainedAtomsSet);
5867  constrainedAtomsSet = new AtomSetList(numConstrainedAtomsSet);
5868  msg->get(numConstrainedAtomsSet*sizeof(AtomSet), (char *)(constrainedAtomsSet->begin()));
5869  }
5870 
5871 #else
5872  delete [] atoms;
5873  atoms= new Atom[numAtoms];
5874  msg->get(numAtoms*sizeof(Atom), (char*)atoms);
5875 
5876  // Get the bond information
5877  msg->get(numRealBonds);
5878  msg->get(numBonds);
5879  if (numBonds)
5880  {
5881  delete [] bonds;
5882  bonds=new Bond[numBonds];
5883  msg->get(numBonds*sizeof(Bond), (char*)bonds);
5884  }
5885 
5886  // Get the angle information
5887  msg->get(numAngles);
5888  if (numAngles)
5889  {
5890  delete [] angles;
5891  angles=new Angle[numAngles];
5892  msg->get(numAngles*sizeof(Angle), (char*)angles);
5893  }
5894 
5895  // Get the dihedral information
5896  msg->get(numDihedrals);
5897  if (numDihedrals)
5898  {
5899  delete [] dihedrals;
5900  dihedrals=new Dihedral[numDihedrals];
5901  msg->get(numDihedrals*sizeof(Dihedral), (char*)dihedrals);
5902  }
5903 
5904  if (simParams->sdScaling) {
5905  msg->get(num_alch_unpert_Bonds);
5906  alch_unpert_bonds=new Bond[num_alch_unpert_Bonds];
5907  msg->get(num_alch_unpert_Bonds*sizeof(Bond), (char*)alch_unpert_bonds);
5908 
5909  msg->get(num_alch_unpert_Angles);
5910  alch_unpert_angles=new Angle[num_alch_unpert_Angles];
5911  msg->get(num_alch_unpert_Angles*sizeof(Angle), (char*)alch_unpert_angles);
5912 
5913  msg->get(num_alch_unpert_Dihedrals);
5914  alch_unpert_dihedrals=new Dihedral[num_alch_unpert_Dihedrals];
5915  msg->get(num_alch_unpert_Dihedrals*sizeof(Dihedral), (char*)alch_unpert_dihedrals);
5916  }
5917 
5918  // Get the improper information
5919  msg->get(numImpropers);
5920  if (numImpropers)
5921  {
5922  delete [] impropers;
5923  impropers=new Improper[numImpropers];
5924  msg->get(numImpropers*sizeof(Improper), (char*)impropers);
5925  }
5926 
5927  // Get the crossterm information
5928  msg->get(numCrossterms);
5929  if (numCrossterms)
5930  {
5931  delete [] crossterms;
5932  crossterms=new Crossterm[numCrossterms];
5933  msg->get(numCrossterms*sizeof(Crossterm), (char*)crossterms);
5934  }
5935 
5936  // Get the hydrogen bond donors
5937  msg->get(numDonors);
5938  if (numDonors)
5939  {
5940  delete [] donors;
5941  donors=new Bond[numDonors];
5942  msg->get(numDonors*sizeof(Bond), (char*)donors);
5943  }
5944 
5945  // Get the hydrogen bond acceptors
5946  msg->get(numAcceptors);
5947  if (numAcceptors)
5948  {
5949  delete [] acceptors;
5950  acceptors=new Bond[numAcceptors];
5951  msg->get(numAcceptors*sizeof(Bond), (char*)acceptors);
5952  }
5953 
5954  // Get the exclusion information
5955  msg->get(numExclusions);
5956  if (numExclusions)
5957  {
5958  delete [] exclusions;
5959  exclusions=new Exclusion[numExclusions];
5960  msg->get(numExclusions*sizeof(Exclusion), (char*)exclusions);
5961  }
5962 
5963  // Get the constraint information, if they are active
5964  if (simParams->constraintsOn)
5965  {
5966  msg->get(numConstraints);
5967 
5968  delete [] consIndexes;
5969  consIndexes = new int32[numAtoms];
5970 
5971  msg->get(numAtoms, consIndexes);
5972 
5973  if (numConstraints)
5974  {
5975  delete [] consParams;
5976  consParams = new ConstraintParams[numConstraints];
5977 
5978  msg->get(numConstraints*sizeof(ConstraintParams), (char*)consParams);
5979  }
5980  }
5981 #endif
5982 
5983  /* BEGIN gf */
5984  if (simParams->mgridforceOn)
5985  {
5986  DebugM(3, "Receiving gridforce info\n");
5987 
5988  msg->get(numGridforceGrids);
5989 
5990  DebugM(3, "numGridforceGrids = " << numGridforceGrids << "\n");
5991 
5992  delete [] numGridforces;
5993  numGridforces = new int[numGridforceGrids];
5994 
5995  delete [] gridfrcIndexes; // Should I be deleting elements of these first?
5996  delete [] gridfrcParams;
5997  delete [] gridfrcGrid;
5998  gridfrcIndexes = new int32*[numGridforceGrids];
5999  gridfrcParams = new GridforceParams*[numGridforceGrids];
6000  gridfrcGrid = new GridforceGrid*[numGridforceGrids];
6001 
6002  int grandTotalGrids = 0;
6003  for (int gridnum = 0; gridnum < numGridforceGrids; gridnum++) {
6004  msg->get(numGridforces[gridnum]);
6005 
6006  gridfrcIndexes[gridnum] = new int32[numAtoms];
6007  msg->get(numAtoms, gridfrcIndexes[gridnum]);
6008 
6009  if (numGridforces[gridnum])
6010  {
6011  gridfrcParams[gridnum] = new GridforceParams[numGridforces[gridnum]];
6012  msg->get(numGridforces[gridnum]*sizeof(GridforceParams), (char*)gridfrcParams[gridnum]);
6013  }
6014 
6015  gridfrcGrid[gridnum] = GridforceGrid::unpack_grid(gridnum, msg);
6016 
6017  grandTotalGrids += gridfrcGrid[gridnum]->get_total_grids();
6018  }
6019  }
6020  /* END gf */
6021 
6022  // Get the stirring information, if stirring is active
6023  if (simParams->stirOn)
6024  {
6025  msg->get(numStirredAtoms);
6026 
6027  delete [] stirIndexes;
6028  stirIndexes = new int32[numAtoms];
6029 
6030  msg->get(numAtoms, stirIndexes);
6031 
6032  if (numStirredAtoms)
6033  {
6034  delete [] stirParams;
6035  stirParams = new StirParams[numStirredAtoms];
6036 
6037  msg->get(numStirredAtoms*sizeof(StirParams), (char*)stirParams);
6038  }
6039  }
6040 
6041  // Get the moving drag information, if it is active
6042  if (simParams->movDragOn) {
6043  msg->get(numMovDrag);
6044  delete [] movDragIndexes;
6045  movDragIndexes = new int32[numAtoms];
6046  msg->get(numAtoms, movDragIndexes);
6047  if (numMovDrag)
6048  {
6049  delete [] movDragParams;
6050  movDragParams = new MovDragParams[numMovDrag];
6051  msg->get(numMovDrag*sizeof(MovDragParams), (char*)movDragParams);
6052  }
6053  }
6054 
6055  // Get the rotating drag information, if it is active
6056  if (simParams->rotDragOn) {
6057  msg->get(numRotDrag);
6058  delete [] rotDragIndexes;
6059  rotDragIndexes = new int32[numAtoms];
6060  msg->get(numAtoms, rotDragIndexes);
6061  if (numRotDrag)
6062  {
6063  delete [] rotDragParams;
6064  rotDragParams = new RotDragParams[numRotDrag];
6065  msg->get(numRotDrag*sizeof(RotDragParams), (char*)rotDragParams);
6066  }
6067  }
6068 
6069  // Get the "constant" torque information, if it is active
6070  if (simParams->consTorqueOn) {
6071  msg->get(numConsTorque);
6072  delete [] consTorqueIndexes;
6073  consTorqueIndexes = new int32[numAtoms];
6074  msg->get(numAtoms, consTorqueIndexes);
6075  if (numConsTorque)
6076  {
6077  delete [] consTorqueParams;
6078  consTorqueParams = new ConsTorqueParams[numConsTorque];
6079  msg->get(numConsTorque*sizeof(ConsTorqueParams), (char*)consTorqueParams);
6080  }
6081  }
6082 
6083  // Get the constant force information, if it's active
6084  if (simParams->consForceOn)
6085  { msg->get(numConsForce);
6086  delete [] consForceIndexes;
6087  consForceIndexes = new int32[numAtoms];
6088  msg->get(numAtoms, consForceIndexes);
6089  if (numConsForce)
6090  { delete [] consForce;
6091  consForce = new Vector[numConsForce];
6092  msg->get(numConsForce*sizeof(Vector), (char*)consForce);
6093  }
6094  }
6095 
6096  if (simParams->excludeFromPressure) {
6097  exPressureAtomFlags = new int32[numAtoms];
6098  msg->get(numExPressureAtoms);
6099  msg->get(numAtoms, exPressureAtomFlags);
6100  }
6101 
6102 #ifndef MEM_OPT_VERSION
6103  // Get the langevin parameters, if they are active
6104  if (simParams->langevinOn || simParams->tCoupleOn)
6105  {
6106  delete [] langevinParams;
6107  langevinParams = new Real[numAtoms];
6108 
6109  msg->get(numAtoms, langevinParams);
6110  }
6111 
6112  // Get the fixed atoms, if they are active
6113  if (simParams->fixedAtomsOn)
6114  {
6115  delete [] fixedAtomFlags;
6116  fixedAtomFlags = new int32[numAtoms];
6117 
6118  msg->get(numFixedAtoms);
6119  msg->get(numAtoms, fixedAtomFlags);
6120  msg->get(numFixedRigidBonds);
6121  }
6122 
6123  if (simParams->qmForcesOn)
6124  {
6125  if( qmAtomGroup != 0)
6126  delete [] qmAtomGroup;
6127  qmAtomGroup = new Real[numAtoms];
6128 
6129  msg->get(numAtoms, qmAtomGroup);
6130 
6131  msg->get(qmNumQMAtoms);
6132 
6133  if( qmAtmChrg != 0)
6134  delete [] qmAtmChrg;
6135  qmAtmChrg = new Real[qmNumQMAtoms];
6136 
6137  msg->get(qmNumQMAtoms, qmAtmChrg);
6138 
6139  if( qmAtmIndx != 0)
6140  delete [] qmAtmIndx;
6141  qmAtmIndx = new int[qmNumQMAtoms];
6142 
6143  msg->get(qmNumQMAtoms, qmAtmIndx);
6144 
6145  msg->get(qmNoPC);
6146 
6147  msg->get(qmNumBonds);
6148 
6149  msg->get(qmMeNumBonds);
6150 
6151  if( qmMeMMindx != 0)
6152  delete [] qmMeMMindx;
6153  qmMeMMindx = new int[qmMeNumBonds];
6154 
6155  msg->get(qmMeNumBonds, qmMeMMindx);
6156 
6157  if( qmMeQMGrp != 0)
6158  delete [] qmMeQMGrp;
6159  qmMeQMGrp = new Real[qmMeNumBonds];
6160 
6161  msg->get(qmMeNumBonds, qmMeQMGrp);
6162 
6163  msg->get(qmPCFreq);
6164 
6165  msg->get(qmNumGrps);
6166 
6167  if( qmGrpID != 0)
6168  delete [] qmGrpID;
6169  qmGrpID = new Real[qmNumGrps];
6170  msg->get(qmNumGrps, qmGrpID);
6171 
6172  if( qmCustPCSizes != 0)
6173  delete [] qmCustPCSizes;
6174  qmCustPCSizes = new int[qmNumGrps];
6175  msg->get(qmNumGrps, qmCustPCSizes);
6176 
6177  msg->get(qmTotCustPCs);
6178 
6179  if( qmCustomPCIdxs != 0)
6180  delete [] qmCustomPCIdxs;
6181  qmCustomPCIdxs = new int[qmTotCustPCs];
6182  msg->get(qmTotCustPCs, qmCustomPCIdxs);
6183  }
6184 
6185 //fepb
6186  //receive fep atom info
6187  if (simParams->alchOn || simParams->lesOn || simParams->pairInteractionOn) {
6188  delete [] fepAtomFlags;
6189  fepAtomFlags = new unsigned char[numAtoms];
6190 
6191  msg->get(numFepInitial);
6192  msg->get(numFepFinal);
6193  msg->get(numAtoms*sizeof(unsigned char), (char*)fepAtomFlags);
6194  }
6195 //fepe
6196 
6197 //soluteScaling
6198  if (simParams->soluteScalingOn) {
6199  delete [] ssAtomFlags;
6200  delete [] ss_vdw_type;
6201  delete [] ss_index;
6202  ssAtomFlags = new unsigned char[numAtoms];
6203  ss_vdw_type = new int [params->get_num_vdw_params()];
6204  ss_index = new int [numAtoms];
6205  msg->get(numAtoms*sizeof(unsigned char), (char*)ssAtomFlags);
6206  msg->get(ss_num_vdw_params);
6207  msg->get(params->get_num_vdw_params()*sizeof(int), (char*)ss_vdw_type);
6208  msg->get(numAtoms*sizeof(int), (char*)ss_index);
6209  }
6210 //soluteScaling
6211 #ifdef OPENATOM_VERSION
6212  // This needs to be refactored into its own version
6213  if (simParams->openatomOn) {
6214  delete [] fepAtomFlags;
6215  fepAtomFlags = new unsigned char[numAtoms];
6216 
6217  msg->get(numFepInitial);
6218  msg->get(numAtoms*sizeof(unsigned char), (char*)fepAtomFlags);
6219 #endif //OPENATOM_VERSION
6220 
6221  // DRUDE: receive data read from PSF
6222  msg->get(is_lonepairs_psf);
6223  if (is_lonepairs_psf) {
6224  msg->get(numLphosts);
6225  delete[] lphosts;
6226  lphosts = new Lphost[numLphosts];
6227  msg->get(numLphosts*sizeof(Lphost), (char*)lphosts);
6228  }
6229  msg->get(is_drude_psf);
6230  if (is_drude_psf) {
6231  delete[] drudeConsts;
6232  drudeConsts = new DrudeConst[numAtoms];
6233  msg->get(numAtoms*sizeof(DrudeConst), (char*)drudeConsts);
6234  msg->get(numTholes);
6235  delete[] tholes;
6236  tholes = new Thole[numTholes];
6237  msg->get(numTholes*sizeof(Thole), (char*)tholes);
6238  msg->get(numAnisos);
6239  delete[] anisos;
6240  anisos = new Aniso[numAnisos];
6241  msg->get(numAnisos*sizeof(Aniso), (char*)anisos);
6242  }
6243  msg->get(numZeroMassAtoms);
6244  // DRUDE
6245 
6246  //LCPO
6247  if (simParams->LCPOOn) {
6248  delete [] lcpoParamType;
6249  lcpoParamType = new int[numAtoms];
6250  msg->get(numAtoms, (int*)lcpoParamType);
6251  }
6252 
6253  //Receive GromacsPairStuff -- JLai
6254 
6255  if (simParams->goGroPair) {
6256  msg->get(numLJPair);
6257  delete [] indxLJA;
6258  indxLJA = new int[numLJPair];
6259  msg->get(numLJPair,indxLJA);
6260  delete [] indxLJB;
6261  indxLJB = new int[numLJPair];
6262  msg->get(numLJPair,indxLJB);
6263  delete [] pairC6;
6264  pairC6 = new Real[numLJPair];
6265  msg->get(numLJPair,pairC6);
6266  delete [] pairC12;
6267  pairC12 = new Real[numLJPair];
6268  msg->get(numLJPair,pairC12);
6269  delete [] gromacsPair_type;
6270  gromacsPair_type = new int[numLJPair];
6271  msg->get(numLJPair,gromacsPair_type);
6272  delete [] pointerToLJBeg;
6273  pointerToLJBeg = new int[numAtoms];
6274  msg->get((numAtoms),pointerToLJBeg);
6275  delete [] pointerToLJEnd;
6276  pointerToLJEnd = new int[numAtoms];
6277  msg->get((numAtoms),pointerToLJEnd);
6278  // JLai
6279  delete [] gromacsPair;
6281  for(int i=0; i < numLJPair; i++) {
6282  gromacsPair[i].atom1 = indxLJA[i];
6283  gromacsPair[i].atom2 = indxLJB[i];
6284  gromacsPair[i].pairC6 = pairC6[i];
6285  gromacsPair[i].pairC12 = pairC12[i];
6286  gromacsPair[i].gromacsPair_type = gromacsPair_type[i];
6287  }
6288  //
6289  msg->get(numGaussPair);
6290  delete [] indxGaussA;
6291  indxGaussA = new int[numGaussPair];
6292  msg->get(numGaussPair,indxGaussA);
6293  delete [] indxGaussB;
6294  indxGaussB = new int[numGaussPair];
6295  msg->get(numGaussPair,indxGaussB);
6296  delete [] gA;
6297  gA = new Real[numGaussPair];
6298  msg->get(numGaussPair,gA);
6299  delete [] gMu1;
6300  gMu1 = new Real[numGaussPair];
6301  msg->get(numGaussPair,gMu1);
6302  delete [] giSigma1;
6303  giSigma1 = new Real[numGaussPair];
6304  msg->get(numGaussPair,giSigma1);
6305  delete [] gMu2;
6306  gMu2 = new Real[numGaussPair];
6307  msg->get(numGaussPair,gMu2);
6308  delete [] giSigma2;
6309  giSigma2 = new Real[numGaussPair];
6310  msg->get(numGaussPair,giSigma2);
6311  delete [] gRepulsive;
6312  gRepulsive = new Real[numGaussPair];
6313  msg->get(numGaussPair,gRepulsive);
6314  delete [] pointerToGaussBeg;
6315  pointerToGaussBeg = new int[numAtoms];
6316  msg->get((numAtoms),pointerToGaussBeg);
6317  delete [] pointerToGaussEnd;
6318  pointerToGaussEnd = new int[numAtoms];
6319  msg->get((numAtoms),pointerToGaussEnd);
6320  //
6321  }
6322 #endif
6323 
6324  // Now free the message
6325  delete msg;
6326 
6327 #ifdef MEM_OPT_VERSION
6328 
6329  build_excl_check_signatures();
6330 
6331  //set num{Calc}Tuples(Bonds,...,Impropers) to 0
6332  numBonds = numCalcBonds = 0;
6333  numAngles = numCalcAngles = 0;
6334  numDihedrals = numCalcDihedrals = 0;
6335  numImpropers = numCalcImpropers = 0;
6336  numCrossterms = numCalcCrossterms = 0;
6337  numTotalExclusions = numCalcExclusions = numCalcFullExclusions = 0;
6338  // JLai
6339  numLJPair = numCalcLJPair = 0;
6340  // End of JLai
6341 
6342 #else
6343 
6344  // analyze the data and find the status of each atom
6345  build_atom_status();
6346  build_lists_by_atom();
6347 
6348 
6349 #endif
6350 }
6351  /* END OF FUNCTION receive_Molecule */
6352 
6353 /* BEGIN gf */
6354  /************************************************************************/
6355  /* */
6356  /* FUNCTION build_gridforce_params */
6357  /* */
6358  /* INPUTS: */
6359  /* gridfrcfile - Value of gridforcefile from config file */
6360  /* gridfrccol - Value of gridforcecol from config file */
6361  /* gridfrcchrgcol - Value of gridforcechargecol from config file */
6362  /* potfile - Value of gridforcepotfile from config file */
6363  /* initial_pdb - PDB object that contains initial positions */
6364  /* cwd - Current working directory */
6365  /* */
6366  // This function builds all the parameters that are necessary to
6367  // do gridforcing. This involves looking through a PDB object to
6368  // determine which atoms are to be gridforced, and what the force
6369  // multiplier is for each atom. This information is then stored
6370  // in the arrays gridfrcIndexes and gridfrcParams.
6371  /************************************************************************/
6372 
6374  StringList *gridfrccol,
6375  StringList *gridfrcchrgcol,
6376  StringList *potfile,
6377  PDB *initial_pdb,
6378  char *cwd)
6379 {
6380  PDB *kPDB;
6381  register int i; // Loop counters
6382  register int j;
6383  register int k;
6384 
6385  DebugM(3, "Entered build_gridforce_params multi...\n");
6386 // DebugM(3, "\tgridfrcfile = " << gridfrcfile->data << endi);
6387 // DebugM(3, "\tgridfrccol = " << gridfrccol->data << endi);
6388 
6389  MGridforceParams* mgridParams = simParams->mgridforcelist.get_first();
6390  numGridforceGrids = 0;
6391  while (mgridParams != NULL) {
6392  numGridforceGrids++;
6393  mgridParams = mgridParams->next;
6394  }
6395 
6396  DebugM(3, "numGridforceGrids = " << numGridforceGrids << "\n");
6397  gridfrcIndexes = new int32*[numGridforceGrids];
6398  gridfrcParams = new GridforceParams*[numGridforceGrids];
6399  gridfrcGrid = new GridforceGrid*[numGridforceGrids];
6400  numGridforces = new int[numGridforceGrids];
6401 
6402  int grandTotalGrids = 0; // including all subgrids
6403 
6404  mgridParams = simParams->mgridforcelist.get_first();
6405  for (int gridnum = 0; gridnum < numGridforceGrids; gridnum++) {
6406  int current_index=0; // Index into values used
6407  int kcol = 5; // Column to look for force constant in
6408  int qcol = 0; // Column for charge (default 0: use electric charge)
6409  Real kval = 0; // Force constant value retreived
6410  char filename[NAMD_FILENAME_BUFFER_SIZE]; // PDB filename
6411  char potfilename[NAMD_FILENAME_BUFFER_SIZE]; // Potential file name
6412 
6413  if (mgridParams == NULL) {
6414  NAMD_die("Problem with mgridParams!");
6415  }
6416 
6417  // Now load values from mgridforcelist object
6418  if (mgridParams->gridforceFile == NULL)
6419  {
6420  if ( ! initial_pdb ) NAMD_die("Initial PDB file unavailable, gridforceFile required.");
6421  kPDB = initial_pdb;
6422  }
6423  else
6424  {
6425  DebugM(4, "mgridParams->gridforceFile = " << mgridParams->gridforceFile << "\n" << endi);
6426 
6427  if ( (cwd == NULL) || (mgridParams->gridforceFile[0] == '/') )
6428  {
6429  strcpy(filename, mgridParams->gridforceFile);
6430  }
6431  else
6432  {
6433  strcpy(filename, cwd);
6434  strcat(filename, mgridParams->gridforceFile);
6435  }
6436 
6437  kPDB = new PDB(filename);
6438  if ( kPDB == NULL )
6439  {
6440  NAMD_die("Memory allocation failed in Molecule::build_gridforce_params");
6441  }
6442 
6443  if (kPDB->num_atoms() != numAtoms)
6444  {
6445  NAMD_die("Number of atoms in grid force PDB doesn't match coordinate PDB");
6446  }
6447  }
6448 
6449  // Get the column that the force constant is going to be in. It
6450  // can be in any of the 5 floating point fields in the PDB, according
6451  // to what the user wants. The allowable fields are X, Y, Z, O, or
6452  // B which correspond to the 1st, 2nd, ... 5th floating point fields.
6453  // The default is the 5th field, which is beta (temperature factor)
6454  if (mgridParams->gridforceCol == NULL)
6455  {
6456  kcol = 5;
6457  }
6458  else
6459  {
6460  if (strcasecmp(mgridParams->gridforceCol, "X") == 0)
6461  {
6462  kcol=1;
6463  }
6464  else if (strcasecmp(mgridParams->gridforceCol, "Y") == 0)
6465  {
6466  kcol=2;
6467  }
6468  else if (strcasecmp(mgridParams->gridforceCol, "Z") == 0)
6469  {
6470  kcol=3;
6471  }
6472  else if (strcasecmp(mgridParams->gridforceCol, "O") == 0)
6473  {
6474  kcol=4;
6475  }
6476  else if (strcasecmp(mgridParams->gridforceCol, "B") == 0)
6477  {
6478  kcol=5;
6479  }
6480  else
6481  {
6482  NAMD_die("gridforcecol must have value of X, Y, Z, O, or B");
6483  }
6484  }
6485 
6486  // Get the column that the charge is going to be in.
6487  if (mgridParams->gridforceQcol == NULL)
6488  {
6489  qcol = 0; // Default: don't read charge from file, use electric charge
6490  }
6491  else
6492  {
6493  if (strcasecmp(mgridParams->gridforceQcol, "X") == 0)
6494  {
6495  qcol=1;
6496  }
6497  else if (strcasecmp(mgridParams->gridforceQcol, "Y") == 0)
6498  {
6499  qcol=2;
6500  }
6501  else if (strcasecmp(mgridParams->gridforceQcol, "Z") == 0)
6502  {
6503  qcol=3;
6504  }
6505  else if (strcasecmp(mgridParams->gridforceQcol, "O") == 0)
6506  {
6507  qcol=4;
6508  }
6509  else if (strcasecmp(mgridParams->gridforceQcol, "B") == 0)
6510  {
6511  qcol=5;
6512  }
6513  else
6514  {
6515  NAMD_die("gridforcechargecol must have value of X, Y, Z, O, or B");
6516  }
6517  }
6518 
6519  if (kcol == qcol) {
6520  NAMD_die("gridforcecol and gridforcechargecol cannot have same value");
6521  }
6522 
6523 
6524  // Allocate an array that will store an index into the constraint
6525  // parameters for each atom. If the atom is not constrained, its
6526  // value will be set to -1 in this array.
6527  gridfrcIndexes[gridnum] = new int32[numAtoms];
6528 
6529  if (gridfrcIndexes[gridnum] == NULL)
6530  {
6531  NAMD_die("memory allocation failed in Molecule::build_gridforce_params()");
6532  }
6533 
6534  // Loop through all the atoms and find out which ones are constrained
6535  for (i=0; i<numAtoms; i++)
6536  {
6537  // Get the k value based on where we were told to find it
6538  switch (kcol)
6539  {
6540  case 1:
6541  kval = (kPDB->atom(i))->xcoor();
6542  break;
6543  case 2:
6544  kval = (kPDB->atom(i))->ycoor();
6545  break;
6546  case 3:
6547  kval = (kPDB->atom(i))->zcoor();
6548  break;
6549  case 4:
6550  kval = (kPDB->atom(i))->occupancy();
6551  break;
6552  case 5:
6553  kval = (kPDB->atom(i))->temperaturefactor();
6554  break;
6555  }
6556 
6557  if (kval > 0.0)
6558  {
6559  // This atom is constrained
6560  gridfrcIndexes[gridnum][i] = current_index;
6561  current_index++;
6562  }
6563  else
6564  {
6565  // This atom is not constrained
6566  gridfrcIndexes[gridnum][i] = -1;
6567  }
6568  }
6569 
6570  if (current_index == 0)
6571  {
6572  // Constraints were turned on, but there weren't really any constrained
6573  iout << iWARN << "NO GRIDFORCE ATOMS WERE FOUND, BUT GRIDFORCE IS ON . . .\n" << endi;
6574  }
6575  else
6576  {
6577  // Allocate an array to hold the constraint parameters
6578  gridfrcParams[gridnum] = new GridforceParams[current_index];
6579  if (gridfrcParams[gridnum] == NULL)
6580  {
6581  NAMD_die("memory allocation failed in Molecule::build_gridforce_params");
6582  }
6583  }
6584 
6585  numGridforces[gridnum] = current_index;
6586 
6587  // Loop through all the atoms and assign the parameters for those
6588  // that are constrained
6589  for (i=0; i<numAtoms; i++)
6590  {
6591  if (gridfrcIndexes[gridnum][i] != -1)
6592  {
6593  // This atom has grid force, so get the k value again
6594  switch (kcol)
6595  {
6596  case 1:
6597  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].k = (kPDB->atom(i))->xcoor();
6598  break;
6599  case 2:
6600  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].k = (kPDB->atom(i))->ycoor();
6601  break;
6602  case 3:
6603  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].k = (kPDB->atom(i))->zcoor();
6604  break;
6605  case 4:
6606  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].k = (kPDB->atom(i))->occupancy();
6607  break;
6608  case 5:
6609  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].k = (kPDB->atom(i))->temperaturefactor();
6610  break;
6611  }
6612 
6613  // Also get charge column
6614  switch (qcol)
6615  {
6616  case 0:
6617 #ifdef MEM_OPT_VERSION
6618  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = atomChargePool[eachAtomCharge[i]];
6619 #else
6620  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = atoms[i].charge;
6621 #endif
6622  break;
6623  case 1:
6624  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = (kPDB->atom(i))->xcoor();
6625  break;
6626  case 2:
6627  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = (kPDB->atom(i))->ycoor();
6628  break;
6629  case 3:
6630  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = (kPDB->atom(i))->zcoor();
6631  break;
6632  case 4:
6633  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = (kPDB->atom(i))->occupancy();
6634  break;
6635  case 5:
6636  gridfrcParams[gridnum][gridfrcIndexes[gridnum][i]].q = (kPDB->atom(i))->temperaturefactor();
6637  break;
6638  }
6639  }
6640  }
6641 
6642  // If we had to create new PDB objects, delete them now
6643  if (mgridParams->gridforceFile != NULL)
6644  {
6645  delete kPDB;
6646  }
6647 
6648  // Now we fill in our grid information
6649 
6650  // Open potential file
6651  if ( (cwd == NULL) || (mgridParams->gridforceVfile[0] == '/') )
6652  {
6653  strcpy(potfilename, mgridParams->gridforceVfile);
6654  }
6655  else
6656  {
6657  strcpy(potfilename, cwd);
6658  strcat(potfilename, mgridParams->gridforceVfile);
6659  }
6660 
6661 // iout << iINFO << "Allocating grid " << gridnum
6662 // << "\n" << endi;
6663 
6664  DebugM(3, "allocating GridforceGrid(" << gridnum << ")\n");
6665  gridfrcGrid[gridnum] = GridforceGrid::new_grid(gridnum, potfilename, simParams, mgridParams);
6666 
6667  grandTotalGrids += gridfrcGrid[gridnum]->get_total_grids();
6668  DebugM(4, "grandTotalGrids = " << grandTotalGrids << "\n" << endi);
6669 
6670  // Finally, get next mgridParams pointer
6671  mgridParams = mgridParams->next;
6672  }
6673 }
6674 /* END gf */