OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
BoxParticleCachingPolicy.h
Go to the documentation of this file.
1 #ifndef BOX_PARTICLE_CACHING_POLICY
2 #define BOX_PARTICLE_CACHING_POLICY
3 
4 /*
5  *
6  * The Box caching layout ensures that each node has all ghost particles
7  * for each external particle that is inside an extended bounding box
8  *
9  */
10 
11 
12 #include <algorithm>
13 #include <map>
14 
15 #include "Message/Message.h"
16 #include "Message/Communicate.h"
17 #include "Message/Format.h"
18 #include "Message/MsgBuffer.h"
19 
20 template <class T, unsigned Dim, class Mesh, class CachingPolicy> class ParticleSpatialLayout;
21 
22 template<class T, unsigned Dim, class Mesh>
24 public:
26  {
27  std::fill(boxDimension, boxDimension+Dim, T());
28  }
29 
30  void setCacheDimension(int d, T length)
31  {
32  boxDimension[d] = length;
33  }
34 
35  void setAllCacheDimensions(T length)
36  {
37  std::fill(boxDimension, boxDimension+Dim, length);
38  }
39  template<class C>
42  )
43  {
44  RegionLayout<T,Dim,Mesh> &RLayout = PLayout.getLayout();
45  NDRegion<T,Dim> globalDomain = RLayout.getDomain();
46 
47  typename RegionLayout<T,Dim,Mesh>::iterator_iv localVN = RLayout.begin_iv();
48  typename RegionLayout<T,Dim,Mesh>::iterator_iv localVNend = RLayout.end_iv();
49 
50  regions.clear();
51 
52 
53  //fill in boundary conditions
54  std::fill(periodic, periodic+2*Dim, false);
55 
57  {
58  ParticleBConds<T,Dim>& pBConds = PLayout.getBConds();
60 
61  for (unsigned d=0; d<2*Dim; ++d)
62  {
63  if(pBConds[d] == periodicBCond)
64  {
65  periodic[d] = true;
66  }
67  }
68  }
69 
70 
71  for (;localVN!=localVNend;++localVN)
72  {
73  //get local domain
74  NDRegion<T,Dim> ldom = (*localVN).second->getDomain();
75 
76  //extrude local domain
77  NDRegion<T,Dim> exdom;
78  for(unsigned int d = 0;d<Dim;++d)
79  {
80  exdom[d] = PRegion<T>(ldom[d].first()- boxDimension[d],
81  ldom[d].last() + boxDimension[d]);
82  }
83 
84  Offset_t offset;
85  std::fill(offset.begin(), offset.end(), 0);
86 
87  //get all relevant offsets
88  for(unsigned int d = 0;d<Dim;++d)
89  {
90  if(periodic[2*d] && (exdom[d].first() < globalDomain[d].first()))
91  {
92  offset[d] = globalDomain[d].length();
93  }
94  else if(periodic[2*d+1] && (exdom[d].last() > globalDomain[d].last()))
95  {
96  offset[d] = -globalDomain[d].length();
97  }
98  }
99  //cycle through all combinations
100  int onoff[Dim];
101  std::fill(onoff, onoff+Dim, 0);
102  while(true)
103  {
104 
105  NDRegion<T,Dim> chckdom;
106  for(unsigned int d = 0;d<Dim;++d)
107  {
108  chckdom[d] = PRegion<T>(ldom[d].first()- boxDimension[d]+onoff[d]*offset[d],
109  ldom[d].last() + boxDimension[d]+onoff[d]*offset[d]);
110  }
111 
112  //get touched external domains
113  typename RegionLayout<T,Dim,Mesh>::touch_range_dv touchRange = RLayout.touch_range_rdv(chckdom);
114 
115 
117 
118 
119  for(i = touchRange.first; i != touchRange.second; ++i)
120  {
121  int node = (*i).second->getNode();
122  if(node == Ippl::myNode())//don't add local node
123  continue;
124  NDRegion<T,Dim> dom = (*i).second->getDomain();
125  Offset_t tmpoffset;
126  for(unsigned int d = 0;d<Dim;++d)
127  {
128  dom[d] = PRegion<T>(dom[d].first() - onoff[d]*offset[d],
129  dom[d].last() - onoff[d]*offset[d]);
130  tmpoffset[d] = onoff[d]*offset[d];
131  }
132 
133  regions[node].push_back(std::make_pair(dom,tmpoffset));
134 
135  }
136 
137  //generate next combinations. this is basically a binary incrementer
138  unsigned int j = 0;
139  for(;j<Dim;++j)
140  {
141  if(offset[j]==0)
142  continue;//skip irrelevant directions
143  if((onoff[j] = !onoff[j]))
144  break;//flip and continue if there's a "carry"
145  }
146 
147  if(j==Dim)
148  break;
149  }
150 
151  }
152  }
153 
154  template<class C>
158  )
159  {
160 
161  Ippl::Comm->barrier();
162  typedef typename std::map<unsigned, std::list<std::pair<NDRegion<T,Dim>, Offset_t> > >::iterator m_iterator;
163 
164  //dump the old ghost particles
165  PData.ghostDestroy(PData.getGhostNum(), 0);
166 
167  //get tag
169 
170  //these are needed to free data for nonblocking sends
171  std::vector<MPI_Request> requests;
172  std::vector<MsgBuffer*> buffers;
173 
174  //for each possible target node
175  for(m_iterator n = regions.begin();n!=regions.end();++n)
176  {
177  int node = n->first;
178 
179  //find particles that need to be sent
180  std::vector<size_t> sendlist;
181  std::vector<Offset_t> offsetlist;
182  for(typename std::list<std::pair<NDRegion<T,Dim>, Offset_t> >::iterator li = n->second.begin();li!=n->second.end();++li)
183  {
184  NDRegion<T, Dim> region = (*li).first;
185 
186  for (unsigned int i = 0;i < PData.getLocalNum();++i)
187  {
188  NDRegion<T,Dim> ploc;
189  for (unsigned int d = 0;d < Dim;++d)
190  ploc[d] = PRegion<T>(PData.R[i][d] - boxDimension[d],
191  PData.R[i][d] + boxDimension[d]);
192 
193  if(region.touches(ploc))
194  {
195  sendlist.push_back(i);
196  offsetlist.push_back((*li).second);
197  }
198  }
199  }
200 
201 
202  //and send them
203  if(sendlist.empty())
204  {
205  //don't bother creating an empty buffer just send an empty message
206  requests.push_back(Ippl::Comm->raw_isend(0, 0, node, tag));
207  }
208  else
209  {
210  //pack and send ghost particles
211  MsgBuffer *msgbuf = 0;
212  PData.writeMsgBufferWithOffsets(msgbuf, sendlist,offsetlist);
213  MPI_Request request = Ippl::Comm->raw_isend(msgbuf->getBuffer(), msgbuf->getSize(), node, tag);
214 
215  requests.push_back(request);
216  buffers.push_back(msgbuf);
217  }
218 
219  }
220 
221 
222  //receive ghost particles
223  Format *format = PData.getFormat();
224 
225  for(unsigned int n = 0;n<regions.size();++n)
226  {
227  int node = Communicate::COMM_ANY_NODE;
228  char *buffer = 0;
229  int bufsize = Ippl::Comm->raw_probe_receive(buffer, node, tag);
230  if(bufsize>0)
231  {
232  MsgBuffer recvbuf(format, buffer, bufsize);
233  PData.readGhostMsgBuffer(&recvbuf, node);
234  }
235  }
236 
237  //wait for communication to finish and clean up buffers
238  MPI_Request* requests_ptr = requests.empty()? static_cast<MPI_Request*>(0): &(requests[0]);
239  MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
240  for (unsigned int j = 0; j<buffers.size(); ++j)
241  {
242  delete buffers[j]->getFormat();
243  delete buffers[j];
244  }
245 
246  delete format;
247  }
248 protected:
250 private:
251  struct Offset_t
252  {
254  T& operator[](int i) { return data[i]; }
255  T operator[](int i) const { return data[i]; }
256  T* begin() { return data; }
257  T* end() { return data+Dim; }
258  };
259 
261  bool periodic[2*Dim];
262  std::map<unsigned, std::list<std::pair<NDRegion<T,Dim>, Offset_t> > > regions;
263 };
264 
265 #endif
void setCacheDimension(int d, T length)
RegionLayout< T, Dim, Mesh > & getLayout()
void updateCacheInformation(ParticleSpatialLayout< T, Dim, Mesh, C > &PLayout)
void barrier(void)
static int myNode()
Definition: IpplInfo.cpp:691
void * getBuffer()
Definition: MsgBuffer.h:54
iterator_iv begin_iv()
Definition: RegionLayout.h:146
int next_tag(int t, int s=1000)
Definition: TagMaker.h:39
virtual MPI_Request raw_isend(void *, int, int, int)
Definition: Communicate.h:196
#define P_SPATIAL_GHOST_TAG
Definition: Tags.h:83
int getSize()
Definition: MsgBuffer.h:50
std::string::iterator iterator
Definition: MSLang.h:15
touch_range_dv touch_range_rdv(const NDRegion< T, Dim > &domain)
Definition: RegionLayout.h:159
static Communicate * Comm
Definition: IpplInfo.h:84
#define P_LAYOUT_CYCLE
Definition: Tags.h:86
const unsigned Dim
virtual int raw_probe_receive(char *&, int &, int &)
Definition: Communicate.h:208
Definition: Format.h:27
const NDRegion< T, Dim > & getDomain() const
Definition: RegionLayout.h:131
void updateGhostParticles(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, C > > &PData, ParticleSpatialLayout< T, Dim, Mesh, C > &)
ParticleBConds< T, Dim > & getBConds()
T ParticlePeriodicBCond(const T t, const T minval, const T maxval)
std::map< unsigned, std::list< std::pair< NDRegion< T, Dim >, Offset_t > > > regions
iterator_iv end_iv()
Definition: RegionLayout.h:147
bool getUpdateFlag(UpdateFlags f) const
bool touches(const NDRegion< T, Dim > &nr) const
Definition: NDRegion.h:175