8#ifndef PARTICLE_SPATIAL_LAYOUT_H
9#define PARTICLE_SPATIAL_LAYOUT_H
51template <
class T,
unsigned Dim,
class Mesh,
class CachingPolicy>
59template <
class T,
unsigned Dim,
class Mesh=UniformCartesian<Dim,T>,
class CachingPolicy=BoxParticleCachingPolicy<T,Dim,Mesh > >
115 return RLayout.getFieldLayout();
201 template <
class PB >
219 for (i=1; i < haveLocal; ++i)
221 for (d=0; d <
Dim; ++d)
223 if (PData.R[i][d] < minpos[d])
224 minpos[d] = PData.R[i][d];
225 if (PData.R[i][d] > maxpos[d])
226 maxpos[d] = PData.R[i][d];
257 size_t tmphaveLocal = 0;
261 while (unreceived > 0)
265 msg->
get(tmphaveLocal);
266 if (tmphaveLocal > 0)
270 for (i=0; i <
Dim; ++i)
272 if (tmpminpos[i] < minpos[i])
273 minpos[i] = tmpminpos[i];
274 if (tmpmaxpos[i] > maxpos[i])
275 maxpos[i] = tmpmaxpos[i];
287 for (i=0; i <
Dim; ++i)
289 if (minpos[i] >= 0.0)
290 minpos[i] = (int)(minpos[i]);
292 minpos[i] = (int)(minpos[i] - 1);
293 maxpos[i] = (int)(maxpos[i] + 1);
309 for (i=0; i <
Dim; ++i)
310 range[i] =
Index((
int)(minpos[i]), (
int)(maxpos[i]));
319 RLayout.changeDomain(range, vn);
329 template <
class PB >
413 for (d = 1; d <
Dim; ++d)
415 T first = (*(
RLayout.begin_iv())).second->getDomain()[d].first();
416 T last = (*(
RLayout.begin_iv())).second->getDomain()[d].last();
417 T mid = first + 0.5 * (last - first);
421 for (d = 0; d <
Dim; ++d)
431 for (i = 0; i < N; i++)
437 for (ip=0; ip<LocalNum; ++ip)
441 for (j = 0; j <= d; j++)
442 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
445 bool foundit =
false;
449 for (localV =
RLayout.begin_iv();
450 localV != localEnd && !foundit; ++localV)
452 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
463 if (touchingVN.first == touchingVN.second)
466 ERRORMSG(
"Local particle " << ip <<
" with ID=");
468 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
470 ERRORMSG(
"This occurred when searching for point " << pLoc);
478 unsigned node = (*(touchingVN.first)).second->getNode();
483 PData.destroy(1, ip);
493 for (i = 0; i < N; i++)
501 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
516 LocalNum -= PData.getDestroyNum();
517 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
518 PData.performDestroy();
522 while (sendnum-- > 0)
527 while ((recvd = PData.getMessage(*recmsg)) > 0)
536 for (i = 0; i < N; ++i)
543 while ((recvd = PData.getMessage(*recmsg)) > 0)
555 msg <<
"case getEmptyNode(myN) " <<
endl;
557 for (i = 0; i < N; i++)
563 for (ip=0; ip<LocalNum; ++ip)
566 for (j = 0; j <
Dim; j++)
567 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
574 if (touchingVN.first == touchingVN.second)
576 ERRORMSG(
"Local particle " << ip <<
" with ID=");
578 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
580 ERRORMSG(
"This occurred when searching for point " << pLoc);
587 unsigned node = (*(touchingVN.first)).second->getNode();
592 PData.destroy(1, ip);
597 for (i = 0; i < N; i++)
605 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
616 LocalNum -= PData.getDestroyNum();
617 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
618 PData.performDestroy();
631 template <
class PB >
653 for (d = 1; d <
Dim; ++d)
655 T first = (*(
RLayout.begin_iv())).second->getDomain()[d].first();
656 T last = (*(
RLayout.begin_iv())).second->getDomain()[d].last();
657 T mid = first + 0.5 * (last - first);
661 for (d = 0; d <
Dim; ++d)
671 for (i = 0; i < N; i++)
677 for (ip=0; ip<LocalNum; ++ip)
681 for (j = 0; j <= d; j++)
682 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
685 bool foundit =
false;
687 for (localV =
RLayout.begin_iv();
688 localV != localEnd && !foundit; ++localV)
690 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
702 unsigned node = (*(touchingVN.first)).second->getNode();
707 PData.destroy(1, ip);
715 std::vector<MPI_Request> requests;
716 std::vector<MsgBuffer*> buffers;
719 for (i = 0; i < N; i++)
728 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
741 LocalNum -= PData.getDestroyNum();
742 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
743 PData.performDestroy();
747 while (sendnum-- > 0)
752 while ((recvd = PData.getMessage(*recmsg)) > 0)
776 template <
class PB >
856 for (d = 1; d <
Dim; ++d)
858 T first = (*(
RLayout.begin_iv())).second->getDomain()[d].first();
859 T last = (*(
RLayout.begin_iv())).second->getDomain()[d].last();
860 T mid = first + 0.5 * (last - first);
864 for (d = 0; d <
Dim; ++d)
874 for (i = 0; i < N; i++)
880 for (ip=0; ip<LocalNum; ++ip)
882 if (!
bool(canSwap[ip]))
continue;
885 for (j = 0; j <= d; j++)
886 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
889 bool foundit =
false;
893 for (localV =
RLayout.begin_iv();
894 localV != localEnd && !foundit; ++localV)
896 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
907 if (touchingVN.first == touchingVN.second)
910 ERRORMSG(
"Local particle " << ip <<
" with ID=");
912 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
914 ERRORMSG(
"This occurred when searching for point " << pLoc);
921 unsigned node = (*(touchingVN.first)).second->getNode();
926 PData.destroy(1, ip);
936 for (i = 0; i < N; i++)
944 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
959 LocalNum -= PData.getDestroyNum();
960 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
961 PData.performDestroy();
965 while (sendnum-- > 0)
970 while ((recvd = PData.getMessage(*recmsg)) > 0)
979 for (i = 0; i < N; ++i)
986 while ((recvd = PData.getMessage(*recmsg)) > 0)
999 for (i = 0; i < N; i++)
1005 for (ip=0; ip<LocalNum; ++ip)
1007 if (!
bool(canSwap[ip]))
continue;
1009 for (j = 0; j <
Dim; j++)
1010 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1014 RLayout.touch_range_rdv(pLoc);
1017 if (touchingVN.first == touchingVN.second)
1019 ERRORMSG(
"Local particle " << ip <<
" with ID=");
1021 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
1023 ERRORMSG(
"This occurred when searching for point " << pLoc);
1030 unsigned node = (*(touchingVN.first)).second->getNode();
1035 PData.destroy(1, ip);
1040 for (i = 0; i < N; i++)
1048 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
1059 LocalNum -= PData.getDestroyNum();
1060 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
1061 PData.performDestroy();
1076 template <
class PB >
1080 static int sent = 0;
1088 std::vector<int> msgsend(N, 0);
1089 std::vector<int> msgrecv(N, 0);
1093 std::multimap<unsigned, unsigned> p2n;
1095 int particlesLeft = LocalNum;
1096 bool responsibleNodeNotFound =
false;
1097 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1099 for (
unsigned int j = 0; j <
Dim; j++)
1100 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1102 unsigned destination = myN;
1104 for (localV =
RLayout.begin_iv(); localV != localEnd && !found; ++localV)
1106 if ((((*localV).second)->getDomain()).touches(pLoc))
1116 if (touchingVN.first == touchingVN.second) {
1117 responsibleNodeNotFound =
true;
1120 destination = (*(touchingVN.first)).second->getNode();
1122 msgsend[destination] = 1;
1124 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1131 std::logical_or<bool>());
1133 if (responsibleNodeNotFound) {
1134 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1135 "could not find node responsible for particle");
1139 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1145 std::unique_ptr<Format> format(PData.getFormat());
1148 std::vector<MPI_Request> requests;
1149 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1151 while (i!=p2n.end())
1153 unsigned cur_destination = i->first;
1155 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1157 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1160 PData.putMessage(msg, i->second);
1161 PData.destroy(1, i->second);
1165 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1168 requests.push_back(request);
1169 buffers.push_back(msgbuf);
1172 LocalNum -= PData.getDestroyNum();
1173 PData.performDestroy();
1176 for (
int k = 0; k<msgrecv[myN]; ++k)
1181 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1186 LocalNum += PData.getSingleMessage(*msg);
1188 msg = recvbuf.
get();
1195 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1196 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
1201 template <
class PB >
1206 static int sent = 0;
1214 std::vector<int> msgsend(N, 0);
1215 std::vector<int> msgrecv(N, 0);
1219 std::multimap<unsigned, unsigned> p2n;
1221 int particlesLeft = LocalNum;
1222 bool responsibleNodeNotFound =
false;
1223 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1225 if (!
bool(canSwap[ip]))
1228 for (
unsigned int j = 0; j <
Dim; j++)
1229 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1231 unsigned destination = myN;
1233 for (localV =
RLayout.begin_iv(); localV != localEnd && !found; ++localV)
1235 if ((((*localV).second)->getDomain()).touches(pLoc))
1245 if (touchingVN.first == touchingVN.second) {
1246 responsibleNodeNotFound =
true;
1249 destination = (*(touchingVN.first)).second->getNode();
1251 msgsend[destination] = 1;
1253 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1260 std::logical_or<bool>());
1262 if (responsibleNodeNotFound) {
1263 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1264 "could not find node responsible for particle");
1268 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1274 std::unique_ptr<Format> format(PData.getFormat());
1276 std::vector<MPI_Request> requests;
1277 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1279 while (i!=p2n.end())
1281 unsigned cur_destination = i->first;
1283 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1285 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1288 PData.putMessage(msg, i->second);
1289 PData.destroy(1, i->second);
1293 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1296 requests.push_back(request);
1297 buffers.push_back(msgbuf);
1300 LocalNum -= PData.getDestroyNum();
1301 PData.performDestroy();
1304 for (
int k = 0; k<msgrecv[myN]; ++k)
1309 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1314 LocalNum += PData.getSingleMessage(*msg);
1316 msg = recvbuf.
get();
1321 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1322 MPI_Waitall(requests.size(), requests_ptr, 0);
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
void allreduce(const T *input, T *output, int count, Op op)
#define P_SPATIAL_TRANSFER_TAG
#define P_SPATIAL_RANGE_TAG
#define P_SPATIAL_RETURN_TAG
std::ostream & operator<<(std::ostream &, const ParticleSpatialLayout< T, Dim, Mesh, CachingPolicy > &)
Inform & endl(Inform &inf)
#define ADDIPPLSTAT(stat, amount)
std::string::iterator iterator
Message & getMessage(Message &m)
Message & putMessage(Message &m) const
virtual MPI_Request raw_isend(void *, int, int, int)
bool send(Message *, int node, int tag, bool delmsg=true)
virtual int raw_probe_receive(char *&, int &, int &)
virtual int broadcast_others(Message *, int, bool delmsg=true)
Message * receive_block(int &node, int &tag)
Message & put(const T &val)
Message & get(const T &cval)
int next_tag(int t, int s=1000)
int getNodeCount(unsigned i) const
void rebuild_layout(size_t haveLocal, PB &PData)
ParticleAttrib< Index_t > ParticleIndex_t
ParticleAttrib< SingleParticlePos_t > ParticlePos_t
const RegionLayout< T, Dim, Mesh > & getLayout() const
bool getEmptyNode(unsigned i) const
virtual void Repartition(UserList *)
RegionLayout< T, Dim, Mesh > & getLayout()
virtual void notifyUserOfDelete(UserList *)
ParticleLayout< T, Dim >::SingleParticlePos_t SingleParticlePos_t
RegionLayout< T, Dim, Mesh > RLayout
void update(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, CachingPolicy > > &p, const ParticleAttrib< char > *canSwap=0)
size_t new_swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
ParticleLayout< T, Dim >::Index_t Index_t
size_t new_swap_particles(size_t LocalNum, PB &PData)
std::vector< size_t > * PutList
size_t swap_particles(size_t LocalNum, PB &PData)
size_t short_swap_particles(size_t LocalNum, PB &PData)
FieldLayout< Dim > & getFieldLayout()
unsigned NeighborNodes[Dim]
RegionLayout< T, Dim, Mesh > RegionLayout_t
size_t swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
void printDebug(Inform &)
ac_id_vnodes::iterator iterator_iv
std::pair< touch_iterator_dv, touch_iterator_dv > touch_range_dv
static void abort(const char *=0)
static Communicate * Comm