Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

ComputeGlobal.C

Go to the documentation of this file.
00001 
00007 /*
00008    Forwards atoms to master node for force evaluation.
00009 */
00010 
00011 #include "InfoStream.h"
00012 #include "Node.h"
00013 #include "PatchMap.h"
00014 #include "PatchMap.inl"
00015 #include "AtomMap.h"
00016 #include "ComputeGlobal.h"
00017 #include "ComputeGlobalMsgs.h"
00018 #include "PatchMgr.h"
00019 #include "Molecule.h"
00020 #include "ReductionMgr.h"
00021 #include "ComputeMgr.h"
00022 #include "ComputeMgr.decl.h"
00023 #include "SimParameters.h"
00024 #include <stdio.h>
00025 
00026 //#define DEBUGM
00027 #define MIN_DEBUG_LEVEL 1
00028 #include "Debug.h"
00029 
00030 // CLIENTS
00031 
00032 ComputeGlobal::ComputeGlobal(ComputeID c, ComputeMgr *m)
00033         : ComputeHomePatches(c)
00034 {
00035   DebugM(3,"Constructing client\n");
00036   aid.resize(0);
00037   gdef.resize(0);
00038   comm = m;
00039   firsttime = 1;
00040   int i, numAtoms=Node::Object()->molecule->numAtoms;
00041   isRequested = new int[numAtoms];
00042   for (i=0; i<numAtoms; ++i)
00043     isRequested[i] = 0;
00044   SimParameters *sp = Node::Object()->simParameters;
00045   dofull = (sp->fullDirectOn || sp->FMAOn || sp->PMEOn);
00046   fid = new AtomIDList;
00047   totalForce = new ForceList;
00048   reduction = ReductionMgr::Object()->willSubmit(REDUCTIONS_BASIC);
00049 }
00050 
00051 ComputeGlobal::~ComputeGlobal()
00052 {
00053   delete[] isRequested;
00054   delete fid;
00055   delete totalForce;
00056   delete reduction;
00057 }
00058 
00059 void ComputeGlobal::configure(AtomIDList newaid, AtomIDList newgdef) {
00060   DebugM(4,"Receiving configuration (" << newaid.size() <<
00061         " atoms and " << newgdef.size() << " atoms/groups) on client\n");
00062 
00063   AtomIDList::iterator a, a_e;
00064   
00065   for (a=aid.begin(),a_e=aid.end(); a!=a_e; ++a)
00066     isRequested[*a] = 0;
00067 
00068   // store data
00069   aid = newaid;
00070   gdef = newgdef;
00071   
00072   for (a=aid.begin(),a_e=aid.end(); a!=a_e; ++a)
00073     isRequested[*a] = 1;
00074 
00075   // calculate group masses
00076   Molecule *mol = Node::Object()->molecule;
00077   gmass.resize(0);
00078   AtomIDList::iterator g_i, g_e;
00079   g_i = gdef.begin(); g_e = gdef.end();
00080   for ( ; g_i != g_e; ++g_i ) {
00081     BigReal mass = 0;
00082     for ( ; *g_i != -1; ++g_i ) {
00083       mass += mol->atommass(*g_i);
00084     }
00085     gmass.add(mass);
00086   }
00087 }
00088 
00089 void ComputeGlobal::recvConfig(ComputeGlobalConfigMsg *msg) {
00090   DebugM(3,"Receiving configure on client\n");
00091   configure(msg->aid,msg->gdef);
00092   delete msg;
00093   sendData();
00094 }
00095 
00096 void ComputeGlobal::recvResults(ComputeGlobalResultsMsg *msg) {
00097   DebugM(3,"Receiving results (" << msg->aid.size() << " forces, "
00098          << msg->newgdef.size() << " new group atoms) on client\n");
00099 
00100   // set the forces only if we aren't going to resend the data
00101   int setForces = !msg->resendCoordinates;
00102 
00103   if(setForces) { // we are requested to 
00104     // Store forces to patches
00105     PatchMap *patchMap = PatchMap::Object();
00106     int numPatches = patchMap->numPatches();
00107     AtomMap *atomMap = AtomMap::Object();
00108     const Lattice & lattice = patchList[0].p->lattice;
00109     ResizeArrayIter<PatchElem> ap(patchList);
00110     Force **f = new Force*[numPatches];
00111     FullAtom **t = new FullAtom*[numPatches];
00112     for ( int i = 0; i < numPatches; ++i ) { f[i] = 0; t[i] = 0; }
00113     Force extForce = 0.;
00114     Tensor extVirial;
00115 
00116     for (ap = ap.begin(); ap != ap.end(); ap++) {
00117       (*ap).r = (*ap).forceBox->open();
00118       f[(*ap).patchID] = (*ap).r->f[Results::normal];
00119       t[(*ap).patchID] = (*ap).p->getAtomList().begin();
00120     }
00121 
00122     AtomIDList::iterator a = msg->aid.begin();
00123     AtomIDList::iterator a_e = msg->aid.end();
00124     ForceList::iterator f2 = msg->f.begin();
00125     for ( ; a != a_e; ++a, ++f2 ) {
00126       DebugM(1,"processing atom "<<(*a)<<", F="<<(*f2)<<"...\n");
00127       /* XXX if (*a) is out of bounds here we get a segfault */
00128       LocalID localID = atomMap->localID(*a);
00129       if ( localID.pid == notUsed || ! f[localID.pid] ) continue;
00130       Force f_atom = (*f2);
00131       f[localID.pid][localID.index] += f_atom;
00132       Position x_orig = t[localID.pid][localID.index].position;
00133       Transform trans = t[localID.pid][localID.index].transform;
00134       Position x_atom = lattice.reverse_transform(x_orig,trans);
00135       extForce += f_atom;
00136       extVirial += outer(f_atom,x_atom);
00137     }
00138     DebugM(1,"done with the loop\n");
00139 
00140   // calculate forces for atoms in groups
00141     Molecule *mol = Node::Object()->molecule;
00142     AtomIDList::iterator g_i, g_e;
00143     g_i = gdef.begin(); g_e = gdef.end();
00144     ResizeArray<BigReal>::iterator gm_i = gmass.begin();
00145     ForceList::iterator gf_i = msg->gforce.begin();
00146     //iout << iDEBUG << "recvResults\n" << endi;
00147     for ( ; g_i != g_e; ++g_i, ++gm_i, ++gf_i ) {
00148       //iout << iDEBUG << *gf_i << '\n' << endi;
00149       Vector accel = (*gf_i) / (*gm_i);
00150       for ( ; *g_i != -1; ++g_i ) {
00151         //iout << iDEBUG << *g_i << '\n' << endi;
00152         LocalID localID = atomMap->localID(*g_i);
00153         if ( localID.pid == notUsed || ! f[localID.pid] ) continue;
00154         Force f_atom = accel * mol->atommass(*g_i);
00155         f[localID.pid][localID.index] += f_atom;
00156         Position x_orig = t[localID.pid][localID.index].position;
00157         Transform trans = t[localID.pid][localID.index].transform;
00158         Position x_atom = lattice.reverse_transform(x_orig,trans);
00159         extForce += f_atom;
00160         extVirial += outer(f_atom,x_atom);
00161       }
00162     }
00163     DebugM(1,"done with the groups\n");
00164 
00165     for (ap = ap.begin(); ap != ap.end(); ap++) {
00166       (*ap).forceBox->close(&((*ap).r));
00167     }
00168 
00169     delete [] f;
00170     delete [] t;
00171 
00172     ADD_VECTOR_OBJECT(reduction,REDUCTION_EXT_FORCE_NORMAL,extForce);
00173     ADD_TENSOR_OBJECT(reduction,REDUCTION_VIRIAL_NORMAL,extVirial);
00174     reduction->submit();
00175   }
00176   // done setting the forces
00177 
00178   // Get reconfiguration if present
00179   if ( msg->reconfig ) configure(msg->newaid, msg->newgdef);
00180 
00181   // send another round of data if requested
00182 
00183   if(msg->resendCoordinates) {
00184     DebugM(3,"Sending requested data right away\n");
00185     sendData();
00186   }
00187 
00188   delete msg;
00189   DebugM(3,"Done processing results\n");
00190 }
00191 
00192 void ComputeGlobal::doWork()
00193 {
00194   DebugM(2,"doWork\n");
00195   if(!firsttime) sendData();
00196   else {
00197     ComputeGlobalDataMsg *msg = new ComputeGlobalDataMsg;
00198     comm->sendComputeGlobalData(msg);
00199     firsttime = 0;
00200   }
00201   DebugM(2,"done with doWork\n");
00202 }
00203 
00204 void ComputeGlobal::sendData()
00205 {
00206   DebugM(2,"sendData\n");
00207   // Get positions from patches
00208   PatchMap *patchMap = PatchMap::Object();
00209   int numPatches = patchMap->numPatches();
00210   AtomMap *atomMap = AtomMap::Object();
00211   const Lattice & lattice = patchList[0].p->lattice;
00212   ResizeArrayIter<PatchElem> ap(patchList);
00213   CompAtom **x = new CompAtom*[numPatches];
00214   FullAtom **t = new FullAtom*[numPatches];
00215   for ( int i = 0; i < numPatches; ++i ) { x[i] = 0; t[i] = 0; }
00216 
00217   int step = -1;
00218   for (ap = ap.begin(); ap != ap.end(); ap++) {
00219     x[(*ap).patchID] = (*ap).positionBox->open();
00220     t[(*ap).patchID] = (*ap).p->getAtomList().begin();
00221     step = (*ap).p->flags.step;
00222   }
00223 
00224   ComputeGlobalDataMsg *msg = new  ComputeGlobalDataMsg;
00225 
00226   msg->step = step;
00227 
00228   AtomIDList::iterator a = aid.begin();
00229   AtomIDList::iterator a_e = aid.end();
00230   for ( ; a != a_e; ++a ) {
00231     LocalID localID = atomMap->localID(*a);
00232     if ( localID.pid == notUsed || ! x[localID.pid] ) continue;
00233     msg->aid.add(*a);
00234     Position x_orig = x[localID.pid][localID.index].position;
00235     Transform trans = t[localID.pid][localID.index].transform;
00236     msg->p.add(lattice.reverse_transform(x_orig,trans));
00237   }
00238 
00239   // calculate group centers of mass
00240   Molecule *mol = Node::Object()->molecule;
00241   AtomIDList::iterator g_i, g_e;
00242   g_i = gdef.begin(); g_e = gdef.end();
00243   ResizeArray<BigReal>::iterator gm_i = gmass.begin();
00244   for ( ; g_i != g_e; ++g_i, ++gm_i ) {
00245     Vector com(0,0,0);
00246     for ( ; *g_i != -1; ++g_i ) {
00247       LocalID localID = atomMap->localID(*g_i);
00248       if ( localID.pid == notUsed || ! x[localID.pid] ) continue;
00249       Position x_orig = x[localID.pid][localID.index].position;
00250       Transform trans = t[localID.pid][localID.index].transform;
00251       com += lattice.reverse_transform(x_orig,trans) * mol->atommass(*g_i);
00252     }
00253     com /= *gm_i;
00254     DebugM(1,"Adding center of mass "<<com<<"\n");
00255     msg->gcom.add(com);
00256   }
00257 
00258   for (ap = ap.begin(); ap != ap.end(); ap++) {
00259     (*ap).positionBox->close(&(x[(*ap).patchID]));
00260   }
00261   
00262   msg->fid = *fid;
00263   msg->tf = *totalForce;
00264   delete fid;
00265   delete totalForce;
00266   fid = new AtomIDList;
00267   totalForce = new ForceList;
00268 
00269   delete [] x;
00270   delete [] t;
00271 
00272   DebugM(3,"Sending data (" << msg->aid.size() << " positions) on client\n");
00273   comm->sendComputeGlobalData(msg);
00274 }
00275 
00276 
00277 // This function is called by each HomePatch after force
00278 // evaluation. It stores the indices and forces of the requested
00279 // atoms here, to be sent to GlobalMasterServer during the next
00280 // time step. The total force is the sum of three components:
00281 // "normal", "nbond" and "slow", the latter two may be calculated
00282 // less frequently, so their most recent values are stored in
00283 // "f_saved" and used here. If we don't do full electrostatics,
00284 // there's no "slow" part.
00285 void ComputeGlobal::saveTotalForces(HomePatch *homePatch)
00286 {
00287   int fixedAtomsOn = Node::Object()->simParameters->fixedAtomsOn;
00288   int i, index, num=homePatch->numAtoms;
00289   FullAtomList atoms = homePatch->atom;
00290   ForceList f1=homePatch->f[Results::normal], f2=homePatch->f_saved[Results::nbond],
00291             f3=homePatch->f_saved[Results::slow];
00292   Force f_sum;
00293   
00294   for (i=0; i<num; ++i)
00295     if (isRequested[index=atoms[i].id])
00296     { f_sum = f1[i]+f2[i];
00297       if (dofull)
00298         f_sum += f3[i];
00299       if ( fixedAtomsOn && atoms[i].atomFixed ) f_sum = 0.;
00300       fid->add(index);
00301       totalForce->add(f_sum);
00302     }
00303 }

Generated on Mon Nov 23 04:59:19 2009 for NAMD by  doxygen 1.3.9.1