OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
ParticleSpatialLayout.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  ***************************************************************************/
7 
8 // include files
11 #include "Index/NDIndex.h"
12 #include "Region/RegionLayout.h"
13 #include "Message/Communicate.h"
14 #include "Message/Message.h"
15 #include "Utility/IpplInfo.h"
16 #include "Utility/IpplStats.h"
18 
19 
20 // forward declarations
21 template <unsigned Dim> class FieldLayout;
22 class UserList;
23 
25 // constructor, from a FieldLayout
26 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
28  : RLayout(fl)
29 {
30  setup(); // perform necessary setup
31 }
32 
33 
35 // constructor, from a FieldLayout
36 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
38  Mesh& mesh)
39  : RLayout(fl,mesh)
40 {
41  setup(); // perform necessary setup
42 }
43 
44 
46 // constructor, from a RegionLayout
47 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
49  RegionLayout<T,Dim,Mesh>& rl) : RLayout(rl)
50 {
51  setup(); // perform necessary setup
52 }
53 
54 
56 // default constructor ... this does not initialize the RegionLayout,
57 // it will be instead initialized during the first update.
58 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
60 {
61  setup(); // perform necessary setup
62 }
63 
64 
66 // perform common constructor tasks
67 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
69 {
70 
71  unsigned i; // loop variable
72 
73  caching = false;
74 
75  // check ourselves in as a user of the RegionLayout
76  RLayout.checkin(*this);
77 
78  // create storage for message pointers used in swapping particles
79  unsigned N = Ippl::getNodes();
80  SwapMsgList = new Message*[N];
81  for (i = 0; i < Dim; ++i)
82  SwapNodeList[i] = new bool[N];
83  PutList = new std::vector<size_t>[N];
84 
85  // create storage for the number of particles on each node
86  // and flag for empty node domain
87  NodeCount = new size_t[N];
88  EmptyNode = new bool[N];
89  for (i = 0; i < N; ++i)
90  {
91  NodeCount[i] = 0;
92  EmptyNode[i] = false;
93  }
94 }
95 
96 
98 // destructor
99 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
101 {
102 
103  delete [] NodeCount;
104  delete [] EmptyNode;
105  delete [] SwapMsgList;
106  for (unsigned int i=0; i < Dim; i++)
107  delete [] (SwapNodeList[i]);
108  delete [] PutList;
109 
110  // check ourselves out as a user of the RegionLayout
111  RLayout.checkout(*this);
112 }
113 
114 
116 // Update the location and indices of all atoms in the given IpplParticleBase
117 // object. This handles swapping particles among processors if
118 // needed, and handles create and destroy requests. When complete,
119 // all nodes have correct layout information.
120 template <class T, unsigned Dim, class Mesh, class CachingPolicy>
123  const ParticleAttrib<char>* canSwap)
124 {
125 
126  unsigned N = Ippl::getNodes();
127  unsigned myN = Ippl::myNode();
128  size_t LocalNum = PData.getLocalNum();
129  size_t DestroyNum = PData.getDestroyNum();
130  size_t TotalNum;
131  int node;
132 
133  //Inform dbgmsg("SpatialLayout::update", INFORM_ALL_NODES);
134  //dbgmsg << "At start of update:" << endl;
135  //PData.printDebug(dbgmsg);
136 
137  // delete particles in destroy list, update local num
138  PData.performDestroy();
139  LocalNum -= DestroyNum;
140 
141  // set up our layout, if not already done ... we could also do this if
142  // we needed to expand our spatial region.
143  if ( ! RLayout.initialized())
144  rebuild_layout(LocalNum,PData);
145 
146  // apply boundary conditions to the particle positions
147  if (this->getUpdateFlag(ParticleLayout<T,Dim>::BCONDS))
148  this->apply_bconds(LocalNum, PData.R, this->getBConds(), RLayout.getDomain());
149 
150  if(caching)
151  this->updateCacheInformation(*this);
152 
153  // swap particles, if necessary
154  if (N > 1 && this->getUpdateFlag(ParticleLayout<T,Dim>::SWAP))
155  {
156  // Now we can swap particles that have moved outside the region of
157  // local field space. This is done in several passes, one for each
158  // spatial dimension. The NodeCount values are updated by this routine.
159 
160  static IpplMessageCounterRegion swapCounter("Swap Particles");
161  swapCounter.begin();
162  //MPI_Pcontrol( 1,"swap_particles");
163 
164  if (canSwap==0)
165  LocalNum = new_swap_particles(LocalNum, PData);
166  else
167  LocalNum = new_swap_particles(LocalNum, PData, *canSwap);
168 
169  swapCounter.end();
170  }
171 
172  // Save how many local particles we have.
173  TotalNum = NodeCount[myN] = LocalNum;
174 
175  // there is extra work to do if there are multipple nodes, to distribute
176  // the particle layout data to all nodes
177  if (N > 1)
178  {
179  // At this point, we can send our particle count updates to node 0, and
180  // receive back the particle layout.
183  if (myN != 0)
184  {
185  Message *msg = new Message;
186 
187  // put local particle count in the message
188  msg->put(LocalNum);
189  // send this info to node 0
190  Ippl::Comm->send(msg, 0, tag1);
191 
192  // receive back the number of particles on each node
193  node = 0;
194  Message* recmsg = Ippl::Comm->receive_block(node, tag2);
195  recmsg->get(NodeCount);
196  recmsg->get(TotalNum);
197  delete recmsg;
198  }
199  else // do update tasks particular to node 0
200  {
201  // receive messages from other nodes describing what they have
202  int notrecvd = N - 1; // do not need to receive from node 0
203  TotalNum = LocalNum;
204  while (notrecvd > 0)
205  {
206  // receive a message from another node. After recv, node == sender.
208  Message *recmsg = Ippl::Comm->receive_block(node, tag1);
209  size_t remNodeCount = 0;
210  recmsg->get(remNodeCount);
211  delete recmsg;
212  notrecvd--;
213 
214  // update values based on data from remote node
215  TotalNum += remNodeCount;
216  NodeCount[node] = remNodeCount;
217  }
218 
219  // send info back to all the client nodes
220  Message *msg = new Message;
221  msg->put(NodeCount, NodeCount + N);
222  msg->put(TotalNum);
223  Ippl::Comm->broadcast_others(msg, tag2);
224  }
225  }
226 
227  // update our particle number counts
228  PData.setTotalNum(TotalNum); // set the total atom count
229  PData.setLocalNum(LocalNum); // set the number of local atoms
230 
231  if(caching)
232  this->updateGhostParticles(PData, *this);
233 
234  //dbgmsg << endl << "At end of update:" << endl;
235  //PData.printDebug(dbgmsg);
236 }
237 
238 
239 
240 
241 
243 // print it out
244 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
245 std::ostream& operator<<(std::ostream& out, const ParticleSpatialLayout<T,Dim,Mesh,CachingPolicy>& L)
246 {
247 
248  out << "ParticleSpatialLayout, with particle distribution:\n ";
249  for (unsigned int i=0; i < (unsigned int) Ippl::getNodes(); ++i)
250  out << "Number of particles " << L.getNodeCount(i) << " ";
251  out << "\nSpatialLayout decomposition = " << L.getLayout();
252  return out;
253 }
254 
255 
257 // Print out information for debugging purposes.
258 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
260 {
261 
262  o << "PSpatial: distrib = ";
263  for (int i=0; i < Ippl::getNodes(); ++i)
264  o << NodeCount[i] << " ";
265 }
266 
267 
269 // Repartition onto a new layout, if the layout changes ... this is a
270 // virtual function called by a UserList, as opposed to the RepartitionLayout
271 // function used by the particle load balancing mechanism.
272 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
274 {
275 }
276 
277 
279 // Tell the subclass that the FieldLayoutBase is being deleted, so
280 // don't use it anymore
281 template < class T, unsigned Dim, class Mesh, class CachingPolicy >
283 {
284 
285  // really, nothing to do, since the RegionLayout we use only gets
286  // deleted when we are deleted ourselves.
287  return;
288 }
Message & put(const T &val)
Definition: Message.h:406
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent this
Definition: LICENSE:43
Message * receive_block(int &node, int &tag)
static int myNode()
Definition: IpplInfo.cpp:691
virtual void notifyUserOfDelete(UserList *)
virtual void Repartition(UserList *)
int next_tag(int t, int s=1000)
Definition: TagMaker.h:39
Message & get(const T &cval)
Definition: Message.h:476
virtual int broadcast_others(Message *, int, bool delmsg=true)
#define P_SPATIAL_RETURN_TAG
Definition: Tags.h:81
clearpage the user may choose between constant or variable radius This model includes fringe fields L
Definition: multipole_t.tex:7
static int getNodes()
Definition: IpplInfo.cpp:670
void update(IpplParticleBase< ParticleSpatialLayout< T, Dim, Mesh, CachingPolicy > > &p, const ParticleAttrib< char > *canSwap=0)
static Communicate * Comm
Definition: IpplInfo.h:84
Definition: Inform.h:42
#define P_LAYOUT_CYCLE
Definition: Tags.h:86
#define P_SPATIAL_LAYOUT_TAG
Definition: Tags.h:80
const unsigned Dim
bool send(Message *, int node, int tag, bool delmsg=true)
Definition: Mesh.h:35