11 #ifndef PARTICLE_SPATIAL_LAYOUT_H
12 #define PARTICLE_SPATIAL_LAYOUT_H
52 template <
class T,
unsigned Dim,
class Mesh,
class CachingPolicy>
53 std::ostream& operator<<(std::ostream&, const ParticleSpatialLayout<T,Dim,Mesh,CachingPolicy>&);
60 template <
class T,
unsigned Dim,
class Mesh=UniformCartesian<Dim,T>,
class CachingPolicy=BoxParticleCachingPolicy<T,Dim,Mesh > >
219 template <
class PB >
237 for (i=1; i < haveLocal; ++i)
239 for (d=0; d <
Dim; ++d)
241 if (PData.R[i][d] < minpos[d])
242 minpos[d] = PData.R[i][d];
243 if (PData.R[i][d] > maxpos[d])
244 maxpos[d] = PData.R[i][d];
275 size_t tmphaveLocal = 0;
279 while (unreceived > 0)
283 msg->
get(tmphaveLocal);
284 if (tmphaveLocal > 0)
288 for (i=0; i <
Dim; ++i)
290 if (tmpminpos[i] < minpos[i])
291 minpos[i] = tmpminpos[i];
292 if (tmpmaxpos[i] > maxpos[i])
293 maxpos[i] = tmpmaxpos[i];
305 for (i=0; i <
Dim; ++i)
307 if (minpos[i] >= 0.0)
308 minpos[i] = (int)(minpos[i]);
310 minpos[i] = (int)(minpos[i] - 1);
311 maxpos[i] = (int)(maxpos[i] + 1);
327 for (i=0; i <
Dim; ++i)
328 range[i] =
Index((
int)(minpos[i]), (
int)(maxpos[i]));
347 template <
class PB >
432 for (d = 1; d <
Dim; ++d)
436 T mid = first + 0.5 * (last - first);
440 for (d = 0; d <
Dim; ++d)
450 for (i = 0; i < N; i++)
456 for (ip=0; ip<LocalNum; ++ip)
460 for (j = 0; j <= d; j++)
461 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
464 bool foundit =
false;
469 localV != localEnd && !foundit; ++localV)
471 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
481 #ifdef IPPL_USE_SINGLE_PRECISION
487 while (nudgeDim <= d && touchingVN.first == touchingVN.second)
490 T val = PData.R[ip][nudgeDim];
507 if (touchingVN.first == touchingVN.second)
510 ERRORMSG(
"Local particle " << ip <<
" with ID=");
512 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
514 ERRORMSG(
"This occurred when searching for point " << pLoc);
541 unsigned node = (*(touchingVN.first)).second->getNode();
546 PData.destroy(1, ip);
556 for (i = 0; i < N; i++)
564 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
579 LocalNum -= PData.getDestroyNum();
580 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
581 PData.performDestroy();
585 while (sendnum-- > 0)
590 while ((recvd = PData.getMessage(*recmsg)) > 0)
599 for (i = 0; i < N; ++i)
606 while ((recvd = PData.getMessage(*recmsg)) > 0)
618 msg <<
"case getEmptyNode(myN) " <<
endl;
620 for (i = 0; i < N; i++)
626 for (ip=0; ip<LocalNum; ++ip)
629 for (j = 0; j <
Dim; j++)
630 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
637 if (touchingVN.first == touchingVN.second)
639 ERRORMSG(
"Local particle " << ip <<
" with ID=");
641 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
643 ERRORMSG(
"This occurred when searching for point " << pLoc);
650 unsigned node = (*(touchingVN.first)).second->getNode();
655 PData.destroy(1, ip);
660 for (i = 0; i < N; i++)
668 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
679 LocalNum -= PData.getDestroyNum();
680 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
681 PData.performDestroy();
694 template <
class PB >
697 static int sent = 0, old_sent=0;
716 for (d = 1; d <
Dim; ++d)
720 T mid = first + 0.5 * (last - first);
724 for (d = 0; d <
Dim; ++d)
734 for (i = 0; i < N; i++)
740 for (ip=0; ip<LocalNum; ++ip)
744 for (j = 0; j <= d; j++)
745 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
748 bool foundit =
false;
751 localV != localEnd && !foundit; ++localV)
753 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
765 unsigned node = (*(touchingVN.first)).second->getNode();
770 PData.destroy(1, ip);
778 std::vector<MPI_Request> requests;
779 std::vector<MsgBuffer*> buffers;
782 for (i = 0; i < N; i++)
791 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
804 LocalNum -= PData.getDestroyNum();
805 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
806 PData.performDestroy();
810 while (sendnum-- > 0)
815 while ((recvd = PData.getMessage(*recmsg)) > 0)
841 template <
class PB >
922 for (d = 1; d <
Dim; ++d)
926 T mid = first + 0.5 * (last - first);
930 for (d = 0; d <
Dim; ++d)
940 for (i = 0; i < N; i++)
946 for (ip=0; ip<LocalNum; ++ip)
948 if (!
bool(canSwap[ip]))
continue;
951 for (j = 0; j <= d; j++)
952 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
955 bool foundit =
false;
960 localV != localEnd && !foundit; ++localV)
962 foundit= (((*localV).second)->getDomain())[d].touches(pLoc[d]);
973 if (touchingVN.first == touchingVN.second)
976 ERRORMSG(
"Local particle " << ip <<
" with ID=");
978 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
980 ERRORMSG(
"This occurred when searching for point " << pLoc);
1006 unsigned node = (*(touchingVN.first)).second->getNode();
1011 PData.destroy(1, ip);
1021 for (i = 0; i < N; i++)
1029 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
1044 LocalNum -= PData.getDestroyNum();
1045 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
1046 PData.performDestroy();
1050 while (sendnum-- > 0)
1055 while ((recvd = PData.getMessage(*recmsg)) > 0)
1064 for (i = 0; i < N; ++i)
1071 while ((recvd = PData.getMessage(*recmsg)) > 0)
1084 for (i = 0; i < N; i++)
1090 for (ip=0; ip<LocalNum; ++ip)
1092 if (!
bool(canSwap[ip]))
continue;
1094 for (j = 0; j <
Dim; j++)
1095 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1102 if (touchingVN.first == touchingVN.second)
1104 ERRORMSG(
"Local particle " << ip <<
" with ID=");
1106 ERRORMSG(PData.R[ip] <<
" is outside of global domain ");
1108 ERRORMSG(
"This occurred when searching for point " << pLoc);
1115 unsigned node = (*(touchingVN.first)).second->getNode();
1120 PData.destroy(1, ip);
1125 for (i = 0; i < N; i++)
1133 PData.putMessage(*(
SwapMsgList[i]), (
size_t) 0, (
size_t) 0);
1144 LocalNum -= PData.getDestroyNum();
1145 ADDIPPLSTAT(incParticlesSwapped, PData.getDestroyNum());
1146 PData.performDestroy();
1161 template <
class PB >
1165 static int sent = 0;
1173 std::vector<int> msgsend(N, 0);
1174 std::vector<int> msgrecv(N, 0);
1178 std::multimap<unsigned, unsigned> p2n;
1180 int minParticlesPerNode = PData.getMinimumNumberOfParticlesPerCore();
1181 int particlesLeft = LocalNum;
1182 bool responsibleNodeNotFound =
false;
1183 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1185 for (
unsigned int j = 0; j <
Dim; j++)
1186 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1188 unsigned destination = myN;
1190 for (localV =
RLayout.
begin_iv(); localV != localEnd && !found; ++localV)
1192 if ((((*localV).second)->getDomain()).touches(pLoc))
1199 if (particlesLeft <= minParticlesPerNode)
1205 if (touchingVN.first == touchingVN.second) {
1206 responsibleNodeNotFound =
true;
1209 destination = (*(touchingVN.first)).second->getNode();
1211 msgsend[destination] = 1;
1213 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1220 std::logical_or<bool>());
1222 if (responsibleNodeNotFound) {
1223 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1224 "could not find node responsible for particle");
1228 MPI_Allreduce(&(msgsend[0]), &(msgrecv[0]), N, MPI_INT, MPI_SUM,
Ippl::getComm());
1234 std::unique_ptr<Format> format(PData.getFormat());
1237 std::vector<MPI_Request> requests;
1238 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1240 while (i!=p2n.end())
1242 unsigned cur_destination = i->first;
1244 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1246 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1249 PData.putMessage(msg, i->second);
1250 PData.destroy(1, i->second);
1254 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1257 requests.push_back(request);
1258 buffers.push_back(msgbuf);
1261 LocalNum -= PData.getDestroyNum();
1262 PData.performDestroy();
1265 for (
int k = 0; k<msgrecv[myN]; ++k)
1270 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1275 LocalNum += PData.getSingleMessage(*msg);
1277 msg = recvbuf.
get();
1284 MPI_Waitall(requests.size(), &(requests[0]), MPI_STATUSES_IGNORE);
1289 template <
class PB >
1294 static int sent = 0;
1302 std::vector<int> msgsend(N, 0);
1303 std::vector<int> msgrecv(N, 0);
1307 std::multimap<unsigned, unsigned> p2n;
1309 int minParticlesPerNode = PData.getMinimumNumberOfParticlesPerCore();
1310 int particlesLeft = LocalNum;
1311 bool responsibleNodeNotFound =
false;
1312 for (
unsigned int ip=0; ip<LocalNum; ++ip)
1314 if (!
bool(canSwap[ip]))
1317 for (
unsigned int j = 0; j <
Dim; j++)
1318 pLoc[j] =
PRegion<T>(PData.R[ip][j], PData.R[ip][j]);
1320 unsigned destination = myN;
1322 for (localV =
RLayout.
begin_iv(); localV != localEnd && !found; ++localV)
1324 if ((((*localV).second)->getDomain()).touches(pLoc))
1331 if (particlesLeft <= minParticlesPerNode)
1337 if (touchingVN.first == touchingVN.second) {
1338 responsibleNodeNotFound =
true;
1341 destination = (*(touchingVN.first)).second->getNode();
1343 msgsend[destination] = 1;
1345 p2n.insert(std::pair<unsigned, unsigned>(destination, ip));
1352 std::logical_or<bool>());
1354 if (responsibleNodeNotFound) {
1355 throw IpplException(
"ParticleSpatialLayout::new_swap_particles",
1356 "could not find node responsible for particle");
1360 MPI_Allreduce(&(msgsend[0]), &(msgrecv[0]), N, MPI_INT, MPI_SUM,
Ippl::getComm());
1366 std::unique_ptr<Format> format(PData.getFormat());
1368 std::vector<MPI_Request> requests;
1369 std::vector<std::shared_ptr<MsgBuffer> > buffers;
1371 while (i!=p2n.end())
1373 unsigned cur_destination = i->first;
1375 std::shared_ptr<MsgBuffer> msgbuf(
new MsgBuffer(format.get(), p2n.count(i->first)));
1377 for (; i!=p2n.end() && i->first == cur_destination; ++i)
1380 PData.putMessage(msg, i->second);
1381 PData.destroy(1, i->second);
1385 MPI_Request request =
Ippl::Comm->
raw_isend( msgbuf->getBuffer(), msgbuf->getSize(), cur_destination, tag);
1388 requests.push_back(request);
1389 buffers.push_back(msgbuf);
1392 LocalNum -= PData.getDestroyNum();
1393 PData.performDestroy();
1396 for (
int k = 0; k<msgrecv[myN]; ++k)
1401 MsgBuffer recvbuf(format.get(), buffer, bufsize);
1406 LocalNum += PData.getSingleMessage(*msg);
1408 msg = recvbuf.
get();
1413 MPI_Waitall(requests.size(), &(requests[0]), 0);
1422 #endif // PARTICLE_SPATIAL_LAYOUT_H
RegionLayout< T, Dim, Mesh > RLayout
void changeDomain(FieldLayout< Dim > &)
static void abort(const char *=0, int exitcode=(-1))
constexpr double e
The value of .
virtual void Repartition(UserList *)
RegionLayout< T, Dim, Mesh > & getLayout()
const NDRegion< T, Dim > & getDomain() const
const RegionLayout< T, Dim, Mesh > & getLayout() const
int getNeighborNode(unsigned int d, unsigned int n)
bool getEmptyNode(unsigned i) const
virtual MPI_Request raw_isend(void *, int, int, int)
virtual int raw_probe_receive(char *&, int &, int &)
size_t new_swap_particles(size_t LocalNum, PB &PData)
void update(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, CachingPolicy > > &p, const ParticleAttrib< char > *canSwap=0)
void printDebug(Inform &)
int getNodeCount(unsigned i) const
ParticleLayout< T, Dim >::Index_t Index_t
int next_tag(int t, int s=1000)
ac_id_vnodes::size_type size_iv() const
#define P_SPATIAL_RETURN_TAG
#define P_SPATIAL_RANGE_TAG
unsigned NeighborNodes[Dim]
size_t short_swap_particles(size_t LocalNum, PB &PData)
ac_domain_vnodes::size_type size_rdv() const
ParticleLayout< T, Dim >::SingleParticlePos_t SingleParticlePos_t
FieldLayout< Dim > & getFieldLayout()
void allreduce(const T *input, T *output, int count, Op op)
size_t new_swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
void rebuild_layout(size_t haveLocal, PB &PData)
virtual int broadcast_others(Message *, int, bool delmsg=true)
std::vector< size_t > * PutList
ParticleAttrib< SingleParticlePos_t > ParticlePos_t
static MPI_Comm getComm()
Message & get(const T &cval)
Message & put(const T &val)
#define ADDIPPLSTAT(stat, amount)
RegionLayout< T, Dim, Mesh > RegionLayout_t
void rebuild_neighbor_data()
touch_range_dv touch_range_rdv(const NDRegion< T, Dim > &domain)
virtual void notifyUserOfDelete(UserList *)
FieldLayout< Dim > & getFieldLayout()
Message & putMessage(Message &m) const
size_t swap_particles(size_t LocalNum, PB &PData, const ParticleAttrib< char > &canSwap)
std::string::iterator iterator
size_t swap_particles(size_t LocalNum, PB &PData)
Message * receive_block(int &node, int &tag)
Message & getMessage(Message &m)
ParticleAttrib< Index_t > ParticleIndex_t
static Communicate * Comm
#define P_SPATIAL_TRANSFER_TAG
bool send(Message *, int node, int tag, bool delmsg=true)
Inform & endl(Inform &inf)