8 #ifndef PARTICLE_SPATIAL_LAYOUT_H
9 #define PARTICLE_SPATIAL_LAYOUT_H
51 template <
class T,
unsigned Dim,
class Mesh,
class CachingPolicy>
59 template <
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 >
634 static int sent = 0, old_sent=0;
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)
778 template <
class PB >
858 for (d = 1; d <
Dim; ++d)
860 T first = (*(
RLayout.begin_iv())).second->getDomain()[d].first();
861 T last = (*(
RLayout.begin_iv())).second->getDomain()[d].last();
862 T mid = first + 0.5 * (last - first);
866 for (d = 0; d <
Dim; ++d)
876 for (i = 0; i < N; i++)
882 for (ip=0; ip<LocalNum; ++ip)
884 if (!
bool(canSwap[ip]))
continue;
887 for (j = 0; j <= d; j++)
888 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
891 bool foundit =
false;
895 for (localV =
RLayout.begin_iv();
896 localV != localEnd && !foundit; ++localV)
898 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
909 if (touchingVN.first == touchingVN.second)
912 ERRORMSG(
"Local particle " << ip <<
" with ID=");
914 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
916 ERRORMSG(
"This occurred when searching for point " << pLoc);
923 unsigned node = (*(touchingVN.first)).second->getNode();
928 PData.destroy(1, ip);
938 for (i = 0; i < N; i++)
946 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
961 LocalNum -= PData.getDestroyNum();
962 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
963 PData.performDestroy();
967 while (sendnum-- > 0)
972 while ((recvd = PData.getMessage(*recmsg)) > 0)
981 for (i = 0; i < N; ++i)
988 while ((recvd = PData.getMessage(*recmsg)) > 0)
1001 for (i = 0; i < N; i++)
1007 for (ip=0; ip<LocalNum; ++ip)
1009 if (!
bool(canSwap[ip]))
continue;
1011 for (j = 0; j <
Dim; j++)
1012 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1016 RLayout.touch_range_rdv(pLoc);
1019 if (touchingVN.first == touchingVN.second)
1021 ERRORMSG(
"Local particle " << ip <<
" with ID=");
1023 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
1025 ERRORMSG(
"This occurred when searching for point " << pLoc);
1032 unsigned node = (*(touchingVN.first)).second->getNode();
1037 PData.destroy(1, ip);
1042 for (i = 0; i < N; i++)
1050 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
1061 LocalNum -= PData.getDestroyNum();
1062 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
1063 PData.performDestroy();
1078 template <
class PB >
1082 static int sent = 0;
1090 std::vector<int> msgsend(N, 0);
1091 std::vector<int> msgrecv(N, 0);
1095 std::multimap<unsigned, unsigned> p2n;
1097 int particlesLeft = LocalNum;
1098 bool responsibleNodeNotFound =
false;
1099 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1101 for (
unsigned int j = 0; j <
Dim; j++)
1102 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1104 unsigned destination = myN;
1106 for (localV =
RLayout.begin_iv(); localV != localEnd && !found; ++localV)
1108 if ((((*localV).second)->getDomain()).touches(pLoc))
1118 if (touchingVN.first == touchingVN.second) {
1119 responsibleNodeNotFound =
true;
1122 destination = (*(touchingVN.first)).second->getNode();
1124 msgsend[destination] = 1;
1126 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1133 std::logical_or<bool>());
1135 if (responsibleNodeNotFound) {
1136 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1137 "could not find node responsible for particle");
1141 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1147 std::unique_ptr<Format> format(PData.getFormat());
1150 std::vector<MPI_Request> requests;
1151 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1153 while (i!=p2n.end())
1155 unsigned cur_destination = i->first;
1157 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1159 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1162 PData.putMessage(msg, i->second);
1163 PData.destroy(1, i->second);
1167 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1170 requests.push_back(request);
1171 buffers.push_back(msgbuf);
1174 LocalNum -= PData.getDestroyNum();
1175 PData.performDestroy();
1178 for (
int k = 0; k<msgrecv[myN]; ++k)
1183 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1188 LocalNum += PData.getSingleMessage(*msg);
1190 msg = recvbuf.
get();
1197 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1198 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
1203 template <
class PB >
1208 static int sent = 0;
1216 std::vector<int> msgsend(N, 0);
1217 std::vector<int> msgrecv(N, 0);
1221 std::multimap<unsigned, unsigned> p2n;
1223 int particlesLeft = LocalNum;
1224 bool responsibleNodeNotFound =
false;
1225 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1227 if (!
bool(canSwap[ip]))
1230 for (
unsigned int j = 0; j <
Dim; j++)
1231 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1233 unsigned destination = myN;
1235 for (localV =
RLayout.begin_iv(); localV != localEnd && !found; ++localV)
1237 if ((((*localV).second)->getDomain()).touches(pLoc))
1247 if (touchingVN.first == touchingVN.second) {
1248 responsibleNodeNotFound =
true;
1251 destination = (*(touchingVN.first)).second->getNode();
1253 msgsend[destination] = 1;
1255 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1262 std::logical_or<bool>());
1264 if (responsibleNodeNotFound) {
1265 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1266 "could not find node responsible for particle");
1270 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1276 std::unique_ptr<Format> format(PData.getFormat());
1278 std::vector<MPI_Request> requests;
1279 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1281 while (i!=p2n.end())
1283 unsigned cur_destination = i->first;
1285 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1287 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1290 PData.putMessage(msg, i->second);
1291 PData.destroy(1, i->second);
1295 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1298 requests.push_back(request);
1299 buffers.push_back(msgbuf);
1302 LocalNum -= PData.getDestroyNum();
1303 PData.performDestroy();
1306 for (
int k = 0; k<msgrecv[myN]; ++k)
1311 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1316 LocalNum += PData.getSingleMessage(*msg);
1318 msg = recvbuf.
get();
1323 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1324 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 & putMessage(Message &m) const
Message & getMessage(Message &m)
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
bool getEmptyNode(unsigned i) const
RegionLayout< T, Dim, Mesh > & getLayout()
ParticleLayout< T, Dim >::Index_t Index_t
virtual void Repartition(UserList *)
virtual void notifyUserOfDelete(UserList *)
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)
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()
ParticleLayout< T, Dim >::SingleParticlePos_t SingleParticlePos_t
unsigned NeighborNodes[Dim]
RegionLayout< T, Dim, Mesh > RegionLayout_t
const RegionLayout< T, Dim, Mesh > & getLayout() const
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