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/ParticleUniformLayout.h"
00028 #include "Utility/IpplInfo.h"
00029 #include "Message/Communicate.h"
00030 #include "Message/Message.h"
00031 #include "Profile/Profiler.h"
00032 #include <stddef.h>
00033
00034
00036
00037
00038 template<class T, unsigned Dim>
00039 ParticleUniformLayout<T, Dim>::ParticleUniformLayout() {
00040 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00041 TAU_PROFILE("ParticleUniformLayout::ParticleUniformLayout()", taustr,
00042 TAU_PARTICLE);
00043
00044 int N = Ippl::getNodes();
00045 LocalSize = new int[N];
00046 Change = new int[N];
00047 MsgCount = new int[N];
00048 }
00049
00050
00052
00053 template<class T, unsigned Dim>
00054 ParticleUniformLayout<T, Dim>::~ParticleUniformLayout() {
00055 TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00056 TAU_PROFILE("ParticleUniformLayout::~ParticleUniformLayout()", taustr,
00057 TAU_PARTICLE);
00058
00059 delete [] LocalSize;
00060 delete [] Change;
00061 delete [] MsgCount;
00062 }
00063
00064
00066
00067
00068
00069
00070 template<class T, unsigned Dim>
00071 void ParticleUniformLayout<T, Dim>::update(
00072 ParticleBase< ParticleUniformLayout<T, Dim> >& PData,
00073 const ParticleAttrib<char>* canSwap) {
00074 TAU_TYPE_STRING(taustr, " void (" + CT(PData) + "ParticleAttrib<char>* )");
00075 TAU_PROFILE("ParticleUniformLayout::update()", taustr,
00076 TAU_PARTICLE);
00077
00078 int i, j;
00079 int N = Ippl::getNodes();
00080 int myN = Ippl::myNode();
00081 size_t TotalNum = PData.getTotalNum();
00082 size_t LocalNum = PData.getLocalNum();
00083 size_t DestroyNum = PData.getDestroyNum();
00084 float Weight = 1.0 / (float)N;
00085
00086
00087
00088
00089
00090
00091
00092
00093 if (N == 1) {
00094
00095 PData.performDestroy();
00096
00097
00098 LocalNum -= DestroyNum;
00099
00100
00101 PData.setTotalNum(LocalNum);
00102 PData.setLocalNum(LocalNum);
00103
00104 return;
00105 }
00106
00107
00108 int tag1 = Ippl::Comm->next_tag(P_WEIGHTED_LAYOUT_TAG, P_LAYOUT_CYCLE);
00109 int tag2 = Ippl::Comm->next_tag(P_WEIGHTED_RETURN_TAG, P_LAYOUT_CYCLE);
00110 int tag3 = Ippl::Comm->next_tag(P_WEIGHTED_TRANSFER_TAG, P_LAYOUT_CYCLE);
00111 int node, sendnum, recnum;
00112 int nodedata[3];
00113 Message *msg = 0;
00114
00115
00116 if (myN != 0) {
00117
00118
00119 nodedata[0] = LocalNum;
00120 nodedata[1] = DestroyNum;
00121 msg = new Message;
00122 msg->put(nodedata, nodedata + 2);
00123
00124
00125 Ippl::Comm->send(msg, 0, tag1);
00126
00127 } else {
00128
00129
00130
00131
00132
00133
00134 LocalSize[0] = LocalNum - DestroyNum;
00135 TotalNum = LocalSize[0];
00136
00137
00138
00139 int notrecvd = N - 1;
00140 while (notrecvd > 0) {
00141
00142 node = Communicate::COMM_ANY_NODE;
00143 msg = Ippl::Comm->receive_block(node, tag1);
00144 msg->get(nodedata);
00145 delete msg;
00146
00147
00148 LocalSize[node] = nodedata[0] - nodedata[1];
00149 TotalNum += LocalSize[node];
00150
00151
00152 notrecvd--;
00153 }
00154
00155
00156 if (getUpdateFlag(ParticleLayout<T,Dim>::SWAP)) {
00157 int accounted = 0;
00158 for (i = 0; i < N; i++) {
00159 Change[i] = (int)((float)TotalNum * Weight);
00160 accounted += Change[i];
00161 }
00162 accounted -= TotalNum;
00163 if (accounted < 0) {
00164 while (accounted != 0) {
00165 Change[(-accounted) % N]++;
00166 accounted++;
00167 }
00168 } else {
00169 int whichnode = 0;
00170 while (accounted != 0) {
00171 if (Change[whichnode] > 0) {
00172 Change[whichnode]--;
00173 accounted--;
00174 }
00175 whichnode = (whichnode + 1) % N;
00176 }
00177 }
00178 for (i = 0; i < N; i++) {
00179 Change[i] = Change[i] - LocalSize[i];
00180 MsgCount[i] = Change[i];
00181 }
00182 } else {
00183 for (i = 0; i < N; i++) {
00184 Change[i] = MsgCount[i] = 0;
00185 }
00186 }
00187
00188
00189 for (i = 0; i < N; i++) {
00190
00191 nodedata[0] = TotalNum;
00192 if (Change[i] <= 0) {
00193 nodedata[1] = -Change[i];
00194 nodedata[2] = 0;
00195 }
00196 else {
00197 nodedata[1] = 0;
00198 nodedata[2] = Change[i];
00199 }
00200 msg = new Message;
00201 msg->put(nodedata, nodedata + 3);
00202
00203
00204
00205 if (Change[i] <= 0) {
00206 for (j = 0; j < N && MsgCount[i] < 0; j++) {
00207 if (j != i && MsgCount[j] > 0) {
00208 nodedata[0] = j;
00209 if ((-MsgCount[i]) > MsgCount[j])
00210 nodedata[1] = MsgCount[j];
00211 else
00212 nodedata[1] = -MsgCount[i];
00213 MsgCount[i] += nodedata[1];
00214 MsgCount[j] -= nodedata[1];
00215 msg->put(nodedata, nodedata + 2);
00216 }
00217 }
00218 }
00219
00220 Ippl::Comm->send(msg, i, tag2);
00221 }
00222 }
00223
00224
00225 node = Communicate::COMM_ANY_NODE;
00226
00227 msg = Ippl::Comm->receive_block(node, tag2);
00228 msg->get(nodedata);
00229 TotalNum = nodedata[0];
00230 sendnum = nodedata[1];
00231 recnum = nodedata[2];
00232
00233
00234
00235
00236 PData.performDestroy();
00237 LocalNum -= DestroyNum;
00238
00239
00240
00241
00242 if (canSwap==0) {
00243 while (sendnum > 0) {
00244
00245 msg->get(nodedata);
00246 LocalNum -= nodedata[1];
00247 sendnum -= nodedata[1];
00248
00249
00250
00251
00252
00253 Message *sendmsg = new Message;
00254 PData.putMessage(*sendmsg, nodedata[1], LocalNum);
00255 Ippl::Comm->send(sendmsg, nodedata[0], tag3);
00256
00257
00258 PData.destroy(nodedata[1], LocalNum, true);
00259 }
00260 }
00261 else {
00262 while (sendnum > 0) {
00263
00264 msg->get(nodedata);
00265
00266
00267 Message *sendmsg = new Message;
00268 int delpart = LocalNum-1;
00269 for (int ip=0; ip<nodedata[1]; ip++) {
00270 while ( !(bool((*canSwap)[delpart])) ) { --delpart; }
00271 PData.putMessage(*sendmsg, 1, delpart);
00272
00273 PData.destroy(1, delpart, true);
00274 }
00275 LocalNum -= nodedata[1];
00276 sendnum -= nodedata[1];
00277
00278
00279
00280
00281 Ippl::Comm->send(sendmsg, nodedata[0], tag3);
00282 }
00283 }
00284
00285
00286 delete msg;
00287
00288
00289 while (recnum > 0) {
00290
00291 node = Communicate::COMM_ANY_NODE;
00292
00293 msg = Ippl::Comm->receive_block(node, tag3);
00294 int recvamt = PData.getMessage(*msg);
00295 delete msg;
00296
00297
00298 LocalNum += recvamt;
00299 recnum -= recvamt;
00300 }
00301
00302
00303 PData.setTotalNum(TotalNum);
00304 PData.setLocalNum(LocalNum);
00305 }
00306
00307
00309
00310 template<class T, unsigned Dim>
00311 inline
00312 ostream& operator<<(ostream& out, const ParticleUniformLayout<T,Dim>& L) {
00313 TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(L) + " )");
00314 TAU_PROFILE("ParticleBase::singleInitNode()", taustr,
00315 TAU_PARTICLE | TAU_IO);
00316 out << "ParticleUniformLayout" << endl;
00317 return out;
00318 }
00319
00320
00322
00323 template<class T, unsigned Dim>
00324 void ParticleUniformLayout<T, Dim>::printDebug(Inform& o) {
00325 TAU_PROFILE("ParticleUniformLayout::printDebug()", "void (Inform)",
00326 TAU_PARTICLE | TAU_IO);
00327
00328 o << "ParticleUniformLayout";
00329 }
00330
00331
00332
00333
00334
00335
00336
00337