NAMD
Public Member Functions | List of all members
ComputeQM Class Reference

#include <ComputeQM.h>

Inheritance diagram for ComputeQM:
ComputeHomePatches Compute

Public Member Functions

 ComputeQM (ComputeID c)
 
virtual ~ComputeQM ()
 
void initialize ()
 
void doWork ()
 
void saveResults (QMForceMsg *)
 
void processFullQM (QMCoordMsg *)
 
- Public Member Functions inherited from ComputeHomePatches
 ComputeHomePatches (ComputeID c)
 
virtual ~ComputeHomePatches ()
 
virtual void atomUpdate ()
 
FlagsgetFlags (void)
 
- Public Member Functions inherited from Compute
 Compute (ComputeID)
 
int type ()
 
virtual ~Compute ()
 
void setNumPatches (int n)
 
int getNumPatches ()
 
virtual void patchReady (PatchID, int doneMigration, int seq)
 
virtual int noWork ()
 
virtual void finishPatch (int)
 
int sequence (void)
 
int priority (void)
 
int getGBISPhase (void)
 
virtual void gbisP2PatchReady (PatchID, int seq)
 
virtual void gbisP3PatchReady (PatchID, int seq)
 

Additional Inherited Members

- Public Attributes inherited from Compute
const ComputeID cid
 
LDObjHandle ldObjHandle
 
LocalWorkMsg *const localWorkMsg
 
- Protected Member Functions inherited from Compute
void enqueueWork ()
 
- Protected Attributes inherited from ComputeHomePatches
int useAvgPositions
 
int hasPatchZero
 
ComputeHomePatchList patchList
 
PatchMappatchMap
 
- Protected Attributes inherited from Compute
int computeType
 
int basePriority
 
int gbisPhase
 
int gbisPhasePriority [3]
 

Detailed Description

Definition at line 114 of file ComputeQM.h.

Constructor & Destructor Documentation

◆ ComputeQM()

ComputeQM::ComputeQM ( ComputeID  c)

Definition at line 600 of file ComputeQM.C.

References ReductionMgr::Object(), REDUCTIONS_BASIC, and ReductionMgr::willSubmit().

600  :
601  ComputeHomePatches(c), oldForces(0)
602 {
603  CProxy_ComputeQMMgr::ckLocalBranch(
604  CkpvAccess(BOCclass_group).computeQMMgr)->setCompute(this);
605 
607 
608 }
SubmitReduction * willSubmit(int setID, int size=-1)
Definition: ReductionMgr.C:366
static ReductionMgr * Object(void)
Definition: ReductionMgr.h:279
ComputeHomePatches(ComputeID c)

◆ ~ComputeQM()

ComputeQM::~ComputeQM ( )
virtual

Definition at line 610 of file ComputeQM.C.

611 {
612  if (oldForces != 0)
613  delete [] oldForces;
614 }

Member Function Documentation

◆ doWork()

void ComputeQM::doWork ( void  )
virtual

Reimplemented from Compute.

Definition at line 676 of file ComputeQM.C.

References ResizeArrayIter< T >::begin(), ComputeQMAtom::charge, QMCoordMsg::coord, DebugM, ResizeArrayIter< T >::end(), SortedArray< Elem >::find(), ComputeQMAtom::homeIndx, ComputeQMAtom::id, CompAtomExt::id, QMCoordMsg::numAtoms, ComputeHomePatches::patchList, ComputeQMAtom::position, ComputeQMAtom::qmGrpID, ResizeArray< Elem >::size(), QMCoordMsg::sourceNode, QMCoordMsg::timestep, ComputeQMAtom::vdwType, and CompAtom::vdwType.

