16 #define MIN_DEBUG_LEVEL 1    25 #include "ComputeQMMgr.decl.h"    30 #include "ComputeMgr.decl.h"    41 #include "ComputePmeMgr.decl.h"    46 #if defined(WIN32) && !defined(__CYGWIN__)    48 #define mkdir(X,Y) _mkdir(X)    49 #define S_ISDIR(X) ((X) & S_IFDIR)    53 #define SQRT_PI 1.7724538509055160273     59 #define QMPCSCHEMENONE 1    60 #define QMPCSCHEMEROUND 2    61 #define QMPCSCHEMEZERO 3    63 #define QMPCSCALESHIFT 1    64 #define QMPCSCALESWITCH 2    76                   Real qmInit, 
int hiInit, 
int newvdwType) {
   100 #define PCMODEUPDATESEL 1   101 #define PCMODEUPDATEPOS 2   102 #define PCMODECUSTOMSEL 3   138                      Real qmInit, 
int hiInit, 
Real newDist, 
   139                      Mass newM, 
int newvdwType) {
   161         return (
id < ref.
id);
   164         return (
id == ref.
id) ;
   196 # define QMATOMTYPE_DUMMY 0   197 # define QMATOMTYPE_QM 1   198 # define QMPCTYPE_IGNORE 0   199 # define QMPCTYPE_CLASSICAL 1   200 # define QMPCTYPE_EXTRA 2   203 #define QMLSSCLASSICALRES 2   232         return !(*
this == ref);
   276         bool returnVal = 
true;
   307                int bountToIndxInit, 
int newType, 
   308                char *elementInit, 
