OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
42template<class PLayout>
43AmrParticleBase<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
55template<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
70template<class PLayout>
73{
74 return LocalNumPerLevel_m;
75}
76
77
78template<class PLayout>
81{
82 return LocalNumPerLevel_m;
83}
84
85
86template<class PLayout>
88 const ParticleLevelCounter_t& LocalNumPerLevel)
89{
90 LocalNumPerLevel_m = LocalNumPerLevel;
91}
92
93
94template<class PLayout>
95void 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
109template<class PLayout>
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
134template<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
151template<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
165template<class PLayout>
167 // update all level
168 this->update(0, -1);
169}
170
171
172template<class PLayout>
173void 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
193template<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
214template<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
243template<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
252template<class PLayout>
254 forbidTransform_m = forbidTransform;
255}
256
257
258template<class PLayout>
260 return forbidTransform_m;
261}
262
263
264template<class PLayout>
265const 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
337template<class PLayout>
339 return scale_m;
340}
341
342template<class PLayout>
344 lorentzFactor_m = lorentzFactor;
345}
346
347
348template<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
369template<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)
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
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
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
#define PAssert(c)
Definition: PAssert.h:102
#define INCIPPLSTAT(stat)
Definition: IpplStats.h:236
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