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->GBISserOn || sp->GBISOn || 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 #if 0
00090 void ComputeGlobal::recvConfig(ComputeGlobalConfigMsg *msg) {
00091   DebugM(3,"Receiving configure on client\n");
00092   configure(msg->aid,msg->gdef);
00093   delete msg;
00094   sendData();
00095 }
00096 #endif
00097 
00098 void ComputeGlobal::recvResults(ComputeGlobalResultsMsg *msg) {
00099   DebugM(3,"Receiving results (" << msg->aid.size() << " forces, "
00100          << msg->newgdef.size() << " new group atoms) on client\n");
00101 
00102   // set the forces only if we aren't going to resend the data
00103   int setForces = !msg->resendCoordinates;
00104 
00105   if(setForces) { // we are requested to 
00106     // Store forces to patches
00107     PatchMap *patchMap = PatchMap::Object();
00108     int numPatches = patchMap->numPatches();
00109     AtomMap *atomMap = AtomMap::Object();
00110     const Lattice & lattice = patchList[0].p->lattice;
00111     ResizeArrayIter<PatchElem> ap(patchList);
00112     Force **f = new Force*[numPatches];
00113     FullAtom **t = new FullAtom*[numPatches];
00114     for ( int i = 0; i < numPatches; ++i ) { f[i] = 0; t[i] = 0; }
00115     Force extForce = 0.;
00116     Tensor extVirial;
00117 
00118     for (ap = ap.begin(); ap != ap.end(); ap++) {
00119       (*ap).r = (*ap).forceBox->open();
00120       f[(*ap).patchID] = (*ap).r->f[Results::normal];
00121       t[(*ap).patchID] = (*ap).p->getAtomList().begin();
00122     }
00123 
00124     AtomIDList::iterator a = msg->aid.begin();
00125     AtomIDList::iterator a_e = msg->aid.end();
00126     ForceList::iterator f2 = msg->f.begin();
00127     for ( ; a != a_e; ++a, ++f2 ) {
00128       DebugM(1,"processing atom "<<(*a)<<", F="<<(*f2)<<"...\n");
00129       /* XXX if (*a) is out of bounds here we get a segfault */
00130       LocalID localID = atomMap->localID(*a);
00131       if ( localID.pid == notUsed || ! f[localID.pid] ) continue;
00132       Force f_atom = (*f2);
00133       f[localID.pid][localID.index] += f_atom;
00134       Position x_orig = t[localID.pid][localID.index].position;
00135       Transform trans = t[localID.pid][localID.index].transform;
00136       Position x_atom = lattice.reverse_transform(x_orig,trans);
00137       extForce += f_atom;
00138       extVirial += outer(f_atom,x_atom);
00139     }
00140     DebugM(1,"done with the loop\n");
00141 
00142   // calculate forces for atoms in groups
00143     Molecule *mol = Node::Object()->molecule;
00144     AtomIDList::iterator g_i, g_e;
00145     g_i = gdef.begin(); g_e = gdef.end();
00146     ResizeArray<BigReal>::iterator gm_i = gmass.begin();
00147     ForceList::iterator gf_i = msg->gforce.begin();
00148     //iout << iDEBUG << "recvResults\n" << endi;
00149     for ( ; g_i != g_e; ++g_i, ++gm_i, ++gf_i ) {
00150       //iout << iDEBUG << *gf_i << '\n' << endi;
00151       Vector accel = (*gf_i) / (*gm_i);
00152       for ( ; *g_i != -1; ++g_i ) {
00153         //iout << iDEBUG << *g_i << '\n' << endi;
00154         LocalID localID = atomMap->localID(*g_i);
00155         if ( localID.pid == notUsed || ! f[localID.pid] ) continue;
00156         Force f_atom = accel * mol->atommass(*g_i);
00157         f[localID.pid][localID.index] += f_atom;
00158         Position x_orig = t[localID.pid][localID.index].position;
00159         Transform trans = t[localID.pid][localID.index].transform;
00160         Position x_atom = lattice.reverse_transform(x_orig,trans);
00161         extForce += f_atom;
00162         extVirial += outer(f_atom,x_atom);
00163       }
00164     }
00165     DebugM(1,"done with the groups\n");
00166 
00167     for (ap = ap.begin(); ap != ap.end(); ap++) {
00168       (*ap).forceBox->close(&((*ap).r));
00169     }
00170 
00171     delete [] f;
00172     delete [] t;
00173 
00174     ADD_VECTOR_OBJECT(reduction,REDUCTION_EXT_FORCE_NORMAL,extForce);
00175     ADD_TENSOR_OBJECT(reduction,REDUCTION_VIRIAL_NORMAL,extVirial);
00176     reduction->submit();
00177   }
00178   // done setting the forces
00179 
00180   // Get reconfiguration if present
00181   if ( msg->reconfig ) configure(msg->newaid, msg->newgdef);
00182 
00183   // send another round of data if requested
00184 
00185   if(msg->resendCoordinates) {
00186     DebugM(3,"Sending requested data right away\n");
00187     sendData();
00188   }
00189 
00190   delete msg;
00191   DebugM(3,"Done processing results\n");
00192 }
00193 
00194 void ComputeGlobal::doWork()
00195 {
00196   DebugM(2,"doWork\n");
00197   if(!firsttime) sendData();
00198   else {
00199     ComputeGlobalDataMsg *msg = new ComputeGlobalDataMsg;
00200     comm->sendComputeGlobalData(msg);
00201     firsttime = 0;
00202   }
00203   DebugM(2,"done with doWork\n");
00204 }
00205 
00206 void ComputeGlobal::sendData()
00207 {
00208   DebugM(2,"sendData\n");
00209   // Get positions from patches
00210   PatchMap *patchMap = PatchMap::Object();
00211   int numPatches = patchMap->numPatches();
00212   AtomMap *atomMap = AtomMap::Object();
00213   const Lattice & lattice = patchList[0].p->lattice;
00214   ResizeArrayIter<PatchElem> ap(patchList);
00215   CompAtom **x = new CompAtom*[numPatches];
00216   FullAtom **t = new FullAtom*[numPatches];
00217   for ( int i = 0; i < numPatches; ++i ) { x[i] = 0; t[i] = 0; }
00218 
00219   int step = -1;
00220   for (ap = ap.begin(); ap != ap.end(); ap++) {
00221     x[(*ap).patchID] = (*ap).positionBox->open();
00222     t[(*ap).patchID] = (*ap).p->getAtomList().begin();
00223     step = (*ap).p->flags.step;
00224   }
00225 
00226   ComputeGlobalDataMsg *msg = new  ComputeGlobalDataMsg;
00227 
00228   msg->step = step;
00229 
00230   AtomIDList::iterator a = aid.begin();
00231   AtomIDList::iterator a_e = aid.end();
00232   for ( ; a != a_e; ++a ) {
00233     LocalID localID = atomMap->localID(*a);
00234     if ( localID.pid == notUsed || ! x[localID.pid] ) continue;
00235     msg->aid.add(*a);
00236     Position x_orig = x[localID.pid][localID.index].position;
00237     Transform trans = t[localID.pid][localID.index].transform;
00238     msg->p.add(lattice.reverse_transform(x_orig,trans));
00239   }
00240 
00241   // calculate group centers of mass
00242   Molecule *mol = Node::Object()->molecule;
00243   AtomIDList::iterator g_i, g_e;
00244   g_i = gdef.begin(); g_e = gdef.end();
00245   ResizeArray<BigReal>::iterator gm_i = gmass.begin();
00246   for ( ; g_i != g_e; ++g_i, ++gm_i ) {
00247     Vector com(0,0,0);
00248     for ( ; *g_i != -1; ++g_i ) {
00249       LocalID localID = atomMap->localID(*g_i);
00250       if ( localID.pid == notUsed || ! x[localID.pid] ) continue;
00251       Position x_orig = x[localID.pid][localID.index].position;
00252       Transform trans = t[localID.pid][localID.index].transform;
00253       com += lattice.reverse_transform(x_orig,trans) * mol->atommass(*g_i);
00254     }
00255     com /= *gm_i;
00256     DebugM(1,"Adding center of mass "<<com<<"\n");
00257     msg->gcom.add(com);
00258   }
00259 
00260   for (ap = ap.begin(); ap != ap.end(); ap++) {
00261     (*ap).positionBox->close(&(x[(*ap).patchID]));
00262   }
00263   
00264   msg->fid = *fid;
00265   msg->tf = *totalForce;
00266   delete fid;
00267   delete totalForce;
00268   fid = new AtomIDList;
00269   totalForce = new ForceList;
00270 
00271   delete [] x;
00272   delete [] t;
00273 
00274   DebugM(3,"Sending data (" << msg->aid.size() << " positions) on client\n");
00275   comm->sendComputeGlobalData(msg);
00276 }
00277 
00278 
00279 // This function is called by each HomePatch after force
00280 // evaluation. It stores the indices and forces of the requested
00281 // atoms here, to be sent to GlobalMasterServer during the next
00282 // time step. The total force is the sum of three components:
00283 // "normal", "nbond" and "slow", the latter two may be calculated
00284 // less frequently, so their most recent values are stored in
00285 // "f_saved" and used here. If we don't do full electrostatics,
00286 // there's no "slow" part.
00287 void ComputeGlobal::saveTotalForces(HomePatch *homePatch)
00288 {
00289   if ( Node::Object()->simParameters->accelMDOn && Node::Object()->simParameters->accelMDDebugOn && Node::Object()->simParameters->accelMDdihe ) {
00290     int i, index, num=homePatch->numAtoms;
00291     FullAtomList atoms = homePatch->atom;
00292     ForceList af=homePatch->f[Results::amdf];
00293 
00294     for (i=0; i<num; ++i)
00295       if (isRequested[index=atoms[i].id]) {
00296         fid->add(index);
00297         totalForce->add(af[i]);
00298       }
00299     return;
00300   }
00301 
00302   int fixedAtomsOn = Node::Object()->simParameters->fixedAtomsOn;
00303   int i, index, num=homePatch->numAtoms;
00304   FullAtomList atoms = homePatch->atom;
00305   ForceList f1=homePatch->f[Results::normal], f2=homePatch->f_saved[Results::nbond],
00306             f3=homePatch->f_saved[Results::slow];
00307   Force f_sum;
00308   
00309   for (i=0; i<num; ++i)
00310     if (isRequested[index=atoms[i].id])
00311     { f_sum = f1[i]+f2[i];
00312       if (dofull)
00313         f_sum += f3[i];
00314       if ( fixedAtomsOn && atoms[i].atomFixed ) f_sum = 0.;
00315       fid->add(index);
00316       totalForce->add(f_sum);
00317     }
00318 }

Generated on Fri May 25 04:07:14 2012 for NAMD by  doxygen 1.3.9.1