Real newDist) {
   314         strncpy(
element,elementInit,3);
   370   static char tmp_string[25];
   371   const double maxnum = 9999999999.9999;
   372   if ( 
X > maxnum ) 
X = maxnum;
   373   if ( 
X < -maxnum ) 
X = -maxnum;
   374   sprintf(tmp_string,
" %14.4f",
X); 
   380   static char tmp_string[25];
   381   sprintf(tmp_string,
" %14s",
X); 
   387   static char tmp_string[21];
   388   sprintf(tmp_string,
"QMENERGY: %7d",
X); 
   399 typedef std::vector<ComputeQMPntChrg> 
QMPCVec ;
   431     ComputeQMMgr_SDAG_CODE
   433     CProxy_ComputeQMMgr QMProxy;
   437     int numArrivedQMMsg, numArrivedPntChrgMsg, numRecQMRes;
   441     std::vector<int> qmPEs ;
   475     Real *grpChrg, *grpMult;
   505     int dcdOutFile, dcdPosOutFile;
   509     void procBonds(
int numBonds,
   510                      const int *
const qmGrpBondsGrp,
   511                      const int *
const qmMMBondedIndxGrp,
   512                      const int *
const *
const chargeTarget,
   513                      const int *
const numTargs,
   520     void lssUpdate(
int grpIter, 
QMAtmVec &grpQMAtmVec, 
QMPCVec &grpPntChrgVec);
   522         void calcCSMD(
int grpIndx,
int numQMAtoms, 
const QMAtomData *atmP, 
Force *resForce) ;
   525     int cSMDnumInstances, cSMDInitGuides;
   527     int const * 
const * cSMDindex;
   529     int const * cSMDindxLen;
   533     int const * 
const * cSMDpairs;
   537     Real const * cSMDVels;
   539     Real const * cSMDcoffs;
   544     void Write_PDB(std::string Filename, 
const QMGrpCalcMsg *dataMsg);
   545     void Write_PDB(std::string Filename, 
const QMCoordMsg *dataMsg);
   550   QMProxy(thisgroup), QMCompute(0), numSources(0), numArrivedQMMsg(0), 
   551   numArrivedPntChrgMsg(0), numRecQMRes(0), qmCoordMsgs(0), pntChrgCoordMsgs(0),
   552   qmCoord(0), force(0), numAtoms(0), dcdOutFile(0), outputData(0), pcIDListSize(0) {
   554   CkpvAccess(BOCclass_group).computeQMMgr = thisgroup;
   560     if (qmCoordMsgs != 0) {
   561         for ( 
int i=0; i<numSources; ++i ) {
   562             if (qmCoordMsgs[i] != 0)
   563                 delete qmCoordMsgs[i];
   565         delete [] qmCoordMsgs;
   568     if (pntChrgCoordMsgs != 0) {
   569         for ( 
int i=0; i<numSources; ++i ) {
   570             if (pntChrgCoordMsgs[i] != 0)
   571                 delete pntChrgCoordMsgs[i];
   573         delete [] pntChrgCoordMsgs;
   586     if (dcdPosOutFile != 0)
   590         delete [] outputData;
   603   CProxy_ComputeQMMgr::ckLocalBranch(
   604         CkpvAccess(BOCclass_group).computeQMMgr)->setCompute(
this);
   632         for (
int i=0; i<meNumMMIndx; i++)
   643     cutoff = simParams->
cutoff;
   648         customPCLists.
resize(numQMGrps);
   654         int minI = 0, maxI = 0, grpIter = 0;
   656         while (grpIter < numQMGrps) {
   658             maxI += custPCSizes[grpIter];
   660             for (
size_t i=minI; i < maxI; i++) {
   662                 customPCLists[grpIter].
add( customPCIdxs[i] ) ;
   666             minI += custPCSizes[grpIter];
   678     CProxy_ComputeQMMgr QMProxy(CkpvAccess(BOCclass_group).computeQMMgr);
   685     DebugM(4,
"----> Initiating QM work on rank " << CkMyPe() <<
   692     int numLocalQMAtoms = 0, localMM1atoms = 0;
   693     for (ap = ap.
begin(); ap != ap.
end(); ap++) {
   695         int localNumAtoms = (*ap).p->getNumAtoms();
   698                     (*ap).positionBox->open(),
   701         for(
int i=0; i<localNumAtoms; ++i) {
   702             if ( qmAtomGroup[xExt[i].
id] > 0 ) {
   705             else if (meNumMMIndx > 0) {
   719         timeStep = (*ap).p->flags.step ;
   722     DebugM(4, 
"Node " << CkMyPe() << 
" has " << numLocalQMAtoms
   723     << 
" QM atoms." << std::endl) ;
   725     if (localMM1atoms > 0)
   726         DebugM(4, 
"Node " << CkMyPe() << 
" has " << localMM1atoms
   727             << 
" MM1 atoms." << std::endl) ;
   734     msg->
numAtoms = numLocalQMAtoms + localMM1atoms;
   741     for (
auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
   744         const CompAtomExt *xExt =  (*pdIt).homePatchP->getCompAtomExtInfo();
   745         int localNumAtoms =  (*pdIt).homePatchP->getNumAtoms();
   746         const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
   748         for(
int i=0; i<localNumAtoms; ++i) {
   750             if ( qmAtomGroup[xExt[i].
id] > 0 ) {
   754                 for (
int qi=0; qi<numQMAtms; qi++) {
   755                     if (qmAtmIndx[qi] == xExt[i].
id) {
   756                         charge = qmAtmChrg[qi];
   762                                                           fullAtms[i].transform) ;
   764                 data_ptr->
charge = charge;
   765                 data_ptr->
id = xExt[i].
id;
   766                 data_ptr->
qmGrpID = qmAtomGroup[xExt[i].
id] ;
   772             else if (meNumMMIndx > 0) {
   781                     DebugM(3,
"Found atom " << retIt->mmIndx << 
"," << retIt->qmGrp << 
"\n" );
   784                                                           fullAtms[i].transform) ;
   788                     data_ptr->
id = xExt[i].
id;
   789                     data_ptr->
qmGrpID = retIt->qmGrp ;
   808         for (
auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
   810             (*pdIt).posBoxP->close(&x);
   814     QMProxy[0].recvPartQM(msg);
   823     if ( ! numSources ) {
   824         DebugM(4,
"Initializing ComputeQMMgr variables." << std::endl);
   827         DebugM(4,
"There are " << numSources << 
" nodes with patches." << std::endl);
   829         for ( 
int i=0; i<numSources; ++i ) { 
   835         DebugM(4,
"Getting data from molecule and simParameters." << std::endl);
   846         noPC = simParams->
qmNoPC ;
   848         if (noPC && meNumMMIndx == 0) {
   849             pntChrgCoordMsgs = NULL;
   853             for ( 
int i=0; i<numSources; ++i ) { 
   854                 pntChrgCoordMsgs[i] = 0;
   859         resendPCList = 
false;
   883         numArrivedQMMsg = 0 ;
   884         numArrivedPntChrgMsg = 0 ;
   907                 cSMDguides = 
new Position[cSMDnumInstances];
   908                 cSMDForces = 
new Force[cSMDnumInstances];
   912         DebugM(4,
"Initializing DCD file for charge information." << std::endl);
   916             std::string dcdOutFileStr;
   917             dcdOutFileStr.clear();
   919             dcdOutFileStr.append(
".qdcd") ;
   923                 iout << 
iERROR << 
"DCD file " << dcdOutFile << 
" already exists!!\n" << 
endi;
   924                 NAMD_err(
"Could not write QM charge DCD file.");
   925             } 
else if (dcdOutFile < 0) {
   926                 iout << 
iERROR << 
"Couldn't open DCD file " << dcdOutFile << 
".\n" << 
endi;
   927                 NAMD_err(
"Could not write QM charge DCD file.");
   928             } 
else if (! dcdOutFile) {
   929                 NAMD_bug(
"ComputeQMMgr::recvPartQM open_dcd_write returned fileid of zero");
   934             int NSAVC, NFILE, NPRIV, NSTEP;
   937             NSTEP = NPRIV - NSAVC;
   942             numQMAtms, NFILE, NPRIV, NSAVC, NSTEP,
   946                 NAMD_err(
"Writing of DCD header failed!!");
   951             outputData = 
new Real[3*numQMAtms];
   954         DebugM(4,
"Initializing DCD file for position information." << std::endl);
   957             std::string dcdPosOutFileStr;
   958             dcdPosOutFileStr.clear();
   960             dcdPosOutFileStr.append(
".QMonly.dcd") ;
   964                 iout << 
iERROR << 
"DCD file " << dcdPosOutFile << 
" already exists!!\n" << 
endi;
   965                 NAMD_err(
"Could not write QM charge DCD file.");
   966             } 
else if (dcdPosOutFile < 0) {
   967                 iout << 
iERROR << 
"Couldn't open DCD file " << dcdPosOutFile << 
".\n" << 
endi;
   968                 NAMD_err(
"Could not write QM charge DCD file.");
   969             } 
else if (! dcdPosOutFile) {
   970                 NAMD_bug(
"ComputeQMMgr::recvPartQM open_dcd_write returned fileid of zero");
   975             int NSAVC, NFILE, NPRIV, NSTEP;
   978             NSTEP = NPRIV - NSAVC;
   982             int ret_code = 
write_dcdheader(dcdPosOutFile, dcdPosOutFileStr.c_str(),
   983             numQMAtms, NFILE, NPRIV, NSAVC, NSTEP,
   987                 NAMD_err(
"Writing of DCD header failed!!");
   992             outputData = 
new Real[3*numQMAtms];
   997         int zeroNodeSize = CmiNumPesOnPhysicalNode(0);
  1000         if ( zeroNodeSize < simsPerNode ) {
  1001             iout << 
iERROR << 
"There are " << zeroNodeSize << 
" cores pernode, but "  1002             << simsPerNode << 
" QM simulations per node were requested.\n" << 
endi ;
  1003             NAMD_die(
"Error preparing QM simulations.");
  1006         DebugM(4,
"Preparing PE list for QM execution.\n");
  1009         int numNodes = CmiNumPhysicalNodes();
  1010         int numPlacedQMGrps = 0;
  1011         int placedOnNode = 0;
  1015         if ( simsPerNode <= 0 ) {
  1017             numPlacedQMGrps = 1;
  1020         while ( (numPlacedQMGrps < numQMGrps) && (simsPerNode > 0) ) {
  1023             if (nodeIt == numNodes) {
  1029             CmiGetPesOnPhysicalNode(CmiPhysicalNodeID(nodeIt), &pelist, &nodeSize);
  1031             DebugM(4,
"Checking node " << nodeIt +1 << 
" out of " << numNodes
  1032             << 
" (" << nodeSize << 
" PEs: " << pelist[0] << 
" to "   1033             << pelist[nodeSize-1] << 
")." << std::endl );
  1035             for ( 
int i=0; i<nodeSize; ++i ) {
  1039                     DebugM(1,
"PE " << pelist[i] << 
" has no patches! We'll skip it."   1046                 qmPEs.push_back(pelist[i]);
  1048                 DebugM(1,
"Added PE to QM execution list: " << pelist[i]  << 
"\n");
  1053                 if (placedOnNode == simsPerNode) {
  1054                     DebugM(1,
"Placed enought simulations on this node.\n");
  1065         if ( numPlacedQMGrps < numQMGrps ) {
  1066             iout << 
iWARN << 
"Could not compute all QM groups in parallel.\n" << 
endi ;
  1069         iout << 
iINFO << 
"List of ranks running QM simulations: " << qmPEs[0] ;
  1070         for (
int i=1; i < qmPEs.size(); i++) {
  1071             iout << 
", " << qmPEs[i] ;
  1078     << 
" a total of " << msg->
numAtoms << 
" QM atoms." << std::endl);
  1082     if (meNumMMIndx > 0) {
  1087         for (
int i=0; i<msg->
numAtoms; i++) {
  1088             if (data_ptr[i].vdwType < 0) {
  1089                 tmpAtm.
add(data_ptr[i]) ;
  1100         if (tmpAtm.
size() > 0) {
  1108             for (
int i=0; i<msg->
numAtoms; i++) {
  1109                 if (data_ptr[i].vdwType < 0) {
  1112                     newPCData->
id = data_ptr[i].
id ;
  1115                     newPCData->
dist = 0 ;
  1116                     newPCData->
mass = 0 ;
  1121                     *newMsgData = data_ptr[i] ;
  1130         qmCoordMsgs[numArrivedQMMsg] = newMsg;
  1133         pntChrgCoordMsgs[numArrivedPntChrgMsg] = pntChrgMsg;
  1134         ++numArrivedPntChrgMsg;
  1137         qmCoordMsgs[numArrivedQMMsg] = msg;
  1141     if ( numArrivedQMMsg < numSources ) 
  1145     for (
int msgIt=0; msgIt < numArrivedQMMsg; msgIt++){
  1147         DebugM(1, 
"Getting positions for " << qmCoordMsgs[msgIt]->numAtoms 
  1148         << 
" QM atoms in this message." << std::endl);
  1150         for ( 
int i=0; i < qmCoordMsgs[msgIt]->
numAtoms; ++i ) {
  1151             qmCoord[qmAtmIter] = qmCoordMsgs[msgIt]->
coord[i];
  1156     if (qmAtmIter != numQMAtms) {
  1157         iout << 
iERROR << 
"The number of QM atoms received (" << qmAtmIter
  1158         << 
") is different than expected: " << numQMAtms << 
"\n" << 
endi;
  1159         NAMD_err(
"Problems broadcasting QM atoms.");
  1163     numArrivedQMMsg = 0;
  1166     timeStep = qmCoordMsgs[0]->
timestep;
  1171     for (
int i=0; i<numAtoms; ++i ) {
  1180     for (
int i=0; i<numQMAtms; i++) {
  1183         if (force[qmCoord[i].
id].homeIndx != -1
  1184             && force[qmCoord[i].
id].homeIndx != qmCoord[i].homeIndx
  1187             << qmCoord[i].
id << 
"; home index: "   1190             NAMD_die(
"Error preparing QM simulations.");
  1197         force[qmCoord[i].
id].
replace = replaceForces;
  1206         QMProxy[0].recvPntChrg(pntChrgMsg);
  1212         int msgPCListSize = 0;
  1214         if ( qmPCFreq > 0 ) {
  1215             if (timeStep % qmPCFreq == 0) {
  1219                 resendPCList = 
true;
  1237                     msgPCListSize = pcIDListSize;
  1238                     resendPCList = 
false;
  1247         DebugM(1,
"Broadcasting current positions of QM atoms.\n");
  1248         for ( 
int j=0; j < numSources; ++j ) {
  1256             int *msgPCListP = qmFullMsg->
pcIndxs;
  1258             for (
int i=0; i<numQMAtms; i++) {
  1261                 data_ptr->
id = qmCoord[i].
id;
  1267             for (
int i=0; i<msgPCListSize; i++) {
  1268                 msgPCListP[i] = pcIDList[i] ;
  1273                 Write_PDB(
"qmMsg.pdb", qmFullMsg) ;
  1277             QMProxy[qmCoordMsgs[j]->
sourceNode].recvFullQM(qmFullMsg);
  1284     if (subsArray.
size() > 0)
  1290 typedef std::map<Real, std::pair<Position,BigReal> > 
GrpDistMap ;
  1312     DebugM(4,
"Rank " << CkMyPe() << 
" receiving from rank " << qmFullMsg->
sourceNode  1313     << 
" a total of " << qmFullMsg->
numAtoms << 
" QM atoms and "   1314     << qmFullMsg->
numPCIndxs << 
" PC IDs." << std::endl);
  1321         pcIDSortList.
clear();
  1323         int *pcIndx = qmFullMsg->
pcIndxs;
  1324         for (
int i=0; i< qmFullMsg->
numPCIndxs;i++) {
  1325             pcIDSortList.
load(pcIndx[i]);
  1328         pcIDSortList.
sort();
  1331     int totalNodeAtoms = 0;
  1333     int uniqueCounter = 0;
  1342     DebugM(4,
"Updating PC selection.\n")
  1346     for (
auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
  1349         const CompAtomExt *xExt =  (*pdIt).homePatchP->getCompAtomExtInfo();
  1350         int localNumAtoms =  (*pdIt).homePatchP->getNumAtoms();
  1351         const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
  1353         totalNodeAtoms += localNumAtoms;
  1356         for(
int i=0; i<localNumAtoms; ++i) {
  1361             Real pcGrpID = qmAtomGroup[xExt[i].
id];
  1369                 for (
int qi=0; qi<numQMAtms; qi++) {
  1370                     if (qmAtmIndx[qi] == xExt[i].
id) {
  1371                         charge = qmAtmChrg[qi];
  1377             qmDataPtn = qmFullMsg->
coord;
  1378             for(
int j=0; j<qmFullMsg->
numAtoms; j++, ++qmDataPtn) {
  1391                 if (qmGrpID == pcGrpID) {
  1400                 if ( dist < cutoff ){
  1407                     auto ret = chrgGrpMap.find(qmGrpID) ;
  1415                     if ( ret ==  chrgGrpMap.end()) {
  1416                         chrgGrpMap.insert(std::pair<Real,PosDistPair>(qmGrpID, 
  1424                         if (dist < ret->second.second) {
  1425                             ret->second.first = posMM ;
  1426                             ret->second.second = dist ;
  1432             for(
auto mapIt = chrgGrpMap.begin(); 
  1433                 mapIt != chrgGrpMap.end(); mapIt++) {
  1440                                   mapIt->first, atomIter, mapIt->second.second, 
  1447             if (chrgGrpMap.size() > 0)
  1453         (*pdIt).posBoxP->close(&x);
  1461     DebugM(4,
"Updating PC positions ONLY.\n")
  1463     for (
auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
  1466         const CompAtomExt *xExt =  (*pdIt).homePatchP->getCompAtomExtInfo();
  1467         int localNumAtoms =  (*pdIt).homePatchP->getNumAtoms();
  1468         const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
  1470         totalNodeAtoms += localNumAtoms;
  1473         for(
int i=0; i<localNumAtoms; ++i) {
  1475             if (pcIDSortList.
find(xExt[i].
id) != NULL ) {
  1480                 bool firstIngroupQM = 
true;
  1481                 qmDataPtn = qmFullMsg->
coord;
  1482                 for(
int j=0; j<qmFullMsg->
numAtoms; j++, ++qmDataPtn) {
  1496                     if ( firstIngroupQM ) {
  1502                         firstIngroupQM = 
false;
  1507                     if ( r12.
length() < dist ) {
  1509                         posMM = qmDataPtn->
position + r12 ;
  1514                 Real pcGrpID = qmAtomGroup[xExt[i].
id];
  1521                     for (
int qi=0; qi<numQMAtms; qi++) {
  1522                         if (qmAtmIndx[qi] == xExt[i].
id) {
  1523                             charge = qmAtmChrg[qi];
  1533                                   fullAtms[i].mass, fullAtms[i].vdwType));
  1539         (*pdIt).posBoxP->close(&x);
  1546     DebugM(4,
"Updating PC positions for custom PC selection.\n")
  1548     for (
auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
  1551         const CompAtomExt *xExt =  (*pdIt).homePatchP->getCompAtomExtInfo();
  1552         int localNumAtoms =  (*pdIt).homePatchP->getNumAtoms();
  1553         const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
  1555         totalNodeAtoms += localNumAtoms;
  1558         for(
int i=0; i<localNumAtoms; ++i) {
  1564             for (
int grpIndx=0; grpIndx<numQMGrps; grpIndx++) {
  1566                 if (customPCLists[grpIndx].find(xExt[i].
id) != NULL){
  1578                     bool firstIngroupQM = 
true;
  1579                     qmDataPtn = qmFullMsg->
coord;
  1580                     for(
int j=0; j<qmFullMsg->
numAtoms; j++, ++qmDataPtn) {
  1584                         if ( qmDataPtn->
qmGrpID != qmGrpIDArray[grpIndx] ) 
continue;
  1591                         if ( firstIngroupQM ) {
  1597                             firstIngroupQM = 
false;
  1602                         if ( r12.
length() < dist ) {
  1604                             posMM = qmDataPtn->
position + r12 ;
  1610                     Real pcGrpID = qmAtomGroup[xExt[i].
id];
  1617                         for (
int qi=0; qi<numQMAtms; qi++) {
  1618                             if (qmAtmIndx[qi] == xExt[i].
id) {
  1619                                 charge = qmAtmChrg[qi];
  1627                                       qmGrpIDArray[grpIndx], atomIter, dist, 
  1628                                       fullAtms[i].mass, fullAtms[i].vdwType));
  1636         (*pdIt).posBoxP->close(&x);
  1642     DebugM(4,
"Rank " << CkMyPe() << 
" found a total of " << compPCVec.
size()
  1643     << 
" point charges, out of " << totalNodeAtoms
  1644     << 
" atoms in this node. " << uniqueCounter << 
" are unique." << std::endl);
  1651     pntChrgMsg->numAtoms = compPCVec.
size();
  1653     for (
int i=0; i<compPCVec.
size(); i++ ) {
  1659         pntChrgMsg->coord[i] = compPCVec[i] ;
  1663     DebugM(4,
"Rank " << pntChrgMsg->sourceNode << 
" sending a total of "   1664     << compPCVec.
size() << 
" elements to rank zero." << std::endl);
  1666     CProxy_ComputeQMMgr QMProxy(CkpvAccess(BOCclass_group).computeQMMgr);
  1667     QMProxy[0].recvPntChrg(pntChrgMsg);
  1674 void ComputeQMMgr::procBonds(
int numBonds,
  1675                              const int *
const qmGrpBondsGrp,
  1676                              const int *
const qmMMBondedIndxGrp,
  1677                              const int *
const *
const chargeTarget,
  1678                              const int *
const numTargs,
  1682     DebugM(1,
"Processing QM-MM bonds in rank zero.\n");
  1685     std::map<int, int> mmPntChrgMap ;
  1690     for (
size_t i=0; i<grpPntChrgVec.size(); i++) {
  1692         mmPntChrgMap.insert(std::pair<int,int>(grpPntChrgVec[i].
id, (
int) i) );
  1694         grpAppldChrgVec.push_back( grpPntChrgVec[i] ) ;
  1701     for (
int bondIt = 0; bondIt < numBonds; bondIt++) {
  1704         int bondIndx = qmGrpBondsGrp[bondIt] ;
  1706         auto retIt = mmPntChrgMap.find(qmMMBondedIndxGrp[bondIt]) ;
  1710         if (retIt == mmPntChrgMap.end()) {
  1713             iout << 
iERROR << 
"The MM atom " << qmMMBondedIndxGrp[bondIt]
  1714             << 
" is bound to a QM atom, but it was not selected as a poitn charge."  1715             << 
" Check your cutoff radius!\n" << 
endi ;
  1717             NAMD_die(
"Charge placement error in QM-MM bond.");
  1721         int mmIndex = (*retIt).second;
  1723         Position mmPos = grpAppldChrgVec[mmIndex].position ;
  1724         BigReal mmCharge = grpAppldChrgVec[mmIndex].charge/numTargs[bondIndx] ;
  1727         for (
int i=0; i<numTargs[bondIndx]; i++){
  1729             int targetIndxGLobal = chargeTarget[bondIndx][i] ;
  1731             retIt = mmPntChrgMap.find(targetIndxGLobal);
  1735             if (retIt == mmPntChrgMap.end()) {
  1737                 iout << 
iERROR << 
"The MM atom " << targetIndxGLobal
  1738                 << 
" is bound to the MM atom of a QM-MM bond and is needed for"  1739                 << 
" the required bond scheme"  1740                 << 
" but it was not selected as a poitn charge."  1741                 << 
" Check your cutoff radius!\n" << 
endi ;
  1743                 NAMD_die(
"Charge placement error in QM-MM bond.");
  1746             int trgIndxLocal = (*retIt).second;
  1770                 Position trgPos = grpAppldChrgVec[trgIndxLocal].position ;
  1774                 grpAppldChrgVec[trgIndxLocal].qmGrpID = -2;
  1775                 grpAppldChrgVec[trgIndxLocal].homeIndx = mmIndex;
  1784                 grpAppldChrgVec.push_back(
  1790                 Vector bondVec = trgPos - mmPos ;
  1796                 Vector bondVec1 = bondVec*Cqp ;
  1797                 Vector bondVec2 = bondVec*Cqm ;
  1799                 Position chrgPos1 = mmPos + bondVec1;
  1800                 Position chrgPos2 = mmPos + bondVec2;
  1803                 BigReal trgChrg2 = -1*mmCharge;
  1805                 grpAppldChrgVec.push_back(
  1809                 grpAppldChrgVec.push_back(
  1835                 Position trgPos = grpAppldChrgVec[trgIndxLocal].position ;
  1839                 grpAppldChrgVec[trgIndxLocal].qmGrpID = -2;
  1840                 grpAppldChrgVec[trgIndxLocal].homeIndx = mmIndex;
  1849                 grpAppldChrgVec.push_back(
  1855                 Vector bondVec = trgPos - mmPos ;
  1859                 Vector bondVec1 = bondVec*Cq1 ;
  1861                 Position chrgPos1 = mmPos + bondVec1;
  1863                 BigReal trgChrg1 = 2*mmCharge;
  1865                 grpAppldChrgVec.push_back(
  1893                     grpAppldChrgVec[trgIndxLocal].charge = 0.0;
  1904         grpAppldChrgVec[mmIndex].qmGrpID = -1 ;
  1922         pntChrgCoordMsgs[numArrivedPntChrgMsg] = msg;
  1923         ++numArrivedPntChrgMsg;
  1925         if ( numArrivedPntChrgMsg < numSources ) 
  1934     for ( 
int k=0; k<3; ++k )
  1935         for ( 
int l=0; l<3; ++l )
  1936             totVirial[k][l] = 0;
  1940     const char *
const *
const elementArray = molPtr->
get_qmElements() ;
  1946     const int *
const *
const qmMMBond = molPtr->
get_qmMMBond() ;
  1956     if ( qmPCFreq > 0 ) {
  1957         DebugM(4,
"Using point charge stride of " << qmPCFreq << 
"\n")
  1962         if (timeStep % qmPCFreq == 0) {
  1963             DebugM(4,
"Loading a new selection of PCs.\n")
  1966             pntChrgMsgVec.clear();
  1967             for (
int pcMsgIt=0; pcMsgIt < numArrivedPntChrgMsg; pcMsgIt++) {
  1969                 for ( 
int i=0; i < pntChrgCoordMsgs[pcMsgIt]->
numAtoms; ++i ) {
  1970                     pntChrgMsgVec.push_back(pntChrgCoordMsgs[pcMsgIt]->coord[i]);
  1976             pcIDListSize = pntChrgMsgVec.size();
  1977             pcIDList = 
new int[pcIDListSize] ;
  1978             for (
size_t i=0; i<pcIDListSize; i++) {
  1979                 pcIDList[i] = pntChrgMsgVec[i].id;
  1984                 force[pntChrgMsgVec[i].id].
homeIndx = pntChrgMsgVec[i].homeIndx;
  1988             DebugM(4,
"Updating position/homeIdex of old PC selection.\n")
  1994             for (
int pcMsgIt=0; pcMsgIt < numArrivedPntChrgMsg; pcMsgIt++) {
  1996                 for ( 
int i=0; i < pntChrgCoordMsgs[pcMsgIt]->
numAtoms; ++i ) {
  1997                     pcDataSort.
load(pntChrgCoordMsgs[pcMsgIt]->coord[i]);
  2002             iout << 
"Loaded new positions in sorted array: " << pcDataSort.
size() << 
"\n" << 
endi;
  2006             for (
size_t i=0; i<pntChrgMsgVec.size(); i++) {
  2008                 auto pntr = pcDataSort.
find(pntChrgMsgVec[i]);
  2010                 pntChrgMsgVec[i].position = pntr->position ;
  2011                 pntChrgMsgVec[i].homeIndx = pntr->homeIndx ;
  2016                 force[pntChrgMsgVec[i].id].
homeIndx = pntChrgMsgVec[i].homeIndx;
  2021         DebugM(4,
"Updating PCs at every step.\n")
  2023         pntChrgMsgVec.clear();
  2024         for (
int pcMsgIt=0; pcMsgIt < numArrivedPntChrgMsg; pcMsgIt++) {
  2026             for ( 
int i=0; i < pntChrgCoordMsgs[pcMsgIt]->
numAtoms; ++i ) {
  2027                 pntChrgMsgVec.push_back(pntChrgCoordMsgs[pcMsgIt]->coord[i]);
  2032         for (
size_t i=0; i<pntChrgMsgVec.size(); i++) {
  2037             if (force[pntChrgMsgVec[i].
id].homeIndx != -1 
  2038                 and force[pntChrgMsgVec[i].
id].homeIndx != pntChrgMsgVec[i].homeIndx
  2040                 iout << 
iERROR << 
"Overloading point charge "   2041                 << pntChrgMsgVec[i].id << 
"; home index: "   2042                 << force[pntChrgMsgVec[i].id].
homeIndx << 
" with " << pntChrgMsgVec[i].homeIndx
  2044                 NAMD_die(
"Error preparing QM simulations.");
  2048             force[pntChrgMsgVec[i].id].
homeIndx = pntChrgMsgVec[i].homeIndx;
  2053     numArrivedPntChrgMsg = 0;
  2055     DebugM(4,
"A total of " << pntChrgMsgVec.size() 
  2056     << 
" point charges arrived." << std::endl);
  2058     DebugM(4,
"Starting QM groups processing.\n");
  2069     std::vector<dummyData> dummyAtoms ;
  2072     thisProxy[0].recvQMResLoop() ;
  2077     for (
int grpIter = 0; grpIter < numQMGrps; grpIter++) {
  2079         grpQMAtmVec.clear();
  2080         grpPntChrgVec.clear();
  2081         grpAppldChrgVec.clear();
  2084         DebugM(4,
"Calculating QM group " << grpIter +1 
  2085         << 
" (ID: " << grpID[grpIter] << 
")." << std::endl);
  2087         DebugM(4,
"Compiling Config Lines into one string for message...\n");
  2091         std::string configLines ;
  2093         for ( ; current; current = current->
next ) {
  2094             std::string confLineStr(current->
data);
  2098                 std::ostringstream itosConv ;
  2099                 itosConv << grpChrg[grpIter] ;
  2100                 confLineStr.append( 
" CHARGE=" );
  2101                 confLineStr.append( itosConv.str() );
  2105             configLines.append(confLineStr);
  2106             configLines.append(
"\n");
  2111         DebugM(4,
"Determining point charges...\n");
  2113         Real qmTotalCharge = 0;
  2115         for (
int qmIt=0; qmIt<numQMAtms; qmIt++){
  2116             if (qmCoord[qmIt].qmGrpID == grpID[grpIter]) {
  2117                 grpQMAtmVec.push_back(qmCoord[qmIt]);
  2118                 qmTotalCharge += qmCoord[qmIt].
charge;
  2121         if ((fabsf(roundf(qmTotalCharge) - qmTotalCharge) <= 0.001f) ) {
  2122             qmTotalCharge = roundf(qmTotalCharge) ;
  2128         Real pcTotalCharge = 0;
  2130         for (
auto pntChrgIt = pntChrgMsgVec.begin(); 
  2131              pntChrgIt != pntChrgMsgVec.end(); pntChrgIt++) {
  2132             if ((*pntChrgIt).qmGrpID == grpID[grpIter] ) {
  2133                 grpPntChrgVec.push_back( (*pntChrgIt) );
  2134                 pcTotalCharge += (*pntChrgIt).charge;
  2137         if ((fabsf(roundf(pcTotalCharge) - pcTotalCharge) <= 0.001f) ) {
  2138             pcTotalCharge = roundf(pcTotalCharge) ;
  2142         if (grpQMAtmVec.size() != qmGrpSize[grpIter]) {
  2143             iout << 
iERROR << 
"The number of QM atoms received for group " << grpID[grpIter]
  2144             << 
" does not match the expected: " << grpQMAtmVec.size()
  2145             << 
" vs " << qmGrpSize[grpIter] << 
"\n" << 
endi ;
  2147             NAMD_die(
"Error processing QM group.");
  2151         DebugM(1,
"Found " << grpPntChrgVec.size() << 
" point charges for QM group "   2152         << grpIter << 
" (ID: " << grpID[grpIter] << 
"; Num QM atoms: "   2153         << grpQMAtmVec.size() <<  
"; Num QM-MM bonds: "   2154         << grpNumBonds[grpIter] << 
")" << std::endl);
  2156         DebugM(1,
"Total QM charge: " << qmTotalCharge 
  2157         << 
"; Total point-charge charge: " << pcTotalCharge << std::endl);
  2161         if ( qmLSSFreq > 0 && ((timeStep + 1) % qmLSSFreq == 0 )) {
  2162             lssUpdate(grpIter, grpQMAtmVec, grpPntChrgVec);
  2169             procBonds(grpNumBonds[grpIter], qmGrpBonds[grpIter], 
  2170                      qmMMBondedIndx[grpIter], 
  2171                      chargeTarget, numTargs, 
  2172                      grpPntChrgVec, grpAppldChrgVec) ;
  2175             grpAppldChrgVec = grpPntChrgVec;
  2180         std::vector< std::pair<int,int> > qmPCLocalIndxPairs ;
  2184         for (
int dummyIt = 0; dummyIt < grpNumBonds[grpIter]; dummyIt++) {
  2186             int qmMMBondIndx = qmGrpBonds[grpIter][dummyIt] ;
  2188             BigReal bondVal = dummyBondVal[qmMMBondIndx] ;
  2190             int mmAtmIndx = qmMMBond[qmMMBondIndx][0] ;
  2191             int qmAtmIndx = qmMMBond[qmMMBondIndx][1] ;
  2197             bool missingQM = 
true, missingMM = 
true;
  2200             for (qmIt=0; qmIt<grpQMAtmVec.size(); qmIt++){
  2201                 if (grpQMAtmVec[qmIt].
id == qmAtmIndx) {
  2202                     qmPos = grpQMAtmVec[qmIt].position;
  2214             for (pcIt=0; pcIt < grpPntChrgVec.size(); pcIt++) {
  2215                 if (grpPntChrgVec[pcIt].
id == mmAtmIndx) {
  2216                     mmPos = grpPntChrgVec[pcIt].position ;
  2226             qmPCLocalIndxPairs.push_back(std::pair<int,int>(qmIt, pcIt) );
  2231             if ( missingMM or missingQM ) {
  2235                     iout << 
iERROR << 
"The MM atom " << mmAtmIndx
  2236                     << 
" is bound to a QM atom, but it was not selected as a poitn charge."  2237                     << 
" Check your cutoff radius!\n" << 
endi ;
  2239                     NAMD_die(
"Error in QM-MM bond processing.");
  2242                     iout << 
iERROR << 
"The QM atom " << qmAtmIndx
  2243                     << 
" is bound to an MM atom, but it was not sent to rank zero for processing."  2244                     << 
" Check your configuration!\n" << 
endi ;
  2246                     NAMD_die(
"Error in QM-MM bond processing.");
  2251             Vector bondVec = mmPos - qmPos ;
  2259                 bondVec = bondVec.
unit() ;
  2260                 bondVec *= bondVal ;
  2267                 bondVec *= bondVal ;
  2270             Position dummyPos = qmPos + bondVec;
  2272             DebugM(1,
"Creating dummy atom " << dummyPos << 
" ; QM ind: "   2273             << qmIt << 
" ; PC ind: " << pcIt << std::endl);
  2275             dummyAtoms.push_back(
dummyData(dummyPos, qmIt, qmMMBondIndx)) ;
  2279         DebugM(3, 
"Creating data for " << grpQMAtmVec.size() << 
" QM atoms "   2280         << dummyAtoms.size() << 
" dummy atoms " << grpPntChrgVec.size()
  2281         << 
" real point charges and " << grpAppldChrgVec.size() - grpPntChrgVec.size()
  2282         << 
" virtual point charges\n") ;
  2284         int dataSize = grpQMAtmVec.size() + dummyAtoms.size() + grpAppldChrgVec.size();
  2289         msg->
charge = grpChrg[grpIter];
  2292         msg->
numAllAtoms = grpQMAtmVec.size() + dummyAtoms.size();
  2320         for (
int i=0; i<grpQMAtmVec.size(); i++) {
  2321             dataP->
position = grpQMAtmVec[i].position ;
  2322             dataP->
charge = grpQMAtmVec[i].charge ;
  2323             dataP->
id = grpQMAtmVec[i].id ;
  2326             strncpy(dataP->
element,elementArray[grpQMAtmVec[i].id],3);
  2330         for (
int i=0; i<dummyAtoms.size(); i++) {
  2331             dataP->
position = dummyAtoms[i].pos ;
  2336             strncpy(dataP->
element,dummyElmArray[dummyAtoms[i].bondIndx],3);
  2340         for (
int i=0; i<grpAppldChrgVec.size(); i++) {
  2341             dataP->
position = grpAppldChrgVec[i].position ;
  2342             dataP->
charge = grpAppldChrgVec[i].charge ;
  2344             dataP->
id = grpAppldChrgVec[i].id ;
  2346             dataP->
dist = grpAppldChrgVec[i].dist ;
  2350             if (i < grpPntChrgVec.size()) {
  2351                 if (grpAppldChrgVec[i].qmGrpID == -1) {
  2354                 else if (grpAppldChrgVec[i].qmGrpID == -2) {
  2377         for( 
auto vecPtr  = qmPCLocalIndxPairs.begin(); 
  2378                   vecPtr != qmPCLocalIndxPairs.end(); 
  2381             int qmLocInd = (*vecPtr).first;
  2382             int pcLocInd = (*vecPtr).second;
  2392             calcCSMD(grpIter, msg->
numQMAtoms, qmP, cSMDForces) ;
  2394         int targetPE = qmPEs[peIter] ;
  2396         DebugM(4,
"Sending QM group " << grpIter << 
" (ID " << grpID[grpIter] 
  2397         << 
") to PE " << targetPE << std::endl);
  2403                 QMProxy[targetPE].calcORCA(msg) ;
  2407                 QMProxy[targetPE].calcMOPAC(msg) ;
  2411                 QMProxy[targetPE].calcUSR(msg) ;
  2417         if (peIter == qmPEs.size())
  2447     for ( 
int k=0; k<3; ++k )
  2448         for ( 
int l=0; l<3; ++l )
  2449             totVirial[k][l] += resMsg->
virial[k][l];
  2452     Real qmTotalCharge = 0;
  2456         force[ fres[i].id ].
force += fres[i].force;
  2459         if (fres[i].replace == 1) {
  2460             force[ fres[i].id ].
charge =  fres[i].charge;
  2461             qmTotalCharge += fres[i].charge;
  2465     if ((fabsf(roundf(qmTotalCharge) - qmTotalCharge) <= 0.001f) ) {
  2466         qmTotalCharge = roundf(qmTotalCharge) ;
  2471         for ( 
int i=0; i < cSMDindxLen[resMsg->
grpIndx]; i++ ) {
  2472             int cSMDit = cSMDindex[resMsg->
grpIndx][i];
  2473             force[ cSMDpairs[cSMDit][0] ].
force += cSMDForces[cSMDit];
  2477     DebugM(4,
"QM total charge received is " << qmTotalCharge << std::endl);
  2479     DebugM(4,
"Current accumulated energy is " << totalEnergy << std::endl);
  2491          timeStep % simParams->
qmOutFreq == 0 ) {
  2493         iout << 
iINFO << 
"Writing QM charge output at step "   2494         << timeStep <<  
"\n" << 
endi;
  2496         Real *x = outputData, 
  2500         for (
int qmIt=0; qmIt<numQMAtms; qmIt++){
  2501             x[qmIt] = qmCoord[qmIt].
id;
  2502             y[qmIt] = force[qmCoord[qmIt].
id].
charge ;
  2514         iout << 
iINFO << 
"Writing QM position output at step "   2515         << timeStep <<  
"\n" << 
endi;
  2519         for(
int i=0; i<numQMAtms;i++) {
  2524         Real *x = outputData, 
  2528         for (
int qmIt=0; qmIt<numQMAtms; qmIt++){
  2529             x[qmIt] = qmCoord[idIndx[qmIt].indx].
position.
x;
  2530             y[qmIt] = qmCoord[idIndx[qmIt].indx].
position.
y;
  2531             z[qmIt] = qmCoord[idIndx[qmIt].indx].
position.
z;
  2538     DebugM(4,
"Distributing QM forces for all ranks.\n");
  2539     for ( 
int j=0; j < numSources; ++j ) {
  2541         std::set<int> auxset0;
  2542         DebugM(1,
"Sending forces and charges to source " << j << std::endl);
  2548         int sourceNode = -1;
  2550         if (pntChrgCoordMsgs == NULL) {
  2552             qmmsg = qmCoordMsgs[j];
  2560             pcmsg = pntChrgCoordMsgs[j];
  2561             pntChrgCoordMsgs[j] = 0;
  2568             for (
int aux=0; aux<numSources; aux++) {
  2570                 if (qmCoordMsgs[aux] == 0)
  2573                 qmmsg = qmCoordMsgs[aux];
  2576                     qmCoordMsgs[aux] = 0;
  2581             DebugM(1,
"Building force mesage for rank "   2589             for ( 
int i=0; i < qmmsg->
numAtoms; ++i ) {
  2590                 auxset0.insert(qmmsg->
coord[i].
id);
  2592             for ( 
int i=0; i < pcmsg->
numAtoms; ++i ) {
  2593                 auxset0.insert(pcmsg->
coord[i].
id);
  2595             totForces = auxset0.size(); 
  2603         DebugM(1,
"Loading QM forces.\n");
  2608         for ( 
int i=0; i < qmmsg->
numAtoms; ++i ) {
  2611             auxset0.insert(qmmsg->
coord[i].
id); 
  2616         if (pntChrgCoordMsgs != NULL) {
  2617             DebugM(1,
"Loading PntChrg forces.\n");
  2619             for ( 
int i=0; i < pcmsg->
numAtoms; ++i ) {
  2621                 if (auxset0.find(pcmsg->
coord[i].
id) == auxset0.end()) {
  2624                     auxset0.insert(pcmsg->
coord[i].
id);
  2631         DebugM(1,
"A total of " << forceIter << 
" forces were loaded." << std::endl);
  2633         for ( 
int i=0; i < subsArray.
size(); ++i ) {
  2634             fmsg->
lssDat[i] = subsArray[i];
  2638         if (subsArray.
size() > 0)
  2639             DebugM(3,
"A total of " << subsArray.
size() << 
" LSS data structures were loaded." << std::endl);
  2643             fmsg->
energy = totalEnergy;
  2644             for ( 
int k=0; k<3; ++k )
  2645                 for ( 
int l=0; l<3; ++l )
  2646                     fmsg->
virial[k][l] = totVirial[k][l];
  2649             for ( 
int k=0; k<3; ++k )
  2650                 for ( 
int l=0; l<3; ++l )
  2654         DebugM(4,
"Sending forces...\n");
  2656         QMProxy[sourceNode].recvForce(fmsg);
  2660     DebugM(4,
"All forces sent from node zero.\n");
  2678     bool callReplaceForces = 
false;
  2686     int totalNumbAtoms = 0;
  2687     for (ap = ap.
begin(); ap != ap.
end(); ap++) {
  2688         totalNumbAtoms += (*ap).p->getNumAtoms();
  2698         delete [] oldForces;
  2699     oldForces = 
new ExtForce[totalNumbAtoms] ;
  2701     for (
int i=0; i < totalNumbAtoms; ++i) {
  2705     DebugM(1,
"Force array has been created and zeroed in rank "   2706     << CkMyPe() << std::endl);
  2709     << CkMyPe() << std::endl);
  2713     for (
int i=0; i < fmsg->
numForces; ++i, ++results_ptr) {
  2720         if (results_ptr->
replace == 1)
  2721             callReplaceForces = 
true;
  2725         if (qmAtomGroup[results_ptr->
id] > 0 && (fmsg->
PMEOn || (numQMGrps > 1) ) ) {
  2728             for (
int qmIter=0; qmIter<numQMAtms; qmIter++) {
  2730                 if (qmAtmIndx[qmIter] == results_ptr->
id) {
  2731                     qmAtmChrg[qmIter] = results_ptr->
charge;
  2741     DebugM(1,
"Placing forces on force boxes in rank "   2742     << CkMyPe() << std::endl);
  2745     int homeIndxIter = 0;
  2746     for (ap = ap.
begin(); ap != ap.
end(); ap++) {
  2747         Results *r = (*ap).forceBox->open();
  2749         const CompAtomExt *xExt = (*ap).p->getCompAtomExtInfo();
  2750         int localNumAtoms = (*ap).p->getNumAtoms();
  2752         for(
int i=0; i<localNumAtoms; ++i) {
  2754             f[i] += oldForces[homeIndxIter].
force;
  2759         if ( callReplaceForces )
  2760             (*ap).p->replaceForces(oldForces);
  2762         (*ap).forceBox->close(&r);
  2766     DebugM(1,
"Forces placed on force boxes in rank "   2767     << CkMyPe() << std::endl);
  2771         DebugM(1,
"PME ON! Accessing PMEmgr in rank " << CkMyPe() << std::endl);
  2774             CkpvAccess(BOCclass_group).computePmeMgr) ;
  2776         DebugM(4, 
"Initiating ComputePme::doQMWork on rank " << CkMyPe() << 
" over "   2777             << 
getComputes(mgrP).size() << 
" pmeComputes." << std::endl) ;
  2785     DebugM(1,
"Submitting reduction in rank " << CkMyPe() << std::endl);
  2788     reduction->
item(REDUCTION_VIRIAL_NORMAL_XX) += fmsg->
virial[0][0];
  2789     reduction->
item(REDUCTION_VIRIAL_NORMAL_XY) += fmsg->
virial[0][1];
  2790     reduction->
item(REDUCTION_VIRIAL_NORMAL_XZ) += fmsg->
virial[0][2];
  2791     reduction->
item(REDUCTION_VIRIAL_NORMAL_YX) += fmsg->
virial[1][0];
  2792     reduction->
item(REDUCTION_VIRIAL_NORMAL_YY) += fmsg->
virial[1][1];
  2793     reduction->
item(REDUCTION_VIRIAL_NORMAL_YZ) += fmsg->
virial[1][2];
  2794     reduction->
item(REDUCTION_VIRIAL_NORMAL_ZX) += fmsg->
virial[2][0];
  2795     reduction->
item(REDUCTION_VIRIAL_NORMAL_ZY) += fmsg->
virial[2][1];
  2796     reduction->
item(REDUCTION_VIRIAL_NORMAL_ZZ) += fmsg->
virial[2][2];
  2805     FILE *inputFile,*outputFile,*chrgFile;
  2808     const size_t lineLen = 256;
  2809     char *line = 
new char[lineLen];
  2811     std::string qmCommand, inputFileName, outputFileName, pntChrgFileName;
  2818     DebugM(4,
"Running MOPAC on PE " << CkMyPe() << std::endl);
  2833         pntChrgSwitching(msg, pcPpme) ;
  2842     std::string baseDir(msg->
baseDir);
  2843     std::ostringstream itosConv ;
  2844     if ( CmiNumPartitions() > 1 ) {
  2845         baseDir.append(
"/") ;
  2846         itosConv << CmiMyPartition() ;
  2847         baseDir += itosConv.str() ;
  2851         if (stat(msg->
baseDir, &info) != 0 ) {
  2852             CkPrintf( 
"Node %d cannot access directory %s\n",
  2853                       CkMyPe(), baseDir.c_str() );
  2854             NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  2856         else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  2857             DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  2858             retVal = mkdir(baseDir.c_str(), S_IRWXU);
  2862     baseDir.append(
"/") ;
  2864     baseDir += itosConv.str() ;
  2866     if (stat(msg->
baseDir, &info) != 0 ) {
  2867         CkPrintf( 
"Node %d cannot access directory %s\n",
  2868                   CkMyPe(), baseDir.c_str() );
  2869         NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  2871     else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  2872         DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  2873         retVal = mkdir(baseDir.c_str(), S_IRWXU);
  2877     Write_PDB(std::string(baseDir)+
"/input.pdb", msg ) ;
  2880     inputFileName.clear();
  2881     inputFileName.append(baseDir.c_str()) ;
  2882     inputFileName.append(
"/qmmm_") ;
  2883     inputFileName += itosConv.str() ;
  2884     inputFileName.append(
".input") ;
  2887     inputFile = fopen(inputFileName.c_str(),
"w");
  2888     if ( ! inputFile ) {
  2889         iout << 
iERROR << 
"Could not open input file for writing: "   2890         << inputFileName << 
"\n" << 
endi ;
  2891         NAMD_err(
"Error writing QM input file.");
  2896     qmCommand.append(
"cd ");
  2897     qmCommand.append(baseDir);
  2898     qmCommand.append(
" ; ");
  2900     qmCommand.append(
" ") ;
  2901     qmCommand.append(inputFileName) ;
  2902     qmCommand.append(
" > /dev/null 2>&1") ;
  2906     outputFileName = inputFileName ;
  2907     outputFileName.append(
".aux") ;
  2911         pntChrgFileName.clear();
  2912         pntChrgFileName.append(baseDir.c_str()) ;
  2913         pntChrgFileName.append(
"/mol.in") ;
  2915         chrgFile = fopen(pntChrgFileName.c_str(),
"w");
  2917             iout << 
iERROR << 
"Could not open charge file for writing: "   2918             << pntChrgFileName << 
"\n" << 
endi ;
  2919             NAMD_err(
"Error writing point charge file.");
  2922         iret = fprintf(chrgFile,
"\n%d %d\n", 
  2924         if ( iret < 0 ) { 
NAMD_err(
"Error writing point charge file."); }
  2929     std::string confLineStr;
  2930     while (std::getline(ss, confLineStr) ) {
  2931         confLineStr.append(
"\n");
  2932         iret = fprintf(inputFile,confLineStr.c_str());
  2933         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  2937     iret = fprintf(inputFile,
"\n");
  2938     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  2942     << 
" point charges in file " << pntChrgFileName.c_str() << 
"\n");
  2946     for (
size_t i=0; i<msg->
numAllAtoms; ++i, ++atmP ) {
  2952         iret = fprintf(inputFile,
"%s %f 1 %f 1 %f 1\n",
  2954         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  2969                 double charge = pcP->
charge;
  2975                 BigReal rij = sqrt((x-xMM)*(x-xMM) +
  2984             phi = phi*constants ;
  2986             iret = fprintf(chrgFile,
"%s %f %f %f %f\n",
  2988             if ( iret < 0 ) { 
NAMD_err(
"Error writing point charge file."); }
  2992     DebugM(4,
"Closing input and charge file\n");
  3001         std::string prepProc(msg->
prepProc) ;
  3002         prepProc.append(
" ") ;
  3003         prepProc.append(inputFileName) ;
  3004         iret = system(prepProc.c_str());
  3005         if ( iret == -1 ) { 
NAMD_err(
"Error running preparation command for QM calculation."); }
  3006         if ( iret ) { 
NAMD_die(
"Error running preparation command for QM calculation."); }
  3010     DebugM(4,
"Running command ->" << qmCommand.c_str() << 
"<-" << std::endl);
  3011     iret = system(qmCommand.c_str());
  3013     if ( iret == -1 ) { 
NAMD_err(
"Error running command for QM forces calculation."); }
  3014     if ( iret ) { 
NAMD_die(
"Error running command for QM forces calculation."); }
  3018         std::string secProc(msg->
secProc) ;
  3019         secProc.append(
" ") ;
  3020         secProc.append(inputFileName) ;
  3024         secProc.append(
" ") ;
  3025         secProc += itosConv.str() ;
  3027         iret = system(secProc.c_str());
  3028         if ( iret == -1 ) { 
NAMD_err(
"Error running second command for QM calculation."); }
  3029         if ( iret ) { 
NAMD_die(
"Error running second command for QM calculation."); }
  3041     DebugM(4,
"Reading QM data from file " << outputFileName.c_str() << std::endl);
  3042     outputFile = fopen(outputFileName.c_str(),
"r");
  3043     if ( ! outputFile ) {
  3058     for ( 
int k=0; k<3; ++k )
  3059         for ( 
int l=0; l<3; ++l )
  3060             resMsg->
virial[k][l] = 0;
  3066         resForce[i].force = 0;
  3067         resForce[i].charge = 0 ;
  3068         if (i < msg->numQMAtoms) {
  3071             resForce[i].replace = 1 ;
  3072             resForce[i].id = atmP->
id;
  3078             resForce[i].replace = 0 ;
  3079             resForce[i].
id = pcP->
id;
  3091     size_t atmIndx = 0, gradCount = 0;
  3092     Bool gradFields = 
false, chargeFields = 
false;
  3093     Bool chargesRead = 
false, gradsRead = 
false;
  3094     while ( fgets(line, lineLen, outputFile) != NULL){
  3104         if ( strstr(line,
"HEAT_OF_FORMATION") != NULL ) {
  3106             char strEnergy[14], *endPtr ;
  3109             strncpy(strEnergy, line + 28, 13) ;
  3110             strEnergy[13] = 
'\0';
  3114             resMsg->
energyOrig = strtod(strEnergy, &endPtr);
  3115             if ( *endPtr == 
'D' ) {
  3117                 resMsg->
energyOrig = strtod(strEnergy, &endPtr);
  3130         if ( strstr(line,
"ATOM_CHARGES") != NULL ) {
  3132             chargeFields = 
true;
  3138                 chargeFields = 
false;
  3142                 chargeFields = 
true;
  3150         if ( strstr(line,
"GRADIENTS") != NULL ) {
  3155                 NAMD_die(
"Error reading QM forces file. Wrong number of atom charges");
  3161             chargeFields = false ;
  3169         if ( strstr(line,
"OVERLAP_MATRIX") != NULL ) {
  3174                 NAMD_die(
"Error reading QM forces file. Wrong number of gradients");
  3187             while ((strIndx < (strlen(line)-9)) && (strlen(line)-1 >=9 ) ) {
  3189                 strncpy(result, line+strIndx,9) ;
  3192                 Real localCharge = atof(result);
  3195                 if (atmIndx < msg->numQMAtoms ) {
  3196                     atmP[atmIndx].
charge = localCharge;
  3197                     resForce[atmIndx].charge = localCharge;
  3203                     atmIndx < msg->numAllAtoms ) {
  3206                     atmP[atmIndx].
charge = localCharge;
  3210                     resForce[qmInd].charge += localCharge;
  3219                     chargeFields = 
false;
  3231                 int numfirstline = sscanf(line,
"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
  3232                                           &buf[0],&buf[1],&buf[2],&buf[3],&buf[4],&buf[5],
  3233                                           &buf[6],&buf[7],&buf[8],&buf[9]);
  3234                 gradLength = strlen(line)/numfirstline;
  3236             while ((strIndx < (strlen(line)-gradLength)) && (strlen(line)-1 >= gradLength ) ) {
  3238                 strncpy(result, line+strIndx,gradLength) ;
  3239                 result[gradLength] = 
'\0';
  3241                 gradient[gradCount] = atof(result);
  3242                 if (gradCount == 2) {
  3244                     if (atmIndx < msg->numQMAtoms ) {
  3246                         resForce[atmIndx].force.x = -1*gradient[0];
  3247                         resForce[atmIndx].force.y = -1*gradient[1];
  3248                         resForce[atmIndx].force.z = -1*gradient[2];
  3257                     atmIndx < msg->numAllAtoms ) {
  3266                         Real linkDist = 
Vector(atmP[atmIndx].position - 
  3267                                         atmP[qmInd].position).
length() ;
  3269                         Force mmForce(0), qmForce(0), 
  3270                             linkForce(gradient[0], gradient[1], gradient[2]);
  3273                         Vector base = (linkDist/(mmqmDist*mmqmDist*mmqmDist))*dir;
  3275                         Vector xuv(1,0,0), yuv(0,1,0), zuv(0,0,1);
  3280                         qmForce += (linkForce*((1 - linkDist/mmqmDist)*xuv + 
  3281                                     (xDelta)*base) )*xuv;
  3283                         qmForce += (linkForce*((1 - linkDist/mmqmDist)*yuv + 
  3284                                     (yDelta)*base) )*yuv;
  3286                         qmForce += (linkForce*((1 - linkDist/mmqmDist)*zuv + 
  3287                                     (zDelta)*base) )*zuv;
  3290                         mmForce += (linkForce*((linkDist/mmqmDist)*xuv -
  3291                                     (xDelta)*base) )*xuv;
  3293                         mmForce += (linkForce*((linkDist/mmqmDist)*yuv -
  3294                                     (yDelta)*base) )*yuv;
  3296                         mmForce += (linkForce*((linkDist/mmqmDist)*zuv -
  3297                                     (zDelta)*base) )*zuv;
  3299                         resForce[qmInd].force += qmForce;
  3300                         resForce[msg->
numQMAtoms + mmInd].force += mmForce;
  3309                 strIndx += gradLength;
  3336         for (; atmIndx < msg->
numQMAtoms; atmIndx++) {
  3339             for (
int qmIter=0; qmIter<globalNumQMAtoms; qmIter++) {
  3341                 if (qmAtmIndx[qmIter] == atmP[atmIndx].
id) {
  3343                     atmP[atmIndx].
charge = qmAtmChrg[qmIter];
  3344                     resForce[atmIndx].charge = qmAtmChrg[qmIter];
  3352         for (
size_t j=msg->
numQMAtoms; j<msg->numAllAtoms; ++j ) {
  3362     if (! (chargesRead && gradsRead) ) {
  3363         NAMD_die(
"Error reading QM forces file. Not all data could be read!");
  3384     std::vector<Force> qmElecForce ;
  3386         qmElecForce.push_back( 
Force(0) );
  3398         Force totalForce(0);
  3408             BigReal force = pntCharge*qmCharge*constants ;
  3419             totalForce += force*rVec.
unit();
  3422             qmElecForce[j] += -1*force*rVec.
unit();
  3428             if (qmAtomGroup[pcP[i].
id] == 0) {
  3431                 resForce[pcIndx].force += totalForce;
  3445             Force mm1Force = (1-Cq)*totalForce ;
  3446             Force mm2Force = Cq*totalForce ;
  3448             resForce[msg->
numQMAtoms + mm1Indx].force += mm1Force;
  3449             resForce[msg->
numQMAtoms + mm2Indx].force += mm2Force;
  3458         if (j < msg->numQMAtoms ) {
  3459             resForce[j].force += qmElecForce[j];
  3474                             atmP[qmInd].position).
length() ;
  3476             Force linkForce = qmElecForce[j];
  3478             Vector base = (linkDist/(mmqmDist*mmqmDist*mmqmDist))*dir;
  3480             Vector xuv(1,0,0), yuv(0,1,0), zuv(0,0,1);
  3485             Force qmForce = (linkForce*((1 - linkDist/mmqmDist)*xuv + 
  3486                         (xDelta)*base) )*xuv;
  3488             qmForce += (linkForce*((1 - linkDist/mmqmDist)*yuv + 
  3489                         (yDelta)*base) )*yuv;
  3491             qmForce += (linkForce*((1 - linkDist/mmqmDist)*zuv + 
  3492                         (zDelta)*base) )*zuv;
  3495             Force mmForce = (linkForce*((linkDist/mmqmDist)*xuv -
  3496                         (xDelta)*base) )*xuv;
  3498             mmForce += (linkForce*((linkDist/mmqmDist)*yuv -
  3499                         (yDelta)*base) )*yuv;
  3501             mmForce += (linkForce*((linkDist/mmqmDist)*zuv -
  3502                         (zDelta)*base) )*zuv;
  3504             resForce[qmInd].force += qmForce;
  3505             resForce[msg->
numQMAtoms + mmInd].force += mmForce;
  3513         DebugM(1,
"Correcting forces and energy for PME.\n");
  3516         BigReal TwoBySqrtPi = 1.12837916709551;
  3517         pi_ewaldcof = TwoBySqrtPi * ewaldcof;
  3524             const BigReal kq_i = p_i_charge * constants;
  3526             for (
size_t j=i+1; j < msg->
numQMAtoms; j++) {
  3537                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  3540                 BigReal recip_energy = (1-tmp_b)/r;
  3543                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  3546                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  3548                 Force fixForce = -1*kq_i*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  3559                 resForce[i].force -= fixForce ;
  3560                 resForce[j].force -= -1*fixForce ;
  3577             const BigReal kq_i = p_i_charge * constants;
  3592                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  3595                 BigReal recip_energy = (1-tmp_b)/r;
  3598                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  3601                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  3603                 fixForce += -1*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  3614             resForce[pcIndx].force -= kq_i*fixForce ;
  3624         for ( 
int k=0; k<3; ++k )
  3625             for ( 
int l=0; l<3; ++l )
  3626                 resMsg->
virial[k][l] = -1*resForce[i].force[k]*atmP[i].
position[l];
  3633         for ( 
int k=0; k<3; ++k )
  3634             for ( 
int l=0; l<3; ++l )
  3635                 resMsg->
virial[k][l] = -1*resForce[pcIndx].force[k]*pcP[i].
position[l];
  3641     QMProxy[0].recvQMRes(resMsg);
  3653     FILE *inputFile,*outputFile,*chrgFile;
  3656     const size_t lineLen = 256;
  3657     char *line = 
new char[lineLen];
  3659     std::string qmCommand, inputFileName, outputFileName, pntChrgFileName, pcGradFilename;
  3660     std::string tmpRedirectFileName, pcGradFileName;
  3667     DebugM(4,
"Running ORCA on PE " << CkMyPe() << std::endl);
  3681         pntChrgSwitching(msg, pcPpme) ;
  3690     std::string baseDir(msg->
baseDir);
  3691     std::ostringstream itosConv ;
  3692     if ( CmiNumPartitions() > 1 ) {
  3693         baseDir.append(
"/") ;
  3694         itosConv << CmiMyPartition() ;
  3695         baseDir += itosConv.str() ;
  3699         if (stat(msg->
baseDir, &info) != 0 ) {
  3700             CkPrintf( 
"Node %d cannot access directory %s\n",
  3701                       CkMyPe(), baseDir.c_str() );
  3702             NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  3704         else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  3705             DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  3706             retVal = mkdir(baseDir.c_str(), S_IRWXU);
  3710     baseDir.append(
"/") ;
  3712     baseDir += itosConv.str() ;
  3714     if (stat(msg->
baseDir, &info) != 0 ) {
  3715         CkPrintf( 
"Node %d cannot access directory %s\n",
  3716                   CkMyPe(), baseDir.c_str() );
  3717         NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  3719     else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  3720         DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  3721         int retVal = mkdir(baseDir.c_str(), S_IRWXU);
  3725     Write_PDB(std::string(baseDir)+
"/input.pdb", msg ) ;
  3728     inputFileName.clear();
  3729     inputFileName.append(baseDir.c_str()) ;
  3730     inputFileName.append(
"/qmmm_") ;
  3731     inputFileName += itosConv.str() ;
  3732     inputFileName.append(
".input") ;
  3735     inputFile = fopen(inputFileName.c_str(),
"w");
  3736     if ( ! inputFile ) {
  3737         iout << 
iERROR << 
"Could not open input file for writing: "   3738         << inputFileName << 
"\n" << 
endi ;
  3739         NAMD_err(
"Error writing QM input file.");
  3744     qmCommand.append(
"cd ");
  3745     qmCommand.append(baseDir);
  3746     qmCommand.append(
" ; ");
  3748     qmCommand.append(
" ") ;
  3749     qmCommand.append(inputFileName) ;
  3753     tmpRedirectFileName = inputFileName ;
  3754     tmpRedirectFileName.append(
".TmpOut") ;
  3756     qmCommand.append(
" > ") ;
  3757     qmCommand.append(tmpRedirectFileName) ;
  3761     outputFileName = inputFileName ;
  3762     outputFileName.append(
".engrad") ;
  3766     pcGradFilename = inputFileName ;
  3767     pcGradFilename.append(
".pcgrad") ;
  3771         pntChrgFileName = inputFileName ;
  3772         pntChrgFileName.append(
".pntchrg") ;
  3774         pcGradFileName = inputFileName;
  3775         pcGradFileName.append(
".pcgrad");
  3777         chrgFile = fopen(pntChrgFileName.c_str(),
"w");
  3779             iout << 
iERROR << 
"Could not open charge file for writing: "   3780             << pntChrgFileName << 
"\n" << 
endi ;
  3781             NAMD_err(
"Error writing point charge file.");
  3784         int numPntChrgs = 0;
  3790         iret = fprintf(chrgFile,
"%d\n", numPntChrgs);
  3791         if ( iret < 0 ) { 
NAMD_err(
"Error writing point charge file."); }
  3796     std::string confLineStr;
  3797     while (std::getline(ss, confLineStr) ) {
  3798         confLineStr.append(
"\n");
  3799         iret = fprintf(inputFile,confLineStr.c_str());
  3800         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3804         iret = fprintf(inputFile,
"%%pointcharges \"%s\"\n", pntChrgFileName.c_str());
  3805         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3808     iret = fprintf(inputFile,
"\n\n%%coords\n  CTyp xyz\n");
  3809     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3811     iret = fprintf(inputFile,
"  Charge %f\n",msg->
charge);
  3812     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3814     iret = fprintf(inputFile,
"  Mult %f\n",msg->
multiplicity);
  3815     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3817     iret = fprintf(inputFile,
"  Units Angs\n  coords\n\n");
  3818     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3822     " point charges in file " << pntChrgFileName.c_str() << 
"\n");
  3826     for (
size_t i=0; i<msg->
numAllAtoms; ++i, ++atmP ) {
  3829         double y = atmP->position.y;
  3830         double z = atmP->position.z;
  3832         iret = fprintf(inputFile,
"  %s %f %f %f\n",
  3833                        atmP->element,x,y,z);
  3834         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3838     iret = fprintf(inputFile,
"  end\nend\n");
  3839     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  3849             double charge = pcP->
charge;
  3855             iret = fprintf(chrgFile,
"%f %f %f %f\n",
  3857             if ( iret < 0 ) { 
NAMD_err(
"Error writing point charge file."); }
  3863     DebugM(4,
"Closing input and charge file\n");
  3868         std::string prepProc(msg->
prepProc) ;
  3869         prepProc.append(
" ") ;
  3870         prepProc.append(inputFileName) ;
  3871         iret = system(prepProc.c_str());
  3872         if ( iret == -1 ) { 
NAMD_err(
"Error running preparation command for QM calculation."); }
  3873         if ( iret ) { 
NAMD_die(
"Error running preparation command for QM calculation."); }
  3877     DebugM(4,
"Running command ->" << qmCommand.c_str() << 
"<-" << std::endl);
  3878     iret = system(qmCommand.c_str());
  3880     if ( iret == -1 ) { 
NAMD_err(
"Error running command for QM forces calculation."); }
  3881     if ( iret ) { 
NAMD_die(
"Error running command for QM forces calculation."); }
  3885         std::string secProc(msg->
secProc) ;
  3886         secProc.append(
" ") ;
  3887         secProc.append(inputFileName) ;
  3891         secProc.append(
" ") ;
  3892         secProc += itosConv.str() ;
  3894         iret = system(secProc.c_str());
  3895         if ( iret == -1 ) { 
NAMD_err(
"Error running second command for QM calculation."); }
  3896         if ( iret ) { 
NAMD_die(
"Error running second command for QM calculation."); }
  3908     DebugM(4,
"Reading QM data from file " << outputFileName.c_str() << std::endl);
  3909     outputFile = fopen(outputFileName.c_str(),
"r");
  3910     if ( ! outputFile ) {
  3925     for ( 
int k=0; k<3; ++k )
  3926         for ( 
int l=0; l<3; ++l )
  3927             resMsg->
virial[k][l] = 0;
  3933         resForce[i].force = 0;
  3934         resForce[i].charge = 0 ;
  3935         if (i < msg->numQMAtoms) {
  3938             resForce[i].replace = 1 ;
  3939             resForce[i].id = atmP->id;
  3945             resForce[i].replace = 0 ;
  3946             resForce[i].id = pcP->
id;
  3955     size_t atmIndx = 0, gradCount = 0;
  3956     int numAtomsInFile = 0;
  3962     for (
int i = 0; i < 3; i++) {
  3963         fgets(line, lineLen, outputFile); 
  3966     iret = fscanf(outputFile,
"%d\n", &numAtomsInFile);
  3968         NAMD_die(
"Error reading QM forces file.");
  3973         NAMD_die(
"Error reading QM forces file. Number of atoms in QM output\  3974         does not match the expected.");
  3979     for (
int i = 0; i < 3; i++) {
  3980         fgets(line, lineLen, outputFile); 
  3983     iret = fscanf(outputFile,
"%lf\n", &resMsg->
energyOrig);
  3985         NAMD_die(
"Error reading QM forces file.");
  3997     for (
int i = 0; i < 3; i++) {
  3998         fgets(line, lineLen, outputFile) ;
  4009         iret = fscanf(outputFile,
"%lf\n", &gradient[gradCount]);
  4010         if ( iret != 1 ) { 
NAMD_die(
"Error reading QM forces file."); }
  4012         if (gradCount == 2){
  4017             if (atmIndx < msg->numQMAtoms ) {
  4018                 resForce[atmIndx].force.x = -1*gradient[0]*1185.82151;
  4019                 resForce[atmIndx].force.y = -1*gradient[1]*1185.82151;
  4020                 resForce[atmIndx].force.z = -1*gradient[2]*1185.82151;
  4029             atmIndx < msg->numAllAtoms ) {
  4032                 int qmInd = atmP[atmIndx].bountToIndx ;
  4033                 int mmInd = atmP[qmInd].bountToIndx ;
  4038                 Real linkDist = 
Vector(atmP[atmIndx].position - atmP[qmInd].position).
length() ;
  4040                 Force mmForce(0), qmForce(0), linkForce(gradient[0], gradient[1], gradient[2]);
  4041                 linkForce *= -1*1185.82151;
  4043                 Vector base = (linkDist/(mmqmDist*mmqmDist*mmqmDist))*dir;
  4045                 Vector xuv(1,0,0), yuv(0,1,0), zuv(0,0,1);
  4046                 Real xDelta = pcP[mmInd].
position.
x - atmP[qmInd].position.x;
  4047                 Real yDelta = pcP[mmInd].
position.
y - atmP[qmInd].position.y;
  4048                 Real zDelta = pcP[mmInd].
position.
z - atmP[qmInd].position.z;
  4050                 qmForce += (linkForce*((1 - linkDist/mmqmDist)*xuv + 
  4051                             (xDelta)*base) )*xuv;
  4053                 qmForce += (linkForce*((1 - linkDist/mmqmDist)*yuv + 
  4054                             (yDelta)*base) )*yuv;
  4056                 qmForce += (linkForce*((1 - linkDist/mmqmDist)*zuv + 
  4057                             (zDelta)*base) )*zuv;
  4060                 mmForce += (linkForce*((linkDist/mmqmDist)*xuv -
  4061                             (xDelta)*base) )*xuv;
  4063                 mmForce += (linkForce*((linkDist/mmqmDist)*yuv -
  4064                             (yDelta)*base) )*yuv;
  4066                 mmForce += (linkForce*((linkDist/mmqmDist)*zuv -
  4067                             (zDelta)*base) )*zuv;
  4069                 resForce[qmInd].force += qmForce;
  4070                 resForce[msg->
numQMAtoms + mmInd].force += mmForce;
  4090         for (; atmIndx < msg->
numQMAtoms; atmIndx++) {
  4093             for (
int qmIter=0; qmIter<globalNumQMAtoms; qmIter++) {
  4095                 if (qmAtmIndx[qmIter] == atmP[atmIndx].
id) {
  4097                     atmP[atmIndx].charge = qmAtmChrg[qmIter];
  4098                     resForce[atmIndx].charge = qmAtmChrg[qmIter];
  4109         outputFile = fopen(tmpRedirectFileName.c_str(),
"r");
  4110         if ( ! outputFile ) {
  4111             iout << 
iERROR << 
"Could not find Redirect output file:"  4112             << tmpRedirectFileName << std::endl << 
endi;
  4116         DebugM(4,
"Opened tmeporary output for charge reading: " << tmpRedirectFileName.c_str() << 
"\n");
  4120         while ( fgets(line, lineLen, outputFile) != NULL){
  4132                 if ( strstr(line,
"MULLIKEN ATOMIC CHARGES") != NULL ) {
  4141                 if ( strstr(line,
"Sum of atomic charges") != NULL ) {
  4146                     strncpy(result, line + 31,12) ;
  4149                     DebugM(4,
"Total charge of QM region calculated by ORCA is: "   4150                     << atof(result) << std::endl )
  4158                 if (lineState == 1) {
  4164                 if (lineState == 2) {
  4166                     strncpy(result, line+8,12) ;
  4169                     Real localCharge = atof(result);
  4172                     if (atmIndx < msg->numQMAtoms ) {
  4173                         atmP[atmIndx].charge = localCharge;
  4174                         resForce[atmIndx].charge = localCharge;
  4180                         atmIndx < msg->numAllAtoms ) {
  4181                         int qmInd = atmP[atmIndx].bountToIndx ;
  4182                         atmP[qmInd].charge += localCharge;
  4183                         resForce[qmInd].charge += localCharge;
  4202                 if ( strstr(line,
"CHELPG Charges") != NULL ) {
  4211                 if ( strstr(line,
"Total charge") != NULL ) {
  4216                     strncpy(result, line + 14,13) ;
  4219                     DebugM(4,
"Total charge of QM region calculated by ORCA is: "   4220                     << atof(result) << std::endl )
  4228                 if (lineState == 1) {
  4234                 if (lineState == 2) {
  4236                     strncpy(result, line+12,15) ;
  4239                     Real localCharge = atof(result);
  4242                     if (atmIndx < msg->numQMAtoms ) {
  4243                         atmP[atmIndx].charge = localCharge;
  4244                         resForce[atmIndx].charge = localCharge;
  4250                         atmIndx < msg->numAllAtoms ) {
  4251                         int qmInd = atmP[atmIndx].bountToIndx ;
  4252                         atmP[qmInd].charge += localCharge;
  4253                         resForce[qmInd].charge += localCharge;
  4293         outputFile = fopen(pcGradFileName.c_str(),
"r");
  4294         if ( ! outputFile ) {
  4295             iout << 
iERROR << 
"Could not find PC gradient output file:"  4296             << pcGradFileName << std::endl << 
endi;
  4300         DebugM(4,
"Opened pc output for gradient reading: " << pcGradFileName.c_str() << 
"\n");
  4302         int pcgradNumPC = 0, readPC = 0;
  4303         iret = fscanf(outputFile,
"%d\n", &pcgradNumPC );
  4305             NAMD_die(
"Error reading PC forces file.");
  4307         DebugM(4,
"Found in pc gradient output: " << pcgradNumPC << 
" point charge grads.\n");
  4315             Force totalForce(0);
  4324             fgets(line, lineLen, outputFile);
  4326             iret = sscanf(line,
"%lf %lf %lf\n", &totalForce[0], &totalForce[1], &totalForce[2] );
  4328                 NAMD_die(
"Error reading PC forces file.");
  4333             totalForce *= -1185.82151;
  4338                 if (qmAtomGroup[pcP[i].
id] == 0) {
  4341                     resForce[pcIndx].force += totalForce;
  4348                 Force mm1Force(0), mm2Force(0);
  4357                 mm1Force = (1-Cq)*totalForce ;
  4358                 mm2Force = Cq*totalForce ;
  4360                 resForce[msg->
numQMAtoms + mm1Indx].force += mm1Force;
  4361                 resForce[msg->
numQMAtoms + mm2Indx].force += mm2Force;
  4375         DebugM(1,
"Correcting forces and energy for PME.\n");
  4378         BigReal TwoBySqrtPi = 1.12837916709551;
  4379         pi_ewaldcof = TwoBySqrtPi * ewaldcof;
  4383             BigReal p_i_charge = atmP[i].charge ;
  4384             Position pos_i = atmP[i].position ;
  4386             for (
size_t j=i+1; j < msg->
numQMAtoms; j++) {
  4388                 BigReal p_j_charge = atmP[j].charge ;
  4390                 Position pos_j = atmP[j].position ;
  4397                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  4400                 BigReal recip_energy = (1-tmp_b)/r;
  4403                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  4405                 const BigReal kq_i = p_i_charge * constants;
  4408                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  4410                 Force fixForce = -1*kq_i*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  4420                 resForce[i].force -= fixForce ;
  4421                 resForce[j].force -= -1*fixForce;
  4436             const BigReal kq_i = p_i_charge * constants;
  4442                 BigReal p_j_charge = atmP[j].charge ;
  4444                 Position pos_j = atmP[j].position ;
  4451                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  4454                 BigReal recip_energy = (1-tmp_b)/r;
  4457                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  4460                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  4462                 fixForce += -1*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  4474             resForce[pcIndx].force -= kq_i*fixForce ;
  4479     DebugM(1,
"Determining virial...\n");
  4486         for ( 
int k=0; k<3; ++k )
  4487             for ( 
int l=0; l<3; ++l )
  4488                 resMsg->
virial[k][l] = -1*resForce[i].force[k]*atmP[i].position[l];
  4495         for ( 
int k=0; k<3; ++k )
  4496             for ( 
int l=0; l<3; ++l )
  4497                 resMsg->
virial[k][l] = -1*resForce[pcIndx].force[k]*pcP[i].
position[l];
  4500     DebugM(1,
"End of QM processing. Sending result message.\n");
  4503     QMProxy[0].recvQMRes(resMsg);
  4514     FILE *inputFile,*outputFile;
  4517     std::string qmCommand, inputFileName, outputFileName;
  4522     DebugM(4,
"Running USER DEFINED SOFTWARE on PE " << CkMyPe() << std::endl);
  4536         pntChrgSwitching(msg, pcPpme) ;
  4545     std::string baseDir(msg->
baseDir);
  4546     std::ostringstream itosConv ;
  4547     if ( CmiNumPartitions() > 1 ) {
  4548         baseDir.append(
"/") ;
  4549         itosConv << CmiMyPartition() ;
  4550         baseDir += itosConv.str() ;
  4554         if (stat(msg->
baseDir, &info) != 0 ) {
  4555             CkPrintf( 
"Node %d cannot access directory %s\n",
  4556                       CkMyPe(), baseDir.c_str() );
  4557             NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  4559         else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  4560             DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  4561             retVal = mkdir(baseDir.c_str(), S_IRWXU);
  4565     baseDir.append(
"/") ;
  4567     baseDir += itosConv.str() ;
  4569     if (stat(msg->
baseDir, &info) != 0 ) {
  4570         CkPrintf( 
"Node %d cannot access directory %s\n",
  4571                   CkMyPe(), baseDir.c_str() );
  4572         NAMD_die(
"QM calculation could not be ran. Check your qmBaseDir!");
  4574     else if (! (stat(baseDir.c_str(), &info) == 0 && S_ISDIR(info.st_mode)) ) {
  4575         DebugM(4,
"Creating directory " << baseDir.c_str() << std::endl);
  4576         int retVal = mkdir(baseDir.c_str(), S_IRWXU);
  4580     Write_PDB(std::string(baseDir)+
"/input.pdb", msg ) ;
  4583     inputFileName.clear();
  4584     inputFileName.append(baseDir.c_str()) ;
  4585     inputFileName.append(
"/qmmm_") ;
  4586     inputFileName += itosConv.str() ;
  4587     inputFileName.append(
".input") ;
  4590     inputFile = fopen(inputFileName.c_str(),
"w");
  4591     if ( ! inputFile ) {
  4592         iout << 
iERROR << 
"Could not open input file for writing: "   4593         << inputFileName << 
"\n" << 
endi ;
  4594         NAMD_err(
"Error writing QM input file.");
  4599     qmCommand.append(
"cd ");
  4600     qmCommand.append(baseDir);
  4601     qmCommand.append(
" ; ");
  4603     qmCommand.append(
" ") ;
  4604     qmCommand.append(inputFileName) ;
  4608     outputFileName = inputFileName ;
  4609     outputFileName.append(
".result") ;
  4611     int numPntChrgs = 0;
  4617     iret = fprintf(inputFile,
"%d %d\n",msg->
numAllAtoms, numPntChrgs);
  4618     if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  4622         " point charges." << std::endl);
  4626     for (
size_t i=0; i<msg->
numAllAtoms; ++i, ++atmP ) {
  4629         double y = atmP->position.y;
  4630         double z = atmP->position.z;
  4632         iret = fprintf(inputFile,
"%f %f %f %s\n",
  4633                        x,y,z,atmP->element);
  4634         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  4638     int numWritenPCs = 0;
  4646         double charge = pcP->
charge;
  4652         iret = fprintf(inputFile,
"%f %f %f %f\n",
  4654         if ( iret < 0 ) { 
NAMD_err(
"Error writing QM input file."); }
  4659     DebugM(4,
"Closing input file\n");
  4664         std::string prepProc(msg->
prepProc) ;
  4665         prepProc.append(
" ") ;
  4666         prepProc.append(inputFileName) ;
  4667         iret = system(prepProc.c_str());
  4668         if ( iret == -1 ) { 
NAMD_err(
"Error running preparation command for QM calculation."); }
  4669         if ( iret ) { 
NAMD_die(
"Error running preparation command for QM calculation."); }
  4673     DebugM(4,
"Running command ->" << qmCommand.c_str() << 
"<-" << std::endl);
  4674     iret = system(qmCommand.c_str());
  4676     if ( iret == -1 ) { 
NAMD_err(
"Error running command for QM forces calculation."); }
  4677     if ( iret ) { 
NAMD_die(
"Error running command for QM forces calculation."); }
  4681         std::string secProc(msg->
secProc) ;
  4682         secProc.append(
" ") ;
  4683         secProc.append(inputFileName) ;
  4687         secProc.append(
" ") ;
  4688         secProc += itosConv.str() ;
  4690         iret = system(secProc.c_str());
  4691         if ( iret == -1 ) { 
NAMD_err(
"Error running second command for QM calculation."); }
  4692         if ( iret ) { 
NAMD_die(
"Error running second command for QM calculation."); }
  4704     DebugM(4,
"Reading QM data from file " << outputFileName.c_str() << std::endl);
  4705     outputFile = fopen(outputFileName.c_str(),
"r");
  4706     if ( ! outputFile ) {
  4721     for ( 
int k=0; k<3; ++k )
  4722         for ( 
int l=0; l<3; ++l )
  4723             resMsg->
virial[k][l] = 0;
  4729         resForce[i].force = 0;
  4730         resForce[i].charge = 0 ;
  4731         if (i < msg->numQMAtoms) {
  4734             resForce[i].replace = 1 ;
  4735             resForce[i].id = atmP->id;
  4741             resForce[i].replace = 0 ;
  4742             resForce[i].id = pcP->
id;
  4756     const size_t lineLen = 256;
  4757     char *line = 
new char[lineLen];
  4759     fgets(line, lineLen, outputFile);
  4762     iret = sscanf(line,
"%lf %i\n", &resMsg->
energyOrig, &usrPCnum);
  4764         NAMD_die(
"Error reading energy from QM results file.");
  4769     if (iret == 2 && numWritenPCs != usrPCnum) {
  4770         iout << 
iERROR << 
"Number of point charges does not match what was provided!\n" << 
endi ;
  4771         NAMD_die(
"Error reading QM results file.");
  4775     double localForce[3];
  4777     for (atmIndx = 0; atmIndx < msg->
numAllAtoms; atmIndx++) {
  4779         iret = fscanf(outputFile,
"%lf %lf %lf %lf\n", 
  4785             NAMD_die(
"Error reading forces and charge from QM results file.");
  4790         if (atmIndx < msg->numQMAtoms ) {
  4792             resForce[atmIndx].force.x = localForce[0];
  4793             resForce[atmIndx].force.y = localForce[1];
  4794             resForce[atmIndx].force.z = localForce[2];
  4796             atmP[atmIndx].charge = localCharge;
  4797             resForce[atmIndx].charge = localCharge;
  4806         atmIndx < msg->numAllAtoms ) {
  4810             atmP[atmIndx].charge = localCharge;
  4815             int qmInd = atmP[atmIndx].bountToIndx ;
  4816             resForce[qmInd].charge += localCharge;
  4820             int mmInd = atmP[qmInd].bountToIndx ;
  4825             Real linkDist = 
Vector(atmP[atmIndx].position - 
  4826                             atmP[qmInd].position).
length() ;
  4828             Force mmForce(0), qmForce(0), 
  4829                 linkForce(localForce[0], localForce[1], localForce[2]);
  4831             Vector base = (linkDist/(mmqmDist*mmqmDist*mmqmDist))*dir;
  4833             Vector xuv(1,0,0), yuv(0,1,0), zuv(0,0,1);
  4834             Real xDelta = pcP[mmInd].
position.
x - atmP[qmInd].position.x;
  4835             Real yDelta = pcP[mmInd].
position.
y - atmP[qmInd].position.y;
  4836             Real zDelta = pcP[mmInd].
position.
z - atmP[qmInd].position.z;
  4838             qmForce += (linkForce*((1 - linkDist/mmqmDist)*xuv + 
  4839                         (xDelta)*base) )*xuv;
  4841             qmForce += (linkForce*((1 - linkDist/mmqmDist)*yuv + 
  4842                         (yDelta)*base) )*yuv;
  4844             qmForce += (linkForce*((1 - linkDist/mmqmDist)*zuv + 
  4845                         (zDelta)*base) )*zuv;
  4848             mmForce += (linkForce*((linkDist/mmqmDist)*xuv -
  4849                         (xDelta)*base) )*xuv;
  4851             mmForce += (linkForce*((linkDist/mmqmDist)*yuv -
  4852                         (yDelta)*base) )*yuv;
  4854             mmForce += (linkForce*((linkDist/mmqmDist)*zuv -
  4855                         (zDelta)*base) )*zuv;
  4857             resForce[qmInd].force += qmForce;
  4858             resForce[msg->
numQMAtoms + mmInd].force += mmForce;
  4873             Force totalForce(0);
  4882             iret = fscanf(outputFile,
"%lf %lf %lf\n", 
  4883                            &totalForce[0], &totalForce[1], &totalForce[2]);
  4885                 NAMD_die(
"Error reading PC forces from QM results file.");
  4891                 if (qmAtomGroup[pcP[i].
id] == 0) {
  4894                     resForce[pcIndx].force += totalForce;
  4901                 Force mm1Force(0), mm2Force(0);
  4910                 mm1Force = (1-Cq)*totalForce ;
  4911                 mm2Force = Cq*totalForce ;
  4913                 resForce[msg->
numQMAtoms + mm1Indx].force += mm1Force;
  4914                 resForce[msg->
numQMAtoms + mm2Indx].force += mm2Force;
  4932         for (; atmIndx < msg->
numQMAtoms; atmIndx++) {
  4935             for (
int qmIter=0; qmIter<globalNumQMAtoms; qmIter++) {
  4937                 if (qmAtmIndx[qmIter] == atmP[atmIndx].
id) {
  4939                     atmP[atmIndx].charge = qmAtmChrg[qmIter];
  4940                     resForce[atmIndx].charge = qmAtmChrg[qmIter];
  4948         for (
size_t j=msg->
numQMAtoms; j<msg->numAllAtoms; ++j ) {
  4958     if (usrPCnum == 0) {
  4974             Force totalForce(0);
  4982                 BigReal qmCharge = atmP[j].charge ;
  4984                 BigReal force = pntCharge*qmCharge*constants ;
  4986                 Position rVec = posMM - atmP[j].position ;
  4995                 totalForce += force*rVec.
unit();
  5001                 if (qmAtomGroup[pcP[i].
id] == 0) {
  5004                     resForce[pcIndx].force += totalForce;
  5011                 Force mm1Force(0), mm2Force(0);
  5020                 mm1Force = (1-Cq)*totalForce ;
  5021                 mm2Force = Cq*totalForce ;
  5023                 resForce[msg->
numQMAtoms + mm1Indx].force += mm1Force;
  5024                 resForce[msg->
numQMAtoms + mm2Indx].force += mm2Force;
  5034         DebugM(1,
"Correcting forces and energy for PME.\n");
  5037         BigReal TwoBySqrtPi = 1.12837916709551;
  5038         pi_ewaldcof = TwoBySqrtPi * ewaldcof;
  5042             BigReal p_i_charge = atmP[i].charge ;
  5043             Position pos_i = atmP[i].position ;
  5045             for (
size_t j=i+1; j < msg->
numQMAtoms; j++) {
  5047                 BigReal p_j_charge = atmP[j].charge ;
  5049                 Position pos_j = atmP[j].position ;
  5056                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  5059                 BigReal recip_energy = (1-tmp_b)/r;
  5062                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  5064                 const BigReal kq_i = p_i_charge * constants;
  5067                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  5069                 Force fixForce = -1*kq_i*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  5079                 resForce[i].force -= fixForce ;
  5080                 resForce[j].force -= -1*fixForce;
  5095             const BigReal kq_i = p_i_charge * constants;
  5101                 BigReal p_j_charge = atmP[j].charge ;
  5103                 Position pos_j = atmP[j].position ;
  5110                 BigReal corr_gradient = pi_ewaldcof*exp(-(tmp_a*tmp_a))*r + tmp_b;
  5113                 BigReal recip_energy = (1-tmp_b)/r;
  5116                 BigReal recip_gradient = -(1-corr_gradient)/(r*r);
  5119                 BigReal energy = kq_i * p_j_charge * recip_energy ;
  5121                 fixForce += -1*p_j_charge*(recip_gradient/r)*(pos_i - pos_j) ;
  5133             resForce[pcIndx].force -= kq_i*fixForce ;
  5138     DebugM(1,
"Determining virial...\n");
  5145         for ( 
int k=0; k<3; ++k )
  5146             for ( 
int l=0; l<3; ++l )
  5147                 resMsg->
virial[k][l] = -1*resForce[i].force[k]*atmP[i].position[l];
  5154         for ( 
int k=0; k<3; ++k )
  5155             for ( 
int l=0; l<3; ++l )
  5156                 resMsg->
virial[k][l] = -1*resForce[pcIndx].force[k]*pcP[i].
position[l];
  5159     DebugM(1,
"End of QM processing. Sending result message.\n");
  5162     QMProxy[0].recvQMRes(resMsg);
  5182     DebugM(1,
"Initiating point charge switching and processing in rank "   5183     << CkMyPe() << 
"\n" ) ;
  5188     Real PCScaleCharge = 0;
  5190         PCScaleCharge += pcP[i].
charge;
  5192     DebugM(4, 
"The initial total Point-Charge charge is " << PCScaleCharge
  5193             << 
" before scaling type: " << msg->
switchType << 
"\n" );
  5219                 Real coef = 1- dist2;
  5220                 pcP[i].
charge *= coef*coef ;
  5231                 if (pcP[i].dist > swdist) {
  5238                     Real swdist2 = swdist*swdist;
  5239                     Real coef = (dist2 - cutoff2)*(dist2 - cutoff2) ;
  5240                     coef *= (cutoff2 + 2*dist2 - 3*swdist2) ;
  5241                     coef /= (cutoff2 - swdist2)*(cutoff2 - swdist2)*(cutoff2 - swdist2);
  5251         PCScaleCharge += pcP[i].
charge;
  5253     DebugM(4, 
"The final total Point-Charge charge is " << PCScaleCharge
  5254             << 
" after scaling.\n" );
  5258     << 
" point charges were selected for point charge scheme " << msg->
pcScheme << 
"\n" );
  5260     Real totalPCCharge = 0, correction = 0;
  5266                 totalPCCharge += pcP[i].
charge;
  5268             DebugM(4, 
"The total Point-Charge charge is " << totalPCCharge 
  5271             if ((fabsf(roundf(totalPCCharge) - totalPCCharge) <= 0.001f) ) {
  5272                 DebugM(4, 
"Charge is already a whole number!\n" );
  5275                 correction = roundf(totalPCCharge) -totalPCCharge ;
  5276                 DebugM(4, 
"Adding to system the charge: " << correction << 
"\n" );
  5283                 totalPCCharge += pcP[i].
charge;
  5285             DebugM(4, 
"The total Point-Charge charge is " << totalPCCharge << 
"\n");
  5287             DebugM(4, 
"Total QM system charge is: " << msg->
charge << 
"\n" );
  5289             correction = -1*(totalPCCharge + msg->
charge);
  5290             if ((fabsf(correction) <= 0.001f) ) {
  5292                 DebugM(4, 
"Total QM + PC charge is already zero!\n" );
  5295                 DebugM(4, 
"Adding a charge of " << correction << 
" to the system\n");
  5300     if (correction != 0) {
  5302         int maxi = sortedDists.
size(), mini = sortedDists.
size()/2;
  5303         Real fraction = correction/(maxi - mini); 
  5305         DebugM(4, 
"The charge fraction added to the " << (maxi - mini)
  5306         << 
" most distant point charges is " << fraction << 
"\n");
  5308         for (
size_t i=mini; i<maxi ; i++) {
  5317             totalPCCharge += pcP[i].
charge;
  5319         DebugM(4, 
"The total Point-Charge charge is " << totalPCCharge 
  5326 void ComputeQMMgr::lssPrepare() {
  5331     DebugM (4, 
"Preparing LSS for " << numQMGrps << 
" QM groups.\n" )
  5333     for (
int i=0; i<numQMGrps; i++) {
  5334         lssTotRes += qmLSSSize[i];
  5339     grpIDResNum.
resize(numQMGrps);
  5343         lssGrpRefMass.
resize(numQMGrps);
  5345         for (
int i=0; i<qmLSSResSize; i++)
  5346             lssResMass += qmLSSMass[i];
  5348         DebugM(4, 
"Total residue mass is " << lssResMass << 
"\n" )
  5352     int solvResBeg = 0, refAtmBeg = 0, locIter = 0, solvIndx = 0;
  5353     int *lssIndxs, *refAtmsIndxs ;
  5354     Mass *lssMasses, *refAtmMasses;
  5355     while (locIter < numQMGrps) {
  5356         lssIndxs = qmLSSIdxs + solvResBeg;
  5358         DebugM (4, 
"Loading atom IDs for QM group " << locIter 
  5359             << 
" with " << qmLSSSize[locIter]
  5360             << 
" solvent molecules.\n" )
  5367             lssMasses = qmLSSMass + solvResBeg;
  5370             for (
int i=0; i<qmLSSSize[locIter]; i++) {
  5372                 lssPos[solvIndx] = 0;
  5374                 Debug( 
iout << 
"Getting atom IDs from QM solvent molecule "   5375                 << solvIndx << 
"\n") ;
  5376                 for (
int j=0; j<qmLSSResSize; j++) {
  5378                     int atmID = lssIndxs[i*qmLSSResSize + j];
  5379                     Mass atmMass = lssMasses[i*qmLSSResSize + j];
  5380                     Debug( 
iout << atmID << 
" (" << atmMass << 
") ") ;
  5391             refAtmsIndxs = qmLSSRefIDs + refAtmBeg;
  5393             for (
int i=0; i<qmLSSRefSize[locIter]; i++) {
  5394                 lssGrpRefMass[locIter].
insert( 
  5395                     refLSSData( refAtmsIndxs[i], refAtmMasses[i] ) 
  5398             refAtmBeg += qmLSSRefSize[locIter] ;
  5404             for (
int i=0; i<qmLSSSize[locIter]; i++) {
  5406                 lssPos[solvIndx] = 0;
  5408                 Debug( 
iout << 
"Getting atom IDs from QM solvent molecule "   5409                 << solvIndx << 
"\n") ;
  5410                 for (
int j=0; j<qmLSSResSize; j++) {
  5412                     int atmID = lssIndxs[i*qmLSSResSize + j];
  5426         solvResBeg += qmLSSSize[locIter]*qmLSSResSize ;
  5433 void ComputeQMMgr::lssUpdate(
int grpIter, 
QMAtmVec& grpQMAtmVec, 
  5441     DebugM(3, 
"LSS UPDATE...\n")
  5443     int solvResBeg = 0 ;
  5444     for (
int i=0; i<grpIter; i++)
  5445         solvResBeg += qmLSSSize[i] ;
  5451         DebugM(3, 
"Using COM for LSS in group " << grpIter << 
"\n")
  5454         for(
int i=0; i<grpQMAtmVec.size(); i++) {
  5456             auto it = lssGrpRefMass[grpIter].
find(grpQMAtmVec[i].
id);
  5457             if ( it != lssGrpRefMass[grpIter].end() ) {
  5458                 refCOM += grpQMAtmVec[i].position*it->second ;
  5459                 totMass += it->second ;
  5464         DebugM ( 3, 
"Reference COM position: " << refCOM << 
"\n");
  5467         for (
int solvIter=solvResBeg; solvIter<solvResBeg+qmLSSSize[grpIter]; solvIter++) {
  5468             lssPos[solvIter] = 0 ;
  5471         DebugM(3, 
"Calculating distance of QM solvent COM from reference COM of group.\n")
  5478         for(
int i=0; i<grpQMAtmVec.size(); i++) {
  5479             auto it = grpIDResNum[grpIter].
find(grpQMAtmVec[i].
id) ;
  5480             if (it != grpIDResNum[grpIter].end()) {
  5481                 lssPos[it->second.resIndx] += grpQMAtmVec[i].position*it->second.mass ;
  5484                 auto itRes = resQMDist.find(it->second.resIndx) ;
  5485                 if (itRes == resQMDist.end() ) {
  5486                     resQMDist.insert(std::pair<int,lssDistSort >(
  5495                 resQMDist[it->second.resIndx].idIndx.add(
idIndxStr(grpQMAtmVec[i].
id,i)) ;
  5499         DebugM(3, 
"QM Solvent molecules " << solvResBeg 
  5500         << 
" to " << solvResBeg+qmLSSSize[grpIter] << 
"\n")
  5503         for (
int solvIter=solvResBeg; solvIter<solvResBeg+qmLSSSize[grpIter]; solvIter++) {
  5505             resQMDist[solvIter].dist = dist ;
  5506             solvDist.
add(resQMDist[solvIter]);
  5510         DebugM(3, 
"We loaded the following QM solvent residues and distances:\n")
  5511         for (
int i=0; i<solvDist.size(); i++) {
  5512             iout << i << 
") type: " << solvDist[i].type 
  5513             << 
" dist " << solvDist[i].dist
  5515             for (
int j=0; j<solvDist[i].idIndx.
size(); j++) 
  5516                 iout << solvDist[i].idIndx[j].ID << 
" " ;
  5526         std::map<int,lssDistSort > resPCSize ;
  5528         for(
int i=0; i<grpPntChrgVec.size(); i++) {
  5531             auto it = molPtr->
get_qmMMSolv().find(grpPntChrgVec[i].
id) ;
  5535                 auto itRes = resPCSize.find(it->second) ;
  5536                 if (itRes == resPCSize.end() ) {
  5537                     resPCSize.insert(std::pair<int,lssDistSort >(
  5546                 resPCSize[it->second].idIndx.add(
idIndxStr(grpPntChrgVec[i].
id,i)) ;
  5553         for (
auto it=resPCSize.begin(); it!=resPCSize.end(); it++) {
  5555             if (it->second.idIndx.size() == qmLSSResSize) {
  5562                 for (
int i=0; i<it->second.idIndx.size(); i++) {
  5567                     currCOM += grpPntChrgVec[it->second.idIndx[i].indx].position*grpPntChrgVec[it->second.idIndx[i].indx].mass;
  5568                     totalMass += grpPntChrgVec[it->second.idIndx[i].indx].mass;
  5570                 currCOM /= totalMass;
  5574                 it->second.dist = currDist ;
  5576                 solvDist.
add(it->second) ;
  5584         DebugM(3, 
"Using minimal distances for LSS in group " << grpIter << 
"\n")
  5586         DebugM(3, "QM Solvent molecules " << solvResBeg 
  5587         << " to " << solvResBeg+qmLSSSize[grpIter] << "\n")
  5597         for(
int i=0; i<grpQMAtmVec.size(); i++) {
  5599             auto it = grpIDResNum[grpIter].
find(grpQMAtmVec[i].
id) ;
  5600             if (it != grpIDResNum[grpIter].end()) {
  5603                 auto itRes = resQMDist.find(it->second.resIndx) ;
  5604                 if (itRes == resQMDist.end() ) {
  5605                     resQMDist.insert(std::pair<int,lssDistSort >(
  5614                 resQMDist[it->second.resIndx].idIndx.add(
idIndxStr(grpQMAtmVec[i].
id,i)) ;
  5624         for (
auto it=resQMDist.begin(); it != resQMDist.end(); it++) {
  5628             it->second.dist = 
Vector(
  5629                     grpQMAtmVec[it->second.idIndx[0].indx].position - 
  5630                     grpQMAtmVec[qmRefIndx[0]].position
  5633             for (
int i=0; i<it->second.idIndx.size(); i++) {
  5635                 for(
int j=0; j<qmRefIndx.size(); j++) {
  5637                         grpQMAtmVec[it->second.idIndx[i].indx].position - 
  5638                         grpQMAtmVec[qmRefIndx[j]].position
  5641                     if (currDist < it->second.dist)
  5642                         it->second.dist = currDist;
  5648             solvDist.
add(it->second) ;
  5653         DebugM(3, 
"We loaded the following QM solvent residues and distances:\n")
  5654         for (
int i=0; i<solvDist.size(); i++) {
  5655             iout << i << 
") type: " << solvDist[i].type 
  5656             << 
" dist " << solvDist[i].dist
  5658             for (
int j=0; j<solvDist[i].idIndx.
size(); j++) 
  5659                 iout << solvDist[i].idIndx[j].ID << 
" " ;
  5669         std::map<int,lssDistSort > resPCSize ;
  5671         for(
int i=0; i<grpPntChrgVec.size(); i++) {
  5674             auto it = molPtr->
get_qmMMSolv().find(grpPntChrgVec[i].
id) ;
  5678                 auto itRes = resPCSize.find(it->second) ;
  5679                 if (itRes == resPCSize.end() ) {
  5680                     resPCSize.insert(std::pair<int,lssDistSort >(
  5689                 resPCSize[it->second].idIndx.add(
idIndxStr(grpPntChrgVec[i].
id,i)) ;
  5696         for (
auto it=resPCSize.begin(); it!=resPCSize.end(); it++) {
  5698             if (it->second.idIndx.size() == qmLSSResSize) {
  5702                 it->second.dist = 
Vector(
  5703                         grpPntChrgVec[it->second.idIndx[0].indx].position - 
  5704                         grpQMAtmVec[qmRefIndx[0]].position
  5707                 for (
int i=0; i<it->second.idIndx.size(); i++) {
  5709                     for(
int j=0; j<qmRefIndx.size(); j++) {
  5711                             grpPntChrgVec[it->second.idIndx[i].indx].position - 
  5712                             grpQMAtmVec[qmRefIndx[j]].position
  5715                         if (currDist < it->second.dist)
  5716                             it->second.dist = currDist;
  5720                 solvDist.
add(it->second) ;
  5730     DebugM(3, 
"Final selection of solvent residues and distances:\n")
  5731     for (
int i=0; i<qmLSSSize[grpIter]; i++) {
  5736             typeS = 
"Classical";
  5737         iout << i << 
") type: " << typeS
  5738         << 
" dist " << solvDist[i].dist
  5740         for (
int j=0; j<solvDist[i].idIndx.
size(); j++) 
  5741             iout << solvDist[i].idIndx[j].ID << 
" " ;
  5749     DebugM(3, 
"Determining residues to be swaped...\n")
  5753     for (
int resIter = 0; resIter < qmLSSSize[grpIter] ; resIter++) {
  5755             nearMM.add(solvDist[resIter]);
  5759     for (
int resIter=qmLSSSize[grpIter]; resIter<solvDist.
size(); resIter++) {
  5761             farQM.add(solvDist[resIter]);
  5764         if (farQM.size() == nearMM.size()) 
break;
  5767     if (farQM.size() != nearMM.size())
  5768         NAMD_die(
"Could not find complementing residues to be swapped in LSS.") ;
  5771     DebugM(3, 
"Removing the following QM residues:\n")
  5772     for (
int i=0; i<farQM.size();i++) {
  5777             typeS = 
"Classical";
  5778         iout << i << 
") type: " << typeS
  5779         << 
" dist " << farQM[i].dist
  5781         for (
int j=0; j<farQM[i].idIndx.size(); j++) 
  5782             iout << farQM[i].idIndx[j].ID << 
" " ;
  5786     DebugM(3, 
"Replacing with the following Classical residues:\n")
  5787     for (
int i=0; i<nearMM.size();i++) {
  5792             typeS = 
"Classical";
  5793         iout << i << 
") type: " << typeS
  5794         << 
" dist " << nearMM[i].dist
  5796         for (
int j=0; j<nearMM[i].idIndx.size(); j++) 
  5797             iout << nearMM[i].idIndx[j].ID << 
" " ;
  5801     DebugM(3, 
"Building substitution array...\n")
  5804     iout << 
iINFO << 
"LSS is swapping " << farQM.size() << 
" solvent residues in QM group "  5805     << grpIter << 
"\n" << 
endi;
  5810     for (
int i=0; i<farQM.size();i++) {
  5812         for(
int j=0; j<qmLSSResSize; j++) {
  5814             int qIndx= farQM[i].idIndx[j].indx;
  5815             int mIndx= nearMM[i].idIndx[j].indx;
  5818                                        grpPntChrgVec[mIndx].
id,
  5819                                        grpPntChrgVec[mIndx].vdwType,
  5820                                        grpPntChrgVec[mIndx].charge ) );
  5823                                        grpQMAtmVec[qIndx].
id,
  5824                                        grpQMAtmVec[qIndx].vdwType,
  5825                                        grpQMAtmVec[qIndx].charge ) );
  5831     for(
int i=0; i<subsArray.
size() ;i++) {
  5832         DebugM(3, CkMyPe() << 
") Storing LSS atom " << subsArray[i].origID
  5833         << 
" Which will become " << subsArray[i].newID
  5834         << 
" - " << subsArray[i].newVdWType
  5835         << 
" - " << subsArray[i].newCharge << 
"\n" ); 
  5842 void ComputeQMMgr::calcCSMD(
int grpIndx, 
int numQMAtoms, 
const QMAtomData *atmP, 
Force *cSMDForces) {
  5846     for ( 
int i=0; i < cSMDindxLen[grpIndx]; i++ ) {
  5853         int cSMDit = cSMDindex[grpIndx][i] ;
  5854         AtomID src = -1, trgt = -1;
  5857         for (
size_t indx=0; indx < numQMAtoms; ++indx) {
  5859             if ( cSMDpairs[cSMDit][0] == atmP[indx].
id )
  5862             if ( cSMDpairs[cSMDit][1] == atmP[indx].
id )
  5865             if (src != -1 && trgt != -1)
  5871         tdist = trgtDir.
length();
  5875         if (cSMDInitGuides < cSMDnumInstances) {
  5876             cSMDguides[cSMDit] = atmP[src].
position;
  5882         if (tdist > cSMDcoffs[cSMDit]) {
  5884             cSMDguides[cSMDit] += trgtDir*cSMDVels[cSMDit];
  5889             guideDir *= cSMDKs[cSMDit] ;
  5890             cSMDforce = guideDir ;
  5896             cSMDguides[cSMDit] = atmP[src].
position;
  5899         DebugM(4, cSMDit << 
") Center at  " << cSMDguides[cSMDit] << 
" for target distance " << 
  5900         tdist << 
" and direction " << trgtDir << 
  5904         cSMDForces[cSMDit] = cSMDforce;
  5906         iout << 
iINFO << 
"Calculated cSMD force vector " << cSMDforce
  5907         << 
" (atom "  << cSMDpairs[cSMDit][0] << 
" to " << cSMDpairs[cSMDit][1] << 
")\n" << 
endi;
  5915 void ComputeQMMgr::Write_PDB(std::string Filename, 
const QMGrpCalcMsg *dataMsg)
  5917     std::ofstream OutputTmpPDB ;
  5922         OutputTmpPDB.open( Filename.c_str(), std::fstream::out );
  5924         OutputTmpPDB << 
"REMARK Information used by NAMD to create the QM simulation." << std::endl ;
  5925         OutputTmpPDB << 
"REMARK Occupancy: bount to index; Beta: System ID; " << std::endl ;
  5939             std::string name(
" x  ");
  5940             std::string resName (
"  uk");
  5941             std::string chainName(
"X");
  5942             std::string element(
"") ;
  5943             if (i < dataMsg->numAllAtoms ) {
  5962             OutputTmpPDB << 
"ATOM  " ; 
  5964             OutputTmpPDB.width(5) ; 
  5965             OutputTmpPDB.right ;
  5968             OutputTmpPDB << 
" " ; 
  5970             OutputTmpPDB.width(4) ; 
  5971             OutputTmpPDB << name ;
  5973             OutputTmpPDB << 
" " ; 
  5975             OutputTmpPDB.width(4) ; 
  5976             OutputTmpPDB << resName ;
  5978             OutputTmpPDB.width(1) ; 
  5979             OutputTmpPDB << chainName ;
  5981             OutputTmpPDB.width(4) ; 
  5984             OutputTmpPDB << 
" " ; 
  5986             OutputTmpPDB << 
"   " ; 
  5988             OutputTmpPDB.width(8) ; 
  5989             OutputTmpPDB.right ;
  5990             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  5991             OutputTmpPDB.precision(3) ;
  5994             OutputTmpPDB.width(8) ; 
  5995             OutputTmpPDB.right ;
  5996             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  5997             OutputTmpPDB.precision(3) ;
  6000             OutputTmpPDB.width(8) ; 
  6001             OutputTmpPDB.right ;
  6002             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6003             OutputTmpPDB.precision(3) ;
  6006             OutputTmpPDB.width(6) ; 
  6007             OutputTmpPDB.right ;
  6008             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6009             OutputTmpPDB.precision(2) ;
  6012             OutputTmpPDB.width(6) ; 
  6013             OutputTmpPDB.right ;
  6014             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6015             OutputTmpPDB.precision(2) ;
  6016             OutputTmpPDB << dataP[i].
id ;
  6018             OutputTmpPDB.width(6) ; 
  6019             OutputTmpPDB << 
"      " ;
  6021             OutputTmpPDB.width(4) ; 
  6023             OutputTmpPDB << 
"QM  ";
  6025             OutputTmpPDB.width(2) ; 
  6026             OutputTmpPDB.right ;
  6027             OutputTmpPDB << element ;
  6029             OutputTmpPDB.width(2) ; 
  6030             OutputTmpPDB.right ;
  6031             OutputTmpPDB << dataP[i].
charge ;
  6033             OutputTmpPDB << std::endl;
  6037         OutputTmpPDB << 
"END" << std::endl;
  6039         OutputTmpPDB.close();
  6045         throw "Generic exception!" ;
  6050 void ComputeQMMgr::Write_PDB(std::string Filename, 
const QMCoordMsg *dataMsg)
  6052     std::ofstream OutputTmpPDB ;
  6057         OutputTmpPDB.open( Filename.c_str(), std::fstream::out );
  6059         OutputTmpPDB << 
"REMARK Information used by NAMD to create the QM simulation." << std::endl ;
  6060         OutputTmpPDB << 
"REMARK Occupancy: bount to index; Beta: System ID; " << std::endl ;
  6064         for ( 
int i=0 ; i < dataMsg->
numAtoms; i++ )
  6074             std::string name(
" x  ");
  6075             std::string resName (
" atm");
  6076             std::string chainName(
"X");
  6077             std::string element(
"") ;
  6079             OutputTmpPDB << 
"ATOM  " ; 
  6081             OutputTmpPDB.width(5) ; 
  6082             OutputTmpPDB.right ;
  6085             OutputTmpPDB << 
" " ; 
  6087             OutputTmpPDB.width(4) ; 
  6088             OutputTmpPDB << name ;
  6090             OutputTmpPDB << 
" " ; 
  6092             OutputTmpPDB.width(4) ; 
  6093             OutputTmpPDB << resName ;
  6095             OutputTmpPDB.width(1) ; 
  6096             OutputTmpPDB << chainName ;
  6098             OutputTmpPDB.width(4) ; 
  6101             OutputTmpPDB << 
" " ; 
  6103             OutputTmpPDB << 
"   " ; 
  6105             OutputTmpPDB.width(8) ; 
  6106             OutputTmpPDB.right ;
  6107             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6108             OutputTmpPDB.precision(3) ;
  6111             OutputTmpPDB.width(8) ; 
  6112             OutputTmpPDB.right ;
  6113             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6114             OutputTmpPDB.precision(3) ;
  6117             OutputTmpPDB.width(8) ; 
  6118             OutputTmpPDB.right ;
  6119             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6120             OutputTmpPDB.precision(3) ;
  6123             OutputTmpPDB.width(6) ; 
  6124             OutputTmpPDB.right ;
  6125             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6126             OutputTmpPDB.precision(2) ;
  6127             OutputTmpPDB << dataP[i].
qmGrpID ;
  6129             OutputTmpPDB.width(6) ; 
  6130             OutputTmpPDB.right ;
  6131             OutputTmpPDB.setf(std::ios::fixed,std::ios::floatfield) ;
  6132             OutputTmpPDB.precision(2) ;
  6133             OutputTmpPDB << dataP[i].
id ;
  6135             OutputTmpPDB.width(6) ; 
  6136             OutputTmpPDB << 
"      " ;
  6138             OutputTmpPDB.width(4) ; 
  6140             OutputTmpPDB << 
"QM  ";
  6142             OutputTmpPDB.width(2) ; 
  6143             OutputTmpPDB.right ;
  6144             OutputTmpPDB << element ;
  6146             OutputTmpPDB.width(2) ; 
  6147             OutputTmpPDB.right ;
  6148             OutputTmpPDB << dataP[i].
charge ;
  6150             OutputTmpPDB << std::endl;
  6154         OutputTmpPDB << 
"END" << std::endl;
  6156         OutputTmpPDB.close();
  6162         throw "Generic exception!" ;
  6169 #include "ComputeQMMgr.def.h" 
int insert(const Elem &elem, int index)
 
lssDistSort(const lssDistSort &ref)
 
BigReal PMEEwaldCoefficient
 
std::ostream & iINFO(std::ostream &s)
 
std::map< int, Mass > LSSRefMap
 
ComputeQMPntChrg(Position posInit, float chrgInit, int idInit, Real qmInit, int hiInit, Real newDist, Mass newM, int newvdwType)
 
const int * get_qmMMNumTargs()
 
void NAMD_err(const char *err_msg)
 
void recvPartQM(QMCoordMsg *)
 
void setCompute(ComputeQM *c)
 
ComputeQMAtom(Position posInit, float chrgInit, int idInit, Real qmInit, int hiInit, int newvdwType)
 
SortedArray< LSSSubsDat > & lssSubs(ComputeQMMgr *mgr)
 
idIndxStr & operator=(const idIndxStr &ref)
 
const int * get_qmGrpNumBonds()
 
bool operator==(const idIndxStr &ref) const
 
const int * get_qmAtmIndx()
 
std::pair< Position, BigReal > PosDistPair
 
static PatchMap * Object()
 
virtual void submit(void)=0
 
SimParameters * simParameters
 
ComputeHomePatchList patchList
 
const int *const  * get_qmMMBondedIndx()
 
#define QMPCTYPE_CLASSICAL
 
std::ostream & endi(std::ostream &s)
 
char qmPrepProc[NAMD_FILENAME_BUFFER_SIZE]
 
std::ostream & iWARN(std::ostream &s)
 
SubmitReduction * willSubmit(int setID, int size=-1)
 
bool operator<(const idIndxStr &ref)
 
idIndxStr(const idIndxStr &ref)
 
ResizeArrayIter< T > begin(void) const
 
dummyData(Position newPos, int newQmInd, int newIndx)
 
static ReductionMgr * Object(void)
 
int const  * get_cSMDindxLen()
 
SortedArray< idIndxStr > idIndx
 
void storeQMRes(QMGrpResMsg *)
 
void recvPntChrg(QMPntChrgMsg *)
 
int add(const Elem &elem)
 
SortedArray< LSSSubsDat > & get_subsArray()
 
std::map< int, int > & get_qmMMSolv()
 
const char *const  * get_qmDummyElement()
 
Molecule stores the structural information for the system. 
 
char qmExecPath[NAMD_FILENAME_BUFFER_SIZE]
 
char outputFilename[NAMD_FILENAME_BUFFER_SIZE]
 
int open_dcd_write(const char *dcdname)
 
const int *const  * get_qmGrpBonds()
 
int const  *const  * get_cSMDpairs()
 
char qmSecProc[NAMD_FILENAME_BUFFER_SIZE]
 
lssDistSort(int newType, Real newDist)
 
static char * QMETITLE(int X)
 
int index(const Elem &elem)
 
pntChrgDist(int newIndx, Real newDist)
 
int insert(const Elem &elem)
 
int add(const Elem &elem)
 
lssDistSort & operator=(const lssDistSort &ref)
 
std::pair< int, Mass > refLSSData
 
int operator<(const pntChrgDist &v)
 
bool operator<(const lssDistSort &ref)
 
ResizeArray< ComputePme * > & getComputes(ComputePmeMgr *mgr)
 
NAMD_HOST_DEVICE BigReal length(void) const
 
void NAMD_bug(const char *err_msg)
 
void recvFullQM(QMCoordMsg *)
 
int write_dcdstep(int fd, int N, float *X, float *Y, float *Z, double *cell)
 
const int *const  * get_qmMMBond()
 
bool operator==(const ComputeQMPntChrg &ref)
 
NAMD_HOST_DEVICE BigReal length2(void) const
 
int load(const Elem &elem)
 
idIndxStr(int newID, int newIndx)
 
std::vector< ComputeQMPntChrg > QMPCVec
 
bool custom_ComputeQMAtom_Less(const ComputeQMAtom a, const ComputeQMAtom b)
 
const Real * get_qmAtomGroup() const
 
BigReal PMEEwaldCoefficient
 
bool operator<(const ComputeQMPntChrg &ref)
 
const Real * get_cSMDcoffs()
 
void NAMD_die(const char *err_msg)
 
static char * FORMAT(BigReal X)
 
void calcORCA(QMGrpCalcMsg *)
 
const int *const  * get_qmMMChargeTarget()
 
int * get_qmCustPCSizes()
 
int write_dcdheader(int fd, const char *filename, int N, int NFILE, int NPRIV, int NSAVC, int NSTEP, double DELTA, int with_unitcell)
 
void processFullQM(QMCoordMsg *)
 
const char *const  * get_qmElements()
 
Bool qmMOPACAddConfigChrg
 
void calcUSR(QMGrpCalcMsg *)
 
void saveResults(QMForceMsg *)
 
void calcMOPAC(QMGrpCalcMsg *)
 
const Real * get_cSMDKs()
 
void recvForce(QMForceMsg *)
 
virtual void initialize()
 
bool operator!=(const idIndxStr &ref) const
 
Elem * find(const Elem &elem)
 
int find(const Elem &e) const
 
bool operator==(const lssDistSort &ref)
 
std::map< Real, std::pair< Position, BigReal > > GrpDistMap
 
std::pair< int, LSSDataStr > atmLSSData
 
int * get_qmCustomPCIdxs()
 
const Real * get_cSMDVels()
 
ComputeQMAtom(const ComputeQMAtom &ref)
 
int get_qmNumGrps() const
 
std::ostream & iERROR(std::ostream &s)
 
StringList * find(const char *name) const
 
void close_dcd_write(int fd)
 
LSSDataStr(int newResIndx, Mass newMass)
 
int const  *const  * get_cSMDindex()
 
Mass * get_qmLSSRefMass()
 
char qmBaseDir[NAMD_FILENAME_BUFFER_SIZE]
 
NAMD_HOST_DEVICE Vector unit(void) const
 
ResizeArrayIter< T > end(void) const
 
ComputeQMPntChrg(const ComputeQMPntChrg &ref)
 
const BigReal * get_qmDummyBondVal()
 
QMAtomData(Position posInit, float chrgInit, int idInit, int bountToIndxInit, int newType, char *elementInit, Real newDist)
 
#define QMLSSCLASSICALRES
 
std::map< int, LSSDataStr > LSSDataMap
 
NAMD_HOST_DEVICE Vector delta(const Position &pos1, const Position &pos2) const
 
const int * get_qmGrpSizes()
 
std::vector< ComputeQMAtom > QMAtmVec