NAMD
MoleculeQM.C
Go to the documentation of this file.
1 
7 #ifdef DEBUG_QM
8  #define DEBUGM
9 #endif
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15 #include "ResizeArray.h"
16 #include "InfoStream.h"
17 #include "Molecule.h"
18 #include "strlib.h"
19 #include "MStream.h"
20 #include "Communicate.h"
21 #include "Node.h"
22 #include "ObjectArena.h"
23 #include "Parameters.h"
24 #include "PDB.h"
25 #include "SimParameters.h"
26 #include "Hydrogen.h"
27 #include "UniqueSetIter.h"
28 #include "charm++.h"
29 #include "ConfigList.h"
30 
31 #define MIN_DEBUG_LEVEL 3
32 //#define DEBUGM
33 #include "Debug.h"
34 #include "CompressPsf.h"
35 #include "ParallelIOMgr.h"
36 #include <deque>
37 #include <algorithm>
38 
39 #ifndef CODE_REDUNDANT
40 #define CODE_REDUNDANT 0
41 #endif
42 
43 #include <string>
44 #include <sstream>
45 #include <fstream>
46 
47 class qmSolvData {
48 public:
49  char segName[5];
51  std::vector<int> atmIDs ;
53 
54  qmSolvData() : resID(-1), begAtmID(-1), size(0) {}
55  qmSolvData(int newResID, int newBegAtm, int newSize) {
56  resID = newResID;
57  begAtmID = newBegAtm;
58  size = newSize;
59  }
60  qmSolvData(int newResID, int newBegAtm, int newSize,
61  const char* newSegName, Real newQMID) {
62  resID = newResID;
63  begAtmID = newBegAtm;
64  size = newSize;
65  strncpy(segName, newSegName,5);
66  atmIDs.push_back(newBegAtm) ;
67  qmGrpID = newQMID;
68  }
69 
70  bool operator <(const qmSolvData& ref) {return begAtmID < ref.begAtmID;}
71  bool operator ==(const qmSolvData& ref) {return begAtmID == ref.begAtmID;}
72 };
73 
74 std::vector<std::string> split(const std::string &text, std::string delimiter) {
75 
76  std::vector<std::string> tokens;
77  std::size_t start = 0, end = 0;
78 
79  while ((end = text.find(delimiter, start)) != std::string::npos) {
80 
81  std::string temp = text.substr(start, end - start);
82 
83  if (! temp.empty()) tokens.push_back(temp);
84 
85  start = end + delimiter.length();
86  }
87 
88  // Gets last item
89  std::string temp = text.substr(start);
90  if (! temp.empty()) tokens.push_back(temp);
91 
92  return tokens;
93 }
94 
95 struct refSelStr {
96  std::string segid;
97  int resid;
98 
99  refSelStr() {} ;
100  refSelStr(std::string newSegID, int newResid) {
101  segid = newSegID;
102  resid = newResid;
103  }
104 } ;
105 
106 typedef std::vector<refSelStr> refSelStrVec ;
107 typedef std::map<Real, refSelStrVec> refSelStrMap ;
108 typedef std::pair<Real,refSelStrVec> refSelStrPair ;
109 
110 void Molecule::prepare_qm(const char *pdbFileName,
111  Parameters *params, ConfigList *cfgList) {
112 #ifdef MEM_OPT_VERSION
113  NAMD_die("QMMM interface is not supported in memory optimized builds.");
114 #else
115 
116  PDB *pdbP; // Pointer to PDB object to use
117 
118  qmNumQMAtoms = 0;
119 
120  qmNumGrps = 0 ;
121 
122  iout << iINFO << "Using the following PDB file for QM parameters: " <<
123  pdbFileName << "\n" << endi;
124  if (pdbFileName)
125  pdbP = new PDB(pdbFileName);
126  else
127  iout << "pdbFile name not defined!\n\n" << endi ;
128 
129  if (pdbP->num_atoms() != numAtoms)
130  {
131  NAMD_die("Number of atoms in QM parameter PDB file doesn't match coordinate PDB");
132  }
133 
134  qmElementArray = new char*[numAtoms] ;
135 
136  qmAtomGroup = new Real[numAtoms] ;
137 
138  BigReal bondVal;
139  Real atmGrp;
140 
141  std::set<Real> atmGrpSet;
142 
143  std::vector<Real> grpChrgVec;
144 
145  // Value in the bond column fro QM-MM bonds.
146  std::vector<BigReal> qmBondValVec;
147  // Identifiers of different QM regions
148  std::vector<Real> qmGroupIDsVec;
149  // This maps the qm group ID with the serail index of this group in
150  // various arrays.
151  std::map<Real,int> qmGrpIDMap ;
152 
153  std::vector<int> qmAtmIndxVec, qmGrpSizeVec;
154 
155  // Used to parse user selection in different places.
156  std::vector<std::string> strVec;
157 
158  qmNoPC = simParams->qmNoPC;
159 
160  // We set to zero by default, So there is no need for extra processing.
161  qmPCFreq = 0;
162  if (simParams->qmPCSelFreq > 1)
163  qmPCFreq = simParams->qmPCSelFreq;
164 
165 
168 
169 
170  qmLSSTotalNumAtms = 0;
171  SortedArray< qmSolvData> lssGrpRes;
172  std::map<Real,std::vector<int> > lssGrpRefIDs;
173  refSelStrMap lssRefUsrSel;
174  int totalNumRefAtms = 0;
175  int lssClassicResIndx = 0 ;
176  int lssCurrClassResID = -1 ;
177  char lssCurrClassResSegID[5];
178  if (simParams->qmLSSOn) {
179  DebugM(4, "LSS is ON! Processing QM solvent.\n") ;
180 
181  if (resLookup == NULL)
182  NAMD_die("We need residue data to conduct LSS.");
183 
184  if (simParams->qmLSSMode == QMLSSMODECOM) {
185 
186  StringList *current = cfgList->find("QMLSSRef");
187  for ( ; current; current = current->next ) {
188 
189  strVec = split( std::string(current->data) , " ");
190 
191  if (strVec.size() != 3 ) {
192  iout << iERROR << "Format error in QM LSS size: "
193  << current->data
194  << "\n" << endi;
195  NAMD_die("Error processing QM information.");
196  }
197 
198  std::stringstream storConv ;
199 
200  storConv << strVec[0] ;
201  Real grpID ;
202  storConv >> grpID;
203  if (storConv.fail()) {
204  iout << iERROR << "Error parsing QMLSSRef selection: "
205  << current->data
206  << "\n" << endi;
207  NAMD_die("Error processing QM information.");
208  }
209 
210  std::string segName = strVec[1].substr(0,4);
211 
212  storConv.clear() ;
213  storConv << strVec[2];
214  int resID ;
215  storConv >> resID;
216  if (storConv.fail()) {
217  iout << iERROR << "Error parsing QMLSSRef selection: "
218  << current->data
219  << "\n" << endi;
220  NAMD_die("Error processing QM information.");
221  }
222 
223  auto it = lssRefUsrSel.find(grpID) ;
224  if (it == lssRefUsrSel.end())
225  lssRefUsrSel.insert(refSelStrPair(grpID,refSelStrVec()));
226 
227  lssRefUsrSel[grpID].push_back(refSelStr(segName, resID));
228  }
229 
230  for (auto it=lssRefUsrSel.begin(); it!=lssRefUsrSel.end(); it++) {
231  iout << iINFO << "LSS user selection for COM composition of group "
232  << it->first << ":\n" << endi ;
233  for (int i=0; i<it->second.size();i++) {
234  iout << iINFO << "Segment " << it->second[i].segid
235  << " ; residue " << it->second[i].resid << "\n" << endi ;
236  }
237  }
238  }
239  }
240 
241 
242 
245 
246 
247  for (int atmInd = 0 ; atmInd < numAtoms; atmInd++) {
248 
249  // If we are looking for QM-MM bonds, then we need to store extra info.
250  // We only store extra information if the QM bond column was defined in
251  // the configuration file. If not, we are using QM bond guessing.
252  if (simParams->qmBondOn and (simParams->qmBondColumnDefined)) {
253 
254  // We store both the qm group and the bond value
255  if ( strcmp(simParams->qmColumn,"beta") == 0 ){
256  atmGrp = pdbP->atom(atmInd)->temperaturefactor() ;
257 
258  bondVal = pdbP->atom(atmInd)->occupancy() ;
259  }
260  else {
261  atmGrp = pdbP->atom(atmInd)->occupancy() ;
262 
263  bondVal = pdbP->atom(atmInd)->temperaturefactor() ;
264  }
265 
266  qmBondValVec.push_back(bondVal);
267  }
268  else {
269 
270  if ( strcmp(simParams->qmColumn,"beta") == 0 ){
271  atmGrp = pdbP->atom(atmInd)->temperaturefactor() ;
272  }
273  else {
274  atmGrp = pdbP->atom(atmInd)->occupancy() ;
275  }
276  }
277 
278  // We store all atom QM Group IDs in an array for
279  // future transport to all PEs.
280  qmAtomGroup[atmInd] = atmGrp;
281 
282  // We store all atom's elements for quick access in the QM code.
283  // Elements are used to tell the QM code the atom type.
284  qmElementArray[atmInd] = new char[3];
285  strncpy(qmElementArray[atmInd],pdbP->atom(atmInd)->element(),3);
286 
287  // For QM atoms, we keep global atom indices and parse different QM Group
288  // IDs, keeping track of each groups size
289  if (atmGrp > 0){
290 
291  if (simParams->fixedAtomsOn) {
292  if ( fixedAtomFlags[atmInd] == 1 ) {
293  iout << iERROR << "QM atom cannot be fixed in space!\n"
294  << endi;
295  NAMD_die("Error processing QM information.");
296  }
297  }
298 
299  // Changes the VdW type of QM atoms.
300  // This is may be used to counter balance the overpolarization
301  // that QM atoms sufer.
302  if (simParams->qmVDW) {
303  // Creating a new type string
304  std::string qmType(qmElementArray[atmInd]) ;
305  // Erases empty spaces
306  qmType.erase(
307  std::remove_if(qmType.begin(), qmType.end(), isspace ),
308  qmType.end());
309  // pre-pends a "q" to the element name.
310  qmType = std::string("q") + qmType;
311 
312 // iout << "QM VdW type: " << atoms[atmInd].vdw_type
313 // << " atom type: " << atomNames[atmInd].atomtype
314 // << " new type "<< qmType << "\n" << endi;
315 
316  /* Look up the vdw constants for this atom */
317  // I am casting a non-const here because the function doesn't actually
318  // change the string value, but it doesn't ask for a const char* as
319  // an argument.
320  params->assign_vdw_index(const_cast<char*>( qmType.c_str()),
321  &(atoms[atmInd]));
322 
323 // iout << "----> new VdW type: " << atoms[atmInd].vdw_type << "\n" << endi;
324  }
325 
326  // Indexes all global indices of QM atoms.
327  qmAtmIndxVec.push_back(atmInd);
328 
329  auto retVal = atmGrpSet.insert(atmGrp);
330 
331  // If a new QM group is found, store the reverse reference in a map
332  // and increase the total count.
333  if (retVal.second) {
334  // This mak makes the reverse identification from the group ID
335  // to the sequential order in which each group was first found.
336  qmGrpIDMap.insert(std::pair<BigReal,int>(atmGrp, qmNumGrps));
337 
338  // This vector keeps track of the group ID for each group
339  qmGroupIDsVec.push_back(atmGrp);
340 
341  // This counter is used to keep track of the sequential order in
342  // which QM groups were first seen in the reference PDB file.
343  qmNumGrps++ ;
344 
345  // If this is a new QM group, initialize a new variable in the
346  // vector to keep track of the number of atoms in this group.
347  qmGrpSizeVec.push_back(1);
348 
349  // For each new QM group, a new entry in the total charge
350  // vector is created
351  grpChrgVec.push_back( atoms[atmInd].charge );
352  }
353  else {
354  // If the QM group has already been seen, increase the count
355  // of atoms in that group.
356  qmGrpSizeVec[ qmGrpIDMap[atmGrp] ]++ ;
357 
358  // If the QM group exists, adds current atom charge to total charge.
359  grpChrgVec[ qmGrpIDMap[atmGrp] ] += atoms[atmInd].charge;
360  }
361 
362  // In case we are using live solvent selection
363  if(simParams->qmLSSOn) {
364 
365  int resID = pdbP->atom(atmInd)->residueseq();
366  char segName[5];
367  strncpy(segName, pdbP->atom(atmInd)->segmentname(),5);
368 
369  int resSize = get_residue_size(segName,resID);
370 
371  int i =-1, end =-1;
372 
373  resLookup->lookup(segName,resID,&i, &end);
374 
375  if ( strncasecmp(pdbP->atom(atmInd)->residuename(),
376  simParams->qmLSSResname, 4) == 0) {
377 
378  // We try to insert every residue from every atom
379  qmSolvData *resP = lssGrpRes.find(qmSolvData(resID, i, resSize));
380 
381  if (resP != NULL) {
382  resP->atmIDs.push_back(atmInd) ;
383 // DebugM(3, "Existing residue " << resP->resID
384 // << " from segID " << resP->segName
385 // << " received atom "
386 // << atmInd << "\n" );
387  }
388  else {
389  lssGrpRes.insert(qmSolvData(resID, i, resSize, segName, atmGrp));
390 // DebugM(3, lssGrpRes.size() << ") Inserted new residue: "
391 // << resID << " from segID " << segName
392 // << " with atom "
393 // << i << "\n" ) ;
394  }
395  }
396  else {
397  // We store the QM atoms, per group, which are NOT part of
398  // solvent molecules.
399 
400  // Checks if we have a vector for this QM group.
401  auto itNewGrp = lssGrpRefIDs.find(atmGrp) ;
402  if (itNewGrp == lssGrpRefIDs.end()) {
403  lssGrpRefIDs.insert(std::pair<Real, std::vector<int> >(
404  atmGrp, std::vector<int>() ) );
405  }
406 
407  switch (simParams->qmLSSMode)
408  {
409 
410  case QMLSSMODECOM:
411  {
412  // If we are using COM selection, checks if the atom
413  // is part of the user selected residues
414  for(int i=0; i<lssRefUsrSel[atmGrp].size(); i++) {
415  if (lssRefUsrSel[atmGrp][i].resid == resID &&
416  strncmp(lssRefUsrSel[atmGrp][i].segid.c_str(),
417  segName,5) == 0 ) {
418 
419  lssGrpRefIDs[atmGrp].push_back(atmInd);
420  totalNumRefAtms++;
421  }
422  }
423 
424  } break;
425 
426  case QMLSSMODEDIST:
427  {
428 
429  lssGrpRefIDs[atmGrp].push_back(atmInd);
430  totalNumRefAtms++;
431 
432  } break;
433 
434  }
435  }
436 
437  }
438 
439  }
440  else if (atmGrp == 0) {
441 
442  if(simParams->qmLSSOn) {
443 
444  if ( strncasecmp(pdbP->atom(atmInd)->residuename(),
445  simParams->qmLSSResname, 4) == 0) {
446 
447  int resID = pdbP->atom(atmInd)->residueseq();
448  char segName[5];
449  strncpy(segName, pdbP->atom(atmInd)->segmentname(),5);
450 
451  if (lssCurrClassResID < 0) {
452  lssCurrClassResID = resID ;
453  strncpy(lssCurrClassResSegID, segName,5);
454  lssClassicResIndx = 0;
455  }
456  else if (lssCurrClassResID != resID ||
457  strcmp(lssCurrClassResSegID, segName) != 0 ) {
458  lssCurrClassResID = resID ;
459  strncpy(lssCurrClassResSegID, segName,5);
460  lssClassicResIndx++;
461  }
462 
463  qmClassicSolv.insert(std::pair<int,int>(atmInd,lssClassicResIndx));
464 
465  }
466  }
467  }
468  else if(atmGrp < 0) {
469  iout << iERROR << "QM group ID cannot be less than zero!\n" << endi;
470  NAMD_die("Error processing QM information.");
471  }
472  }
473 
474  // Sanity check
475  if (simParams->qmLSSOn) {
476  if (lssGrpRes.size() == 0)
477  NAMD_die("LSS was activated but there are no QM solvent molecules!\n");
478 
479  for (auto it=lssRefUsrSel.begin(); it!=lssRefUsrSel.end(); it++) {
480  auto itTarget = qmGrpIDMap.find(it->first);
481  if (itTarget == qmGrpIDMap.end()) {
482  iout << iERROR << "QM group ID for LSS could not be found in input!"
483  << " QM group ID: " << it->first << "\n" << endi;
484  NAMD_die("Error processing QM information.");
485  }
486  }
487 
488  DebugM(3,"We found " << lssClassicResIndx << " classical solvent molecules totalling "
489  << qmClassicSolv.size() << " atoms.\n" );
490 
491  }
492 
493  qmNumQMAtoms = qmAtmIndxVec.size();
494 
495  if (qmNumQMAtoms == 0)
496  NAMD_die("No QM atoms were found in this QM simulation!") ;
497 
498  iout << iINFO << "Number of QM atoms (excluding Dummy atoms): " <<
499  qmNumQMAtoms << "\n" << endi;
500 
501  qmAtmChrg = new Real[qmNumQMAtoms] ;
502  qmAtmIndx = new int[qmNumQMAtoms] ;
503  for (int i=0; i<qmNumQMAtoms; i++) {
504  // qmAtmChrg gets initialized with the PSF charges at the end of this
505  // function, but values may change as QM steps are taken.
506  qmAtmChrg[i] = 0;
507  qmAtmIndx[i] = qmAtmIndxVec[i] ;
508  }
509 
510  // This map relates the QM group index with a vector of pairs
511  // of bonded MM-QM atoms (with the bonded atoms ins this order:
512  // MM first, QM second).
513  std::map<int, std::vector<std::pair<int,int> > > qmGrpIDBonds ;
514  int bondCounter = 0;
515  if (simParams->qmBondOn) {
516 
517  iout << iINFO << "Storing QM-MM bonds.\n" << endi;
518 
519  // Checks all bonds for QM-MM pairs.
520  // Makes sanity checks against QM-QM pairs and MM-MM pairs that
521  // are flagged by the user to be bonds between QM and MM regions.
522  // QM-QM bonds will be removed in another function.
523  for (int bndIt = 0; bndIt < numBonds; bndIt++) {
524 
525  bond curr = bonds[bndIt] ;
526 
527  bool storeBond = false ;
528 
529 
530 
531  if (simParams->qmBondGuess) {
532  // In case we are using QM region definitions and topology to
533  // determine QM-MM bonds.
534  if ((qmAtomGroup[curr.atom1] == 0 || qmAtomGroup[curr.atom2] == 0) &&
535  (qmAtomGroup[curr.atom1] != qmAtomGroup[curr.atom2]))
536  {
537  storeBond = true;
538  }
539 
540  }
541  else
542  {
543  // In case we are using the user-provided QM bond column values
544  // to determine QM-MM bonds.
545 
546  // In case BOTH atoms have a non-zero bond column value
547  if (qmBondValVec[curr.atom1] != 0 &&
548  qmBondValVec[curr.atom2] != 0 ) {
549 
550  storeBond = true;
551 
552  // Sanity checks (1 of 2)
553  if (qmAtomGroup[curr.atom1] != 0 &&
554  qmAtomGroup[curr.atom2] != 0) {
555  iout << iINFO << "Skipping Bond! Atoms " << curr.atom1
556  << " and " << curr.atom2 <<
557  " are assigned as QM atoms.\n" << endi;
558  storeBond = false;
559  }
560 
561  // Sanity checks (2 of 2)
562  if (qmAtomGroup[curr.atom1] == 0 &&
563  qmAtomGroup[curr.atom2] == 0) {
564  iout << iINFO << "Skipping Bond! Atoms " << curr.atom1
565  << " and " << curr.atom2 <<
566  " are assigned as MM atoms.\n" << endi;
567  storeBond = false;
568  }
569  }
570 
571  }
572 
573  if (storeBond) {
574  int currGrpID = 0;
575  std::pair<int,int> newPair(0,0);
576 
577  // We create a QM-MM pair with the MM atom first
578  if (qmAtomGroup[curr.atom1] != 0) {
579  newPair = std::pair<int,int>(curr.atom2, curr.atom1) ;
580  currGrpID = qmAtomGroup[curr.atom1];
581  } else {
582  newPair = std::pair<int,int>(curr.atom1, curr.atom2) ;
583  currGrpID = qmAtomGroup[curr.atom2];
584  }
585 
586  int grpIndx = qmGrpIDMap[currGrpID] ;
587 
588  // Stores bonds in vectors key-ed by the QM group ID of the QM atom.
589  auto retIter = qmGrpIDBonds.find(grpIndx) ;
590  // In case thi QM-MM bonds belong to a QM group we have not seen
591  // yet, stores a new vector in the map.
592  if (retIter == qmGrpIDBonds.end()) {
593  qmGrpIDBonds.insert(std::pair<BigReal,std::vector<std::pair<int,int> > >(
594  grpIndx, std::vector<std::pair<int,int> >() ) );
595  }
596 
597  qmGrpIDBonds[grpIndx].push_back( newPair );
598 
599  bondCounter++ ;
600  }
601 
602 
603  }
604 
605 // iout << "Finished processing QM-MM bonds.\n" << endi ;
606 
607  if (bondCounter == 0)
608  iout << iWARN << "We found " << bondCounter << " QM-MM bonds.\n" << endi ;
609  else
610  iout << iINFO << "We found " << bondCounter << " QM-MM bonds.\n" << endi ;
611 
612  }
613 
614  // Initializes several arrays used to setup the QM simulation.
615  qmNumBonds = bondCounter ;
616 
617  qmMMBond = new int*[qmNumBonds];
618 
619  qmDummyBondVal = new BigReal[qmNumBonds];
620 
621  qmMMChargeTarget = new int*[qmNumBonds] ;
622  qmMMNumTargs = new int[qmNumBonds] ;
623 
624  qmDummyElement = new char*[qmNumBonds] ;
625 
626 
627  qmNumGrps = atmGrpSet.size();
628 
629  qmGrpSizes = new int[qmNumGrps];
630 
631  qmGrpID = new Real[qmNumGrps];
632 
633  qmGrpChrg = new Real[qmNumGrps];
634 
635  qmGrpMult = new Real[qmNumGrps] ;
636 
637  qmGrpNumBonds = new int[qmNumGrps];
638 
639  qmGrpBonds = new int*[qmNumGrps];
640  qmMMBondedIndx = new int*[qmNumGrps];
641 
642 
645 
646 
647  // We first initialize the multiplicity vector with
648  // default values, then populate it with user defined values.
649  for (int grpIter = 0; grpIter < qmNumGrps; grpIter++) {
650  qmGrpMult[grpIter] = 0;
651  }
652 
653  int multCount = 0;
654  StringList *current = cfgList->find("QMMult");
655  for ( ; current; current = current->next ) {
656 
657  auto strVec = split( std::string(current->data) , " ");
658 
659  if (strVec.size() != 2 ) {
660  iout << iERROR << "Format error in QM Multiplicity string: "
661  << current->data
662  << "\n" << endi;
663  NAMD_die("Error processing QM information.");
664  }
665 
666  std::stringstream storConv ;
667 
668  storConv << strVec[0] ;
669  Real grpID ;
670  storConv >> grpID;
671  if (storConv.fail()) {
672  iout << iERROR << "Error parsing QMMult selection: "
673  << current->data
674  << "\n" << endi;
675  NAMD_die("Error processing QM information.");
676  }
677 
678  storConv.clear() ;
679  storConv << strVec[1];
680  Real multiplicity ;
681  storConv >> multiplicity;
682  if (storConv.fail()) {
683  iout << iERROR << "Error parsing QMMult selection: "
684  << current->data
685  << "\n" << endi;
686  NAMD_die("Error processing QM information.");
687  }
688 
689  auto it = qmGrpIDMap.find(grpID);
690 
691  if (it == qmGrpIDMap.end()) {
692  iout << iERROR << "Error parsing QMMult selection. Could not find QM group ID: "
693  << grpID
694  << "\n" << endi;
695  NAMD_die("Error processing QM information.");
696  }
697  else {
698  iout << iINFO << "Applying user defined multiplicity "
699  << multiplicity << " to QM group ID " << grpID << "\n" << endi;
700  qmGrpMult[it->second] = multiplicity;
701  }
702 
703  multCount++;
704  }
705 
706  if (multCount != qmNumGrps && simParams->qmFormat == QMFormatORCA) {
707  NAMD_die("ORCA neds multiplicity values for all QM regions.");
708  }
709 
710 
713 
714 
715  for (size_t grpIndx = 0; grpIndx < qmGrpSizeVec.size(); grpIndx++) {
716 
717  bool nonInteger = true;
718  if ((fabsf(roundf(grpChrgVec[grpIndx]) - grpChrgVec[grpIndx]) <= 0.001f) ) {
719  grpChrgVec[grpIndx] = roundf(grpChrgVec[grpIndx]) ;
720  nonInteger = false;
721  }
722 
723  iout << iINFO << grpIndx + 1 << ") Group ID: " << qmGroupIDsVec[grpIndx]
724  << " ; Group size: " << qmGrpSizeVec[grpIndx] << " atoms"
725  << " ; Total PSF charge: " << grpChrgVec[grpIndx] << "\n" << endi ;
726 
727  if (nonInteger && simParams->PMEOn)
728  NAMD_die("QM atoms do not add up to a whole charge, which is needed for PME.") ;
729  }
730 
731  int chrgCount = 0;
732  current = cfgList->find("QMCharge");
733  for ( ; current; current = current->next ) {
734 
735  auto strVec = split( std::string(current->data) , " ");
736 
737  if (strVec.size() != 2 ) {
738  iout << iERROR << "Format error in QM Charge string: "
739  << current->data
740  << "\n" << endi;
741  NAMD_die("Error processing QM information.");
742  }
743 
744  std::stringstream storConv ;
745 
746  storConv << strVec[0] ;
747  Real grpID ;
748  storConv >> grpID;
749  if (storConv.fail()) {
750  iout << iERROR << "Error parsing QMCharge selection: "
751  << current->data
752  << "\n" << endi;
753  NAMD_die("Error processing QM information.");
754  }
755 
756  storConv.clear() ;
757  storConv << strVec[1];
758  Real charge ;
759  storConv >> charge;
760  if (storConv.fail()) {
761  iout << iERROR << "Error parsing QMCharge selection: "
762  << current->data
763  << "\n" << endi;
764  NAMD_die("Error processing QM information.");
765  }
766 
767  auto it = qmGrpIDMap.find(grpID);
768 
769  if (it == qmGrpIDMap.end()) {
770  iout << iERROR << "Error parsing QMCharge selection. Could not find QM group ID: "
771  << grpID
772  << "\n" << endi;
773  NAMD_die("Error processing QM information.");
774  }
775  else {
776  iout << iINFO << "Found user defined charge "
777  << charge << " for QM group ID " << grpID << ". Will ignore PSF charge.\n" << endi;
778  grpChrgVec[it->second] = charge;
779  }
780 
781  chrgCount++;
782  }
783 
784  simParams->qmMOPACAddConfigChrg = false;
785  // Checks if QM group charges can be defined for MOPAC.
786  // Since charge can be defined in QMConfigLine, we need extra logic.
787  if (simParams->qmFormat == QMFormatMOPAC) {
788 
789  // Checks if group charge was supplied in config line for MOPAC.
790  std::string::size_type chrgLoc = std::string::npos ;
791 
792  // This will hold a sting with the first user supplied configuration line for MOPAC.
793  std::string configLine(cfgList->find("QMConfigLine")->data) ;
794  chrgLoc = configLine.find("CHARGE") ;
795 
796  if ( chrgLoc != std::string::npos ) {
797  iout << iINFO << "Found user defined charge in command line. This \
798 will be used for all QM regions and will take precedence over all other charge \
799 definitions.\n" << endi;
800  }
801  else if ( chrgLoc == std::string::npos && (simParams->qmChrgFromPSF || chrgCount == qmNumGrps) ) {
802  // If no charge was defined in the configuration line, gets from PSF and/or
803  // from user defined charges (through the QMCharge keyword).
804  simParams->qmMOPACAddConfigChrg = true;
805  }
806  else
807  {
808  // If we could nont find a charge definition in the config line AND
809  // no specific charge was selected for each QM region through QMCharge AND
810  // the QMChargeFromPSF was not turned ON, the we stop NAMD and scream at the user.
811 // if ( chrgLoc == std::string::npos && (chrgCount != qmNumGrps ) && !simParams->qmChrgFromPSF)
812  iout << iERROR << "Could not find charge for all QM groups. For MOPAC, \
813 charges can be defined through QMConfigLine, QMCharge or QMChargeFromPSF keywords.\n" << endi;
814  NAMD_die("Error processing QM information.");
815  }
816 
817  }
818 
819  if (simParams->qmFormat == QMFormatORCA ) {
820  if ((chrgCount != qmNumGrps ) && !simParams->qmChrgFromPSF) {
821  // If we are not supposed to get charges from the PSF, and not
822  // enough charges were set to cover all QM regions,
823  // we stop NAMD and scream at the user.
824  iout << iERROR << "Could not find charge for all QM groups. For ORCA, \
825 charges can be defined through QMCharge or QMChargeFromPSF keywords.\n" << endi;
826  NAMD_die("Error processing QM information.");
827  }
828  }
829 
830  // If mechanichal embedding was requested but we have QM-MM bonds, we need
831  // to send extra info to ComputeQM to preserve calculation speed.
832  if (qmNumBonds > 0 && qmNoPC) {
833  qmMeNumBonds = qmNumBonds;
834  qmMeMMindx = new int[qmMeNumBonds] ;
835  qmMeQMGrp = new Real[qmMeNumBonds] ;
836  }
837  else {
838  qmMeNumBonds = 0 ;
839  qmMeMMindx = NULL;
840  qmMeQMGrp = NULL;
841  }
842 
843 
846 
847 
848  bondCounter = 0;
849  for (int grpIter = 0; grpIter < qmNumGrps; grpIter++) {
850 
851  qmGrpID[grpIter] = qmGroupIDsVec[grpIter] ;
852 
853  qmGrpSizes[grpIter] = qmGrpSizeVec[grpIter] ;
854 
855  qmGrpChrg[grpIter] = grpChrgVec[grpIter];
856 
857 // iout << "Loaded " << qmGrpSizes[grpIter] << " atoms to this group.\n" << endi;
858 
859  int currNumbBonds = qmGrpIDBonds[grpIter].size() ;
860 
861  // Assigns the number of bonds that the current QM group has.
862  qmGrpNumBonds[grpIter] = currNumbBonds;
863 
864  if (currNumbBonds > 0) {
865 
866  qmGrpBonds[grpIter] = new int[currNumbBonds];
867  qmMMBondedIndx[grpIter] = new int[currNumbBonds];
868 
869  for (int bndIter = 0; bndIter<currNumbBonds; bndIter++) {
870 
871  // Adds the bonds to the overall sequential list.
872  qmMMBond[bondCounter] = new int[2] ;
873  qmMMBond[bondCounter][0] = qmGrpIDBonds[grpIter][bndIter].first ;
874  qmMMBond[bondCounter][1] = qmGrpIDBonds[grpIter][bndIter].second ;
875 
876  // For the current QM group, and the current bond, gets the bond index.
877  qmGrpBonds[grpIter][bndIter] = bondCounter;
878 
879  // For the current QM group, and the current bond, gets the MM atom.
880  qmMMBondedIndx[grpIter][bndIter] = qmGrpIDBonds[grpIter][bndIter].first ;
881 
882  // Assign the default value of dummy element
883  qmDummyElement[bondCounter] = new char[3];
884  strcpy(qmDummyElement[bondCounter],"H\0");
885 
886  // Determines the distance that will separate the new Dummy atom
887  // and the Qm atom to which it will be bound.
888  bondVal = 0;
889  if (simParams->qmBondDist) {
890  if (qmBondValVec[qmMMBond[bondCounter][0]] !=
891  qmBondValVec[qmMMBond[bondCounter][1]]
892  ) {
893  iout << iERROR << "qmBondDist is ON but the values in the bond column are different for atom "
894  << qmMMBond[bondCounter][0] << " and " << qmMMBond[bondCounter][1]
895  << ".\n" << endi ;
896  NAMD_die("Error in QM-MM bond processing.");
897  }
898 
899  bondVal = qmBondValVec[qmMMBond[bondCounter][0]] ;
900  }
901  else {
902 
903  if (strcmp(qmElementArray[qmMMBond[bondCounter][1]],"C") == 0 ) {
904  bondVal = 1.09 ;
905  }
906  else if (strcmp(qmElementArray[qmMMBond[bondCounter][1]],"O") == 0 ) {
907  bondVal = 0.98 ;
908  }
909  else if (strcmp(qmElementArray[qmMMBond[bondCounter][1]],"N") == 0 ) {
910  bondVal = 0.99 ;
911  }
912  else {
913  iout << iERROR << "qmBondDist is OFF but the QM atom has no default distance value. Atom "
914  << qmMMBond[bondCounter][1] << ", with element: "
915  << qmElementArray[qmMMBond[bondCounter][1]]
916  << ".\n" << endi ;
917  NAMD_die("Error in QM-MM bond processing.");
918  }
919 
920  }
921 
922  iout << iINFO << "MM-QM pair: " << qmMMBond[bondCounter][0] << ":"
923  << qmMMBond[bondCounter][1]
924  << " -> Value (distance or ratio): " << bondVal
925  << " (QM Group " << grpIter << " ID " << qmGrpID[grpIter] << ")"
926  << "\n" << endi ;
927 
928  qmDummyBondVal[bondCounter] = bondVal;
929 
930  // In case we are preparing for a mechanical embedding simulation
931  // with no point charges, populate the following vectors
932  if (qmMeNumBonds > 0) {
933  qmMeMMindx[bondCounter] = qmMMBond[bondCounter][0];
934  qmMeQMGrp[bondCounter] = qmGrpID[grpIter];
935  }
936 
937  bondCounter++ ;
938  }
939  }
940 
941  }
942 
943 
946 
947  current = NULL;
948  if (qmNumBonds > 0)
949  current = cfgList->find("QMLinkElement");
950 
951  int numParsedLinkElem = 0;
952  for ( ; current != NULL; current = current->next ) {
953 
954  DebugM(3,"Parsing link atom element: " << current->data << "\n" );
955 
956  strVec = split( std::string(current->data) , " ");
957 
958  // We need the two atoms that compose the QM-MM bonds and
959  // then the element.
960  if (strVec.size() != 3 && qmNumBonds > 1) {
961  iout << iERROR << "Format error in QM link atom element selection: "
962  << current->data
963  << "\n" << endi;
964  NAMD_die("Error processing QM information.");
965  }
966 
967  // If there is only one QM-MM bond, we can accept the element only.
968  if (strVec.size() != 1 && strVec.size() != 3 && qmNumBonds == 1) {
969  iout << iERROR << "Format error in QM link atom element selection: "
970  << current->data
971  << "\n" << endi;
972  NAMD_die("Error processing QM information.");
973  }
974 
975  std::stringstream storConv ;
976  int bondAtom1, bondAtom2;
977  std::string linkElement ;
978 
979  if (strVec.size() == 1) {
980  linkElement = strVec[0].substr(0,2);
981  }
982  else if (strVec.size() == 3) {
983 
984  storConv << strVec[0] ;
985  storConv >> bondAtom1;
986  if (storConv.fail()) {
987  iout << iERROR << "Error parsing link atom element selection: "
988  << current->data
989  << "\n" << endi;
990  NAMD_die("Error processing QM information.");
991  }
992 
993  storConv.clear() ;
994  storConv << strVec[1];
995  storConv >> bondAtom2;
996  if (storConv.fail()) {
997  iout << iERROR << "Error parsing link atom element selection: "
998  << current->data
999  << "\n" << endi;
1000  NAMD_die("Error processing QM information.");
1001  }
1002 
1003  linkElement = strVec[2].substr(0,2);
1004  }
1005 
1006  numParsedLinkElem++;
1007 
1008  if (numParsedLinkElem>qmNumBonds) {
1009  iout << iERROR << "More link atom elements were set than there"
1010  " are QM-MM bonds.\n" << endi;
1011  NAMD_die("Error processing QM information.");
1012  }
1013 
1014  int bondIter;
1015 
1016  if (strVec.size() == 1) {
1017  bondIter = 0;
1018  }
1019  else if (strVec.size() == 3) {
1020 
1021  Bool foundBond = false;
1022 
1023  for (bondIter=0; bondIter<qmNumBonds; bondIter++) {
1024 
1025  if ( (qmMMBond[bondIter][0] == bondAtom1 &&
1026  qmMMBond[bondIter][1] == bondAtom2 ) ||
1027  (qmMMBond[bondIter][0] == bondAtom2 &&
1028  qmMMBond[bondIter][1] == bondAtom1 ) ) {
1029 
1030  foundBond = true;
1031  break;
1032  }
1033  }
1034 
1035  if (! foundBond) {
1036  iout << iERROR << "Error parsing link atom element selection: "
1037  << current->data
1038  << "\n" << endi;
1039  iout << iERROR << "Atom pair was not found to be a QM-MM bond.\n"
1040  << endi;
1041  NAMD_die("Error processing QM information.");
1042  }
1043  }
1044 
1045  strcpy(qmDummyElement[bondIter],linkElement.c_str());
1046  qmDummyElement[bondIter][2] = '\0';
1047 
1048  iout << iINFO << "Applying user defined link atom element "
1049  << qmDummyElement[bondIter] << " to QM-MM bond "
1050  << bondIter << ": " << qmMMBond[bondIter][0]
1051  << " - " << qmMMBond[bondIter][1]
1052  << "\n" << endi;
1053  }
1054 
1055 
1056 
1059 
1060 
1061  int32 **bondsWithAtomLocal = NULL ;
1062  int32 *byAtomSizeLocal = NULL;
1063  ObjectArena <int32 >* tmpArenaLocal = NULL;
1064  if (qmNumBonds > 0) {
1065 
1066  bondsWithAtomLocal = new int32 *[numAtoms];
1067  byAtomSizeLocal = new int32[numAtoms];
1068  tmpArenaLocal = new ObjectArena<int32>;
1069 
1070  // Build the bond lists
1071  for (int i=0; i<numAtoms; i++)
1072  {
1073  byAtomSizeLocal[i] = 0;
1074  }
1075  for (int i=0; i<numRealBonds; i++)
1076  {
1077  byAtomSizeLocal[bonds[i].atom1]++;
1078  byAtomSizeLocal[bonds[i].atom2]++;
1079  }
1080  for (int i=0; i<numAtoms; i++)
1081  {
1082  bondsWithAtomLocal[i] = tmpArenaLocal->getNewArray(byAtomSizeLocal[i]+1);
1083  bondsWithAtomLocal[i][byAtomSizeLocal[i]] = -1;
1084  byAtomSizeLocal[i] = 0;
1085  }
1086  for (int i=0; i<numRealBonds; i++)
1087  {
1088  int a1 = bonds[i].atom1;
1089  int a2 = bonds[i].atom2;
1090  bondsWithAtomLocal[a1][byAtomSizeLocal[a1]++] = i;
1091  bondsWithAtomLocal[a2][byAtomSizeLocal[a2]++] = i;
1092  }
1093  }
1094 
1095  // In this loops we try to find other bonds in which the MM atoms from
1096  // QM-MM bonds may be involved. The other MM atoms (which we will call M2 and M3)
1097  // will be involved in charge manipulation. See ComputeQM.C for details.
1098  for (int qmBndIt = 0; qmBndIt < qmNumBonds; qmBndIt++) {
1099 
1100  // The charge targets are accumulated in a temporary vector and then
1101  // transfered to an array that will be transmited to the ComputeQMMgr object.
1102  std::vector<int> chrgTrgt ;
1103 
1104  int MM1 = qmMMBond[qmBndIt][0], MM2, MM2BondIndx, MM3, MM3BondIndx;
1105 
1106  switch (simParams->qmBondScheme) {
1107 
1108  case QMSCHEMERCD:
1109 
1110  case QMSCHEMECS:
1111  {
1112  // Selects ALL MM2 atoms.
1113  for (int i=0; i<byAtomSizeLocal[MM1]; i++) {
1114  MM2BondIndx = bondsWithAtomLocal[MM1][i] ;
1115 
1116  // Checks which of the atoms in the bond structure is the
1117  // MM2 atom.
1118  if (bonds[MM2BondIndx].atom1 == MM1)
1119  MM2 = bonds[MM2BondIndx].atom2;
1120  else
1121  MM2 = bonds[MM2BondIndx].atom1;
1122 
1123  // In case the bonded atom is a QM atom,
1124  // skips the index.
1125  if (qmAtomGroup[MM2] > 0)
1126  continue;
1127 
1128  chrgTrgt.push_back(MM2);
1129  }
1130 
1131  } break;
1132 
1133  case QMSCHEMEZ3:
1134  {
1135  // Selects all MM3 atoms
1136  for (int i=0; i<byAtomSizeLocal[MM1]; i++) {
1137  MM2BondIndx = bondsWithAtomLocal[MM1][i] ;
1138 
1139  // Checks which of the atoms in the bond structure is the
1140  // MM2 atom.
1141  if (bonds[MM2BondIndx].atom1 == MM1)
1142  MM2 = bonds[MM2BondIndx].atom2;
1143  else
1144  MM2 = bonds[MM2BondIndx].atom1;
1145 
1146  // In case the bonded atom is a QM atom,
1147  // skips the index.
1148  if (qmAtomGroup[MM2] > 0)
1149  continue;
1150 
1151  for (int i=0; i<byAtomSizeLocal[MM2]; i++) {
1152  MM3BondIndx = bondsWithAtomLocal[MM2][i] ;
1153 
1154  // Checks which of the atoms in the bond structure is the
1155  // MM3 atom.
1156  if (bonds[MM3BondIndx].atom1 == MM2)
1157  MM3 = bonds[MM3BondIndx].atom2;
1158  else
1159  MM3 = bonds[MM3BondIndx].atom1;
1160 
1161  // In case the bonded atom is a QM atom,
1162  // skips the index.
1163  // We also keep the search from going back to MM1.
1164  if (qmAtomGroup[MM3] > 0 || MM3 == MM1)
1165  continue;
1166 
1167  chrgTrgt.push_back(MM3);
1168  }
1169 
1170  }
1171 
1172  };
1173 
1174  case QMSCHEMEZ2:
1175  {
1176  // Selects all MM2 atoms
1177  for (int i=0; i<byAtomSizeLocal[MM1]; i++) {
1178  MM2BondIndx = bondsWithAtomLocal[MM1][i] ;
1179 
1180  // Checks which of the atoms in the bond structure is the
1181  // MM2 atom.
1182  if (bonds[MM2BondIndx].atom1 == MM1)
1183  MM2 = bonds[MM2BondIndx].atom2;
1184  else
1185  MM2 = bonds[MM2BondIndx].atom1;
1186 
1187  // In case the bonded atom is a QM atom,
1188  // skips the index.
1189  if (qmAtomGroup[MM2] > 0)
1190  continue;
1191 
1192  chrgTrgt.push_back(MM2);
1193  }
1194 
1195  };
1196 
1197  case QMSCHEMEZ1:
1198  {
1199  // Selects all MM1 atoms
1200  chrgTrgt.push_back(MM1);
1201  } break;
1202  }
1203 
1204 
1205  qmMMChargeTarget[qmBndIt] = new int[chrgTrgt.size()] ;
1206  qmMMNumTargs[qmBndIt] = chrgTrgt.size();
1207 
1208  DebugM(3, "MM-QM bond " << qmBndIt << "; MM atom "
1209  << qmMMBond[qmBndIt][0] << " conections: \n" );
1210 
1211  for (size_t i=0; i < chrgTrgt.size(); i++) {
1212  qmMMChargeTarget[qmBndIt][i] = chrgTrgt[i];
1213  DebugM(3,"MM Bonded to: " << chrgTrgt[i] << "\n" );
1214  }
1215 
1216  chrgTrgt.clear();
1217  }
1218 
1219  if (bondsWithAtomLocal != NULL)
1220  delete [] bondsWithAtomLocal; bondsWithAtomLocal = 0;
1221  if (byAtomSizeLocal != NULL)
1222  delete [] byAtomSizeLocal; byAtomSizeLocal = 0;
1223  if (tmpArenaLocal != NULL)
1224  delete tmpArenaLocal; tmpArenaLocal = 0;
1225 
1226 
1229 
1230 
1231  if(simParams->qmLSSOn) {
1232 
1233  std::map<Real,int> grpLSSSize ;
1234  std::map<Real,int>::iterator itGrpSize;
1235 
1236  qmLSSTotalNumAtms = 0;
1237  qmLSSResidueSize = 0;
1238 
1239  if (simParams->qmLSSFreq == 0)
1240  qmLSSFreq = simParams->stepsPerCycle ;
1241  else
1242  qmLSSFreq = simParams->qmLSSFreq;
1243 
1244  #ifdef DEBUG_QM
1245  int resSize = -1;
1246  #endif
1247 
1248  std::map<Real, int> grpNumLSSRes;
1249  std::map<Real, int>::iterator itGrpNumRes;
1250 
1251  for( auto it = lssGrpRes.begin(); it != lssGrpRes.end();it++ ) {
1252 
1253  if (it->atmIDs.size() != it->size) {
1254  iout << iERROR << "The number of atoms loaded for residue "
1255  << it->resID << " does not match the expected for this residue type.\n"
1256  << endi;
1257  NAMD_die("Error parsing data for LSS.");
1258  }
1259 
1260  qmLSSTotalNumAtms += it->size;
1261 
1262  #ifdef DEBUG_QM
1263  if (resSize < 0) resSize = it->size ;
1264  if (resSize > 0 and resSize != it->size) {
1265  iout << iERROR << "The number of atoms loaded for residue "
1266  << it->resID << " does not match previously loaded residues.\n"
1267  << endi;
1268  NAMD_die("Error parsing data for LSS.");
1269  }
1270 
1271 // DebugM(3,"Residue " << it->resID << ": " << it->segName
1272 // << " - from " << it->begAtmID << " with size "
1273 // << it->size << " (QM ID: " << it->qmGrpID
1274 // << ") has " << it->atmIDs.size() << " atoms: \n" ) ;
1275 // for (int i=0; i<it->atmIDs.size(); i++)
1276 // DebugM(3, it->atmIDs[i] << "\n" );
1277  #endif
1278 
1279  // Calculating total number of atoms per group
1280  itGrpSize = grpLSSSize.find(it->qmGrpID) ;
1281  if (itGrpSize != grpLSSSize.end())
1282  itGrpSize->second += it->size;
1283  else
1284  grpLSSSize.insert(std::pair<Real,int>(it->qmGrpID, it->size));
1285 
1286  // Calculating total number of solvent residues per group
1287  itGrpNumRes = grpNumLSSRes.find(it->qmGrpID) ;
1288  if (itGrpNumRes != grpNumLSSRes.end())
1289  itGrpNumRes->second += 1;
1290  else
1291  grpNumLSSRes.insert(std::pair<Real,int>(it->qmGrpID, 1));
1292  }
1293 
1294  qmLSSResidueSize = lssGrpRes.begin()->size ;
1295 
1296  qmLSSSize = new int[qmNumGrps];
1297 
1298  qmLSSIdxs = new int[qmLSSTotalNumAtms];
1299  int lssAtmIndx = 0;
1300 
1301  switch (simParams->qmLSSMode) {
1302 
1303  case QMLSSMODECOM:
1304  {
1305 
1306  qmLSSRefSize = new int[qmNumGrps];
1307 
1308  qmLSSMass = new Mass[qmLSSTotalNumAtms];
1309 
1310  qmLSSRefIDs = new int[totalNumRefAtms];
1311  qmLSSRefMass = new Mass[totalNumRefAtms];
1312  int lssRefIndx = 0;
1313 
1314  for (int grpIndx=0; grpIndx<qmNumGrps; grpIndx++) {
1315 
1316  itGrpSize = grpNumLSSRes.find(qmGrpID[grpIndx]) ;
1317 
1318  if (itGrpSize != grpNumLSSRes.end())
1319  qmLSSSize[grpIndx] = itGrpSize->second;
1320  else
1321  qmLSSSize[grpIndx] = 0;
1322 
1323  for( auto it = lssGrpRes.begin(); it != lssGrpRes.end();it++ ) {
1324 
1325  if (it->qmGrpID == qmGrpID[grpIndx]) {
1326  for (int i=0; i<it->atmIDs.size(); i++) {
1327  qmLSSIdxs[lssAtmIndx] = it->atmIDs[i];
1328  qmLSSMass[lssAtmIndx] = atoms[it->atmIDs[i]].mass;
1329  lssAtmIndx++;
1330  }
1331  }
1332  }
1333 
1334  DebugM(4, "QM group " << qmGrpID[grpIndx]
1335  << " has " << qmLSSSize[grpIndx] << " solvent molecules, "
1336  << "totalling " << grpLSSSize[qmGrpID[grpIndx]]
1337  << " atoms (check " << lssAtmIndx << ").\n" );
1338 
1339  qmLSSRefSize[grpIndx] = lssGrpRefIDs[qmGrpID[grpIndx]].size();
1340  for(int i=0; i < qmLSSRefSize[grpIndx]; i++) {
1341  qmLSSRefIDs[lssRefIndx] = lssGrpRefIDs[qmGrpID[grpIndx]][i];
1342  qmLSSRefMass[lssRefIndx] = atoms[qmLSSRefIDs[lssRefIndx]].mass;
1343  lssRefIndx++;
1344  }
1345 
1346  DebugM(4, "QM group " << qmGrpID[grpIndx]
1347  << " has " << qmLSSRefSize[grpIndx] << " non-solvent atoms for LSS.\n" );
1348  }
1349 
1350  } break ;
1351 
1352  case QMLSSMODEDIST:
1353  {
1354  for (int grpIndx=0; grpIndx<qmNumGrps; grpIndx++) {
1355 
1356  itGrpSize = grpNumLSSRes.find(qmGrpID[grpIndx]) ;
1357 
1358  if (itGrpSize != grpNumLSSRes.end())
1359  qmLSSSize[grpIndx] = itGrpSize->second;
1360  else
1361  qmLSSSize[grpIndx] = 0;
1362 
1363  for( auto it = lssGrpRes.begin(); it != lssGrpRes.end();it++ ) {
1364 
1365  if (it->qmGrpID == qmGrpID[grpIndx]) {
1366  for (int i=0; i<it->atmIDs.size(); i++) {
1367  qmLSSIdxs[lssAtmIndx] = it->atmIDs[i];
1368  lssAtmIndx++;
1369  }
1370  }
1371  }
1372 
1373  DebugM(4, "QM group " << qmGrpID[grpIndx]
1374  << " has " << qmLSSSize[grpIndx] << " solvent molecules, "
1375  << "totalling " << grpLSSSize[qmGrpID[grpIndx]]
1376  << " atoms (check " << lssAtmIndx << ").\n" );
1377  }
1378 
1379  } break ;
1380 
1381  }
1382  }
1383 
1384 
1387 
1388 
1389  PDB *customPCPDB;
1390 
1391  // In case we have a custom and fixed set of point charges for each QM group,
1392  // we process the files containing information.
1393  current = NULL;
1394  if (simParams->qmCustomPCSel) {
1395  current = cfgList->find("QMCustomPCFile");
1396  }
1397 
1398  std::map<Real,std::vector<int> > qmPCVecMap ;
1399 
1400  int numParsedPBDs = 0;
1401  for ( ; current != NULL; current = current->next ) {
1402 
1403  iout << iINFO << "Parsing QM Custom PC file " << current->data << "\n" << endi;
1404  customPCPDB = new PDB(current->data);
1405 
1406  if (customPCPDB->num_atoms() != numAtoms)
1407  NAMD_die("Number of atoms in QM Custom PC PDB file doesn't match coordinate PDB");
1408 
1409  std::vector< int > currPCSel ;
1410  Real currQMID = 0 ;
1411  int currGrpSize = 0 ;
1412 
1413  for (int atmInd = 0 ; atmInd < numAtoms; atmInd++) {
1414 
1415  BigReal beta = customPCPDB->atom(atmInd)->temperaturefactor() ;
1416  BigReal occ = customPCPDB->atom(atmInd)->occupancy() ;
1417 
1418  if ( beta != 0 && occ != 0)
1419  NAMD_die("An atom cannot be marked as QM and poitn charge simultaneously!");
1420 
1421  // If this is not a QM atom and
1422  if (occ != 0) {
1423  currPCSel.push_back(atmInd) ;
1424  }
1425 
1426  if (beta != 0) {
1427  if (pdbP->atom(atmInd)->temperaturefactor() != beta)
1428  NAMD_die("QM Group selection is different in reference PDB and Custom-PC PDB!");
1429 
1430  if (currQMID == 0) {
1431  // If this is the first QM atom we find, keep the QM Group ID.
1432  currQMID = beta;
1433  }
1434  else {
1435  // For all other atoms, check if it is the same group. It must be!!
1436  if (currQMID != beta)
1437  NAMD_die("Found two different QM group IDs in this file!");
1438  }
1439 
1440  currGrpSize++;
1441  }
1442 
1443  }
1444 
1445  if (currGrpSize != qmGrpSizeVec[ qmGrpIDMap[currQMID] ])
1446  NAMD_die("Reference PDB and Custom-PC PDB have different QM group sizes!") ;
1447 
1448  qmPCVecMap.insert(std::pair<Real,std::vector<int> >(
1449  currQMID, currPCSel ));
1450 
1451  numParsedPBDs++;
1452  delete customPCPDB;
1453  }
1454 
1455  delete pdbP;
1456 
1457  if (numParsedPBDs != qmNumGrps && simParams->qmCustomPCSel) {
1458  iout << iWARN << "The number of files provided for custom point "
1459  "charges is not equal to the number of QM groups!\n" << endi;
1460  }
1461 
1462  // Initializes an array with the number of Custom Point Charges per
1463  // QM group.
1464  qmCustPCSizes = new int[qmNumGrps];
1465  for (int i=0; i<qmNumGrps; i++)
1466  qmCustPCSizes[i] = 0;
1467 
1468  qmTotCustPCs = 0;
1469 
1470  // Stores the size of each Custom PC vector in the array.
1471  // We may not have PCs for all QM groups.
1472  for (auto it = qmPCVecMap.begin(); it != qmPCVecMap.end(); it++) {
1473  qmTotCustPCs += (*it).second.size();
1474  int qmIndx = qmGrpIDMap[(*it).first];
1475  qmCustPCSizes[qmIndx] = (*it).second.size();
1476  }
1477 
1478  qmCustomPCIdxs = new int[qmTotCustPCs];
1479 
1480  if (simParams->qmCustomPCSel) {
1481 
1482  int auxIter = 0;
1483  for (int grpIndx=0; grpIndx<qmNumGrps; grpIndx++) {
1484 
1485  Real currQMID = qmGrpID[grpIndx];
1486 
1487  iout << iINFO << "Loading " << qmPCVecMap[currQMID].size()
1488  << " custom point charges to QM Group " << grpIndx
1489  << " (ID: " << currQMID << ")\n" << endi;
1490 
1491  for (int pcIndx=0; pcIndx<qmPCVecMap[currQMID].size(); pcIndx++) {
1492  qmCustomPCIdxs[auxIter] = qmPCVecMap[currQMID][pcIndx] ;
1493  auxIter++;
1494  }
1495  }
1496  }
1497 
1498  // Conditional SMD option
1499  qmcSMD = simParams->qmCSMD;
1500  if (qmcSMD) {
1501  read_qm_csdm_file(qmGrpIDMap);
1502  }
1503 
1506 
1507  if (simParams->qmElecEmbed) {
1508  // Modifies Atom charges for Electrostatic Embedding.
1509  // QM atoms cannot have charges in the standard location, to keep
1510  // NAMD from calculating electrostatic interactions between QM and MM atoms.
1511  // We handle electrostatics ourselves in ComputeQM.C and in special
1512  // modifications for PME.
1513  for (int i=0; i<qmNumQMAtoms; i++) {
1514  qmAtmChrg[i] = atoms[qmAtmIndx[i]].charge;
1515  atoms[qmAtmIndx[i]].charge = 0;
1516  }
1517  }
1518 
1519 
1520  if ( simParams->extraBondsOn) {
1521  // Lifted from Molecule::build_extra_bonds
1522 
1523  StringList *file = cfgList->find("extraBondsFile");
1524 
1525  char err_msg[512];
1526  int a1,a2; float k, ref;
1527 
1528  for ( ; file; file = file->next ) { // loop over files
1529  FILE *f = fopen(file->data,"r");
1530 // if ( ! f ) {
1531 // sprintf(err_msg, "UNABLE TO OPEN EXTRA BONDS FILE %s", file->data);
1532 // NAMD_err(err_msg);
1533 // } else {
1534 // iout << iINFO << "READING EXTRA BONDS FILE " << file->data <<"\n"<<endi;
1535 // }
1536 
1537  while ( 1 ) {
1538  char buffer[512];
1539  int ret_code;
1540  do {
1541  ret_code = NAMD_read_line(f, buffer);
1542  } while ( (ret_code==0) && (NAMD_blank_string(buffer)) );
1543  if (ret_code!=0) break;
1544 
1545  char type[512];
1546  sscanf(buffer,"%s",type);
1547 
1548  int badline = 0;
1549  if ( ! strncasecmp(type,"bond",4) ) {
1550  if ( sscanf(buffer, "%s %d %d %f %f %s",
1551  type, &a1, &a2, &k, &ref, err_msg) != 5 ) badline = 1;
1552 
1553  // If an extra bond is defined between QM atoms, we make
1554  // note so that it wont be deleted when we delete bonded
1555  // interactions between QM atoms.
1556  if( qmAtomGroup[a1] > 0 && qmAtomGroup[a2]) {
1557  Bond tmp;
1558  tmp.bond_type = 0;
1559  tmp.atom1 = a1; tmp.atom2 = a2;
1560  qmExtraBonds.add(tmp);
1561  }
1562 
1563 
1564  }else if ( ! strncasecmp(type,"#",1) ) {
1565  continue; // comment
1566  }
1567 
1568  }
1569  fclose(f);
1570  }
1571  }
1572 
1573  return;
1574 
1575 #endif // MEM_OPT_VERSION
1576 }
1577 
1578 // Adapted from Molecule::delete_alch_bonded
1580 
1581 #ifdef MEM_OPT_VERSION
1582  NAMD_die("QMMM interface is not supported in memory optimized builds.");
1583 #else
1584 
1585  DebugM(3,"Cleaning QM bonds, angles, dihedrals, impropers and crossterms.\n")
1586 
1587  // Bonds
1588  Bond *nonQMBonds;
1589  nonQMBonds = new Bond[numBonds] ;
1590  int nonQMBondCount = 0;
1591  qmDroppedBonds = 0;
1592  for (int i = 0; i < numBonds; i++) {
1593 
1594  int part1 = qmAtomGroup[bonds[i].atom1];
1595  int part2 = qmAtomGroup[bonds[i].atom2];
1596  if (part1 > 0 && part2 > 0 ) {
1597 
1598  // If the user defined extra bonds, we check if the QM-QM bond is an "extra"
1599  // bond, and do not delete it.
1600  if (simParams->extraBondsOn) {
1601 // std::cout << "Checking Bond: " << bonds[i].atom1 << "," << bonds[i].atom2 << std::endl ;
1602 
1603  for (int ebi=0; ebi < qmExtraBonds.size() ; ebi++) {
1604 
1605  if( (qmExtraBonds[ebi].atom1 == bonds[i].atom1 ||
1606  qmExtraBonds[ebi].atom1 == bonds[i].atom2) &&
1607  (qmExtraBonds[ebi].atom2 == bonds[i].atom1 ||
1608  qmExtraBonds[ebi].atom2 == bonds[i].atom2) ) {
1609 // std::cout << "This is an extra bond! We will keep it." << std::endl;
1610  nonQMBonds[nonQMBondCount++] = bonds[i];
1611  break;
1612  }
1613  }
1614  }
1615 
1616  qmDroppedBonds++;
1617  } else {
1618  // Just a simple sanity check.
1619  // If there are no QM bonds defined by the user but we find a
1620  // bond between a QM and an MM atom, error out.
1621  if ((part1 > 0 || part2 > 0) && qmNumBonds == 0) {
1622  iout << iERROR << " Atoms " << bonds[i].atom1
1623  << " and " << bonds[i].atom2 << " form a QM-MM bond!\n" << endi ;
1624  NAMD_die("No QM-MM bonds were defined by the user, but one was found.");
1625  }
1626  nonQMBonds[nonQMBondCount++] = bonds[i];
1627  }
1628  }
1629  numBonds = nonQMBondCount;
1630  delete [] bonds;
1631  bonds = new Bond[numBonds];
1632  for (int i = 0; i < nonQMBondCount; i++) {
1633  bonds[i]=nonQMBonds[i];
1634  }
1635  delete [] nonQMBonds;
1637 
1638  // Angles
1639  Angle *nonQMAngles;
1640  nonQMAngles = new Angle[numAngles];
1641  int nonQMAngleCount = 0;
1642  qmDroppedAngles = 0;
1643  for (int i = 0; i < numAngles; i++) {
1644  int part1 = qmAtomGroup[angles[i].atom1];
1645  int part2 = qmAtomGroup[angles[i].atom2];
1646  int part3 = qmAtomGroup[angles[i].atom3];
1647  if (part1 > 0 && part2 > 0 && part3 > 0) {
1648  //CkPrintf("-----ANGLE ATOMS %i %i %i partitions %i %i %i\n",angles[i].atom1, angles[i].atom2, angles[i].atom3, part1, part2, part3);
1649  qmDroppedAngles++;
1650  }
1651  else {
1652  nonQMAngles[nonQMAngleCount++] = angles[i];
1653  }
1654  }
1655  numAngles = nonQMAngleCount;
1656  delete [] angles;
1657  angles = new Angle[numAngles];
1658  for (int i = 0; i < nonQMAngleCount; i++) {
1659  angles[i]=nonQMAngles[i];
1660  }
1661  delete [] nonQMAngles;
1662 
1663 
1664  // Dihedrals
1665  Dihedral *nonQMDihedrals;
1666  nonQMDihedrals = new Dihedral[numDihedrals];
1667  int nonQMDihedralCount = 0;
1668  qmDroppedDihedrals = 0;
1669  for (int i = 0; i < numDihedrals; i++) {
1670  int part1 = qmAtomGroup[dihedrals[i].atom1];
1671  int part2 = qmAtomGroup[dihedrals[i].atom2];
1672  int part3 = qmAtomGroup[dihedrals[i].atom3];
1673  int part4 = qmAtomGroup[dihedrals[i].atom4];
1674  if (part1 > 0 && part2 > 0 && part3 > 0 && part4 > 0) {
1675  //CkPrintf("-----i %i DIHEDRAL ATOMS %i %i %i %i partitions %i %i %i %i\n",i,dihedrals[i].atom1, dihedrals[i].atom2, dihedrals[i].atom3, dihedrals[i].atom4, part1, part2, part3,part4);
1676  qmDroppedDihedrals++;
1677  }
1678  else {
1679  nonQMDihedrals[nonQMDihedralCount++] = dihedrals[i];
1680  }
1681  }
1682  numDihedrals = nonQMDihedralCount;
1683  delete [] dihedrals;
1684  dihedrals = new Dihedral[numDihedrals];
1685  for (int i = 0; i < numDihedrals; i++) {
1686  dihedrals[i]=nonQMDihedrals[i];
1687  }
1688  delete [] nonQMDihedrals;
1689 
1690  // Impropers
1691  Improper *nonQMImpropers;
1692  nonQMImpropers = new Improper[numImpropers];
1693  int nonQMImproperCount = 0;
1694  qmDroppedImpropers = 0;
1695  for (int i = 0; i < numImpropers; i++) {
1696  int part1 = qmAtomGroup[impropers[i].atom1];
1697  int part2 = qmAtomGroup[impropers[i].atom2];
1698  int part3 = qmAtomGroup[impropers[i].atom3];
1699  int part4 = qmAtomGroup[impropers[i].atom4];
1700  if (part1 > 0 && part2 > 0 && part3 > 0 && part4 > 0) {
1701  //CkPrintf("-----i %i IMPROPER ATOMS %i %i %i %i partitions %i %i %i %i\n",i,impropers[i].atom1, impropers[i].atom2, impropers[i].atom3, impropers[i].atom4, part1, part2, part3,part4);
1702  qmDroppedImpropers++;
1703  }
1704  else {
1705  nonQMImpropers[nonQMImproperCount++] = impropers[i];
1706  }
1707  }
1708  numImpropers = nonQMImproperCount;
1709  delete [] impropers;
1710  impropers = new Improper[numImpropers];
1711  for (int i = 0; i < numImpropers; i++) {
1712  impropers[i]=nonQMImpropers[i];
1713  }
1714  delete [] nonQMImpropers;
1715 
1716  // Crossterms
1717  Crossterm *nonQMCrossterms;
1718  nonQMCrossterms = new Crossterm[numCrossterms];
1719  int nonQMCrosstermCount = 0;
1720  qmDroppedCrossterms = 0 ;
1721  for (int i = 0; i < numCrossterms; i++) {
1722  int part1 = qmAtomGroup[crossterms[i].atom1];
1723  int part2 = qmAtomGroup[crossterms[i].atom2];
1724  int part3 = qmAtomGroup[crossterms[i].atom3];
1725  int part4 = qmAtomGroup[crossterms[i].atom4];
1726  int part5 = qmAtomGroup[crossterms[i].atom5];
1727  int part6 = qmAtomGroup[crossterms[i].atom6];
1728  int part7 = qmAtomGroup[crossterms[i].atom7];
1729  int part8 = qmAtomGroup[crossterms[i].atom8];
1730  if (part1 > 0 && part2 > 0 && part3 > 0 && part4 > 0 &&
1731  part5 > 0 && part6 > 0 && part7 > 0 && part8 > 0) {
1732  //CkPrintf("-----i %i IMPROPER ATOMS %i %i %i %i partitions %i %i %i %i\n",i,impropers[i].atom1, impropers[i].atom2, impropers[i].atom3, impropers[i].atom4, part1, part2, part3,part4);
1733  qmDroppedCrossterms++;
1734  }
1735  else {
1736  nonQMCrossterms[nonQMCrosstermCount++] = crossterms[i];
1737  }
1738  }
1739  numCrossterms = nonQMCrosstermCount;
1740  delete [] crossterms;
1741  crossterms = new Crossterm[numCrossterms] ;
1742  for (int i=0; i < numCrossterms; i++){
1743  crossterms[i] = nonQMCrossterms[i] ;
1744  }
1745  delete [] nonQMCrossterms ;
1746 
1747  if (!CkMyPe()) {
1748  iout << iINFO << "The QM region will remove " << qmDroppedBonds << " bonds, " <<
1749  qmDroppedAngles << " angles, " << qmDroppedDihedrals << " dihedrals, "
1750  << qmDroppedImpropers << " impropers and " << qmDroppedCrossterms
1751  << " crossterms.\n" << endi ;
1752  }
1753 
1754 #endif
1755 }
1756 
1757 typedef std::pair<int,int> cSMDPair ;
1758 
1759 void Molecule::read_qm_csdm_file(std::map<Real,int> &qmGrpIDMap) {
1760 
1761  std::ifstream cSMDInputFile ;
1762  std::string Line("") ;
1763 
1764  iout << iINFO << "Reading QM cSMD configuration file: " <<
1765  simParams->qmCSMDFile << "\n" << endi ;
1766 
1767  cSMDInputFile.open( simParams->qmCSMDFile ) ;
1768 
1769  if (! cSMDInputFile.good())
1770  {
1771  NAMD_die("Configuration file for QM cSMD could not be read!") ;
1772  }
1773 
1774 
1775  // Index of Conditional SMD guides per group
1776  ResizeArray<ResizeArray<int> > cSMDindexV;
1777  cSMDindexV.resize(qmNumGrps);
1778  // Atom indices for Origin and Target of cSMD
1779  ResizeArray<cSMDPair> cSMDpairsV;
1780  // Spring constants for cSMD
1781  ResizeArray<Real> cSMDKsV;
1782  // Speed of movement of guide particles for cSMD.
1783  ResizeArray<Real> cSMDVelsV;
1784  // Distance cutoff for guide particles for cSMD.
1785  ResizeArray<Real> cSMDcoffsV;
1786 
1787  while( ! cSMDInputFile.eof() )
1788  {
1789  getline(cSMDInputFile, Line) ;
1790 
1791  if ( ! Line.length() )
1792  continue;
1793 
1794  if (Line.substr(0,1) == std::string("#") )
1795  continue;
1796 
1797  auto strVec = split( Line, " ");
1798 
1799  if (strVec.size() != 5 ) {
1800  iout << iERROR << "Format error in QM cSDM configuration file: "
1801  << Line << "\n" << endi;
1802  NAMD_die("Error processing QM information.");
1803  }
1804 
1805  std::stringstream storConv ;
1806  Real convData ;
1807 
1808  cSMDpairsV.add( cSMDPair(0,0) );
1809  cSMDKsV.add(0);
1810  cSMDVelsV.add(0);
1811  cSMDcoffsV.add(0);
1812 
1813  for (int i=0; i < 5; i++ ) {
1814  storConv.clear() ;
1815  storConv << strVec[i] ;
1816  storConv >> convData;
1817  if (storConv.fail()) {
1818  iout << iERROR << "Error parsing QM cSMD configuration file: "
1819  << convData << "\n" << endi;
1820  NAMD_die("Error processing QM information.");
1821  }
1822 
1823  switch (i) {
1824  case 0:
1825  cSMDpairsV[cSMDnumInst].first = convData ;
1826  break;
1827  case 1:
1828  cSMDpairsV[cSMDnumInst].second = convData ;
1829  break;
1830  case 2:
1831  cSMDKsV[cSMDnumInst] = convData ;
1832  break;
1833  case 3:
1834  cSMDVelsV[cSMDnumInst] = convData ;
1835  break;
1836  case 4:
1837  cSMDcoffsV[cSMDnumInst] = convData ;
1838  break;
1839  }
1840  }
1841 
1842  // Sanity check
1843  if (cSMDpairsV[cSMDnumInst].first == cSMDpairsV[cSMDnumInst].second) {
1844  iout << iERROR << "Conditional SMD atoms must be different! We got " <<
1845  cSMDpairsV[cSMDnumInst].first << " and " << cSMDpairsV[cSMDnumInst].second << "\n" << endi;
1846  NAMD_die("Error processing QM information.") ;
1847  }
1848 
1849  // Sanity check
1850  if (qmAtomGroup[cSMDpairsV[cSMDnumInst].first] == 0 ||
1851  qmAtomGroup[cSMDpairsV[cSMDnumInst].second] == 0) {
1852  iout << iERROR << "Atoms " << cSMDpairsV[cSMDnumInst].first << " and " <<
1853  cSMDpairsV[cSMDnumInst].second << " MUST be assigned as QM atoms.\n" << endi;
1854  NAMD_die("Error processing QM information.") ;
1855  }
1856 
1857  // Sanity check
1858  if (qmAtomGroup[cSMDpairsV[cSMDnumInst].first] !=
1859  qmAtomGroup[cSMDpairsV[cSMDnumInst].second] ) {
1860  iout << iERROR << "Atoms in cSMD MUST be assigned to the same QM group.\n" << endi;
1861  NAMD_die("Error processing QM information.") ;
1862  }
1863 
1864  int grpIndx = qmGrpIDMap[qmAtomGroup[cSMDpairsV[cSMDnumInst].first]] ;
1865 
1866  iout << iINFO << "Adding cSMD data: (" << cSMDnumInst << ") " <<
1867  cSMDpairsV[cSMDnumInst].first << "," << cSMDpairsV[cSMDnumInst].second << "," <<
1868  cSMDKsV[cSMDnumInst] << "," << cSMDVelsV[cSMDnumInst] << "," << cSMDcoffsV[cSMDnumInst] <<
1869  " to QM Group " << grpIndx << "\n" << endi ;
1870 
1871  cSMDindexV[grpIndx].add(cSMDnumInst);
1872 
1873  cSMDnumInst++;
1874  }
1875 
1876  cSMDindex = new int*[qmNumGrps];
1877  cSMDindxLen = new int[qmNumGrps];
1878 
1879  for (int i=0; i<qmNumGrps; i++) {
1880  cSMDindex[i] = new int[cSMDindexV[i].size()];
1881  cSMDindxLen[i] = cSMDindexV[i].size();
1882 
1883  for (int j=0; j<cSMDindxLen[i]; j++)
1884  cSMDindex[i][j] = cSMDindexV[i][j] ;
1885  }
1886 
1887  cSMDpairs = new int*[cSMDnumInst];
1888  for (int i=0; i<cSMDnumInst; i++)
1889  cSMDpairs[i] = new int[2];
1890  cSMDKs = new Real[cSMDnumInst];
1891  cSMDVels = new Real[cSMDnumInst];
1892  cSMDcoffs = new Real[cSMDnumInst];
1893 
1894  for (int i=0; i<cSMDnumInst; i++) {
1895  cSMDpairs[i][0] = cSMDpairsV[i].first;
1896  cSMDpairs[i][1] = cSMDpairsV[i].second;
1897 
1898  cSMDKs[i] = cSMDKsV[i];
1899  cSMDVels[i] = cSMDVelsV[i];
1900  cSMDcoffs[i] = cSMDcoffsV[i];
1901  }
1902 
1903 }
1904 
1905 
1906 
1907 
1908 
char qmLSSResname[5]
std::ostream & iINFO(std::ostream &s)
Definition: InfoStream.C:81
Type * getNewArray(int n)
Definition: ObjectArena.h:49
std::map< Real, refSelStrVec > refSelStrMap
Definition: MoleculeQM.C:107
#define QMLSSMODECOM
Definition: Molecule.h:127
int begAtmID
Definition: MoleculeQM.C:50
Definition: PDB.h:36
int size(void) const
Definition: ResizeArray.h:131
int numBonds
Definition: Molecule.h:588
#define QMSCHEMEZ2
Definition: Molecule.h:140
int NAMD_read_line(FILE *fd, char *buf, int bufsize)
Definition: strlib.C:38
void assign_vdw_index(const char *, Atom *)
Definition: Parameters.C:4399
std::vector< int > atmIDs
Definition: MoleculeQM.C:51
#define QMSCHEMERCD
Definition: Molecule.h:138
int get_residue_size(const char *segid, int resid) const
Definition: Molecule.C:149
BigReal temperaturefactor(void)
Definition: PDBData.C:450
int lookup(const char *segid, int resid, int *begin, int *end) const
Definition: Molecule.C:81
float Real
Definition: common.h:118
int32_t int32
Definition: common.h:38
#define DebugM(x, y)
Definition: Debug.h:75
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
char qmCSMDFile[NAMD_FILENAME_BUFFER_SIZE]
std::ostream & iWARN(std::ostream &s)
Definition: InfoStream.C:82
int numRealBonds
Definition: Molecule.h:587
int32 atom1
Definition: structures.h:83
refSelStr(std::string newSegID, int newResid)
Definition: MoleculeQM.C:100
#define QMFormatMOPAC
Definition: Molecule.h:130
#define iout
Definition: InfoStream.h:51
int num_atoms(void)
Definition: PDB.C:323
int add(const Elem &elem)
Definition: ResizeArray.h:101
#define QMFormatORCA
Definition: Molecule.h:129
void resize(int i)
Definition: ResizeArray.h:84
#define QMSCHEMEZ3
Definition: Molecule.h:141
int32 atom1
Definition: structures.h:50
#define QMSCHEMEZ1
Definition: Molecule.h:139
#define QMSCHEMECS
Definition: Molecule.h:137
const char * residuename(void)
Definition: PDBData.C:399
int insert(const Elem &elem)
Definition: SortedArray.h:81
std::pair< int, int > cSMDPair
Definition: MoleculeQM.C:1757
PDBAtom * atom(int place)
Definition: PDB.C:393
int NAMD_blank_string(char *str)
Definition: strlib.C:222
Real qmGrpID
Definition: MoleculeQM.C:52
int32 atom1
Definition: structures.h:57
int Bool
Definition: common.h:142
int residueseq(void)
Definition: PDBData.C:411
std::string segid
Definition: MoleculeQM.C:96
std::pair< Real, refSelStrVec > refSelStrPair
Definition: MoleculeQM.C:108
void delete_qm_bonded()
Definition: MoleculeQM.C:1579
void prepare_qm(const char *pdbFileName, Parameters *params, ConfigList *cfgList)
Definition: MoleculeQM.C:110
int numAngles
Definition: Molecule.h:589
int numAtoms
Definition: Molecule.h:585
int numCrossterms
Definition: Molecule.h:596
void NAMD_die(const char *err_msg)
Definition: common.C:147
bool operator<(const qmSolvData &ref)
Definition: MoleculeQM.C:70
int resid
Definition: MoleculeQM.C:97
std::vector< std::string > split(const std::string &text, std::string delimiter)
Definition: MoleculeQM.C:74
int numDihedrals
Definition: Molecule.h:590
int numImpropers
Definition: Molecule.h:595
int32 atom1
Definition: structures.h:74
Bool qmMOPACAddConfigChrg
std::vector< refSelStr > refSelStrVec
Definition: MoleculeQM.C:106
StringList * next
Definition: ConfigList.h:49
iterator begin(void)
Definition: ResizeArray.h:36
char * data
Definition: ConfigList.h:48
char segName[5]
Definition: MoleculeQM.C:49
Bool qmBondColumnDefined
Elem * find(const Elem &elem)
Definition: SortedArray.h:94
iterator end(void)
Definition: ResizeArray.h:37
bool operator==(const qmSolvData &ref)
Definition: MoleculeQM.C:71
float Mass
Definition: ComputeGBIS.inl:20
BigReal occupancy(void)
Definition: PDBData.C:444
std::ostream & iERROR(std::ostream &s)
Definition: InfoStream.C:83
qmSolvData(int newResID, int newBegAtm, int newSize, const char *newSegName, Real newQMID)
Definition: MoleculeQM.C:60
#define QMLSSMODEDIST
Definition: Molecule.h:126
Index bond_type
Definition: structures.h:52
StringList * find(const char *name) const
Definition: ConfigList.C:341
const char * element(void)
Definition: PDBData.C:470
int32 atom1
Definition: structures.h:65
int32 atom2
Definition: structures.h:51
double BigReal
Definition: common.h:123
char qmColumn[16]
const char * segmentname(void)
Definition: PDBData.C:464
qmSolvData(int newResID, int newBegAtm, int newSize)
Definition: MoleculeQM.C:55