00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "Particle/ParticleBase.h"
00028 #include "Particle/ParticleLayout.h"
00029 #include "Particle/ParticleAttrib.h"
00030 #include "Message/Message.h"
00031 #include "Message/Communicate.h"
00032 #include "Utility/Inform.h"
00033 #include "Utility/PAssert.h"
00034 #include "Utility/IpplInfo.h"
00035 #include "Utility/IpplStats.h"
00036 #include "Profile/Profiler.h"
00037
00038 #ifdef IPPL_STDSTL
00039 #include <algorithm>
00040 using namespace std;
00041 #else
00042 #include <algo.h>
00043 #endif // IPPL_STDSTL
00044
00045
00047
00048
00049
00050
00051 template<class PLayout>
00052 void ParticleBase<PLayout>::initialize(PLayout *layout) {
00053 TAU_TYPE_STRING(taustr, CT(*this) + " void (" + CT(*layout) + ")");
00054 TAU_PROFILE("ParticleBase::initialize()", taustr, TAU_PARTICLE);
00055
00056
00057
00058 PAssert(Layout == 0);
00059 PAssert(layout != 0);
00060
00061
00062 Layout = layout;
00063 setup();
00064 }
00065
00066
00068
00069 template<class PLayout>
00070 void ParticleBase<PLayout>::setup() {
00071 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00072 TAU_PROFILE("ParticleBase::setup()", taustr, TAU_PARTICLE);
00073
00074 TotalNum = 0;
00075 LocalNum = 0;
00076 DestroyNum = 0;
00077 GhostNum = 0;
00078
00079
00080 NextID = Ippl::Comm->myNode() - Ippl::Comm->getNodes();
00081
00082
00083
00084 addAttribute(R);
00085 addAttribute(ID);
00086
00087
00088 INCIPPLSTAT(incParticleBases);
00089 }
00090
00091
00093
00094
00095 template<class PLayout>
00096 bool ParticleBase<PLayout>::singleInitNode() const {
00097 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00098 TAU_PROFILE("ParticleBase::singleInitNode()", taustr, TAU_PARTICLE);
00099
00100 return (Ippl::Comm->myNode() == 0);
00101 }
00102
00103
00105
00106
00107 template<class PLayout>
00108 unsigned ParticleBase<PLayout>::getNextID() {
00109 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00110 TAU_PROFILE("ParticleBase::getNextID()", taustr, TAU_PARTICLE);
00111
00112 return (NextID += Ippl::Comm->getNodes());
00113 }
00114
00116
00117 template <class PLayout>
00118 void ParticleBase<PLayout>::resetID(void) {
00119 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00120 TAU_PROFILE("ParticleBase::resetID()", taustr, TAU_PARTICLE);
00121
00122 unsigned int nodes = Ippl::getNodes();
00123 unsigned int myNode = Ippl::myNode();
00124 size_t localNum = this->getLocalNum();
00125 size_t ip;
00126 int master = 0;
00127 if (myNode == master) {
00128
00129 for (ip=0; ip<localNum; ++ip)
00130 this->ID[ip] = ip;
00131
00132 if (nodes == 1) return;
00133
00134
00135 size_t *lp;
00136 lp = new size_t[nodes];
00137 lp[0] = localNum;
00138
00139 int tag1 = Ippl::Comm->next_tag(P_RESET_ID_TAG,P_LAYOUT_CYCLE);
00140 Message* msg1;
00141 for (ip=1; ip<nodes; ++ip) {
00142 int rnode = COMM_ANY_NODE;
00143 msg1 = Ippl::Comm->receive_block(rnode,tag1);
00144 PAssert(msg1);
00145 msg1->get(lp[rnode]);
00146 delete msg1;
00147 }
00148
00149
00150 size_t current, sum = 0;
00151 for (ip=0; ip<nodes; ++ip) {
00152 current = lp[ip];
00153 lp[ip] = sum;
00154 sum += current;
00155 }
00156
00157 int tag2 = Ippl::Comm->next_tag(P_RESET_ID_TAG,P_LAYOUT_CYCLE);
00158 for (ip=1; ip<nodes; ++ip) {
00159 Message* msg2 = new Message;
00160 msg2->put(lp[ip]);
00161 bool success = Ippl::Comm->send(msg2,ip,tag2);
00162 PAssert(success);
00163 }
00164
00165 return;
00166 }
00167 else {
00168
00169 int tag1 = Ippl::Comm->next_tag(P_RESET_ID_TAG,P_LAYOUT_CYCLE);
00170 Message* msg1 = new Message;
00171 msg1->put(localNum);
00172 bool success = Ippl::Comm->send(msg1,master,tag1);
00173 PAssert(success);
00174
00175 size_t initialID;
00176 int tag2 = Ippl::Comm->next_tag(P_RESET_ID_TAG,P_LAYOUT_CYCLE);
00177 Message* msg2 = Ippl::Comm->receive_block(master,tag2);
00178 PAssert(msg2);
00179 msg2->get(initialID);
00180 delete msg2;
00181
00182 for (ip=0; ip<localNum; ++ip)
00183 this->ID[ip] = ip + initialID;
00184
00185 return;
00186 }
00187 }
00188
00189
00191
00192 template<class PLayout>
00193 size_t
00194 ParticleBase<PLayout>::putMessage(Message& msg, size_t M, size_t I) {
00195 TAU_PROFILE("ParticleBase::putMessage()",
00196 "unsigned (Message, unsigned, unsigned)", TAU_PARTICLE);
00197
00198
00199 PAssert(Layout != 0);
00200
00201
00202 msg.put(M);
00203
00204
00205 if (M > 0) {
00206
00207
00208 PAssert(I < R.size() && (I+M) <= R.size());
00209
00210 attrib_container_t::iterator abeg = AttribList.begin();
00211 attrib_container_t::iterator aend = AttribList.end();
00212 for ( ; abeg != aend; abeg++ )
00213 (*abeg)->putMessage(msg, M, I);
00214 }
00215
00216 return M;
00217 }
00218
00219
00221
00222 template<class PLayout>
00223 size_t
00224 ParticleBase<PLayout>::putMessage(Message& msg,
00225 const vector<size_t>& putList)
00226 {
00227 TAU_PROFILE("ParticleBase::putMessage()",
00228 "unsigned (Message, vector<unsigned>)", TAU_PARTICLE);
00229
00230
00231 PAssert(Layout != 0);
00232
00233 vector<size_t>::size_type M = putList.size();
00234 msg.put(M);
00235
00236
00237 if (M > 0) {
00238 attrib_container_t::iterator abeg = AttribList.begin();
00239 attrib_container_t::iterator aend = AttribList.end();
00240 for ( ; abeg != aend; ++abeg )
00241 (*abeg)->putMessage(msg, putList);
00242 }
00243
00244 return M;
00245 }
00246
00247
00249
00250 template<class PLayout>
00251 size_t ParticleBase<PLayout>::getMessage(Message& msg) {
00252 TAU_PROFILE("ParticleBase::getMessage()", "unsigned (Message)",
00253 TAU_PARTICLE);
00254
00255
00256 PAssert(Layout != 0);
00257
00258
00259 size_t numitems;
00260 msg.get(numitems);
00261
00262
00263 if (numitems > 0) {
00264 attrib_container_t::iterator abeg = AttribList.begin();
00265 attrib_container_t::iterator aend = AttribList.end();
00266 for ( ; abeg != aend; abeg++ )
00267 (*abeg)->getMessage(msg, numitems);
00268 }
00269
00270 return numitems;
00271 }
00272
00273
00275
00276
00277
00278 template<class PLayout>
00279 size_t ParticleBase<PLayout>::getMessageAndCreate(Message& msg) {
00280 TAU_PROFILE("ParticleBase::getMessageAndCreate()", "unsigned (Message)",
00281 TAU_PARTICLE);
00282
00283
00284 PAssert(Layout != 0);
00285
00286
00287 size_t numcreate = getMessage(msg);
00288 LocalNum += numcreate;
00289 ADDIPPLSTAT(incParticlesCreated,numcreate);
00290 return numcreate;
00291 }
00292
00293
00295
00296 template<class PLayout>
00297 void ParticleBase<PLayout>::create(size_t M) {
00298 TAU_PROFILE("ParticleBase::create()", "void (unsigned)", TAU_PARTICLE);
00299
00300
00301 PAssert(Layout != 0);
00302
00303
00304 attrib_container_t::iterator abeg = AttribList.begin();
00305 attrib_container_t::iterator aend = AttribList.end();
00306 for ( ; abeg != aend; abeg++ )
00307 (*abeg)->create(M);
00308
00309
00310 size_t i1 = LocalNum;
00311 size_t i2 = i1 + M;
00312 while (i1 < i2)
00313 ID[i1++] = getNextID();
00314
00315
00316 LocalNum += M;
00317 ADDIPPLSTAT(incParticlesCreated,M);
00318 }
00319
00320
00322
00323 template<class PLayout>
00324 void ParticleBase<PLayout>::globalCreate(size_t np) {
00325 TAU_PROFILE("ParticleBase::globalCreate()", "void (unsigned)", TAU_PARTICLE);
00326
00327
00328 PAssert(Layout != 0);
00329
00330
00331 unsigned nPE = IpplInfo::getNodes();
00332 unsigned npLocal = np/nPE;
00333
00334
00335 unsigned myPE = IpplInfo::myNode();
00336 unsigned rem = np - npLocal * nPE;
00337 if (myPE < rem) ++npLocal;
00338
00339
00340
00341 create(npLocal);
00342 }
00343
00344
00346
00347
00348
00349 template<class PLayout>
00350 void ParticleBase<PLayout>::destroy(size_t M, size_t I, bool doNow) {
00351 TAU_PROFILE("ParticleBase::destroy()",
00352 "void (unsigned, unsigned, bool)", TAU_PARTICLE);
00353
00354
00355 PAssert(Layout != 0);
00356
00357 if (M > 0) {
00358 if (doNow) {
00359
00360 bool optDestroy = getUpdateFlag(PLayout::OPTDESTROY);
00361
00362 attrib_container_t::iterator abeg, aend = AttribList.end();
00363 for (abeg = AttribList.begin(); abeg != aend; ++abeg)
00364 (*abeg)->destroy(M,I,optDestroy);
00365 LocalNum -= M;
00366 }
00367 else {
00368
00369 pair<size_t,size_t> destroyEvent(I,M);
00370 DestroyList.push_back(destroyEvent);
00371 DestroyNum += M;
00372 }
00373
00374
00375 ADDIPPLSTAT(incParticlesDestroyed,M);
00376 }
00377 }
00378
00379
00381
00382
00383 template<class PLayout>
00384 void ParticleBase<PLayout>::update() {
00385 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00386 TAU_PROFILE("ParticleBase::update()", taustr, TAU_PARTICLE);
00387
00388
00389 PAssert(Layout != 0);
00390
00391
00392 Layout->update(*this);
00393 INCIPPLSTAT(incParticleUpdates);
00394 }
00395
00396
00398
00399
00400 template<class PLayout>
00401 void ParticleBase<PLayout>::update(const ParticleAttrib<char>& canSwap) {
00402 TAU_TYPE_STRING(taustr, CT(*this) + " void (ParticleAttrib<char>)");
00403 TAU_PROFILE("ParticleBase::update()", taustr, TAU_PARTICLE);
00404
00405
00406 PAssert(Layout != 0);
00407
00408
00409 Layout->update(*this, &canSwap);
00410 INCIPPLSTAT(incParticleUpdates);
00411 }
00412
00413
00414
00415
00416
00417 template<class PLayout>
00418 void ParticleBase<PLayout>::performDestroy() {
00419 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00420 TAU_PROFILE("ParticleBase::performDestroy()", taustr, TAU_PARTICLE);
00421
00422
00423 PAssert(Layout != 0);
00424
00425
00426 if (DestroyList.empty()) return;
00427
00428
00429 bool isSorted = true;
00430 typedef vector< pair<size_t,size_t> > dlist_t;
00431 dlist_t::const_iterator curr = DestroyList.begin(),
00432 last = DestroyList.end();
00433 dlist_t::const_iterator next = curr + 1;
00434 while (next != last && isSorted) {
00435 if (*next++ < *curr++) isSorted = false;
00436 }
00437 if (!isSorted)
00438 ::sort(DestroyList.begin(),DestroyList.end());
00439
00440
00441 bool optDestroy = getUpdateFlag(PLayout::OPTDESTROY);
00442
00443
00444 attrib_container_t::iterator abeg, aend = AttribList.end();
00445 for (abeg = AttribList.begin(); abeg != aend; ++abeg)
00446 (*abeg)->destroy(DestroyList,optDestroy);
00447
00448
00449 DestroyList.erase(DestroyList.begin(),DestroyList.end());
00450 DestroyNum = 0;
00451 }
00452
00453
00455
00456
00457 template<class PLayout>
00458 void ParticleBase<PLayout>::ghostDestroy(size_t M, size_t I) {
00459 TAU_TYPE_STRING(taustr, CT(*this) + " void (unsigned, unsigned)");
00460 TAU_PROFILE("ParticleBase::ghostDestroy()", taustr, TAU_PARTICLE);
00461
00462
00463 PAssert(Layout != 0);
00464
00465 if (M > 0) {
00466
00467 size_t dnum = 0;
00468 attrib_container_t::iterator abeg = AttribList.begin();
00469 attrib_container_t::iterator aend = AttribList.end();
00470 for ( ; abeg != aend; ++abeg )
00471 dnum = (*abeg)->ghostDestroy(M, I);
00472 GhostNum -= dnum;
00473 }
00474 }
00475
00476
00478
00479
00480
00481 template<class PLayout>
00482 size_t
00483 ParticleBase<PLayout>::ghostPutMessage(Message &msg, size_t M, size_t I) {
00484 TAU_PROFILE("ParticleBase::ghostPutMessage()",
00485 "unsigned (Message, unsigned, unsigned)", TAU_PARTICLE);
00486
00487
00488 PAssert(Layout != 0);
00489
00490
00491 if (I >= R.size()) {
00492
00493 if ((I + M) > (R.size() + GhostNum))
00494 M = (R.size() + GhostNum) - I;
00495 } else {
00496
00497 if ((I + M) > R.size())
00498 M = R.size() - I;
00499 }
00500 msg.put(M);
00501
00502
00503 if (M > 0) {
00504 attrib_container_t::iterator abeg = AttribList.begin();
00505 attrib_container_t::iterator aend = AttribList.end();
00506 for ( ; abeg != aend; abeg++ )
00507 (*abeg)->ghostPutMessage(msg, M, I);
00508 }
00509
00510 return M;
00511 }
00512
00513
00515
00516
00517
00518 template<class PLayout>
00519 size_t
00520 ParticleBase<PLayout>::ghostPutMessage(Message &msg,
00521 const vector<size_t>& pl) {
00522 TAU_PROFILE("ParticleBase::ghostPutMessage()",
00523 "unsigned (Message, vector<unsigned>)", TAU_PARTICLE);
00524
00525
00526 PAssert(Layout != 0);
00527
00528 vector<size_t>::size_type M = pl.size();
00529 msg.put(M);
00530
00531
00532 if (M > 0) {
00533 attrib_container_t::iterator abeg = AttribList.begin();
00534 attrib_container_t::iterator aend = AttribList.end();
00535 for ( ; abeg != aend; ++abeg )
00536 (*abeg)->ghostPutMessage(msg, pl);
00537 }
00538
00539 return M;
00540 }
00541
00542
00544
00545 template<class PLayout>
00546 size_t
00547 ParticleBase<PLayout>::ghostGetMessage(Message& msg, int node) {
00548 TAU_TYPE_STRING(taustr, CT(*this) + " unsigned (Message, int)");
00549 TAU_PROFILE("ParticleBase::ghostGetMessage()", taustr, TAU_PARTICLE);
00550
00551
00552 PAssert(Layout != 0);
00553
00554
00555 size_t numitems;
00556 msg.get(numitems);
00557 GhostNum += numitems;
00558
00559
00560 if (numitems > 0) {
00561 attrib_container_t::iterator abeg = AttribList.begin();
00562 attrib_container_t::iterator aend = AttribList.end();
00563 for ( ; abeg != aend; abeg++ )
00564 (*abeg)->ghostGetMessage(msg, numitems);
00565 }
00566
00567 return numitems;
00568 }
00569
00570
00572
00573
00574 template<class PLayout>
00575 void ParticleBase<PLayout>::sort(SortList_t &sortlist) {
00576 attrib_container_t::iterator abeg = AttribList.begin();
00577 attrib_container_t::iterator aend = AttribList.end();
00578 for ( ; abeg != aend; ++abeg )
00579 (*abeg)->sort(sortlist);
00580 }
00581
00582
00584
00585 template<class PLayout>
00586 ostream& operator<<(ostream& out, const ParticleBase<PLayout>& P) {
00587 TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(P) + " )" );
00588 TAU_PROFILE("operator<<()", taustr, TAU_PARTICLE | TAU_IO);
00589 out << "Particle object contents:";
00590 out << "\n Total particles: " << P.getTotalNum();
00591 out << "\n Local particles: " << P.getLocalNum();
00592 out << "\n Attributes (including R and ID): " << P.numAttributes();
00593 out << "\n Layout = " << P.getLayout();
00594 return out;
00595 }
00596
00597
00599
00600 template<class PLayout>
00601 void ParticleBase<PLayout>::printDebug(Inform& o) {
00602 TAU_PROFILE("printDebug()", "void (Inform)", TAU_PARTICLE | TAU_IO);
00603 o << "PBase: total = " << getTotalNum() << ", local = " << getLocalNum();
00604 o << ", attributes = " << AttribList.size() << endl;
00605 for (attrib_container_t::size_type i=0; i < AttribList.size(); ++i) {
00606 o << " ";
00607 AttribList[i]->printDebug(o);
00608 o << endl;
00609 }
00610 o << " ";
00611 Layout->printDebug(o);
00612 }
00613
00614
00615
00616
00617
00618
00619