677 {
678  CProxy_ComputeQMMgr QMProxy(CkpvAccess(BOCclass_group).computeQMMgr);
679 
681 
682  int timeStep;
683 
684  #ifdef DEBUG_QM
685  DebugM(4,"----> Initiating QM work on rank " << CkMyPe() <<
686  " with " << patchList.size() << " patches." << std::endl );
687  #endif
688 
689  patchData.clear();
690 
691  // Determines hou many QM atoms are in this node.
692  int numLocalQMAtoms = 0, localMM1atoms = 0;
693  for (ap = ap.begin(); ap != ap.end(); ap++) {
694  CompAtomExt *xExt = (*ap).p->getCompAtomExtInfo();
695  int localNumAtoms = (*ap).p->getNumAtoms();
696 
697  patchData.push_back(patchDataStrc((*ap).positionBox,
698  (*ap).positionBox->open(),
699  (*ap).p) );
700 
701  for(int i=0; i<localNumAtoms; ++i) {
702  if ( qmAtomGroup[xExt[i].id] > 0 ) {
703  numLocalQMAtoms++;
704  }
705  else if (meNumMMIndx > 0) {
706  // If we have a mechanical embedding simulation with no
707  // point charges, but with QM-MM bonds, we look for the MM1 atoms
708  // here and pass them directly. No need for an extra round of
709  // comms just to get atoms we already know we need.
710 
711  auto retIt = meQMBonds.find(meMMQMGrp(xExt[i].id));
712 
713  if (retIt != NULL) {
714  localMM1atoms++;
715  }
716  }
717  }
718 
719  timeStep = (*ap).p->flags.step ;
720  }
721 
722  DebugM(4, "Node " << CkMyPe() << " has " << numLocalQMAtoms
723  << " QM atoms." << std::endl) ;
724  #ifdef DEBUG_QM
725  if (localMM1atoms > 0)
726  DebugM(4, "Node " << CkMyPe() << " has " << localMM1atoms
727  << " MM1 atoms." << std::endl) ;
728  #endif
729  // Send QM atoms
730 
731  // This pointer will be freed in rank zero.
732  QMCoordMsg *msg = new (numLocalQMAtoms + localMM1atoms,0, 0) QMCoordMsg;
733  msg->sourceNode = CkMyPe();
734  msg->numAtoms = numLocalQMAtoms + localMM1atoms;
735  msg->timestep = timeStep;
736  ComputeQMAtom *data_ptr = msg->coord;
737 
738  // Build a message with coordinates, charge, atom ID and QM group
739  // for all QM atoms in the node, then send it to node zero.
740  int homeCounter = 0;
741  for (auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
742 
743  CompAtom *x = (*pdIt).compAtomP;
744  const CompAtomExt *xExt = (*pdIt).homePatchP->getCompAtomExtInfo();
745  int localNumAtoms = (*pdIt).homePatchP->getNumAtoms();
746  const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
747 
748  for(int i=0; i<localNumAtoms; ++i) {
749 
750  if ( qmAtomGroup[xExt[i].id] > 0 ) {
751 
752  Real charge = 0;
753 
754  for (int qi=0; qi<numQMAtms; qi++) {
755  if (qmAtmIndx[qi] == xExt[i].id) {
756  charge = qmAtmChrg[qi];
757  break;
758  }
759  }
760 
761  data_ptr->position = patchList[0].p->lattice.reverse_transform(x[i].position,
762  fullAtms[i].transform) ;
763 // data_ptr->charge = x[i].charge;
764  data_ptr->charge = charge;
765  data_ptr->id = xExt[i].id;
766  data_ptr->qmGrpID = qmAtomGroup[xExt[i].id] ;
767  data_ptr->homeIndx = homeCounter;
768  data_ptr->vdwType = fullAtms[i].vdwType;
769 
770  ++data_ptr;
771  }
772  else if (meNumMMIndx > 0) {
773  // If we have a mechanical embedding simulation with no
774  // point charges, but with QM-MM bonds, we look for the MM1 atoms
775  // connected here and pass them directly.
776 
777  auto retIt = meQMBonds.find(meMMQMGrp(xExt[i].id));
778 
779  if (retIt != NULL) {
780 
781  DebugM(3,"Found atom " << retIt->mmIndx << "," << retIt->qmGrp << "\n" );
782 
783  data_ptr->position = patchList[0].p->lattice.reverse_transform(x[i].position,
784  fullAtms[i].transform) ;
785  // We force the charge to be zero since we would only get
786  // here if mechanical embeding was selected.
787  data_ptr->charge = 0;
788  data_ptr->id = xExt[i].id;
789  data_ptr->qmGrpID = retIt->qmGrp ;
790  data_ptr->homeIndx = homeCounter;
791 
792  // We re-use this varaible to indicate this is an MM1 atom.
793  data_ptr->vdwType = -1;
794 
795  ++data_ptr;
796 
797  }
798 
799  }
800 
801  homeCounter++;
802 
803  }
804 
805  }
806 
807  if (noPC) {
808  for (auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
809  CompAtom *x = (*pdIt).compAtomP;
810  (*pdIt).posBoxP->close(&x);
811  }
812  }
813 
814  QMProxy[0].recvPartQM(msg);
815 
816 }
int timestep
Definition: ComputeQM.C:108
int size(void) const
Definition: ResizeArray.h:131
ComputeHomePatchList patchList
float charge
Definition: ComputeQM.C:68
float Real
Definition: common.h:118
#define DebugM(x, y)
Definition: Debug.h:75
ComputeQMAtom * coord
Definition: ComputeQM.C:111
uint32 id
Definition: NamdTypes.h:156
Position position
Definition: ComputeQM.C:67
int16 vdwType
Definition: NamdTypes.h:79
int sourceNode
Definition: ComputeQM.C:106
Real qmGrpID
Definition: ComputeQM.C:70
Elem * find(const Elem &elem)
Definition: SortedArray.h:94
int numAtoms
Definition: ComputeQM.C:107

◆ initialize()

void ComputeQM::initialize ( void  )
virtual

Reimplemented from ComputeHomePatches.

Definition at line 616 of file ComputeQM.C.

