OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
AmrParticleBase.hpp
Go to the documentation of this file.
1 #ifndef AMR_PARTICLE_BASE_HPP
2 #define AMR_PARTICLE_BASE_HPP
3 
4 #include <numeric>
5 #include <algorithm>
6 
7 template<class PLayout>
8 AmrParticleBase<PLayout>::AmrParticleBase() : forbidTransform_m(false),
9  scale_m(1.0),
10  lorentzFactor_m(1.0, 1.0, 1.0),
11 // isLorentzTransformed_m(false),
12  LocalNumPerLevel_m()
13 {
14  updateParticlesTimer_m = IpplTimings::getTimer("AMR update particles");
15  sortParticlesTimer_m = IpplTimings::getTimer("AMR sort particles");
16  domainMappingTimer_m = IpplTimings::getTimer("AMR map particles");
17 }
18 
19 
20 template<class PLayout>
22  : IpplParticleBase<PLayout>(layout),
23  forbidTransform_m(false),
24  scale_m(1.0),
25  lorentzFactor_m(1.0, 1.0, 1.0),
26 // isLorentzTransformed_m(false),
27  LocalNumPerLevel_m()
28 {
29  updateParticlesTimer_m = IpplTimings::getTimer("AMR update particles");
30  sortParticlesTimer_m = IpplTimings::getTimer("AMR sort particles");
31  domainMappingTimer_m = IpplTimings::getTimer("AMR map particles");
32 }
33 
34 
35 template<class PLayout>
38 {
39  return LocalNumPerLevel_m;
40 }
41 
42 
43 template<class PLayout>
46 {
47  return LocalNumPerLevel_m;
48 }
49 
50 
51 template<class PLayout>
53  const ParticleLevelCounter_t& LocalNumPerLevel)
54 {
55  LocalNumPerLevel_m = LocalNumPerLevel;
56 }
57 
58 
59 template<class PLayout>
60 void AmrParticleBase<PLayout>::destroy(size_t M, size_t I, bool doNow) {
61  /* if the particles are deleted directly
62  * we need to update the particle level count
63  */
64  if (M > 0) {
65  if ( doNow ) {
66  for (size_t ip = I; ip < M + I; ++ip)
67  --LocalNumPerLevel_m[ Level[ip] ];
68  }
70  }
71 }
72 
73 
74 template<class PLayout>
75 void AmrParticleBase<PLayout>::performDestroy(bool updateLocalNum) {
76  // nothing to do if destroy list is empty
77  if ( this->DestroyList.empty() )
78  return;
79 
80  if ( updateLocalNum ) {
81  typedef std::vector< std::pair<size_t,size_t> > dlist_t;
82  dlist_t::const_iterator curr = this->DestroyList.begin();
83  const dlist_t::const_iterator last = this->DestroyList.end();
84 
85  while ( curr != last ) {
86  for (size_t ip = curr->first;
87  ip < curr->first + curr->second;
88  ++ip)
89  {
90  --LocalNumPerLevel_m[ Level[ip] ];
91  }
92  ++curr;
93  }
94  }
96 }
97 
98 
99 template<class PLayout>
101 
102 // size_t localnum = LocalNumPerLevel_m[0];
103 
104  // particles are created at the coarsest level
105  LocalNumPerLevel_m[0] += M;
106 
108 
109 // for (size_t i = localnum; i < LocalNumPerLevel_m[0]; ++i) {
110 // this->Grid[i] = 0;
111 // this->Level[i] = 0;
112 // }
113 }
114 
115 
116 template<class PLayout>
118 
119 // size_t localnum = LocalNumPerLevel_m[0];
120 
121  ++LocalNumPerLevel_m[0];
122 
124 
125 // this->Grid[localnum] = 0;
126 // this->Level[localnum] = 0;
127 }
128 
129 
130 template<class PLayout>
132  // update all level
133  this->update(0, -1);
134 }
135 
136 
137 template<class PLayout>
138 void AmrParticleBase<PLayout>::update(int lev_min, int lev_max, bool isRegrid) {
139 
140  IpplTimings::startTimer(updateParticlesTimer_m);
141 
142  // make sure we've been initialized
143  PLayout *Layout = &this->getLayout();
144 
145  PAssert(Layout != 0);
146 
147  // ask the layout manager to update our atoms, etc.
148  Layout->update(*this, lev_min, lev_max, isRegrid);
149 
150  //sort the particles by grid and level
151  sort();
152 
153  INCIPPLSTAT(incParticleUpdates);
154 
155  IpplTimings::stopTimer(updateParticlesTimer_m);
156 }
157 
158 template<class PLayout>
160 
161  IpplTimings::startTimer(updateParticlesTimer_m);
162 
163  // make sure we've been initialized
164  PLayout *Layout = &this->getLayout();
165  PAssert(Layout != 0);
166 
167  // ask the layout manager to update our atoms, etc.
168  Layout->update(*this, &canSwap);
169 
170  //sort the particles by grid and level
171  sort();
172 
173  INCIPPLSTAT(incParticleUpdates);
174 
175  IpplTimings::stopTimer(updateParticlesTimer_m);
176 }
177 
178 
179 template<class PLayout>
181 
182  IpplTimings::startTimer(sortParticlesTimer_m);
183  size_t LocalNum = this->getLocalNum();
184  SortList_t slist1(LocalNum); //slist1 holds the index of where each element should go
185  SortList_t slist2(LocalNum); //slist2 holds the index of which element should go in this position
186 
187  //sort the lists by grid and level
188  //slist1 hold the index of where each element should go in the list
189  std::iota(slist1.begin(), slist1.end(), 0);
190  std::sort(slist1.begin(), slist1.end(), [this](const SortListIndex_t &i,
191  const SortListIndex_t &j)
192  {
193  return (this->Level[i] < this->Level[j] ||
194  (this->Level[i] == this->Level[j] && this->Grid[i] < this->Grid[j]));
195  });
196 
197  //slist2 holds the index of which element should go in this position
198  for (unsigned int i = 0; i < LocalNum; ++i)
199  slist2[slist1[i]] = i;
200 
201  //sort the array according to slist2
202  this->sort(slist2);
203 
204  IpplTimings::stopTimer(sortParticlesTimer_m);
205 }
206 
207 
208 template<class PLayout>
210  attrib_container_t::iterator abeg = this->begin();
211  attrib_container_t::iterator aend = this->end();
212  for ( ; abeg != aend; ++abeg )
213  (*abeg)->sort(sortlist);
214 }
215 
216 
217 template<class PLayout>
219  forbidTransform_m = forbidTransform;
220 }
221 
222 
223 template<class PLayout>
225  return forbidTransform_m;
226 }
227 
228 
229 template<class PLayout>
230 const double& AmrParticleBase<PLayout>::domainMapping(bool inverse) {
231  IpplTimings::startTimer(domainMappingTimer_m);
232 
233  double scale = scale_m;
234 
235  Vector_t gamma = lorentzFactor_m;
236 
237  if ( !inverse ) {
238 // if ( !this->DestroyList.empty() ) {
239 // this->performDestroy(true);
240 // }
241 
242  Vector_t rmin = Vector_t(0.0, 0.0, 0.0);
243  Vector_t rmax = Vector_t(0.0, 0.0, 0.0);
244 
245  getGlobalBounds_m(rmin, rmax);
246 
247  /* in case of 1 particle, the bunch is rotated
248  * transformed to the local frame such that this
249  * particle lies on the origin (0, 0, 0).
250  */
251  if ( this->getTotalNum() == 1 ||
252  (rmin == Vector_t(0.0, 0.0, 0.0) && rmax == Vector_t( 0.0, 0.0, 0.0)) ) {
253  rmin = Vector_t(-1.0, -1.0, -1.0);
254  rmax = Vector_t( 1.0, 1.0, 1.0);
255  }
256 
257  /* Lorentz transfomration factor
258  * is not equal 1.0 only in longitudinal
259  * direction
260  */
261  rmin *= gamma;
262  rmax *= gamma;
263 
264  PLayout& layout = this->getLayout();
265 
266  const auto& lo = layout.lowerBound;
267  const auto& hi = layout.upperBound;
268 
269  Vector_t tmp = Vector_t(std::max( std::abs(rmin[0] / lo[0]), std::abs(rmax[0] / hi[0]) ),
270  std::max( std::abs(rmin[1] / lo[1]), std::abs(rmax[1] / hi[1]) ),
271  std::max( std::abs(rmin[2] / lo[2]), std::abs(rmax[2] / hi[2]) )
272  );
273 
274  scale = std::max( tmp[0], tmp[1] );
275  scale = std::max( scale, tmp[2] );
276  } else {
277  // inverse Lorentz transform
278  gamma = 1.0 / gamma;
279  }
280 
281  if ( std::isnan(scale) || std::isinf(scale) ) {
282  if ( !Ippl::myNode() )
283  throw IpplException("AmrParticleBase::domainMapping()",
284  "Scale factor is Nan or Inf");
285  }
286 
287  Vector_t vscale = Vector_t(scale, scale, scale);
288 
289  // Lorentz transform + mapping to [-1, 1]
290  for (unsigned int i = 0; i < this->getLocalNum(); ++i) {
291  this->R[i] = this->R[i] * gamma / vscale;
292  }
293 
294  scale_m = 1.0 / scale;
295 
296  IpplTimings::stopTimer(domainMappingTimer_m);
297 
298  return scale_m;
299 }
300 
301 
302 template<class PLayout>
304  return scale_m;
305 }
306 
307 template<class PLayout>
309  lorentzFactor_m = lorentzFactor;
310 }
311 
312 
313 template<class PLayout>
315  const size_t localNum = this->getLocalNum();
316  if (localNum == 0) {
317  double max = 1e10;
318  rmin = Vector_t( max, max, max);
319  rmax = Vector_t(-max, -max, -max);
320  return;
321  }
322 
323  rmin = this->R[0];
324  rmax = this->R[0];
325  for (size_t i = 1; i < localNum; ++ i) {
326  for (unsigned short d = 0; d < 3u; ++ d) {
327  if (rmin(d) > this->R[i](d)) rmin(d) = this->R[i](d);
328  else if (rmax(d) < this->R[i](d)) rmax(d) = this->R[i](d);
329  }
330  }
331 }
332 
333 
334 template<class PLayout>
336  this->getLocalBounds_m(rmin, rmax);
337 
338  double min[6];
339  for (unsigned int i = 0; i < 3; ++i) {
340  min[2*i] = rmin[i];
341  min[2*i + 1] = -rmax[i];
342  }
343 
344  allreduce(min, 6, std::less<double>());
345 
346  for (unsigned int i = 0; i < 3; ++i) {
347  rmin[i] = min[2*i];
348  rmax[i] = -min[2*i + 1];
349  }
350 }
351 
352 
353 // template<class PLayout>
354 // void AmrParticleBase<PLayout>::lorentzTransform(bool inverse) {
355 //
356 // if ( isLorentzTransformed_m && !inverse ) {
357 // return;
358 // }
359 //
360 // isLorentzTransformed_m = true;
361 //
362 // Vector_t gamma = lorentzFactor_m;
363 //
364 // if ( inverse ) {
365 // gamma = 1.0 / gamma;
366 // isLorentzTransformed_m = false;
367 // }
368 //
369 // for (std::size_t i = 0; i < this->getLocalNum(); ++i)
370 // this->R[i] *= gamma;
371 // }
372 
373 #endif
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
const double & getScalingFactor() const
void getGlobalBounds_m(Vector_t &rmin, Vector_t &rmax)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
void destroy(size_t, size_t, bool=false)
const ParticleLevelCounter_t & getLocalNumPerLevel() const
IpplTimings::TimerRef domainMappingTimer_m
static int myNode()
Definition: IpplInfo.cpp:794
bool isForbidTransform() const
void createWithID(unsigned id)
void performDestroy(bool updateLocalNum=false)
void getLocalBounds_m(Vector_t &rmin, Vector_t &rmax)
void create(size_t M)
std::vector< SortListIndex_t > SortList_t
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187
void createWithID(unsigned id)
void performDestroy(bool updateLocalNum=false)
void setForbidTransform(bool forbidTransform)
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
void setLorentzFactor(const Vector_t &lorentzFactor)
#define INCIPPLSTAT(stat)
Definition: IpplStats.h:235
const double & domainMapping(bool inverse=false)
IpplTimings::TimerRef updateParticlesTimer_m
T isnan(T x)
isnan function with adjusted return type
Definition: matheval.hpp:74
void setLocalNumPerLevel(const ParticleLevelCounter_t &LocalNumPerLevel)
#define PAssert(c)
Definition: PAssert.h:117
IpplTimings::TimerRef sortParticlesTimer_m
std::string::iterator iterator
Definition: MSLang.h:16
static TimerRef getTimer(const char *nm)
Definition: IpplTimings.h:182
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
void destroy(size_t M, size_t I, bool doNow=false)
T isinf(T x)
isinf function with adjusted return type
Definition: matheval.hpp:78