OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
.PartBunch.cpp
Go to the documentation of this file.
1//
2// Class PartBunch
3// Particle Bunch.
4// A representation of a particle bunch as a vector of particles.
5//
6// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
7// All rights reserved
8//
9// This file is part of OPAL.
10//
11// OPAL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation, either version 3 of the License, or
14// (at your option) any later version.
15//
16// You should have received a copy of the GNU General Public License
17// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
18//
19#include "Algorithms/PartBunch.h"
20
21#include <cfloat>
22#include <memory>
23#include <utility>
24
25#include "Particle/ParticleBalancer.h"
26
28#include "Structure/FieldSolver.h"
30
31#ifdef DBG_SCALARFIELD
33#endif
34
35//#define FIELDSTDOUT
36
37PartBunch::PartBunch(const PartData *ref): // Layout is set using setSolver()
38 PartBunch_t(new PartBunch::pbase_t(new Layout_t()), ref),
40{
41
42}
43
44
46
47}
48
49// PartBunch::pbase_t* PartBunch::clone() {
50// return new pbase_t(new Layout_t());
51// }
52
53
55 Layout_t* layout = static_cast<Layout_t*>(&getLayout());
56 layout->getLayout().changeDomain(*fLayout);
57}
58
60
61 Vector_t<double, 3> ll(-0.005);
62 Vector_t<double, 3> ur(0.005);
63
65
66 NDIndex<3> domain = getFieldLayout().getDomain();
67 for (unsigned int i = 0; i < Dimension; i++)
68 nr_m[i] = domain[i].length();
69
70 for (int i = 0; i < 3; i++)
71 hr_m[i] = (ur[i] - ll[i]) / nr_m[i];
72
73 getMesh().set_meshSpacing(&(hr_m[0]));
74 getMesh().set_origin(ll);
75
76 rho_m.initialize(getMesh(),
78 GuardCellSizes<Dimension>(1),
79 bc_m);
80 eg_m.initialize(getMesh(),
82 GuardCellSizes<Dimension>(1),
83 vbc_m);
84
85 fs_m->solver_m->test(this);
86}
87
88
91
92 pbase_t* underlyingPbase =
93 dynamic_cast<pbase_t*>(pbase_m.get());
94
95 BinaryRepartition(*underlyingPbase);
96 update();
98 boundp();
99}
100
101
102void PartBunch::computeSelfFields(int binNumber) {
103 IpplTimings::startTimer(selfFieldTimer_m);
104
107 rho_m = 0.0;
108 Field_t imagePotential = rho_m;
109
112
113 if(fs_m->hasValidSolver()) {
115 resizeMesh();
116
118 this->Q *= this->dt;
120 if(interpolationCache_m.size() < getLocalNum()) {
122 } else {
124 getLocalNum(),
125 true);
126 }
128 this->Q.scatter(this->rho_m, this->R, IntrplCIC_t(), interpolationCache_m);
129 } else {
130 this->Q.scatter(this->rho_m, IntrplCIC_t(), interpolationCache_m);
131 }
132
133 this->Q /= this->dt;
134 this->rho_m /= getdT();
135
137 double scaleFactor = 1;
138 // double scaleFactor = Physics::c * getdT();
139 double gammaz = getBinGamma(binNumber);
140
143 double tmp2 = 1 / hr_m[0] * 1 / hr_m[1] * 1 / hr_m[2] / (scaleFactor * scaleFactor * scaleFactor) / gammaz;
144 rho_m *= tmp2;
145
148 Vector_t<double, 3> hr_scaled = hr_m * Vector_t<double, 3>(scaleFactor);
149 hr_scaled[2] *= gammaz;
150
153 imagePotential = rho_m;
154
155 fs_m->solver_m->computePotential(rho_m, hr_scaled);
156
158 rho_m *= hr_scaled[0] * hr_scaled[1] * hr_scaled[2];
159
163
166 eg_m = -Grad(rho_m, eg_m);
167
170 eg_m *= Vector_t<double, 3>(gammaz / (scaleFactor), gammaz / (scaleFactor), 1.0 / (scaleFactor * gammaz));
171
172 // If desired write E-field and potential to terminal
173#ifdef FIELDSTDOUT
174 // Immediate debug output:
175 // Output potential and e-field along the x-, y-, and z-axes
176 int mx = (int)nr_m[0];
177 int mx2 = (int)nr_m[0] / 2;
178 int my = (int)nr_m[1];
179 int my2 = (int)nr_m[1] / 2;
180 int mz = (int)nr_m[2];
181 int mz2 = (int)nr_m[2] / 2;
182
183 for (int i=0; i<mx; i++ )
184 *gmsg << "Bin " << binNumber
185 << ", Self Field along x axis E = " << eg_m[i][my2][mz2]
186 << ", Pot = " << rho_m[i][my2][mz2] << endl;
187
188 for (int i=0; i<my; i++ )
189 *gmsg << "Bin " << binNumber
190 << ", Self Field along y axis E = " << eg_m[mx2][i][mz2]
191 << ", Pot = " << rho_m[mx2][i][mz2] << endl;
192
193 for (int i=0; i<mz; i++ )
194 *gmsg << "Bin " << binNumber
195 << ", Self Field along z axis E = " << eg_m[mx2][my2][i]
196 << ", Pot = " << rho_m[mx2][my2][i] << endl;
197#endif
198
203 Eftmp.gather(eg_m, IntrplCIC_t(), interpolationCache_m);
204 //Eftmp.gather(eg_m, this->R, IntrplCIC_t());
205
213 double betaC = std::sqrt(gammaz * gammaz - 1.0) / gammaz / Physics::c;
214
215 Bf(0) = Bf(0) - betaC * Eftmp(1);
216 Bf(1) = Bf(1) + betaC * Eftmp(0);
217
218 Ef += Eftmp;
219
222
224 NDIndex<3> domain = getFieldLayout().getDomain();
225 Vector_t<double, 3> origin = rho_m.get_mesh().get_origin();
226 double hz = rho_m.get_mesh().get_meshSpacing(2);
227 double zshift = -(2 * origin(2) + (domain[2].first() + domain[2].last() + 1) * hz) * gammaz * scaleFactor;
228
231 fs_m->solver_m->computePotential(imagePotential, hr_scaled, zshift);
232
234 imagePotential *= hr_scaled[0] * hr_scaled[1] * hr_scaled[2];
235
238 imagePotential *= getCouplingConstant();
239
240#ifdef DBG_SCALARFIELD
241 const int dumpFreq = 100;
242 VField_t tmp_eg = eg_m;
243
244 if ((localTrackStep_m + 1) % dumpFreq == 0) {
245 FieldWriter fwriter;
246 fwriter.dumpField(rho_m, "phi", "V", localTrackStep_m / dumpFreq, &imagePotential);
247 }
248#endif
249
253 eg_m = -Grad(imagePotential, eg_m);
254
257 eg_m *= Vector_t<double, 3>(gammaz / (scaleFactor), gammaz / (scaleFactor), 1.0 / (scaleFactor * gammaz));
258
259 // If desired write E-field and potential to terminal
260#ifdef FIELDSTDOUT
261 // Immediate debug output:
262 // Output potential and e-field along the x-, y-, and z-axes
263 //int mx = (int)nr_m[0];
264 //int mx2 = (int)nr_m[0] / 2;
265 //int my = (int)nr_m[1];
266 //int my2 = (int)nr_m[1] / 2;
267 //int mz = (int)nr_m[2];
268 //int mz2 = (int)nr_m[2] / 2;
269
270 for (int i=0; i<mx; i++ )
271 *gmsg << "Bin " << binNumber
272 << ", Image Field along x axis E = " << eg_m[i][my2][mz2]
273 << ", Pot = " << rho_m[i][my2][mz2] << endl;
274
275 for (int i=0; i<my; i++ )
276 *gmsg << "Bin " << binNumber
277 << ", Image Field along y axis E = " << eg_m[mx2][i][mz2]
278 << ", Pot = " << rho_m[mx2][i][mz2] << endl;
279
280 for (int i=0; i<mz; i++ )
281 *gmsg << "Bin " << binNumber
282 << ", Image Field along z axis E = " << eg_m[mx2][my2][i]
283 << ", Pot = " << rho_m[mx2][my2][i] << endl;
284#endif
285
286#ifdef DBG_SCALARFIELD
287 tmp_eg += eg_m;
288 if ((localTrackStep_m + 1) % dumpFreq == 0) {
289 FieldWriter fwriter;
290 fwriter.dumpField(tmp_eg, "e", "V/m", localTrackStep_m / dumpFreq);
291 }
292#endif
293
298 Eftmp.gather(eg_m, IntrplCIC_t(), interpolationCache_m);
299 //Eftmp.gather(eg_m, this->R, IntrplCIC_t());
300
309 Bf(0) = Bf(0) + betaC * Eftmp(1);
310 Bf(1) = Bf(1) - betaC * Eftmp(0);
311
312 Ef += Eftmp;
313
314 }
315 IpplTimings::stopTimer(selfFieldTimer_m);
316}
317
319 // when OPAL had AMR we need to do this
320 return;
321
322}
323
325 IpplTimings::startTimer(selfFieldTimer_m);
326 rho_m = 0.0;
328
329 if(fs_m->hasValidSolver()) {
330 //mesh the whole domain
331 resizeMesh();
332
333 //scatter charges onto grid
334 this->Q *= this->dt;
335 this->Q.scatter(this->rho_m, this->R, IntrplCIC_t());
336 this->Q /= this->dt;
337 this->rho_m /= getdT();
338
339 //calculating mesh-scale factor
340 double gammaz = sum(this->P)[2] / getTotalNum();
341 gammaz *= gammaz;
342 gammaz = std::sqrt(gammaz + 1.0);
343 double scaleFactor = 1;
344 // double scaleFactor = Physics::c * getdT();
345 //and get meshspacings in real units [m]
346 Vector_t<double, 3> hr_scaled = hr_m * Vector_t<double, 3>(scaleFactor);
347 hr_scaled[2] *= gammaz;
348
349 //double tmp2 = 1/hr_m[0] * 1/hr_m[1] * 1/hr_m[2] / (scaleFactor*scaleFactor*scaleFactor) / gammaz;
350 double tmp2 = 1 / hr_scaled[0] * 1 / hr_scaled[1] * 1 / hr_scaled[2];
351 //divide charge by a 'grid-cube' volume to get [C/m^3]
352 rho_m *= tmp2;
353
354#ifdef DBG_SCALARFIELD
355 FieldWriter fwriter;
356 fwriter.dumpField(rho_m, "rho", "C/m^3", localTrackStep_m);
357#endif
358
359 // charge density is in rho_m
360 fs_m->solver_m->computePotential(rho_m, hr_scaled);
361
362 //do the multiplication of the grid-cube volume coming
363 //from the discretization of the convolution integral.
364 //this is only necessary for the FFT solver
365 //FIXME: later move this scaling into FFTPoissonSolver
366 if (fs_m->getFieldSolverType() == FieldSolverType::FFT ||
367 fs_m->getFieldSolverType() == FieldSolverType::FFTBOX) {
368 rho_m *= hr_scaled[0] * hr_scaled[1] * hr_scaled[2];
369 }
370
371 // the scalar potential is given back in rho_m in units
372 // [C/m] = [F*V/m] and must be divided by
373 // 4*pi*\epsilon_0 [F/m] resulting in [V]
375
376 //write out rho
377#ifdef DBG_SCALARFIELD
378 fwriter.dumpField(rho_m, "phi", "V", localTrackStep_m);
379#endif
380
381 // IPPL Grad divides by hr_m [m] resulting in
382 // [V/m] for the electric field
383 eg_m = -Grad(rho_m, eg_m);
384
385 eg_m *= Vector_t<double, 3>(gammaz / (scaleFactor), gammaz / (scaleFactor), 1.0 / (scaleFactor * gammaz));
386
387 //write out e field
388#ifdef FIELDSTDOUT
389 // Immediate debug output:
390 // Output potential and e-field along the x-, y-, and z-axes
391 int mx = (int)nr_m[0];
392 int mx2 = (int)nr_m[0] / 2;
393 int my = (int)nr_m[1];
394 int my2 = (int)nr_m[1] / 2;
395 int mz = (int)nr_m[2];
396 int mz2 = (int)nr_m[2] / 2;
397
398 for (int i=0; i<mx; i++ )
399 *gmsg << "Field along x axis Ex = " << eg_m[i][my2][mz2] << " Pot = " << rho_m[i][my2][mz2] << endl;
400
401 for (int i=0; i<my; i++ )
402 *gmsg << "Field along y axis Ey = " << eg_m[mx2][i][mz2] << " Pot = " << rho_m[mx2][i][mz2] << endl;
403
404 for (int i=0; i<mz; i++ )
405 *gmsg << "Field along z axis Ez = " << eg_m[mx2][my2][i] << " Pot = " << rho_m[mx2][my2][i] << endl;
406#endif
407
408#ifdef DBG_SCALARFIELD
409 fwriter.dumpField(eg_m, "e", "V/m", localTrackStep_m);
410#endif
411
412 // interpolate electric field at particle positions. We reuse the
413 // cached information about where the particles are relative to the
414 // field, since the particles have not moved since this the most recent
415 // scatter operation.
416 Ef.gather(eg_m, this->R, IntrplCIC_t());
417
425 double betaC = std::sqrt(gammaz * gammaz - 1.0) / gammaz / Physics::c;
426
427 Bf(0) = Bf(0) - betaC * Ef(1);
428 Bf(1) = Bf(1) + betaC * Ef(0);
429 }
430 IpplTimings::stopTimer(selfFieldTimer_m);
431}
432
434 Layout_t* layout = static_cast<Layout_t*>(&getLayout());
435 return dynamic_cast<FieldLayout_t &>(layout->getLayout().getFieldLayout());
436}
437
439 for (int i = 0; i < 2 * 3; ++i) {
440
441 if (Ippl::getNodes()>1) {
442 bc_m[i] = new ParallelInterpolationFace<double, Dimension, Mesh_t, Center_t>(i);
443 //std periodic boundary conditions for gradient computations etc.
444 vbc_m[i] = new ParallelPeriodicFace<Vector_t<double, 3>, Dimension, Mesh_t, Center_t>(i);
445 }
446 else {
447 bc_m[i] = new InterpolationFace<double, Dimension, Mesh_t, Center_t>(i);
448 //std periodic boundary conditions for gradient computations etc.
449 vbc_m[i] = new PeriodicFace<Vector_t<double, 3>, Dimension, Mesh_t, Center_t>(i);
450 }
451 getBConds()[i] = ParticlePeriodicBCond;
452 }
453 dcBeam_m=true;
454 *ippl::Info << level3 << "BC set P3M, all periodic" << endl);
455}
456
458 for (int i = 0; i < 2 * 3; ++i) {
459 bc_m[i] = new ZeroFace<double, 3, Mesh_t, Center_t>(i);
460 vbc_m[i] = new ZeroFace<Vector_t<double, 3>, 3, Mesh_t, Center_t>(i);
461 getBConds()[i] = ParticleNoBCond;
462 }
463 dcBeam_m=false;
464 *ippl::Info << level3 << "BC set for normal Beam" << endl);
465}
466
468 for (int i = 0; i < 2 * 3; ++ i) {
469 if (i >= 4) {
470 if (Ippl::getNodes() > 1) {
471 bc_m[i] = new ParallelPeriodicFace<double, 3, Mesh_t, Center_t>(i);
472 vbc_m[i] = new ParallelPeriodicFace<Vector_t<double, 3>, 3, Mesh_t, Center_t>(i);
473 } else {
474 bc_m[i] = new PeriodicFace<double, 3, Mesh_t, Center_t>(i);
475 vbc_m[i] = new PeriodicFace<Vector_t<double, 3>, 3, Mesh_t, Center_t>(i);
476 }
477
478 getBConds()[i] = ParticlePeriodicBCond;
479 } else {
480 bc_m[i] = new ZeroFace<double, 3, Mesh_t, Center_t>(i);
481 vbc_m[i] = new ZeroFace<Vector_t<double, 3>, 3, Mesh_t, Center_t>(i);
482 getBConds()[i] = ParticleNoBCond;
483 }
484 }
485 dcBeam_m=true;
486 *ippl::Info << level3 << "BC set for DC-Beam, longitudinal periodic" << endl);
487}
488
489
490void PartBunch::updateDomainLength(Vektor<int, 3>& grid) {
491 NDIndex<3> domain = getFieldLayout().getDomain();
492 for (unsigned int i = 0; i < Dimension; i++)
493 grid[i] = domain[i].length();
494}
495
496
498 getMesh().set_meshSpacing(&(hr_m[0]));
499 getMesh().set_origin(origin);
500 rho_m.initialize(getMesh(),
502 GuardCellSizes<Dimension>(1),
503 bc_m);
504 eg_m.initialize(getMesh(),
506 GuardCellSizes<Dimension>(1),
507 vbc_m);
508}
509
510inline
512 const Vector_t<double, 3> maxE = max(eg_m);
513 // const double maxL = max(dot(eg_m,eg_m));
514 const Vector_t<double, 3> minE = min(eg_m);
515 // *ippl::Info << "MaxE= " << maxE << " MinE= " << minE << endl);
516 return VectorPair_t(maxE, minE);
517}
518
519
520inline
521void PartBunch::resetInterpolationCache(bool clearCache) {
523 if(clearCache) {
524 interpolationCache_m.destroy(interpolationCache_m.size(), 0, true);
525 }
526}
527
528void PartBunch::swap(unsigned int i, unsigned int j) {
529
530 // FIXME
531 PartBunch_t::swap(i, j);
532
535}
536
537
538Inform &PartBunch::print(Inform &os) {
539 return PartBunch_t::print(os);
540}
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
Cell Center_t
Definition PBunchDefs.h:23
ippl::FieldLayout< Dim > FieldLayout_t
Definition PBunchDefs.h:27
ippl::Field< double, Dim, ViewArgs... > Field_t
Definition PBunchDefs.h:30
ippl::ParticleSpatialLayout< double, 3, Mesh_t > Layout_t
Definition PBunchDefs.h:21
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
Definition PBunchDefs.h:33
ippl::UniformCartesian< double, 3 > Mesh_t
Definition PBunchDefs.h:19
ippl::Vector< T, Dim > Vector_t
Inform * gmsg
Definition changes.cpp:7
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
long long localTrackStep_m
step in a TRACK command
void updateDomainLength(Vector_t< int, 3 > &grid)
void updateFields(const Vector_t< T, Dim > &, const Vector_t< T, Dim > &origin)
Vector_t< double, Dim > rmin_m
VField_t< T, Dim > eg_m
void computeSelfFields()
ParticleLayout< double, 3 > & getLayout()
Definition .PartBunch.h:115
double getdT() const
const Mesh_t< Dim > & getMesh() const
std::pair< Vector_t< double, 3 >, Vector_t< double, 3 > > VectorPair_t
static const unsigned Dimension
ParticleAttrib< Vector_t< T, Dim > > Ef
Field_t< Dim > rho_m
void boundp()
void swap(unsigned int i, unsigned int j)
IpplParticleBase< Layout_t > pbase_t
Definition .PartBunch.h:26
void resetInterpolationCache(bool clearCache=false)
void do_binaryRepart()
Vector_t< double, Dim > rmax_m
void setBCForDCBeam()
Vector_t< T, Dim > nr_m
ParticleAttrib< double > dt
void setBCAllPeriodic()
bool interpolationCacheSet_m
Definition .PartBunch.h:110
PartBunch()=delete
void get_bounds(Vector_t< T, Dim > &rmin, Vector_t< T, Dim > &rmax) const
size_t getLocalNum() const
void resizeMesh()
Vector_t< double, Dim > R(size_t i)
Definition PartBunch.h:276
ParticleAttrib< Vector_t< T, Dim > > P
ParticleAttrib< Vector_t< T, Dim > > Eftmp
BConds< double, 3, Mesh_t, Center_t > bc_m
for defining the boundary conditions
Definition .PartBunch.h:107
VectorPair_t getEExtrema()
BConds< Vector_t< double, 3 >, 3, Mesh_t, Center_t > vbc_m
Definition .PartBunch.h:108
ParticleBConds< Position_t, Dimension > & getBConds()
PartBunch(PLayout &pl, Vector_t< double, Dim > hr, Vector_t< double, Dim > rmin, Vector_t< double, Dim > rmax, std::array< bool, Dim > decomp, double Qtot)
ParticleAttrib< CacheDataCIC< double, 3U > > interpolationCache_m
Definition .PartBunch.h:112
Vector_t< double, Dim > hr_m
mesh size [m]
void initialize(FieldLayout_t< Dim > &fl, Mesh_t< Dim > &mesh)
Inform & print(Inform &os)
void setBCAllOpen()
FieldLayout_t< Dim > & getFieldLayout()
double getCouplingConstant() const
size_t getTotalNum() const
ParticleAttrib< double > Q
double getBinGamma(int bin)
Get gamma of one bin.
void runTests()
ParticleAttrib< Vector_t< T, Dim > > Bf
Particle reference data.
Definition PartData.h:37
void dumpField(FieldType &field, std::string name, std::string unit, long long step, FieldType *image=nullptr)
Dump a scalar or vector field to a file.