References SortedArray< Elem >::add(), ResizeArray< Elem >::add(), SimParameters::cutoff, Molecule::get_noPC(), Molecule::get_numQMAtoms(), Molecule::get_qmAtmChrg(), Molecule::get_qmAtmIndx(), Molecule::get_qmAtomGroup(), Molecule::get_qmCustomPCIdxs(), Molecule::get_qmCustPCSizes(), Molecule::get_qmGrpID(), Molecule::get_qmMeMMindx(), Molecule::get_qmMeNumBonds(), Molecule::get_qmMeQMGrp(), Molecule::get_qmNumGrps(), Molecule::get_qmTotCustPCs(), ComputeHomePatches::initialize(), Node::molecule, Node::Object(), SimParameters::qmCustomPCSel, ResizeArray< Elem >::resize(), and Node::simParameters.

617 {
619 
620  // Get some pointers that will be used in the future,
622  molPtr = Node::Object()->molecule;
623  // Future comes fast...
624  qmAtomGroup = molPtr->get_qmAtomGroup() ;
625 
626  noPC = molPtr->get_noPC();
627  if (noPC) {
628  meNumMMIndx = molPtr->get_qmMeNumBonds();
629  meMMindx = molPtr->get_qmMeMMindx();
630  meQMGrp =molPtr->get_qmMeQMGrp();
631 
632  for (int i=0; i<meNumMMIndx; i++)
633  meQMBonds.add(meMMQMGrp(meMMindx[i], meQMGrp[i]));
634  }
635 
636  numQMAtms = molPtr->get_numQMAtoms();
637  qmAtmChrg = molPtr->get_qmAtmChrg() ;
638  qmAtmIndx = molPtr->get_qmAtmIndx() ;
639 
640  numQMGrps = molPtr->get_qmNumGrps();
641  qmGrpIDArray = molPtr->get_qmGrpID() ;
642 
643  cutoff = simParams->cutoff;
644 
645  customPC = simParams->qmCustomPCSel;
646  if (customPC) {
647 
648  customPCLists.resize(numQMGrps);
649 
650  int totCustPCs = molPtr->get_qmTotCustPCs();
651  const int *custPCSizes = molPtr->get_qmCustPCSizes();
652  const int *customPCIdxs = molPtr->get_qmCustomPCIdxs();
653 
654  int minI = 0, maxI = 0, grpIter = 0;
655 
656  while (grpIter < numQMGrps) {
657 
658  maxI += custPCSizes[grpIter];
659 
660  for (size_t i=minI; i < maxI; i++) {
661 
662  customPCLists[grpIter].add( customPCIdxs[i] ) ;
663  }
664 
665  // Minimum index gets the size of the current group
666  minI += custPCSizes[grpIter];
667  // Group iterator gets incremented
668  grpIter++;
669 
670  }
671  }
672 
673 }
static Node * Object()
Definition: Node.h:86
Bool get_noPC()
Definition: Molecule.h:903
const int * get_qmAtmIndx()
Definition: Molecule.h:857
SimParameters * simParameters
Definition: Node.h:181
int get_numQMAtoms()
Definition: Molecule.h:859
int add(const Elem &elem)
Definition: ResizeArray.h:101
int get_qmTotCustPCs()
Definition: Molecule.h:910
void resize(int i)
Definition: ResizeArray.h:84
Real * get_qmMeQMGrp()
Definition: Molecule.h:906
int get_qmMeNumBonds()
Definition: Molecule.h:904
int add(const Elem &elem)
Definition: SortedArray.h:55
Real * get_qmGrpID()
Definition: Molecule.h:863
int * get_qmMeMMindx()
Definition: Molecule.h:905
Real * get_qmAtmChrg()
Definition: Molecule.h:856
const Real * get_qmAtomGroup() const
Definition: Molecule.h:853
int * get_qmCustPCSizes()
Definition: Molecule.h:911
#define simParams
Definition: Output.C:129
virtual void initialize()
int * get_qmCustomPCIdxs()
Definition: Molecule.h:912
int get_qmNumGrps() const
Definition: Molecule.h:861
Molecule * molecule
Definition: Node.h:179

◆ processFullQM()

void ComputeQM::processFullQM ( QMCoordMsg qmFullMsg)

Definition at line 1293 of file ComputeQM.C.

References ResizeArray< Elem >::add(), CompAtom::charge, ResizeArray< Elem >::clear(), QMCoordMsg::coord, DebugM, Lattice::delta(), SortedArray< Elem >::find(), CompAtomExt::id, Vector::length(), SortedArray< Elem >::load(), FullAtom::mass, QMCoordMsg::numAtoms, QMCoordMsg::numPCIndxs, ComputeHomePatches::patchList, QMCoordMsg::pcIndxs, PCMODECUSTOMSEL, PCMODEUPDATEPOS, PCMODEUPDATESEL, QMCoordMsg::pcSelMode, ComputeQMAtom::position, ComputeQMAtom::qmGrpID, ResizeArray< Elem >::size(), SortedArray< Elem >::sort(), QMCoordMsg::sourceNode, QMPntChrgMsg::sourceNode, and CompAtom::vdwType.

