00001
00007 #include "InfoStream.h"
00008 #include "Node.h"
00009 #include "PatchMap.h"
00010 #include "PatchMap.inl"
00011 #include "AtomMap.h"
00012 #include "ComputeFullDirect.h"
00013 #include "ComputeNonbondedUtil.h"
00014 #include "PatchMgr.h"
00015 #include "Molecule.h"
00016 #include "ReductionMgr.h"
00017 #include "Communicate.h"
00018 #include "Lattice.h"
00019
00020 #define MIN_DEBUG_LEVEL 3
00021 #include "Debug.h"
00022
00023 ComputeFullDirect::ComputeFullDirect(ComputeID c) : ComputeHomePatches(c)
00024 {
00025 reduction = ReductionMgr::Object()->willSubmit(REDUCTIONS_BASIC);
00026 useAvgPositions = 1;
00027 }
00028
00029 ComputeFullDirect::~ComputeFullDirect()
00030 {
00031 delete reduction;
00032 }
00033
00034 BigReal calc_fulldirect(BigReal *data1, BigReal *results1, int n1,
00035 BigReal *data2, BigReal *results2, int n2,
00036 int selfmode, Lattice *lattice, Tensor &virial)
00037 {
00038 if ( lattice->a_p() || lattice->b_p() || lattice->c_p() ) {
00039 #define FULLDIRECT_PERIODIC
00040 #include "ComputeFullDirectBase.h"
00041 } else {
00042 #undef FULLDIRECT_PERIODIC
00043 #include "ComputeFullDirectBase.h"
00044 }
00045 }
00046
00047 void ComputeFullDirect::doWork()
00048 {
00049 int numLocalAtoms;
00050 BigReal *localData;
00051 BigReal *localResults;
00052 BigReal *newLocalResults;
00053 register BigReal *local_ptr;
00054 Lattice *lattice;
00055
00056 int numWorkingPes = (PatchMap::Object())->numNodesWithPatches();
00057
00058 ResizeArrayIter<PatchElem> ap(patchList);
00059
00060
00061 if ( ! patchList[0].p->flags.doFullElectrostatics )
00062 {
00063 for (ap = ap.begin(); ap != ap.end(); ap++) {
00064 CompAtom *x = (*ap).positionBox->open();
00065 Results *r = (*ap).forceBox->open();
00066 (*ap).positionBox->close(&x);
00067 (*ap).forceBox->close(&r);
00068 }
00069 reduction->submit();
00070 return;
00071 }
00072
00073
00074 numLocalAtoms = 0;
00075 for (ap = ap.begin(); ap != ap.end(); ap++) {
00076 numLocalAtoms += (*ap).p->getNumAtoms();
00077 }
00078
00079 localData = new BigReal[4*numLocalAtoms];
00080 localResults = new BigReal[3*numLocalAtoms];
00081 newLocalResults = new BigReal[3*numLocalAtoms];
00082
00083 lattice = &((*(ap.begin())).p->lattice);
00084
00085
00086 local_ptr = localData;
00087 for (ap = ap.begin(); ap != ap.end(); ap++) {
00088 CompAtom *x = (*ap).positionBox->open();
00089 if ( patchList[0].p->flags.doMolly ) {
00090 (*ap).positionBox->close(&x);
00091 x = (*ap).avgPositionBox->open();
00092 }
00093 int numAtoms = (*ap).p->getNumAtoms();
00094
00095 for(int i=0; i<numAtoms; ++i)
00096 {
00097 *(local_ptr++) = x[i].position.x;
00098 *(local_ptr++) = x[i].position.y;
00099 *(local_ptr++) = x[i].position.z;
00100 *(local_ptr++) = x[i].charge;
00101 }
00102
00103 if ( patchList[0].p->flags.doMolly ) { (*ap).avgPositionBox->close(&x); }
00104 else { (*ap).positionBox->close(&x); }
00105 }
00106
00107
00108 local_ptr = localResults;
00109 for(int j=0; j<numLocalAtoms; ++j)
00110 {
00111 *(local_ptr++) = 0.;
00112 *(local_ptr++) = 0.;
00113 *(local_ptr++) = 0.;
00114 }
00115
00116
00117 BigReal electEnergy = 0;
00118 Tensor virial;
00119
00120 #define PEMOD(N) (((N)+numWorkingPes)%numWorkingPes)
00121
00122 int numStages = numWorkingPes / 2 + 2;
00123 int lastStage = numStages - 2;
00124 int sendDataPE = PEMOD(CkMyPe()+1);
00125 int recvDataPE = PEMOD(CkMyPe()-1);
00126 int sendResultsPE = PEMOD(CkMyPe()-1);
00127 int recvResultsPE = PEMOD(CkMyPe()+1);
00128 int numRemoteAtoms = numLocalAtoms;
00129 int oldNumRemoteAtoms = 0;
00130 BigReal *remoteData = 0;
00131 BigReal *remoteResults = 0;
00132 register BigReal *remote_ptr;
00133 register BigReal *end_ptr;
00134
00135 MOStream *sendDataMsg=CkpvAccess(comm)->
00136 newOutputStream(sendDataPE, FULLTAG, BUFSIZE);
00137 MIStream *recvDataMsg=CkpvAccess(comm)->
00138 newInputStream(recvDataPE, FULLTAG);
00139
00140 for ( int stage = 0; stage < numStages; ++stage )
00141 {
00142
00143 if ( stage > 1 )
00144 {
00145 DebugM(4,"send remoteResults to sendResultsPE " << sendResultsPE << "\n");
00146 MOStream *msg=CkpvAccess(comm)->
00147 newOutputStream(sendResultsPE, FULLFORCETAG, BUFSIZE);
00148 msg->put(3*oldNumRemoteAtoms,remoteResults);
00149 delete [] remoteResults;
00150 msg->end();
00151 delete msg;
00152 sendResultsPE = PEMOD(sendResultsPE-1);
00153 }
00154
00155
00156 if ( stage < lastStage )
00157 {
00158 DebugM(4,"send remoteData to sendDataPE " << sendDataPE << "\n");
00159 sendDataMsg->put(numRemoteAtoms);
00160 sendDataMsg->put(4*numRemoteAtoms,(stage?remoteData:localData));
00161 sendDataMsg->end();
00162 }
00163
00164
00165 if ( stage > 0 && stage <= lastStage )
00166 {
00167 DebugM(4,"allocate new result storage\n");
00168 remoteResults = new BigReal[3*numRemoteAtoms];
00169 remote_ptr = remoteResults;
00170 end_ptr = remoteResults + 3*numRemoteAtoms;
00171 for ( ; remote_ptr != end_ptr; ++remote_ptr ) *remote_ptr = 0.;
00172 }
00173
00174
00175 if ( stage == 0 )
00176 {
00177 DebugM(4,"self interaction\n");
00178 electEnergy += calc_fulldirect(
00179 localData,localResults,numLocalAtoms,
00180 localData,localResults,numLocalAtoms,1,lattice,virial);
00181 }
00182 else if ( stage < lastStage ||
00183 ( stage == lastStage && ( numWorkingPes % 2 ) ) )
00184 {
00185 DebugM(4,"full other interaction\n");
00186 electEnergy += calc_fulldirect(
00187 localData,localResults,numLocalAtoms,
00188 remoteData,remoteResults,numRemoteAtoms,0,lattice,virial);
00189 }
00190 else if ( stage == lastStage )
00191 {
00192 DebugM(4,"half other interaction\n");
00193 if ( CkMyPe() < ( numWorkingPes / 2 ) )
00194 electEnergy += calc_fulldirect(
00195 localData,localResults,numLocalAtoms/2,
00196 remoteData,remoteResults,numRemoteAtoms,0,lattice,virial);
00197 else
00198 electEnergy += calc_fulldirect(
00199 localData,localResults,numLocalAtoms,
00200 remoteData + 4*(numRemoteAtoms/2),
00201 remoteResults + 3*(numRemoteAtoms/2),
00202 numRemoteAtoms - (numRemoteAtoms/2), 0,lattice,virial);
00203 }
00204
00205 delete [] remoteData; remoteData = 0;
00206 oldNumRemoteAtoms = numRemoteAtoms;
00207
00208
00209 if ( stage > 1 )
00210 {
00211 DebugM(4,"receive newLocalResults from recvResultsPE "
00212 << recvResultsPE << "\n");
00213 MIStream *msg=CkpvAccess(comm)->
00214 newInputStream(recvResultsPE, FULLFORCETAG);
00215 msg->get(3*numLocalAtoms,newLocalResults);
00216 delete msg;
00217 recvResultsPE = PEMOD(recvResultsPE+1);
00218 remote_ptr = newLocalResults;
00219 local_ptr = localResults;
00220 end_ptr = localResults + 3*numLocalAtoms;
00221 for ( ; local_ptr != end_ptr; ++local_ptr, ++remote_ptr )
00222 *local_ptr += *remote_ptr;
00223 }
00224
00225
00226 if ( stage < lastStage )
00227 {
00228 DebugM(4,"receive remoteData from recvDataPE "
00229 << recvDataPE << "\n");
00230 recvDataMsg->get(numRemoteAtoms);
00231 remoteData = new BigReal[4*numRemoteAtoms];
00232 recvDataMsg->get(4*numRemoteAtoms,remoteData);
00233 }
00234
00235 }
00236
00237 delete sendDataMsg;
00238 delete recvDataMsg;
00239
00240
00241 DebugM(4,"Full-electrostatics energy: " << electEnergy << "\n");
00242 reduction->item(REDUCTION_ELECT_ENERGY_SLOW) += electEnergy;
00243 reduction->item(REDUCTION_VIRIAL_SLOW_XX) += virial.xx;
00244 reduction->item(REDUCTION_VIRIAL_SLOW_XY) += virial.xy;
00245 reduction->item(REDUCTION_VIRIAL_SLOW_XZ) += virial.xz;
00246 reduction->item(REDUCTION_VIRIAL_SLOW_YX) += virial.yx;
00247 reduction->item(REDUCTION_VIRIAL_SLOW_YY) += virial.yy;
00248 reduction->item(REDUCTION_VIRIAL_SLOW_YZ) += virial.yz;
00249 reduction->item(REDUCTION_VIRIAL_SLOW_ZX) += virial.zx;
00250 reduction->item(REDUCTION_VIRIAL_SLOW_ZY) += virial.zy;
00251 reduction->item(REDUCTION_VIRIAL_SLOW_ZZ) += virial.zz;
00252 reduction->submit();
00253
00254
00255 local_ptr = localResults;
00256 for (ap = ap.begin(); ap != ap.end(); ap++) {
00257 Results *r = (*ap).forceBox->open();
00258 Force *f = r->f[Results::slow];
00259 int numAtoms = (*ap).p->getNumAtoms();
00260
00261 for(int i=0; i<numAtoms; ++i)
00262 {
00263 f[i].x += *(local_ptr++);
00264 f[i].y += *(local_ptr++);
00265 f[i].z += *(local_ptr++);
00266 }
00267
00268 (*ap).forceBox->close(&r);
00269 }
00270
00271
00272 delete [] localData;
00273 delete [] localResults;
00274 delete [] newLocalResults;
00275 }
00276