GlobalMasterServer.C

Go to the documentation of this file.
00001 
00007 /*
00008    Forwards atoms to master node for force evaluation.
00009 */
00010 
00011 #include "ComputeGlobalMsgs.h"
00012 #include "ComputeMgr.h"
00013 #include "NamdTypes.h"
00014 #include "InfoStream.h"
00015 #include "Node.h"
00016 #include "SimParameters.h"
00017 //#define DEBUGM
00018 #define MIN_DEBUG_LEVEL 1
00019 #include "Debug.h"
00020 #include <stdlib.h>
00021 #include <vector>
00022 #include <algorithm>
00023 
00024 using namespace std;
00025 struct position_index {
00026   int atomID;
00027   int index;
00028 };
00029 void GlobalMasterServer::addClient(GlobalMaster *newClient) {
00030   DebugM(3,"Adding client\n");
00031   clientList.add(newClient);
00032   newClient->setLattice(&lattice);
00033   DebugM(2,"Added.\n");
00034 }
00035 
00036 void GlobalMasterServer::recvData(ComputeGlobalDataMsg *msg) {
00037   DebugM(3,"Storing data (" << msg->aid.size() << " positions) on master\n");
00038 
00039   if ( msg->step != -1 ) step = msg->step;
00040 
00041   /* get the beginning and end of the lists */
00042   AtomIDList::iterator a_i = msg->aid.begin();
00043   AtomIDList::iterator a_e = msg->aid.end();
00044   PositionList::iterator p_i = msg->p.begin();
00045   PositionList::iterator g_i = msg->gcom.begin();
00046   PositionList::iterator g_e = msg->gcom.end();
00047   BigRealList::iterator gm_i = msg->gmass.begin();
00048 
00049   /* iterate over each member of the atom lists */
00050   for ( ; a_i != a_e; ++a_i, ++p_i ) {
00051     receivedAtomIDs.add(*a_i);
00052     receivedAtomPositions.add(*p_i);
00053   }
00054   
00055   /* iterate over each member of "total force" lists */
00056   a_e = msg->fid.end();
00057   ForceList::iterator f_i=msg->tf.begin();
00058   for (a_i=msg->fid.begin() ; a_i!=a_e; ++a_i,++f_i) {
00059     receivedForceIDs.add(*a_i);
00060     receivedTotalForces.add(*f_i);
00061   }
00062 
00063   /* iterate over each member of the group position list */
00064   int i=0;
00065   for ( ; g_i != g_e; ++g_i, ++gm_i ) {
00066     DebugM(1,"Received center of mass "<<*g_i<<"\n");
00067     if(i >= totalGroupsRequested) NAMD_bug("Received too many groups.");
00068     receivedGroupPositions[i] += (*g_i);
00069     receivedGroupMasses[i] += (*gm_i);
00070     i++;
00071   }
00072   if(i!=totalGroupsRequested) NAMD_bug("Received too few groups.");
00073 
00074   /* iterate over each member of group total force lists */
00075   int ntf = msg->gtf.size();
00076   if ( ntf && ntf != receivedGroupTotalForces.size() ) NAMD_bug("Received wrong number of group forces.");
00077   ForceList::iterator gf_i=msg->gtf.begin();
00078   ForceList::iterator gf_e=msg->gtf.end();
00079   for ( i=0 ; gf_i != gf_e; ++gf_i, ++i ) {
00080     receivedGroupTotalForces[i] += (*gf_i);
00081   }
00082 
00083   if ( msg->lat.size() ) {
00084     if ( latticeCount ) {
00085       NAMD_bug("GlobalMasterServer::recvData received lattice twice.");
00086     }
00087     lattice = msg->lat[0];
00088     latticeCount = 1;
00089   }
00090 
00091   recvCount += msg->count;
00092 
00093   /* done with the message, delete it */
00094   delete msg;
00095 
00096   /* check whether we've gotten all the expected messages */
00097   if(recvCount > numDataSenders + numForceSenders + 1) {
00098     NAMD_bug("GlobalMasterServer::recvData recvCount too high.");
00099   }
00100   if(recvCount == numDataSenders + numForceSenders + 1) {
00101     if ( ! latticeCount ) {
00102       NAMD_bug("GlobalMasterServer::recvData did not receive lattice.");
00103     }
00104 
00105     int oldTotalGroupsRequested = totalGroupsRequested;
00106 
00107     DebugM(3,"received messages from each of the ComputeGlobals\n");
00108     int resendCoordinates = callClients();
00109 
00110     /* now restart */
00111     step = -1;
00112     receivedAtomIDs.resize(0);
00113     receivedAtomPositions.resize(0);
00114     receivedGroupPositions.resize(totalGroupsRequested);
00115     receivedGroupPositions.setall(Vector(0,0,0));
00116     receivedGroupMasses.resize(totalGroupsRequested);
00117     receivedGroupMasses.setall(0);
00118     latticeCount = 0;
00119     recvCount = 0;
00120     if ( resendCoordinates ) {
00121       recvCount += numForceSenders;
00122     } else {
00123       receivedGroupTotalForces.resize(totalGroupsRequested);
00124       receivedGroupTotalForces.setall(0);
00125       receivedForceIDs.resize(0);
00126       receivedTotalForces.resize(0);
00127     }
00128   }
00129 }
00130 
00131 void GlobalMasterServer::resetAtomList(AtomIDList &atomsRequested) {
00132   atomsRequested.resize(0);
00133 
00134   /* iterate over all of the masters */
00135   GlobalMaster **m_i = clientList.begin();
00136   GlobalMaster **m_e = clientList.end();
00137   while(m_i != m_e) {
00138     /* add all of the atoms in this master */
00139     int i;
00140     for(i=0;i<(*m_i)->requestedAtoms().size();i++) {
00141       atomsRequested.add((*m_i)->requestedAtoms()[i]);
00142     }
00143 
00144     /* go to next master */
00145     m_i++;
00146   }
00147 
00148   /* remove duplicates */
00149   sort(atomsRequested.begin(), atomsRequested.end());
00150   AtomIDList::iterator it = unique(atomsRequested.begin(), atomsRequested.end());
00151   atomsRequested.resize( distance(atomsRequested.begin(), it) );
00152 }
00153 
00154 void GlobalMasterServer::resetGroupList(AtomIDList &groupsRequested,
00155                                         int *numGroups) {
00156   DebugM(3,"Rebuilding the group list\n");
00157   groupsRequested.resize(0);
00158   *numGroups = 0;
00159 
00160   /* iterate over all of the masters */
00161   GlobalMaster **m_i = clientList.begin();
00162   GlobalMaster **m_e = clientList.end();
00163   while(m_i != m_e) {
00164 
00165     /* add all of the groups requested by this master */
00166     int i;
00167     GlobalMaster *master = *m_i;
00168     for(i=0;i<master->requestedGroups().size();i++) {
00169       /* add all of the atoms in this group, then add a -1 */
00170       int j;
00171       const AtomIDList &atoms_in_group = master->requestedGroups()[i];
00172       (*numGroups) ++;
00173       DebugM(1,"adding group "<<*numGroups<<"\n");
00174       for(j=0;j<atoms_in_group.size();j++) {
00175         groupsRequested.add(atoms_in_group[j]); // add an atom
00176       }
00177       DebugM(1,"here\n");
00178       groupsRequested.add(-1); // add a -1 to separate the groups (yuck)
00179     }
00180 
00181     /* go to next master */
00182     m_i++;
00183   }
00184 }
00185 
00186 void GlobalMasterServer::resetForceList(AtomIDList &atomsForced,
00187                                         ForceList &forces,
00188                                         ForceList &groupForces) {
00189   DebugM(1,"Restting forces\n");
00190   atomsForced.resize(0);
00191   forces.resize(0);
00192   groupForces.resize(0);
00193   lastAtomsForced.resize(0);
00194   lastForces.resize(0);
00195 
00196   /* iterate over all of the masters */
00197   GlobalMaster **m_i = clientList.begin();
00198   GlobalMaster **m_e = clientList.end();
00199   while(m_i != m_e) {
00200     (*m_i)->check(); // just in case!
00201 
00202     /* add all of the atoms in this master */
00203     int i;
00204     DebugM(1,"Adding atom forces\n");
00205     for(i=0;i<(*m_i)->forcedAtoms().size();i++) {
00206       atomsForced.add((*m_i)->forcedAtoms()[i]);
00207       forces.add((*m_i)->appliedForces()[i]);
00208       lastAtomsForced.add((*m_i)->forcedAtoms()[i]);
00209       lastForces.add((*m_i)->appliedForces()[i]);
00210     }
00211 
00212     /* add all of the group forces for this master */
00213     DebugM(1,"Adding "<<(*m_i)->requestedGroups().size()<<" group forces\n");
00214     for(i=0;i<(*m_i)->groupForces().size();i++) {
00215       groupForces.add((*m_i)->groupForces()[i]);
00216     }
00217 
00218     /* go to next master */
00219     DebugM(1,"Next master...\n");
00220     m_i++;
00221   }
00222   DebugM(1,"Done restting forces\n");
00223 }
00224 
00225 struct atomID_less {
00226       bool operator ()(position_index const& a, position_index const& b) const {
00227         if (a.atomID < b.atomID) return true;
00228         if (a.atomID > b.atomID) return false;
00229 
00230         return false;
00231 }
00232 };
00233 
00234 int GlobalMasterServer::callClients() {
00235   DebugM(3,"Calling clients\n");
00236   bool forceSendActive = false;
00237   {
00238     GlobalMaster **m_i = clientList.begin();
00239     GlobalMaster **m_e = clientList.end();
00240     for ( ; m_i != m_e; ++m_i ) {
00241       if ( (*m_i)->changedAtoms() ) firstTime = 1;
00242       if ( (*m_i)->changedGroups() ) firstTime = 1;
00243       if ( (*m_i)->requestedTotalForces() ) forceSendActive = true;
00244       (*m_i)->clearChanged();
00245     }
00246   }
00247 
00248   if(firstTime) {
00249  
00250     /* the first time we just get the requested atom ids from the
00251        clients and send messages to the compute globals requesting
00252        those atoms, so they can have coordinates for the first time
00253        step. */
00254     DebugM(1,"first time.\n");
00255     ComputeGlobalResultsMsg *msg = new ComputeGlobalResultsMsg;
00256     resetAtomList(msg->newaid); // add any atom IDs made in constructors
00257     // resetForceList(msg->aid,msg->f,msg->gforce); // same for forces
00258     resetGroupList(msg->newgdef,&totalGroupsRequested);
00259     msg->resendCoordinates = 1;
00260     msg->reconfig = 1;
00261     msg->totalforces = forceSendActive;
00262     totalAtomsRequested = msg->newaid.size(); // record the atom total
00263 
00264     numDataSenders = totalAtomsRequested;
00265     AtomIDList::iterator g_i = msg->newgdef.begin();
00266     AtomIDList::iterator g_e = msg->newgdef.end();
00267     for ( ; g_i != g_e; ++g_i ) {
00268       if ( *g_i != -1 ) ++numDataSenders;
00269     }
00270 
00271     DebugM(3,"Sending configure ("<<totalAtomsRequested<<" atoms, "
00272            <<totalGroupsRequested<<" groups)\n");
00273     myComputeManager->sendComputeGlobalResults(msg);
00274 
00275     firstTime = 0;
00276     return 1;
00277   }
00278 
00279   /* check to make sure we've got everything */
00280   if(receivedAtomIDs.size() != totalAtomsRequested) {
00281     DebugM(3,"Requested " << totalAtomsRequested << " atoms.\n");
00282     NAMD_bug("Got the wrong number of atoms");
00283   }
00284   if(receivedGroupPositions.size() != totalGroupsRequested) {
00285     DebugM(3,"Requested " << totalGroupsRequested << " groups.\n");
00286     DebugM(3,"Got " << receivedGroupPositions.size() << " group positions.\n");
00287     NAMD_bug("Got the wrong number of groups");
00288   }
00289   if(receivedGroupMasses.size() != totalGroupsRequested) {
00290     DebugM(3,"Requested " << totalGroupsRequested << " groups.\n");
00291     DebugM(3,"Got " << receivedGroupMasses.size() << " group masses.\n");
00292     NAMD_bug("Got the wrong number of group masses");
00293   }
00294 
00295   /* get the beginning and end of the lists */
00296   AtomIDList::iterator a_i = receivedAtomIDs.begin();
00297   AtomIDList::iterator a_e = receivedAtomIDs.end();
00298   PositionList::iterator p_i = receivedAtomPositions.begin();
00299   PositionList::iterator g_i = receivedGroupPositions.begin();
00300   PositionList::iterator g_e = receivedGroupPositions.end();
00301   ForceList::iterator gtf_i = receivedGroupTotalForces.begin();
00302   ForceList::iterator gtf_e = receivedGroupTotalForces.end();
00303   AtomIDList::iterator forced_atoms_i = lastAtomsForced.begin();
00304   AtomIDList::iterator forced_atoms_e = lastAtomsForced.end();
00305   ForceList::iterator forces_i = lastForces.begin();
00306   GlobalMaster **m_i = clientList.begin();
00307   GlobalMaster **m_e = clientList.end();
00308     AtomIDList::iterator f_i = receivedForceIDs.begin();
00309     AtomIDList::iterator f_e = receivedForceIDs.end();
00310 
00311   /* renormalize group center of mass by group total mass */
00312   ResizeArray<BigReal>::iterator gm_i = receivedGroupMasses.begin();
00313   for ( ; g_i < g_e; ++g_i, ++gm_i ) { *g_i /= *gm_i; }
00314   g_i = receivedGroupPositions.begin();
00315   gm_i = receivedGroupMasses.begin();
00316 
00317   /* use these to check whether anything has changed for any master */
00318   bool requested_atoms_changed=false;
00319   bool requested_forces_changed=false;
00320   bool requested_groups_changed=false;
00321   forceSendActive = false;
00322   
00323   vector <position_index> positions;
00324   for (int j = 0; a_i != a_e; ++a_i, ++j) {
00325     position_index temp;
00326     temp.atomID = *a_i;
00327     temp.index = j;
00328     positions.push_back(temp); 
00329   }
00330   sort(positions.begin(), positions.end(), atomID_less());
00331 
00332   /* call each of the masters with the coordinates */
00333   while(m_i != m_e) {
00334     int num_atoms_requested, num_groups_requested;
00335     
00336     /* get the masters information */
00337     GlobalMaster *master = *m_i;
00338     num_atoms_requested = master->requestedAtoms().size();
00339     num_groups_requested = master->requestedGroups().size();
00340 
00341     AtomIDList   clientAtomIDs;
00342     PositionList clientAtomPositions;
00343     AtomIDList   clientReceivedForceIDs;
00344     ForceList    clientReceivedTotalForces;
00345 
00346     if (num_atoms_requested) {
00347       vector <int> rqAtoms;
00348       for (int i = 0; i < master->requestedAtoms().size(); i++){
00349         rqAtoms.push_back(master->requestedAtoms()[i]);
00350       }
00351       sort(rqAtoms.begin(), rqAtoms.end());
00352       int j = 0;
00353       for (int i = 0; i < positions.size(); i++){
00354         if (positions[i].atomID == rqAtoms[j]){
00355           clientAtomPositions.add(receivedAtomPositions[positions[i].index]);
00356           clientAtomIDs.add(rqAtoms[j]);
00357           --i;  // rqAtoms may contain repeats
00358           if ( ++j == num_atoms_requested ) break;
00359         }
00360       }
00361       if ( j != num_atoms_requested ) NAMD_bug(
00362         "GlobalMasterServer::callClients() did not find all requested atoms");
00363     }
00364 
00365     AtomIDList::iterator ma_i = clientAtomIDs.begin();
00366     AtomIDList::iterator ma_e = clientAtomIDs.end();
00367     PositionList::iterator mp_i = clientAtomPositions.begin();
00368     AtomIDList::iterator mf_i = clientReceivedForceIDs.begin();
00369     AtomIDList::iterator mf_e = clientReceivedForceIDs.end();
00370     ForceList::iterator mtf_i = clientReceivedTotalForces.begin();
00371 
00372     /* check to make sure we have some atoms left.  This must work for
00373      zero requested atoms, as well! */
00374    // if(a_i+num_atoms_requested > a_e)
00375    //   NAMD_bug("GlobalMasterServer ran out of atom IDs!");
00376 
00377     /* update this master */
00378     master->step = step;
00379     master->processData(ma_i,ma_e,
00380                         mp_i,g_i,g_i+num_groups_requested,
00381                         gm_i,gm_i+num_groups_requested,
00382                         gtf_i,gtf_i+(numForceSenders?master->old_num_groups_requested:0),
00383                         forced_atoms_i,forced_atoms_e,forces_i,
00384       receivedForceIDs.begin(),receivedForceIDs.end(),receivedTotalForces.begin());
00385 
00386     a_i = receivedAtomIDs.begin();
00387     p_i = receivedAtomPositions.begin();
00388 //}
00389 
00390     /* check to see if anything changed */
00391     if(master->changedAtoms()) {
00392       requested_atoms_changed = true;
00393     }
00394     if(master->changedForces()) {
00395       requested_forces_changed = true;
00396     }
00397     if(master->changedGroups()) {
00398       requested_groups_changed = true;
00399     }
00400     master->clearChanged();
00401     if(master->requestedTotalForces()) forceSendActive = true;
00402 
00403     /* go to next master */
00404     m_i++;
00405 
00406     g_i += num_groups_requested;
00407     gm_i += num_groups_requested;
00408     if ( numForceSenders ) gtf_i += master->old_num_groups_requested;
00409     master->old_num_groups_requested = master->requestedGroups().size();  // include changes
00410   } 
00411 
00412   if ( numForceSenders && gtf_i != gtf_e ) NAMD_bug("GlobalMasterServer::callClients bad group total force count");
00413 
00414   /* make a new message */
00415   ComputeGlobalResultsMsg *msg = new ComputeGlobalResultsMsg;
00416 
00417   /* build an atom list, if necessary */
00418   if(requested_atoms_changed || requested_groups_changed) {
00419     resetAtomList(msg->newaid); // add all of the atom IDs
00420     totalAtomsRequested = msg->newaid.size();
00421     msg->reconfig = 1; // request a reconfig
00422     resetGroupList(msg->newgdef,&totalGroupsRequested); // add all of the group IDs
00423     numDataSenders = totalAtomsRequested;
00424     AtomIDList::iterator g_i = msg->newgdef.begin();
00425     AtomIDList::iterator g_e = msg->newgdef.end();
00426     for ( ; g_i != g_e; ++g_i ) {
00427       if ( *g_i != -1 ) ++numDataSenders;
00428     }
00429   }
00430   msg->totalforces = forceSendActive;
00431   numForceSenders = (forceSendActive ? numDataSenders : 0);
00432   resetForceList(msg->aid,msg->f,msg->gforce); // could this be more efficient?
00433 
00434   /* get group acceleration by renormalizing group net force by group total mass */
00435   ForceList::iterator gf_i = msg->gforce.begin();
00436   ForceList::iterator gf_e = msg->gforce.end();
00437   gm_i = receivedGroupMasses.begin();
00438   for ( ; gf_i < gf_e; ++gf_i, ++gm_i ) { *gf_i /= *gm_i; }
00439   
00440   /* now send the results */
00441   DebugM(3,"Sending results ("<<totalAtomsRequested<<" atoms requested, "
00442          <<totalGroupsRequested<<" groups requested, "
00443          <<msg->f.size()<<" forces set)\n");
00444   myComputeManager->sendComputeGlobalResults(msg);
00445   DebugM(3,"Sent.\n");
00446   return 0;
00447 }
00448 
00449 GlobalMasterServer::GlobalMasterServer(ComputeMgr *m,
00450                                        int theNumDataSenders) {
00451   DebugM(3,"Constructing GlobalMasterServer\n");
00452   myComputeManager = m;
00453   numDataSenders = 0; // theNumDataSenders;
00454   numForceSenders = 0;
00455   latticeCount = 0;
00456   lattice = Node::Object()->simParameters->lattice;
00457   recvCount = 0; /* we haven't gotten any messages yet */
00458   firstTime = 1; /* XXX temporary */
00459   step = -1;
00460   totalAtomsRequested = 0;
00461   totalGroupsRequested = 0;
00462   forceSendEnabled = 0;
00463   if ( Node::Object()->simParameters->tclForcesOn ) forceSendEnabled = 1;
00464   if ( Node::Object()->simParameters->colvarsOn ) forceSendEnabled = 1;
00465   DebugM(3,"done constructing\n");
00466 }
00467 
00468 GlobalMasterServer::~GlobalMasterServer() {
00469   GlobalMaster *m_i = *clientList.begin();
00470   GlobalMaster *m_e = *clientList.end();
00471   
00472   /* delete each of the masters */
00473   while(m_i != m_e) {
00474     delete m_i;
00475     m_i++;
00476   }
00477 }
00478 
00479 
00480  

Generated on Mon Nov 20 01:17:12 2017 for NAMD by  doxygen 1.4.7