OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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  {
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  //generate next combinations. this is basically a binary incrementer
137  unsigned int j = 0;
138  for(;j<Dim;++j)
139  {
140  if(offset[j]==0)
141  continue;//skip irrelevant directions
142  if((onoff[j] = !onoff[j]))
143  break;//flip and continue if there's a "carry"
144  }
145 
146  if(j==Dim)
147  break;
148  }
149 
150  }
151  }
152 
153 template<class C>
157  )
158  {
159 
160  Ippl::Comm->barrier();
161  typedef typename std::map<unsigned, std::list<std::pair<NDRegion<T,Dim>, Offset_t> > >::iterator m_iterator;
162 
163  //dump the old ghost particles
164  PData.ghostDestroy(PData.getGhostNum(), 0);
165 
166  //get tag
168 
169  //these are needed to free data for nonblocking sends
170  std::vector<MPI_Request> requests;
171  std::vector<MsgBuffer*> buffers;
172 
173  //for each possible target node
174  for(m_iterator n = regions.begin();n!=regions.end();++n)
175  {
176  int node = n->first;
177 
178  //find particles that need to be sent
179  std::vector<size_t> sendlist;
180  std::vector<Offset_t> offsetlist;
181  for(typename std::list<std::pair<NDRegion<T,Dim>, Offset_t> >::iterator li = n->second.begin();li!=n->second.end();++li)
182  {
183  NDRegion<T, Dim> region = (*li).first;
184 
185  for (unsigned int i = 0;i < PData.getLocalNum();++i)
186  {
187  NDRegion<T,Dim> ploc;
188  for (unsigned int d = 0;d < Dim;++d)
189  ploc[d] = PRegion<T>(PData.R[i][d] - boxDimension[d],
190  PData.R[i][d] + boxDimension[d]);
191 
192  if(region.touches(ploc))
193  {
194  sendlist.push_back(i);
195  offsetlist.push_back((*li).second);
196  }
197  }
198  }
199 
200 
201  //and send them
202  if(sendlist.empty())
203  {
204  //don't bother creating an empty buffer just send an empty message
205  requests.push_back(Ippl::Comm->raw_isend(0, 0, node, tag));
206  }
207  else
208  {
209  //pack and send ghost particles
210  MsgBuffer *msgbuf = 0;
211  PData.writeMsgBufferWithOffsets(msgbuf, sendlist,offsetlist);
212  MPI_Request request = Ippl::Comm->raw_isend(msgbuf->getBuffer(), msgbuf->getSize(), node, tag);
213 
214  requests.push_back(request);
215  buffers.push_back(msgbuf);
216  }
217 
218  }
219 
220 
221  //receive ghost particles
222  Format *format = PData.getFormat();
223 
224  for(unsigned int n = 0;n<regions.size();++n)
225  {
226  int node = Communicate::COMM_ANY_NODE;
227  char *buffer = 0;
228  int bufsize = Ippl::Comm->raw_probe_receive(buffer, node, tag);
229  if(bufsize>0)
230  {
231  MsgBuffer recvbuf(format, buffer, bufsize);
232  PData.readGhostMsgBuffer(&recvbuf, node);
233  }
234  }
235 
236  //wait for communication to finish and clean up buffers
237  MPI_Request* requests_ptr = requests.empty()? static_cast<MPI_Request*>(0): &(requests[0]);
238  MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
239  for (unsigned int j = 0; j<buffers.size(); ++j)
240  {
241  delete buffers[j]->getFormat();
242  delete buffers[j];
243  }
244 
245  delete format;
246  }
247 protected:
249 private:
250  struct Offset_t
251  {
253  T& operator[](int i) { return data[i]; }
254  T operator[](int i) const { return data[i]; }
255  T* begin() { return data; }
256  T* end() { return data+Dim; }
257  };
258 
260  bool periodic[2*Dim];
261  std::map<unsigned, std::list<std::pair<NDRegion<T,Dim>, Offset_t> > > regions;
262 };
263 
264 #endif
const unsigned Dim
#define P_SPATIAL_GHOST_TAG
Definition: Tags.h:83
#define P_LAYOUT_CYCLE
Definition: Tags.h:86
T ParticlePeriodicBCond(const T t, const T minval, const T maxval)
std::string::iterator iterator
Definition: MSLang.h:16
virtual MPI_Request raw_isend(void *, int, int, int)
Definition: Communicate.h:196
virtual int raw_probe_receive(char *&, int &, int &)
Definition: Communicate.h:208
void barrier(void)
Definition: Format.h:27
int getSize()
Definition: MsgBuffer.h:50
void * getBuffer()
Definition: MsgBuffer.h:54
int next_tag(int t, int s=1000)
Definition: TagMaker.h:39
std::map< unsigned, std::list< std::pair< NDRegion< T, Dim >, Offset_t > > > regions
void updateCacheInformation(ParticleSpatialLayout< T, Dim, Mesh, C > &PLayout)
void updateGhostParticles(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, C > > &PData, ParticleSpatialLayout< T, Dim, Mesh, C > &)
void setCacheDimension(int d, T length)
ParticleBConds< T, Dim > & getBConds()
bool getUpdateFlag(UpdateFlags f) const
bool touches(const NDRegion< T, Dim > &nr) const
Definition: NDRegion.h:175
const NDRegion< T, Dim > & getDomain() const
Definition: RegionLayout.h:131
iterator_iv begin_iv()
Definition: RegionLayout.h:146
touch_range_dv touch_range_rdv(const NDRegion< T, Dim > &domain)
Definition: RegionLayout.h:159
ac_id_vnodes::iterator iterator_iv
Definition: RegionLayout.h:66
iterator_iv end_iv()
Definition: RegionLayout.h:147
std::pair< touch_iterator_dv, touch_iterator_dv > touch_range_dv
Definition: RegionLayout.h:71
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84