8 #ifndef PARTICLE_SPATIAL_LAYOUT_H
9 #define PARTICLE_SPATIAL_LAYOUT_H
51 template <
class T,
unsigned Dim,
class Mesh,
class CachingPolicy>
52 std::ostream& operator<<(std::ostream&, const ParticleSpatialLayout<T,Dim,Mesh,CachingPolicy>&);
59 template <
class T,
unsigned Dim,
class Mesh=UniformCartesian<Dim,T>,
class CachingPolicy=BoxParticleCachingPolicy<T,Dim,Mesh > >
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]));
329 template <
class PB >
413 for (d = 1; d <
Dim; ++d)
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;
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 >
650 for (d = 1; d <
Dim; ++d)
654 T mid = first + 0.5 * (last - first);
658 for (d = 0; d <
Dim; ++d)
668 for (i = 0; i < N; i++)
674 for (ip=0; ip<LocalNum; ++ip)
678 for (j = 0; j <= d; j++)
679 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
682 bool foundit =
false;
685 localV != localEnd && !foundit; ++localV)
687 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
699 unsigned node = (*(touchingVN.first)).second->getNode();
704 PData.destroy(1, ip);
711 std::vector<MPI_Request> requests;
712 std::vector<MsgBuffer*> buffers;
715 for (i = 0; i < N; i++)
724 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
737 LocalNum -= PData.getDestroyNum();
738 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
739 PData.performDestroy();
743 while (sendnum-- > 0)
748 while ((recvd = PData.getMessage(*recmsg)) > 0)
772 template <
class PB >
852 for (d = 1; d <
Dim; ++d)
856 T mid = first + 0.5 * (last - first);
860 for (d = 0; d <
Dim; ++d)
870 for (i = 0; i < N; i++)
876 for (ip=0; ip<LocalNum; ++ip)
878 if (!
bool(canSwap[ip]))
continue;
881 for (j = 0; j <= d; j++)
882 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
885 bool foundit =
false;
890 localV != localEnd && !foundit; ++localV)
892 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
903 if (touchingVN.first == touchingVN.second)
906 ERRORMSG(
"Local particle " << ip <<
" with ID=");
908 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
910 ERRORMSG(
"This occurred when searching for point " << pLoc);
917 unsigned node = (*(touchingVN.first)).second->getNode();
922 PData.destroy(1, ip);
932 for (i = 0; i < N; i++)
940 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
955 LocalNum -= PData.getDestroyNum();
956 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
957 PData.performDestroy();
961 while (sendnum-- > 0)
966 while ((recvd = PData.getMessage(*recmsg)) > 0)
975 for (i = 0; i < N; ++i)
982 while ((recvd = PData.getMessage(*recmsg)) > 0)
995 for (i = 0; i < N; i++)
1001 for (ip=0; ip<LocalNum; ++ip)
1003 if (!
bool(canSwap[ip]))
continue;
1005 for (j = 0; j <
Dim; j++)
1006 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1013 if (touchingVN.first == touchingVN.second)
1015 ERRORMSG(
"Local particle " << ip <<
" with ID=");
1017 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
1019 ERRORMSG(
"This occurred when searching for point " << pLoc);
1026 unsigned node = (*(touchingVN.first)).second->getNode();
1031 PData.destroy(1, ip);
1036 for (i = 0; i < N; i++)
1044 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
1055 LocalNum -= PData.getDestroyNum();
1056 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
1057 PData.performDestroy();
1072 template <
class PB >
1083 std::vector<int> msgsend(N, 0);
1084 std::vector<int> msgrecv(N, 0);
1088 std::multimap<unsigned, unsigned> p2n;
1090 bool responsibleNodeNotFound =
false;
1091 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1093 for (
unsigned int j = 0; j <
Dim; j++)
1094 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1096 unsigned destination = myN;
1098 for (localV =
RLayout.
begin_iv(); localV != localEnd && !found; ++localV)
1100 if ((((*localV).second)->getDomain()).touches(pLoc))
1110 if (touchingVN.first == touchingVN.second) {
1111 responsibleNodeNotFound =
true;
1114 destination = (*(touchingVN.first)).second->getNode();
1116 msgsend[destination] = 1;
1118 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1123 std::logical_or<bool>());
1125 if (responsibleNodeNotFound) {
1126 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1127 "could not find node responsible for particle");
1131 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1137 std::unique_ptr<Format> format(PData.getFormat());
1140 std::vector<MPI_Request> requests;
1141 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1143 while (i!=p2n.end())
1145 unsigned cur_destination = i->first;
1147 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1149 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1152 PData.putMessage(msg, i->second);
1153 PData.destroy(1, i->second);
1157 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1160 requests.push_back(request);
1161 buffers.push_back(msgbuf);
1164 LocalNum -= PData.getDestroyNum();
1165 PData.performDestroy();
1168 for (
int k = 0; k<msgrecv[myN]; ++k)
1173 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1178 LocalNum += PData.getSingleMessage(*msg);
1180 msg = recvbuf.
get();
1187 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1188 MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
1193 template <
class PB >
1205 std::vector<int> msgsend(N, 0);
1206 std::vector<int> msgrecv(N, 0);
1210 std::multimap<unsigned, unsigned> p2n;
1212 bool responsibleNodeNotFound =
false;
1213 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1215 if (!
bool(canSwap[ip]))
1218 for (
unsigned int j = 0; j <
Dim; j++)
1219 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1221 unsigned destination = myN;
1223 for (localV =
RLayout.
begin_iv(); localV != localEnd && !found; ++localV)
1225 if ((((*localV).second)->getDomain()).touches(pLoc))
1235 if (touchingVN.first == touchingVN.second) {
1236 responsibleNodeNotFound =
true;
1239 destination = (*(touchingVN.first)).second->getNode();
1241 msgsend[destination] = 1;
1243 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1248 std::logical_or<bool>());
1250 if (responsibleNodeNotFound) {
1251 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1252 "could not find node responsible for particle");
1256 allreduce(msgsend.data(), msgrecv.data(), N, std::plus<int>());
1262 std::unique_ptr<Format> format(PData.getFormat());
1264 std::vector<MPI_Request> requests;
1265 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1267 while (i!=p2n.end())
1269 unsigned cur_destination = i->first;
1271 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1273 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1276 PData.putMessage(msg, i->second);
1277 PData.destroy(1, i->second);
1281 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1284 requests.push_back(request);
1285 buffers.push_back(msgbuf);
1288 LocalNum -= PData.getDestroyNum();
1289 PData.performDestroy();
1292 for (
int k = 0; k<msgrecv[myN]; ++k)
1297 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1302 LocalNum += PData.getSingleMessage(*msg);
1304 msg = recvbuf.
get();
1309 MPI_Request* requests_ptr = requests.
empty()?
static_cast<MPI_Request*
>(0): &(requests[0]);
1310 MPI_Waitall(requests.size(), requests_ptr, 0);
1319 #endif // PARTICLE_SPATIAL_LAYOUT_H
int getNodeCount(unsigned i) const
size_t swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
size_t swap_particles(size_t LocalNum, PB &PData)
Message & put(const T &val)
RegionLayout< T, Dim, Mesh > & getLayout()
RegionLayout< T, Dim, Mesh > RegionLayout_t
Message * receive_block(int &node, int &tag)
const RegionLayout< T, Dim, Mesh > & getLayout() const
virtual void notifyUserOfDelete(UserList *)
Message & getMessage(Message &m)
FieldLayout< Dim > & getFieldLayout()
virtual void Repartition(UserList *)
int next_tag(int t, int s=1000)
#define ADDIPPLSTAT(stat, amount)
virtual MPI_Request raw_isend(void *, int, int, int)
void printDebug(Inform &)
Message & get(const T &cval)
clearpage the user may choose between constant or variable radius This model includes fringe fields begin
virtual int broadcast_others(Message *, int, bool delmsg=true)
Inform & endl(Inform &inf)
#define P_SPATIAL_RETURN_TAG
std::string::iterator iterator
std::vector< size_t > * PutList
ParticleAttrib< SingleParticlePos_t > ParticlePos_t
touch_range_dv touch_range_rdv(const NDRegion< T, Dim > &domain)
void update(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, CachingPolicy > > &p, const ParticleAttrib< char > *canSwap=0)
static Communicate * Comm
ParticleLayout< T, Dim >::Index_t Index_t
ParticleAttrib< Index_t > ParticleIndex_t
bool getEmptyNode(unsigned i) const
#define P_SPATIAL_TRANSFER_TAG
FieldLayout< Dim > & getFieldLayout()
ac_id_vnodes::size_type size_iv() const
void allreduce(const T *input, T *output, int count, Op op)
virtual int raw_probe_receive(char *&, int &, int &)
bool send(Message *, int node, int tag, bool delmsg=true)
size_t new_swap_particles(size_t LocalNum, PB &PData)
Message & putMessage(Message &m) const
RegionLayout< T, Dim, Mesh > RLayout
size_t new_swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
const NDRegion< T, Dim > & getDomain() const
ac_domain_vnodes::size_type size_rdv() const
void changeDomain(FieldLayout< Dim > &)
#define P_SPATIAL_RANGE_TAG
void rebuild_layout(size_t haveLocal, PB &PData)
ParticleLayout< T, Dim >::SingleParticlePos_t SingleParticlePos_t
unsigned NeighborNodes[Dim]
static void abort(const char *=0)
size_t short_swap_particles(size_t LocalNum, PB &PData)