Referenced by ComputeQMMgr::recvFullQM().

1293  {
1294 
1296 
1297  const Lattice & lattice = patchList[0].p->lattice;
1298 
1299  // Dynamically accumulates point charges as they are found.
1300  // The same MM atom may be added to this vector more than once if it is
1301  // within the cutoff region of two or more QM regions.
1302  ResizeArray<ComputeQMPntChrg> compPCVec ;
1303 
1304  // This will keep the set of QM groups with which each
1305  // point charge should be used. It is re-used for each atom in this
1306  // patch so we can controll the creation of the compPCVec vector.
1307  // The first item in the pair is the QM Group ID, the second is a pair
1308  // with the point charge position (after PBC wraping) and the shortest
1309  // distance between the point charge and an atom of this QM group.
1310  GrpDistMap chrgGrpMap ;
1311 
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);
1315 
1316  // If this is the firts step after a step of PC re-selection,
1317  // we store all PC IDs that all PEs found, in case some atoms end up
1318  // here untill the next re-selection step.
1319  if (qmFullMsg->numPCIndxs) {
1320 
1321  pcIDSortList.clear();
1322 
1323  int *pcIndx = qmFullMsg->pcIndxs;
1324  for (int i=0; i< qmFullMsg->numPCIndxs;i++) {
1325  pcIDSortList.load(pcIndx[i]);
1326  }
1327 
1328  pcIDSortList.sort();
1329  }
1330 
1331  int totalNodeAtoms = 0;
1332  int atomIter = 0;
1333  int uniqueCounter = 0;
1334 
1335  const ComputeQMAtom *qmDataPtn = qmFullMsg->coord;
1336 
1337  switch ( qmFullMsg->pcSelMode ) {
1338 
1339  case PCMODEUPDATESEL:
1340  {
1341 
1342  DebugM(4,"Updating PC selection.\n")
1343 
1344  // Loops over all atoms in this node and checks if any MM atom is within
1345  // the cutof radius from a QM atom
1346  for (auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
1347 
1348  CompAtom *x = (*pdIt).compAtomP;
1349  const CompAtomExt *xExt = (*pdIt).homePatchP->getCompAtomExtInfo();
1350  int localNumAtoms = (*pdIt).homePatchP->getNumAtoms();
1351  const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
1352 
1353  totalNodeAtoms += localNumAtoms;
1354 
1355  // Iterates over the local atoms in a PE, all patches.
1356  for(int i=0; i<localNumAtoms; ++i) {
1357 
1358  // A new subset for each atom in this node.
1359  chrgGrpMap.clear();
1360 
1361  Real pcGrpID = qmAtomGroup[xExt[i].id];
1362 
1363  Real charge = x[i].charge;
1364 
1365  // If the atom is a QM atom, there will be no charge info in the
1366  // atom box. Therefore, we take the charge in the previous step
1367  // in case this atom is a point charge for a neighboring QM region.
1368  if (pcGrpID > 0) {
1369  for (int qi=0; qi<numQMAtms; qi++) {
1370  if (qmAtmIndx[qi] == xExt[i].id) {
1371  charge = qmAtmChrg[qi];
1372  break;
1373  }
1374  }
1375  }
1376 
1377  qmDataPtn = qmFullMsg->coord;
1378  for(int j=0; j<qmFullMsg->numAtoms; j++, ++qmDataPtn) {
1379 
1380  Real qmGrpID = qmDataPtn->qmGrpID;
1381 
1382  // We check If a QM atom and the node atom "i"
1383  // belong to the same QM group. If not, atom "i" is either an MM
1384  // atom or a QM atom from another group, which will be seen
1385  // as an MM point charge.
1386  // If they belong to the same group, just skip the distance
1387  // calculation and move on to the next QM atom.
1388  // This loop needs to go over all QM atoms since a point charge
1389  // may me be close to two different QM groups, in which case it
1390  // will be sent to both.
1391  if (qmGrpID == pcGrpID) {
1392  continue;
1393  }
1394 
1395  // calculate distance between QM atom and Poitn Charge
1396  Vector r12 = lattice.delta(x[i].position,qmDataPtn->position);
1397 
1398  BigReal dist = r12.length(); // Distance between atoms
1399 
1400  if ( dist < cutoff ){
1401 
1402  // Since the QM region may have been wrapped around the periodic box, we
1403  // reposition point charges with respect to unwrapped coordinates of QM atoms,
1404  // finding the shortest distance between the point charge and the QM region.
1405 
1406  Position posMM = qmDataPtn->position + r12;
1407  auto ret = chrgGrpMap.find(qmGrpID) ;
1408 
1409  // If 'ret' points to end, it means the item was not found
1410  // and will be added, which means a new QM region has this
1411  // atom within its cutoff region,
1412  // which means a new point charge will be
1413  // created in the QM system in question.
1414  // 'ret' means a lot to me!
1415  if ( ret == chrgGrpMap.end()) {
1416  chrgGrpMap.insert(std::pair<Real,PosDistPair>(qmGrpID,
1417  PosDistPair(posMM,dist) ) );
1418  }
1419  else {
1420  // If the current distance is smaller than the one in
1421  // the map, we update it so that we have the smallest
1422  // distance between the point charge and any QM atom in
1423  // this group.
1424  if (dist < ret->second.second) {
1425  ret->second.first = posMM ;
1426  ret->second.second = dist ;
1427  }
1428  }
1429  }
1430  }
1431 
1432  for(auto mapIt = chrgGrpMap.begin();
1433  mapIt != chrgGrpMap.end(); mapIt++) {
1434 
1435  // We now add the final info about this point charge
1436  // to the vector, repeating it for each QM group that has it
1437  // within its cuttoff radius.
1438  compPCVec.add(
1439  ComputeQMPntChrg(mapIt->second.first, charge, xExt[i].id,
1440  mapIt->first, atomIter, mapIt->second.second,
1441  fullAtms[i].mass, fullAtms[i].vdwType)
1442  );
1443  }
1444 
1445  // Counts how many atoms are seens as point charges, by one or more
1446  // QM groups.
1447  if (chrgGrpMap.size() > 0)
1448  uniqueCounter++;
1449 
1450  atomIter++;
1451  }
1452 
1453  (*pdIt).posBoxP->close(&x);
1454  }
1455 
1456  }break; // End case PCMODEUPDATESEL
1457 
1458  case PCMODEUPDATEPOS:
1459  {
1460 
1461  DebugM(4,"Updating PC positions ONLY.\n")
1462 
1463  for (auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
1464 
1465  CompAtom *x = (*pdIt).compAtomP;
1466  const CompAtomExt *xExt = (*pdIt).homePatchP->getCompAtomExtInfo();
1467  int localNumAtoms = (*pdIt).homePatchP->getNumAtoms();
1468  const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
1469 
1470  totalNodeAtoms += localNumAtoms;
1471 
1472  // Iterates over the local atoms in a PE, all patches.
1473  for(int i=0; i<localNumAtoms; ++i) {
1474 
1475  if (pcIDSortList.find(xExt[i].id) != NULL ) {
1476 
1477  BigReal dist = 0;
1478  Position posMM = 0; // Temporary point charge position for QM calculation.
1479 
1480  bool firstIngroupQM = true;
1481  qmDataPtn = qmFullMsg->coord;
1482  for(int j=0; j<qmFullMsg->numAtoms; j++, ++qmDataPtn) {
1483 
1484  // Assuming we only have one QM region for now
1485  // This optio will be deprecated
1486 
1487  // Only verify distances to atoms in the QM group for which we are
1488  // gathering point charges.
1489 // if ( qmDataPtn->qmGrpID != qmGrpIDArray[grpIndx] ) continue;
1490 
1491  // calculate distance between QM atom and Poitn Charge
1492  Vector r12 = lattice.delta(x[i].position,qmDataPtn->position);
1493 
1494  // We wait to find the first QM atom in the target QM group before we
1495  // set the first guess at a minimal distance and point charge position.
1496  if ( firstIngroupQM ) {
1497  dist = r12.length();
1498 
1499  // Reposition classical point charge with respect to unwrapped QM position.
1500  posMM = qmDataPtn->position + r12;
1501 
1502  firstIngroupQM = false;
1503  }
1504 
1505  // If we find a QM atom with a shorter dstance to the point charge,
1506  // set that as the PC distance and reposition the PC
1507  if ( r12.length() < dist ) {
1508  dist = r12.length();
1509  posMM = qmDataPtn->position + r12 ;
1510  }
1511 
1512  }
1513 
1514  Real pcGrpID = qmAtomGroup[xExt[i].id];
1515  Real charge = x[i].charge;
1516 
1517  // If the atom is a QM atom, there will be no charge info in the
1518  // atom box. Therefore, we take the charge in the previous step
1519  // in case this atom is a point charge for a neighboring QM region.
1520  if (pcGrpID > 0) {
1521  for (int qi=0; qi<numQMAtms; qi++) {
1522  if (qmAtmIndx[qi] == xExt[i].id) {
1523  charge = qmAtmChrg[qi];
1524  break;
1525  }
1526 
1527  }
1528  }
1529 
1530  compPCVec.add(
1531  ComputeQMPntChrg(posMM, charge, xExt[i].id,
1532  0, atomIter, 0,
1533  fullAtms[i].mass, fullAtms[i].vdwType));
1534  }
1535 
1536  atomIter++;
1537  }
1538 
1539  (*pdIt).posBoxP->close(&x);
1540  }
1541  }break ; // End case PCMODEUPDATEPOS
1542 
1543  case PCMODECUSTOMSEL:
1544  {
1545 
1546  DebugM(4,"Updating PC positions for custom PC selection.\n")
1547 
1548  for (auto pdIt = patchData.begin(); pdIt != patchData.end(); pdIt++ ) {
1549 
1550  CompAtom *x = (*pdIt).compAtomP;
1551  const CompAtomExt *xExt = (*pdIt).homePatchP->getCompAtomExtInfo();
1552  int localNumAtoms = (*pdIt).homePatchP->getNumAtoms();
1553  const FullAtom* fullAtms = (*pdIt).homePatchP->getAtomList().const_begin() ;
1554 
1555  totalNodeAtoms += localNumAtoms;
1556 
1557  // Iterates over the local atoms in a PE, all patches.
1558  for(int i=0; i<localNumAtoms; ++i) {
1559 
1560  // Checks if the atom ID belongs to a point charge list,
1561  // which indicates it is to be sent to rank zero for QM calculations.
1562  // With one list per QM group, the same point charge can be added to
1563  // different QM groups, as if it was being dynamically selected.
1564  for (int grpIndx=0; grpIndx<numQMGrps; grpIndx++) {
1565 
1566  if (customPCLists[grpIndx].find(xExt[i].id) != NULL){
1567 
1568  // Initialize the search for the smallest distance between
1569  // point charge and QM atoms. This will determine the closest position
1570  // of the point charge accounting for periodic boundary conditions.
1571 
1572  // Since the QM region may have been wrapped around the periodic box, we
1573  // reposition point charges with respect to unwrapped coordinates of QM atoms.
1574 
1575  BigReal dist = 0;
1576  Position posMM = 0; // Temporary point charge position for QM calculation.
1577 
1578  bool firstIngroupQM = true;
1579  qmDataPtn = qmFullMsg->coord;
1580  for(int j=0; j<qmFullMsg->numAtoms; j++, ++qmDataPtn) {
1581 
1582  // Only verify distances to atoms in the QM group for which we are
1583  // gathering point charges.
1584  if ( qmDataPtn->qmGrpID != qmGrpIDArray[grpIndx] ) continue;
1585 
1586  // calculate distance between QM atom and Poitn Charge
1587  Vector r12 = lattice.delta(x[i].position,qmDataPtn->position);
1588 
1589  // We wait to find the first QM atom in the target QM group before we
1590  // set the first guess at a minimal distance and point charge position.
1591  if ( firstIngroupQM ) {
1592  dist = r12.length();
1593 
1594  // Reposition classical point charge with respect to unwrapped QM position.
1595  posMM = qmDataPtn->position + r12;
1596 
1597  firstIngroupQM = false;
1598  }
1599 
1600  // If we find a QM atom with a shorter dstance to the point charge,
1601  // set that as the PC distance and reposition the PC
1602  if ( r12.length() < dist ) {
1603  dist = r12.length();
1604  posMM = qmDataPtn->position + r12 ;
1605  }
1606 
1607  }
1608 
1609  // After determining the position o fthe point charge, get its partial charge.
1610  Real pcGrpID = qmAtomGroup[xExt[i].id];
1611  Real charge = x[i].charge;
1612 
1613  // If the atom is a QM atom, there will be no charge info in the
1614  // atom box. Therefore, we take the charge in the previous step
1615  // in case this atom is a point charge for a neighboring QM region.
1616  if (pcGrpID > 0) {
1617  for (int qi=0; qi<numQMAtms; qi++) {
1618  if (qmAtmIndx[qi] == xExt[i].id) {
1619  charge = qmAtmChrg[qi];
1620  break;
1621  }
1622  }
1623  }
1624 
1625  compPCVec.add(
1626  ComputeQMPntChrg(posMM, charge, xExt[i].id,
1627  qmGrpIDArray[grpIndx], atomIter, dist,
1628  fullAtms[i].mass, fullAtms[i].vdwType));
1629  }
1630 
1631  }
1632 
1633  atomIter++;
1634  }
1635 
1636  (*pdIt).posBoxP->close(&x);
1637  }
1638 
1639  } break;
1640  }
1641 
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);
1645 
1646  // Send only the MM atoms within radius
1647 
1648  // this pointer should be freed in rank zero, after receiving it.
1649  QMPntChrgMsg *pntChrgMsg = new (compPCVec.size(), 0) QMPntChrgMsg;
1650  pntChrgMsg->sourceNode = CkMyPe();
1651  pntChrgMsg->numAtoms = compPCVec.size();
1652 
1653  for (int i=0; i<compPCVec.size(); i++ ) {
1654 
1655  // Only sends the positions and charges of atoms within
1656  // cutoff of a (any) QM atom. Repeats for the number of QM groups
1657  // this charge is near to, and indicates the QM group it should
1658  // be used with.
1659  pntChrgMsg->coord[i] = compPCVec[i] ;
1660 
1661  }
1662 
1663  DebugM(4,"Rank " << pntChrgMsg->sourceNode << " sending a total of "
1664  << compPCVec.size() << " elements to rank zero." << std::endl);
1665 
1666  CProxy_ComputeQMMgr QMProxy(CkpvAccess(BOCclass_group).computeQMMgr);
1667  QMProxy[0].recvPntChrg(pntChrgMsg);
1668 
1669  delete qmFullMsg;
1670 }
int size(void) const
Definition: ResizeArray.h:131
#define PCMODEUPDATEPOS
Definition: ComputeQM.C:101
std::pair< Position, BigReal > PosDistPair
Definition: ComputeQM.C:1291
int sourceNode
Definition: ComputeQM.C:170
Definition: Vector.h:72
void sort(void)
Definition: SortedArray.h:66
ComputeHomePatchList patchList
int * pcIndxs
Definition: ComputeQM.C:112
float Real
Definition: common.h:118
#define DebugM(x, y)
Definition: Debug.h:75
void clear()
Definition: ResizeArray.h:91
int add(const Elem &elem)
Definition: ResizeArray.h:101
ComputeQMAtom * coord
Definition: ComputeQM.C:111
uint32 id
Definition: NamdTypes.h:156
Charge charge
Definition: NamdTypes.h:78
#define PCMODEUPDATESEL
Definition: ComputeQM.C:100
Position position
Definition: ComputeQM.C:67
NAMD_HOST_DEVICE BigReal length(void) const
Definition: Vector.h:202
int sourceNode
Definition: ComputeQM.C:106
int load(const Elem &elem)
Definition: SortedArray.h:50
Real qmGrpID
Definition: ComputeQM.C:70
int pcSelMode
Definition: ComputeQM.C:110
Elem * find(const Elem &elem)
Definition: SortedArray.h:94
std::map< Real, std::pair< Position, BigReal > > GrpDistMap
Definition: ComputeQM.C:1290
int numAtoms
Definition: ComputeQM.C:107
#define PCMODECUSTOMSEL
Definition: ComputeQM.C:102
int numPCIndxs
Definition: ComputeQM.C:109
double BigReal
Definition: common.h:123
NAMD_HOST_DEVICE Vector delta(const Position &pos1, const Position &pos2) const
Definition: Lattice.h:149
for(int i=0;i< n1;++i)

