OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
AmrParticleBase.hpp
Go to the documentation of this file.
1 //
2 // Class AmrParticleBase
3 // Ippl interface for AMR particles.
4 // The derived classes need to extend the base class by subsequent methods.
5 //
6 // template <class FT, unsigned Dim, class PT>
7 // void scatter(const ParticleAttrib<FT>& attrib, AmrField_t& f,
8 // const ParticleAttrib<Vektor<PT, Dim> >& pp,
9 // int lbase = 0, int lfine = -1) const;
10 //
11 //
12 // gather the data from the given Field into the given attribute, using
13 // the given Position attribute
14 //
15 // template <class FT, unsigned Dim, class PT>
16 // void gather(ParticleAttrib<FT>& attrib, const AmrField_t& f,
17 // const ParticleAttrib<Vektor<PT, Dim> >& pp,
18 // int lbase = 0, int lfine = -1) const;
19 //
20 // Copyright (c) 2016 - 2020, Matthias Frey, Uldis Locans, Paul Scherrer Institut, Villigen PSI, Switzerland
21 // All rights reserved
22 //
23 // Implemented as part of the PhD thesis
24 // "Precise Simulations of Multibunches in High Intensity Cyclotrons"
25 //
26 // This file is part of OPAL.
27 //
28 // OPAL is free software: you can redistribute it and/or modify
29 // it under the terms of the GNU General Public License as published by
30 // the Free Software Foundation, either version 3 of the License, or
31 // (at your option) any later version.
32 //
33 // You should have received a copy of the GNU General Public License
34 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
35 //
36 #ifndef AMR_PARTICLE_BASE_HPP
37 #define AMR_PARTICLE_BASE_HPP
38 
39 #include <numeric>
40 #include <algorithm>
41 
42 template<class PLayout>
43 AmrParticleBase<PLayout>::AmrParticleBase() : forbidTransform_m(false),
44  scale_m(1.0),
45  lorentzFactor_m(1.0, 1.0, 1.0),
46 // isLorentzTransformed_m(false),
47  LocalNumPerLevel_m()
48 {
49  updateParticlesTimer_m = IpplTimings::getTimer("AMR update particles");
50  sortParticlesTimer_m = IpplTimings::getTimer("AMR sort particles");
51  domainMappingTimer_m = IpplTimings::getTimer("AMR map particles");
52 }
53 
54 
55 template<class PLayout>
57  : IpplParticleBase<PLayout>(layout),
58  forbidTransform_m(false),
59  scale_m(1.0),
60  lorentzFactor_m(1.0, 1.0, 1.0),
61 // isLorentzTransformed_m(false),
62  LocalNumPerLevel_m()
63 {
64  updateParticlesTimer_m = IpplTimings::getTimer("AMR update particles");
65  sortParticlesTimer_m = IpplTimings::getTimer("AMR sort particles");
66  domainMappingTimer_m = IpplTimings::getTimer("AMR map particles");
67 }
68 
69 
70 template<class PLayout>
73 {
74  return LocalNumPerLevel_m;
75 }
76 
77 
78 template<class PLayout>
81 {
82  return LocalNumPerLevel_m;
83 }
84 
85 
86 template<class PLayout>
88  const ParticleLevelCounter_t& LocalNumPerLevel)
89 {
90  LocalNumPerLevel_m = LocalNumPerLevel;
91 }
92 
93 
94 template<class PLayout>
95 void AmrParticleBase<PLayout>::destroy(size_t M, size_t I, bool doNow) {
96  /* if the particles are deleted directly
97  * we need to update the particle level count
98  */
99  if (M > 0) {
100  if ( doNow ) {
101  for (size_t ip = I; ip < M + I; ++ip)
102  --LocalNumPerLevel_m[ Level[ip] ];
103  }
105  }
106 }
107 
108 
109 template<class PLayout>
110 void AmrParticleBase<PLayout>::performDestroy(bool updateLocalNum) {
111  // nothing to do if destroy list is empty
112  if ( this->DestroyList.empty() )
113  return;
114 
115  if ( updateLocalNum ) {
116  typedef std::vector< std::pair<size_t,size_t> > dlist_t;
117  dlist_t::const_iterator curr = this->DestroyList.begin();
118  const dlist_t::const_iterator last = this->DestroyList.end();
119 
120  while ( curr != last ) {
121  for (size_t ip = curr->first;
122  ip < curr->first + curr->second;
123  ++ip)
124  {
125  --LocalNumPerLevel_m[ Level[ip] ];
126  }
127  ++curr;
128  }
129  }
131 }
132 
133 
134 template<class PLayout>
136 
137 // size_t localnum = LocalNumPerLevel_m[0];
138 
139  // particles are created at the coarsest level
140  LocalNumPerLevel_m[0] += M;
141 
143 
144 // for (size_t i = localnum; i < LocalNumPerLevel_m[0]; ++i) {
145 // this->Grid[i] = 0;
146 // this->Level[i] = 0;
147 // }
148 }
149 
150 
151 template<class PLayout>
153 
154 // size_t localnum = LocalNumPerLevel_m[0];
155 
156  ++LocalNumPerLevel_m[0];
157 
159 
160 // this->Grid[localnum] = 0;
161 // this->Level[localnum] = 0;
162 }
163 
164 
165 template<class PLayout>
167  // update all level
168  this->update(0, -1);
169 }
170 
171 
172 template<class PLayout>
173 void AmrParticleBase<PLayout>::update(int lev_min, int lev_max, bool isRegrid) {
174 
175  IpplTimings::startTimer(updateParticlesTimer_m);
176 
177  // make sure we've been initialized
178  PLayout *Layout = &this->getLayout();
179 
180  PAssert(Layout != 0);
181 
182  // ask the layout manager to update our atoms, etc.
183  Layout->update(*this, lev_min, lev_max, isRegrid);
184 
185  //sort the particles by grid and level
186  sort();
187 
188  INCIPPLSTAT(incParticleUpdates);
189 
190  IpplTimings::stopTimer(updateParticlesTimer_m);
191 }
192 
193 template<class PLayout>
195 
196  IpplTimings::startTimer(updateParticlesTimer_m);
197 
198  // make sure we've been initialized
199  PLayout *Layout = &this->getLayout();
200  PAssert(Layout != 0);
201 
202  // ask the layout manager to update our atoms, etc.
203  Layout->update(*this, &canSwap);
204 
205  //sort the particles by grid and level
206  sort();
207 
208  INCIPPLSTAT(incParticleUpdates);
209 
210  IpplTimings::stopTimer(updateParticlesTimer_m);
211 }
212 
213 
214 template<class PLayout>
216 
217  IpplTimings::startTimer(sortParticlesTimer_m);
218  size_t LocalNum = this->getLocalNum();
219  SortList_t slist1(LocalNum); //slist1 holds the index of where each element should go
220  SortList_t slist2(LocalNum); //slist2 holds the index of which element should go in this position
221 
222  //sort the lists by grid and level
223  //slist1 hold the index of where each element should go in the list
224  std::iota(slist1.begin(), slist1.end(), 0);
225  std::sort(slist1.begin(), slist1.end(), [this](const SortListIndex_t &i,
226  const SortListIndex_t &j)
227  {
228  return (this->Level[i] < this->Level[j] ||
229  (this->Level[i] == this->Level[j] && this->Grid[i] < this->Grid[j]));
230  });
231 
232  //slist2 holds the index of which element should go in this position
233  for (unsigned int i = 0; i < LocalNum; ++i)
234  slist2[slist1[i]] = i;
235 
236  //sort the array according to slist2
237  this->sort(slist2);
238 
239  IpplTimings::stopTimer(sortParticlesTimer_m);
240 }
241 
242 
243 template<class PLayout>
245  attrib_container_t::iterator abeg = this->begin();
246  attrib_container_t::iterator aend = this->end();
247  for ( ; abeg != aend; ++abeg )
248  (*abeg)->sort(sortlist);
249 }
250 
251 
252 template<class PLayout>
254  forbidTransform_m = forbidTransform;
255 }
256 
257 
258 template<class PLayout>
260  return forbidTransform_m;
261 }
262 
263 
264 template<class PLayout>
265 const double& AmrParticleBase<PLayout>::domainMapping(bool inverse) {
266  IpplTimings::startTimer(domainMappingTimer_m);
267 
268  double scale = scale_m;
269 
270  Vector_t gamma = lorentzFactor_m;
271 
272  if ( !inverse ) {
273 // if ( !this->DestroyList.empty() ) {
274 // this->performDestroy(true);
275 // }
276 
277  Vector_t rmin = Vector_t(0.0, 0.0, 0.0);
278  Vector_t rmax = Vector_t(0.0, 0.0, 0.0);
279 
280  getGlobalBounds_m(rmin, rmax);
281 
282  /* in case of 1 particle, the bunch is rotated
283  * transformed to the local frame such that this
284  * particle lies on the origin (0, 0, 0).
285  */
286  if ( this->getTotalNum() == 1 ||
287  (rmin == Vector_t(0.0, 0.0, 0.0) && rmax == Vector_t( 0.0, 0.0, 0.0)) ) {
288  rmin = Vector_t(-1.0, -1.0, -1.0);
289  rmax = Vector_t( 1.0, 1.0, 1.0);
290  }
291 
292  /* Lorentz transfomration factor
293  * is not equal 1.0 only in longitudinal
294  * direction
295  */
296  rmin *= gamma;
297  rmax *= gamma;
298 
299  PLayout& layout = this->getLayout();
300 
301  const auto& lo = layout.lowerBound;
302  const auto& hi = layout.upperBound;
303 
304  Vector_t tmp = Vector_t(std::max( std::abs(rmin[0] / lo[0]), std::abs(rmax[0] / hi[0]) ),
305  std::max( std::abs(rmin[1] / lo[1]), std::abs(rmax[1] / hi[1]) ),
306  std::max( std::abs(rmin[2] / lo[2]), std::abs(rmax[2] / hi[2]) )
307  );
308 
309  scale = std::max( tmp[0], tmp[1] );
310  scale = std::max( scale, tmp[2] );
311  } else {
312  // inverse Lorentz transform
313  gamma = 1.0 / gamma;
314  }
315 
316  if ( std::isnan(scale) || std::isinf(scale) ) {
317  if ( !Ippl::myNode() )
318  throw IpplException("AmrParticleBase::domainMapping()",
319  "Scale factor is Nan or Inf");
320  }
321 
322  Vector_t vscale = Vector_t(scale, scale, scale);
323 
324  // Lorentz transform + mapping to [-1, 1]
325  for (unsigned int i = 0; i < this->getLocalNum(); ++i) {
326  this->R[i] = this->R[i] * gamma / vscale;
327  }
328 
329  scale_m = 1.0 / scale;
330 
331  IpplTimings::stopTimer(domainMappingTimer_m);
332 
333  return scale_m;
334 }
335 
336 
337 template<class PLayout>
339  return scale_m;
340 }
341 
342 template<class PLayout>
344  lorentzFactor_m = lorentzFactor;
345 }
346 
347 
348 template<class PLayout>
350  const size_t localNum = this->getLocalNum();
351  if (localNum == 0) {
352  double max = 1e10;
353  rmin = Vector_t( max, max, max);
354  rmax = Vector_t(-max, -max, -max);
355  return;
356  }
357 
358  rmin = this->R[0];
359  rmax = this->R[0];
360  for (size_t i = 1; i < localNum; ++ i) {
361  for (unsigned short d = 0; d < 3u; ++ d) {
362  if (rmin(d) > this->R[i](d)) rmin(d) = this->R[i](d);
363  else if (rmax(d) < this->R[i](d)) rmax(d) = this->R[i](d);
364  }
365  }
366 }
367 
368 
369 template<class PLayout>
371  this->getLocalBounds_m(rmin, rmax);
372 
373  double min[6];
374  for (unsigned int i = 0; i < 3; ++i) {
375  min[2*i] = rmin[i];
376  min[2*i + 1] = -rmax[i];
377  }
378 
379  allreduce(min, 6, std::less<double>());
380 
381  for (unsigned int i = 0; i < 3; ++i) {
382  rmin[i] = min[2*i];
383  rmax[i] = -min[2*i + 1];
384  }
385 }
386 
387 
388 // template<class PLayout>
389 // void AmrParticleBase<PLayout>::lorentzTransform(bool inverse) {
390 //
391 // if ( isLorentzTransformed_m && !inverse ) {
392 // return;
393 // }
394 //
395 // isLorentzTransformed_m = true;
396 //
397 // Vector_t gamma = lorentzFactor_m;
398 //
399 // if ( inverse ) {
400 // gamma = 1.0 / gamma;
401 // isLorentzTransformed_m = false;
402 // }
403 //
404 // for (std::size_t i = 0; i < this->getLocalNum(); ++i)
405 // this->R[i] *= gamma;
406 // }
407 
408 #endif
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
#define INCIPPLSTAT(stat)
Definition: IpplStats.h:236
#define PAssert(c)
Definition: PAssert.h:102
std::string::iterator iterator
Definition: MSLang.h:16
T isinf(T x)
isinf function with adjusted return type
Definition: matheval.hpp:70
T isnan(T x)
isnan function with adjusted return type
Definition: matheval.hpp:66
void setLorentzFactor(const Vector_t &lorentzFactor)
bool isForbidTransform() const
const double & getScalingFactor() const
std::vector< SortListIndex_t > SortList_t
void getGlobalBounds_m(Vector_t &rmin, Vector_t &rmax)
void performDestroy(bool updateLocalNum=false)
IpplTimings::TimerRef sortParticlesTimer_m
const ParticleLevelCounter_t & getLocalNumPerLevel() const
void getLocalBounds_m(Vector_t &rmin, Vector_t &rmax)
void setLocalNumPerLevel(const ParticleLevelCounter_t &LocalNumPerLevel)
IpplTimings::TimerRef domainMappingTimer_m
void createWithID(unsigned id)
void create(size_t M)
IpplTimings::TimerRef updateParticlesTimer_m
void destroy(size_t M, size_t I, bool doNow=false)
void setForbidTransform(bool forbidTransform)
const double & domainMapping(bool inverse=false)
void performDestroy(bool updateLocalNum=false)
void createWithID(unsigned id)
void destroy(size_t, size_t, bool=false)
static int myNode()
Definition: IpplInfo.cpp:691
static TimerRef getTimer(const char *nm)
Definition: IpplTimings.h:182
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6