◆ saveResults()

void ComputeQM::saveResults ( QMForceMsg fmsg)

Definition at line 2674 of file ComputeQM.C.

References ResizeArrayIter< T >::begin(), QMForce::charge, DebugM, ResizeArrayIter< T >::end(), QMForceMsg::energy, Results::f, QMForce::force, QMForceMsg::force, ExtForce::force, Molecule::get_numQMAtoms(), Molecule::get_qmAtmChrg(), Molecule::get_qmAtmIndx(), Molecule::get_qmAtomGroup(), Molecule::get_qmNumGrps(), getComputes(), QMForce::homeIndx, QMForce::id, SubmitReduction::item(), Node::molecule, Results::normal, QMForceMsg::numForces, Node::Object(), ComputeHomePatches::patchList, QMForceMsg::PMEOn, REDUCTION_MISC_ENERGY, QMForce::replace, ExtForce::replace, ResizeArray< Elem >::size(), SubmitReduction::submit(), and QMForceMsg::virial.

Referenced by ComputeQMMgr::recvForce().

2674  {
2675 
2677 
2678  bool callReplaceForces = false;
2679 
2680  int numQMAtms = Node::Object()->molecule->get_numQMAtoms();
2681  int numQMGrps = Node::Object()->molecule->get_qmNumGrps();
2682  const Real * const qmAtomGroup = Node::Object()->molecule->get_qmAtomGroup() ;
2683  const int *qmAtmIndx = Node::Object()->molecule->get_qmAtmIndx() ;
2684  Real *qmAtmChrg = Node::Object()->molecule->get_qmAtmChrg() ;
2685 
2686  int totalNumbAtoms = 0;
2687  for (ap = ap.begin(); ap != ap.end(); ap++) {
2688  totalNumbAtoms += (*ap).p->getNumAtoms();
2689  }
2690 
2691  // This is kept to be deleted in the next step so that the message can be
2692  // used in "replaceForces" routine later on, in case there are forces to
2693  // be replaced. The "replaceForces" function uses but DOES NOT free the pointer,
2694  // so we free the data from the previous iteration and allocate a new one for
2695  // the current iteration (remember that the number of atoms can change in a
2696  // home patch between iterations).
2697  if (oldForces != 0)
2698  delete [] oldForces;
2699  oldForces = new ExtForce[totalNumbAtoms] ;
2700 
2701  for (int i=0; i < totalNumbAtoms; ++i) {
2702  oldForces[i].force = Force(0) ;
2703  }
2704 
2705  DebugM(1,"Force array has been created and zeroed in rank "
2706  << CkMyPe() << std::endl);
2707 
2708  DebugM(1,"Preparing " << fmsg->numForces << " forces in rank "
2709  << CkMyPe() << std::endl);
2710 
2711  QMForce *results_ptr = fmsg->force;
2712  // Iterates over the received forces and place them on the full array.
2713  for (int i=0; i < fmsg->numForces; ++i, ++results_ptr) {
2714  // For now we may have more than one item in the message acting on the same
2715  // atom, such as an MM atom which is a point charge for two or more QM regions.
2716 
2717  oldForces[results_ptr->homeIndx].force += results_ptr->force;
2718  oldForces[results_ptr->homeIndx].replace = results_ptr->replace;
2719 
2720  if (results_ptr->replace == 1)
2721  callReplaceForces = true;
2722 
2723  // If the atom is in a QM group, update its charge to the local (this homePatch)
2724  // copy of the qmAtmChrg array.
2725  if (qmAtomGroup[results_ptr->id] > 0 && (fmsg->PMEOn || (numQMGrps > 1) ) ) {
2726 
2727  // Loops over all QM atoms (in all QM groups) comparing their global indices
2728  for (int qmIter=0; qmIter<numQMAtms; qmIter++) {
2729 
2730  if (qmAtmIndx[qmIter] == results_ptr->id) {
2731  qmAtmChrg[qmIter] = results_ptr->charge;
2732  break;
2733  }
2734 
2735  }
2736 
2737  }
2738 
2739  }
2740 
2741  DebugM(1,"Placing forces on force boxes in rank "
2742  << CkMyPe() << std::endl);
2743 
2744  // Places the received forces on the force array for each patch.
2745  int homeIndxIter = 0;
2746  for (ap = ap.begin(); ap != ap.end(); ap++) {
2747  Results *r = (*ap).forceBox->open();
2748  Force *f = r->f[Results::normal];
2749  const CompAtomExt *xExt = (*ap).p->getCompAtomExtInfo();
2750  int localNumAtoms = (*ap).p->getNumAtoms();
2751 
2752  for(int i=0; i<localNumAtoms; ++i) {
2753 
2754  f[i] += oldForces[homeIndxIter].force;
2755 
2756  ++homeIndxIter;
2757  }
2758 
2759  if ( callReplaceForces )
2760  (*ap).p->replaceForces(oldForces);
2761 
2762  (*ap).forceBox->close(&r);
2763 
2764  }
2765 
2766  DebugM(1,"Forces placed on force boxes in rank "
2767  << CkMyPe() << std::endl);
2768 
2769  if (fmsg->PMEOn) {
2770 
2771  DebugM(1,"PME ON! Accessing PMEmgr in rank " << CkMyPe() << std::endl);
2772 
2773  ComputePmeMgr *mgrP = CProxy_ComputePmeMgr::ckLocalBranch(
2774  CkpvAccess(BOCclass_group).computePmeMgr) ;
2775 
2776  DebugM(4, "Initiating ComputePme::doQMWork on rank " << CkMyPe() << " over "
2777  << getComputes(mgrP).size() << " pmeComputes." << std::endl) ;
2778 
2779  for ( int i=0; i< getComputes(mgrP).size(); ++i ) {
2780  // WorkDistrib::messageEnqueueWork(pmeComputes[i]);
2781  getComputes(mgrP)[i]->doQMWork();
2782  }
2783  }
2784 
2785  DebugM(1,"Submitting reduction in rank " << CkMyPe() << std::endl);
2786 
2787  reduction->item(REDUCTION_MISC_ENERGY) += fmsg->energy;
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];
2797  reduction->submit();
2798 
2799  delete fmsg ;
2800 }
static Node * Object()
Definition: Node.h:86
int replace
Definition: ComputeQM.h:102
int size(void) const
Definition: ResizeArray.h:131
BigReal energy
Definition: ComputeQM.C:188
const int * get_qmAtmIndx()
Definition: Molecule.h:857
Vector Force
Definition: NamdTypes.h:32
Definition: Vector.h:72
ComputeHomePatchList patchList
int get_numQMAtoms()
Definition: Molecule.h:859
int numForces
Definition: ComputeQM.C:190
float Real
Definition: common.h:118
BigReal & item(int i)
Definition: ReductionMgr.h:313
#define DebugM(x, y)
Definition: Debug.h:75
int id
Definition: ComputeQM.h:106
ResizeArray< ComputePme * > & getComputes(ComputePmeMgr *mgr)
Definition: ComputePme.C:613
int32 replace
Definition: NamdTypes.h:296
Force * f[maxNumForces]
Definition: PatchTypes.h:146
Real * get_qmAtmChrg()
Definition: Molecule.h:856
float charge
Definition: ComputeQM.h:105
QMForce * force
Definition: ComputeQM.C:192
const Real * get_qmAtomGroup() const
Definition: Molecule.h:853
Force force
Definition: NamdTypes.h:297
Force force
Definition: ComputeQM.h:103
BigReal virial[3][3]
Definition: ComputeQM.C:189
int homeIndx
Definition: ComputeQM.h:104
int get_qmNumGrps() const
Definition: Molecule.h:861
void submit(void)
Definition: ReductionMgr.h:324
Molecule * molecule
Definition: Node.h:179
bool PMEOn
Definition: ComputeQM.C:187

The documentation for this class was generated from the following files: