OPALX (Object Oriented Parallel Accelerator Library for Exascale) MINIorX
OPALX
DistributionMoments.cpp
Go to the documentation of this file.
1
2// Class DistributionMoments
3// Computes the statistics of particle distributions.
4//
5// Copyright (c) 2021, Christof Metzger-Kraus
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18
20
21#include "Utilities/Options.h"
22#include "Utilities/Util.h"
23
24#include "Utility/Inform.h"
25
27
28#include <gsl/gsl_histogram.h>
29
30#include <boost/numeric/conversion/cast.hpp>
31
32extern Inform* gmsg;
33
34const double DistributionMoments::percentileOneSigmaNormalDist_m = std::erf(1 / sqrt(2));
35const double DistributionMoments::percentileTwoSigmasNormalDist_m = std::erf(2 / sqrt(2));
36const double DistributionMoments::percentileThreeSigmasNormalDist_m = std::erf(3 / sqrt(2));
37const double DistributionMoments::percentileFourSigmasNormalDist_m = std::erf(4 / sqrt(2));
38
40 reset();
42
43 moments_m.resize(6, 6, false);
44 notCentMoments_m.resize(6, 6, false);
45}
46
50 size_t Np,
51 size_t Nlocal) {
52 /*
53 Np is the total number of particles (reduced over ranks). In this function, it is only used to
54 average over the number of total particles. For an empty simulation, this leads to divisions by
55 0. Since, however, some of the computed moments might be needed regardless, we compute them but
56 need to make sure that we do not divide by 0.
57 Solution: Set Np to 1 if it is 0.
58 */
59 Np = (Np == 0) ? 1 : Np;
60
61 const int Dim = 3;
62 double loc_centroid[2 * Dim] = {};
63 double centroid[2 * Dim] = {};
64 double loc_Ekin, loc_gamma, loc_gammaz, gammaz;
65
66 int rank;
67 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
68
70 "calc moments of particle distr.", Nlocal,
71 KOKKOS_LAMBDA(
72 const int k, double& ekin, double& gamma, double& gammaz) {
73 double gamma0 = 0.0;
74 double ekin0 = 0.0;
75
76 for(unsigned j=0; j<Dim; j++){
77 gamma0 += Pview(k)[j]*Pview(k)[j];
78 }
79 gamma0 = Kokkos::sqrt(gamma0+1.0);
80 ekin0 = (gamma0-1.0) * Mview(k);
81 gamma += gamma0;
82 ekin += ekin0;
83
84 gammaz += Pview(k)[2];
85 },
86 Kokkos::Sum<double>(loc_Ekin), Kokkos::Sum<double>(loc_gamma), Kokkos::Sum<double>(loc_gammaz));
88
89 for (unsigned i = 0; i < 2 * Dim; ++i) {
91 "calc moments of particle distr.", Nlocal,
92 KOKKOS_LAMBDA(
93 const int k, double& cent) {
94 double part[2 * Dim];
95 part[0] = Rview(k)[0];
96 part[1] = Pview(k)[0];
97 part[2] = Rview(k)[1];
98 part[3] = Pview(k)[1];
99 part[4] = Rview(k)[2];
100 part[5] = Pview(k)[2];
101
102 cent += part[i];
103 },
104 Kokkos::Sum<double>(loc_centroid[i]));
106 }
107 ippl::Comm->barrier();
108
109 MPI_Allreduce(
110 loc_centroid, centroid, 2 * Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
111 MPI_Allreduce(
112 &loc_Ekin, &meanKineticEnergy_m, 1, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
113 MPI_Allreduce(
114 &loc_gamma, &meanGamma_m, 1, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
115 MPI_Allreduce(
116 &loc_gammaz, &gammaz, 1, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
117
118 for (unsigned i = 0; i < 2 * Dim; i++) {
119 centroid_m(i) = centroid[i];
120 means_m(i) = centroid_m[i]/Np;
121 }
122
124 meanGamma_m = meanGamma_m / (1.*Np);
125 gammaz = gammaz / (1.*Np);
126 gammaz *= gammaz;
127 gammaz = std::sqrt(gammaz + 1.0);
128 meanGammaZ_m = gammaz;
129
130 // store mean R, mean P, std R, std P in class member variables
131 for (unsigned i = 0; i < Dim; i++) {
132 meanR_m(i) = means_m[2*i];
133 meanP_m(i) = means_m[2*i+1];
134 }
135}
139 size_t Np,
140 size_t Nlocal) {
141 Np = (Np == 0) ? 1 : Np; // Explanation: see DistributionMoments::computeMeans implementation
142
143 reset();
144 computeMeans(Rview, Pview, Mview, Np, Nlocal);
145
146 double meanR_loc[Dim] = {};
147 double meanP_loc[Dim] = {};
148 double loc_moment[2 * Dim][2 * Dim] = {};
149 double moment[2 * Dim][2 * Dim] = {};
150
151 double loc_moment_ncent[2 * Dim][2 * Dim] = {};
152 double moment_ncent[2 * Dim][2 * Dim] = {};
153
154 // compute central moments
155 for (unsigned i = 0; i < Dim; i++) {
156 meanR_loc[i] = meanR_m[i];
157 meanP_loc[i] = meanP_m[i];
158 }
159
160 for (unsigned i = 0; i < 2 * Dim; ++i) {
162 "calc moments of particle distr.", Nlocal,
163 KOKKOS_LAMBDA(
164 const int k, double& mom0, double& mom1, double& mom2,
165 double& mom3, double& mom4, double& mom5) {
166 double part[2 * Dim];
167 part[0] = Rview(k)[0]-meanR_loc[0];
168 part[1] = Pview(k)[0]-meanP_loc[0];
169 part[2] = Rview(k)[1]-meanR_loc[1];
170 part[3] = Pview(k)[1]-meanP_loc[1];
171 part[4] = Rview(k)[2]-meanR_loc[2];
172 part[5] = Pview(k)[2]-meanP_loc[2];
173
174 mom0 += part[i] * part[0];
175 mom1 += part[i] * part[1];
176 mom2 += part[i] * part[2];
177 mom3 += part[i] * part[3];
178 mom4 += part[i] * part[4];
179 mom5 += part[i] * part[5];
180 },
181 Kokkos::Sum<double>(loc_moment[i][0]),
182 Kokkos::Sum<double>(loc_moment[i][1]), Kokkos::Sum<double>(loc_moment[i][2]),
183 Kokkos::Sum<double>(loc_moment[i][3]), Kokkos::Sum<double>(loc_moment[i][4]),
184 Kokkos::Sum<double>(loc_moment[i][5]));
186 }
187
188 MPI_Allreduce(
189 loc_moment, moment, 2 * Dim * 2 * Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
190
191 for (unsigned i = 0; i < 2 * Dim; i++) {
192 for (unsigned j = 0; j < 2 * Dim; j++) {
193 moments_m(i,j) = moment[i][j] / Np;
194 }
195 }
196
197 for (unsigned i = 0; i < Dim; i++) {
198 stdR_m(i) = std::sqrt( moments_m(2*i, 2*i) );
199 stdP_m(i) = std::sqrt( moments_m(2*i+1, 2*i+1) );
200 }
201
202 double mekin = meanKineticEnergy_m;
203 double loc_std_mekin;
204
205 // compute non-central moments
206 for (unsigned i = 0; i < 2 * Dim; ++i) {
208 "calc moments of particle distr.", Nlocal,
209 KOKKOS_LAMBDA(
210 const int k, double& mom0, double& mom1, double& mom2,
211 double& mom3, double& mom4, double& mom5) {
212 double part[2 * Dim];
213 part[0] = Rview(k)[0];
214 part[1] = Pview(k)[0];
215 part[2] = Rview(k)[1];
216 part[3] = Pview(k)[1];
217 part[4] = Rview(k)[2];
218 part[5] = Pview(k)[2];
219
220 mom0 += part[i] * part[0];
221 mom1 += part[i] * part[1];
222 mom2 += part[i] * part[2];
223 mom3 += part[i] * part[3];
224 mom4 += part[i] * part[4];
225 mom5 += part[i] * part[5];
226 },
227 Kokkos::Sum<double>(loc_moment_ncent[i][0]),
228 Kokkos::Sum<double>(loc_moment_ncent[i][1]), Kokkos::Sum<double>(loc_moment_ncent[i][2]),
229 Kokkos::Sum<double>(loc_moment_ncent[i][3]), Kokkos::Sum<double>(loc_moment_ncent[i][4]),
230 Kokkos::Sum<double>(loc_moment_ncent[i][5]));
232 }
233 ippl::Comm->barrier();
234
236 "calc moments of particle distr.", Nlocal,
237 KOKKOS_LAMBDA(
238 const int k, double& ekin) {
239 double gamma0 = 0;
240 double ekin0 = 0.0;
241
242 for(unsigned j=0; j<Dim; j++){
243 gamma0 += Pview(k)[j]*Pview(k)[j];
244 }
245 gamma0 = Kokkos::sqrt(gamma0+1.0);
246 ekin0 = (gamma0-1.0) * Mview(k);
247
248 ekin += (ekin0-mekin)*(ekin0-mekin);
249 }, Kokkos::Sum<double>(loc_std_mekin) );
251
252 MPI_Allreduce(
253 loc_moment_ncent, moment_ncent, 2 * Dim * 2 * Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
254
255 MPI_Allreduce(
256 &loc_std_mekin, &stdKineticEnergy_m, 1, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
257
259
260 for (unsigned i = 0; i < 2 * Dim; i++) {
261 for (unsigned j = 0; j < 2 * Dim; j++) {
262 notCentMoments_m(i,j) = moment_ncent[i][j];
263 }
264 }
265
266 // compute emmitance, halo, ...
267 double perParticle = 1./(1.*Np);
268 Vector_t<double, 3> squaredEps, fac, sumRP;
269 unsigned int l = 0;
270 for (unsigned int i = 0; i < 3; ++ i, l += 2) {
271 double w1 = centroid_m[2 * i] * perParticle;
272 double w2 = moments_m(2 * i , 2 * i);
273 //not clear which components of non-central moments are computed, needs to be checked
274 double w3 = notCentMoments_m(l, l) * perParticle;
275 double w4 = notCentMoments_m(l + 1, l + 1) * perParticle;
276 double tmp = w2 - std::pow(w1, 2);
277
278 halo_m(i) = (w4 + w1 * (-4 * w3 + 3 * w1 * (tmp + w2))) / tmp;
280 }
281
282 //stdKineticEnergy_m = std::sqrt(localMoments[l++] * perParticle);
283 //totalCharge_m = localMoments[l++];
284 //totalMass_m = localMoments[l++];
285
286 for (unsigned int i = 0; i < 3; ++ i) {
287 sumRP(i) = notCentMoments_m(2 * i, 2 * i + 1) * perParticle - meanR_m(i) * meanP_m(i);
288 stdRP_m(i) = sumRP(i) / (stdR_m(i) * stdP_m(i));
289 squaredEps(i) = std::pow(stdR_m(i) * stdP_m(i), 2) - std::pow(sumRP(i), 2);
290 normalizedEps_m(i) = std::sqrt(std::max(squaredEps(i), 0.0));
291 }
292
293 double betaGamma = std::sqrt(std::pow(meanGamma_m, 2) - 1.0);
295
296}
297
299{
300 const int Dim = 3;
301
302 double rmax_loc[Dim];
303 double rmin_loc[Dim];
304 double rmax[Dim];
305 double rmin[Dim];
306
307 for(int i=0; i<Dim; i++){
308 rmin_loc[i] = 0.;
309 rmax_loc[i] = 0.;
310 }
311
312 for (unsigned d = 0; d < Dim; ++d) {
313 if (Nlocal > 0) {
315 "rel max", Nlocal,
316 KOKKOS_LAMBDA(const int i, double& mm) {
317 double tmp_vel = Rview(i)[d];
318 mm = tmp_vel > mm ? tmp_vel : mm;
319 },
320 Kokkos::Max<double>(rmax_loc[d]));
321
323 "rel min", ippl::getRangePolicy(Rview),
324 KOKKOS_LAMBDA(const int i, double& mm) {
325 double tmp_vel = Rview(i)[d];
326 mm = tmp_vel < mm ? tmp_vel : mm;
327 },
328 Kokkos::Min<double>(rmin_loc[d]));
329 }
330 }
332 MPI_Allreduce(rmax_loc, rmax, Dim, MPI_DOUBLE, MPI_MAX, ippl::Comm->getCommunicator());
333 MPI_Allreduce(rmin_loc, rmin, Dim, MPI_DOUBLE, MPI_MIN, ippl::Comm->getCommunicator());
334 ippl::Comm->barrier();
335
336 // store min and max R in class member variables
337 for (unsigned int i=0; i<Dim; i++) {
338 minR_m(i) = rmin[i];
339 maxR_m(i) = rmax[i];
340 }
341}
342
344 const std::vector<OpalParticle>::const_iterator& /*first*/,
345 const std::vector<OpalParticle>::const_iterator& /*last*/) {
346 *gmsg << "not implemented" << endl;
347}
348
349
350template <class InputIt>
351void DistributionMoments::computePercentiles(const InputIt& first, const InputIt& last) {
353 return;
354 }
355
356 std::vector<gsl_histogram*> histograms(3);
357 // For a normal distribution the number of exchanged data between the cores is minimized
358 // if the number of histogram bins follows the following formula. Since we can't know
359 // how many particles are in each bin for the real distribution we use this formula.
360 unsigned int numBins = 3.5 * std::pow(3, std::log10(totalNumParticles_m));
361
363 for (unsigned int d = 0; d < 3; ++d) {
364 maxR(d) = 1.0000001 * std::max(maxR_m[d] - meanR_m[d], meanR_m[d] - minR_m[d]);
365 histograms[d] = gsl_histogram_alloc(numBins);
366 gsl_histogram_set_ranges_uniform(histograms[d], 0.0, maxR(d));
367 }
368 for (InputIt it = first; it != last; ++it) {
369 OpalParticle const& particle = *it;
370 for (unsigned int d = 0; d < 3; ++d) {
371 gsl_histogram_increment(histograms[d], std::abs(particle[2 * d] - meanR_m[d]));
372 }
373 }
374
375 std::vector<int> localHistogramValues(3 * (numBins + 1)),
376 globalHistogramValues(3 * (numBins + 1));
377 for (unsigned int d = 0; d < 3; ++d) {
378 int j = 0;
379 size_t accumulated = 0;
380 std::generate(
381 localHistogramValues.begin() + d * (numBins + 1) + 1,
382 localHistogramValues.begin() + (d + 1) * (numBins + 1),
383 [&histograms, &d, &j, &accumulated]() {
384 accumulated += gsl_histogram_get(histograms[d], j++);
385 return accumulated;
386 });
387
388 gsl_histogram_free(histograms[d]);
389 }
390
391 ippl::Comm->allreduce(
392 localHistogramValues.data(), globalHistogramValues.data(), 3 * (numBins + 1),
393 std::plus<int>());
394
395 int numParticles68 = boost::numeric_cast<int>(
397 int numParticles95 = boost::numeric_cast<int>(
399 int numParticles99 = boost::numeric_cast<int>(
401 int numParticles99_99 = boost::numeric_cast<int>(
403
404 for (int d = 0; d < 3; ++d) {
405 unsigned int localNum = last - first, current = 0;
406 std::vector<Vector_t<double, 2>> oneDPhaseSpace(localNum);
407 for (InputIt it = first; it != last; ++it, ++current) {
408 OpalParticle const& particle = *it;
409 oneDPhaseSpace[current](0) = particle[2 * d];
410 oneDPhaseSpace[current](1) = particle[2 * d + 1];
411 }
412 std::sort(
413 oneDPhaseSpace.begin(), oneDPhaseSpace.end(),
414 [d, this](Vector_t<double, 2>& left, Vector_t<double, 2>& right) {
415 return std::abs(left[0] - meanR_m[d]) < std::abs(right[0] - meanR_m[d]);
416 });
417
418 iterator_t endSixtyEight, endNinetyFive, endNinetyNine, endNinetyNine_NinetyNine;
419 endSixtyEight = endNinetyFive = endNinetyNine = endNinetyNine_NinetyNine =
420 oneDPhaseSpace.end();
421
422 std::tie(sixtyEightPercentile_m[d], endSixtyEight) = determinePercentilesDetail(
423 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
424 localHistogramValues, d, numParticles68);
425
426 std::tie(ninetyFivePercentile_m[d], endNinetyFive) = determinePercentilesDetail(
427 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
428 localHistogramValues, d, numParticles95);
429
430 std::tie(ninetyNinePercentile_m[d], endNinetyNine) = determinePercentilesDetail(
431 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
432 localHistogramValues, d, numParticles99);
433
434 std::tie(ninetyNine_NinetyNinePercentile_m[d], endNinetyNine_NinetyNine) =
436 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
437 localHistogramValues, d, numParticles99_99);
438
440 computeNormalizedEmittance(oneDPhaseSpace.begin(), endSixtyEight);
442 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyFive);
444 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyNine);
446 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyNine_NinetyNine);
447 }
448}
449
480std::pair<double, DistributionMoments::iterator_t> DistributionMoments::determinePercentilesDetail(
482 const std::vector<int>& globalAccumulatedHistogram,
483 const std::vector<int>& localAccumulatedHistogram, unsigned int dimension,
484 int numRequiredParticles) const {
485 unsigned int numBins = globalAccumulatedHistogram.size() / 3;
486 double percentile = 0.0;
487 iterator_t endPercentile = end;
488 for (unsigned int i = 1; i < numBins; ++i) {
489 unsigned int idx = dimension * numBins + i;
490 if (globalAccumulatedHistogram[idx] > numRequiredParticles) {
491 iterator_t beginBin = begin + localAccumulatedHistogram[idx - 1];
492 iterator_t endBin = begin + localAccumulatedHistogram[idx];
493 unsigned int numMissingParticles =
494 numRequiredParticles - globalAccumulatedHistogram[idx - 1];
495 unsigned int shift = 2;
496 while (numMissingParticles == 0) {
497 beginBin = begin + localAccumulatedHistogram[idx - shift];
498 numMissingParticles =
499 numRequiredParticles - globalAccumulatedHistogram[idx - shift];
500 ++shift;
501 }
502
503 std::vector<unsigned int> numParticlesInBin(ippl::Comm->size() + 1);
504 numParticlesInBin[ippl::Comm->rank() + 1] = endBin - beginBin;
505
506 ippl::Comm->allreduce(
507 &(numParticlesInBin[1]), ippl::Comm->size(), std::plus<unsigned int>());
508
509 std::partial_sum(
510 numParticlesInBin.begin(), numParticlesInBin.end(), numParticlesInBin.begin());
511
512 std::vector<double> positions(numParticlesInBin.back());
513 std::transform(
514 beginBin, endBin, positions.begin() + numParticlesInBin[ippl::Comm->rank()],
515 [&dimension, this](Vector_t<double, 2> const& particle) {
516 return std::abs(particle[0] - meanR_m[dimension]);
517 });
518 ippl::Comm->allreduce(&(positions[0]), positions.size(), std::plus<double>());
519 std::sort(positions.begin(), positions.end());
520
521 percentile = (*(positions.begin() + numMissingParticles - 1)
522 + *(positions.begin() + numMissingParticles))
523 / 2;
524 for (iterator_t it = beginBin; it != endBin; ++it) {
525 if (std::abs((*it)[0] - meanR_m[dimension]) > percentile) {
526 return std::make_pair(percentile, it);
527 }
528 }
529 endPercentile = endBin;
530 break;
531 }
532 }
533 return std::make_pair(percentile, endPercentile);
534}
535
539 double localStatistics[] = {0.0, 0.0, 0.0, 0.0};
540 localStatistics[0] = end - begin;
541 for (iterator_t it = begin; it < end; ++it) {
542 const Vector_t<double, 2>& rp = *it;
543 localStatistics[1] += rp(0);
544 localStatistics[2] += rp(1);
545 localStatistics[3] += rp(0) * rp(1);
546 }
547 ippl::Comm->allreduce(&(localStatistics[0]), 4, std::plus<double>());
548
549 double numParticles = localStatistics[0];
550 double perParticle = 1 / localStatistics[0];
551 double meanR = localStatistics[1] * perParticle;
552 double meanP = localStatistics[2] * perParticle;
553 double RP = localStatistics[3] * perParticle;
554
555 localStatistics[0] = 0.0;
556 localStatistics[1] = 0.0;
557 for (iterator_t it = begin; it < end; ++it) {
558 const Vector_t<double, 2>& rp = *it;
559 localStatistics[0] += std::pow(rp(0) - meanR, 2);
560 localStatistics[1] += std::pow(rp(1) - meanP, 2);
561 }
562 ippl::Comm->allreduce(&(localStatistics[0]), 2, std::plus<double>());
563
564 double stdR = std::sqrt(localStatistics[0] / numParticles);
565 double stdP = std::sqrt(localStatistics[1] / numParticles);
566 double sumRP = RP - meanR * meanP;
567 double squaredEps = std::pow(stdR * stdP, 2) - std::pow(sumRP, 2);
568 double normalizedEps = std::sqrt(std::max(squaredEps, 0.0));
569
570 return normalizedEps;
571}
572
573void DistributionMoments::fillMembers(std::vector<double>& /*localMoments*/) {
574 *gmsg << "not implemented" << endl;
575 /*
576 Vector_t<double, 3> squaredEps, fac, sumRP;
577 double perParticle = 1.0 / totalNumParticles_m;
578
579 unsigned int l = 0;
580 for (; l < 6; l += 2) {
581 stdR_m(l / 2) = std::sqrt(localMoments[l] / totalNumParticles_m);
582 stdP_m(l / 2) = std::sqrt(localMoments[l + 1] / totalNumParticles_m);
583 }
584
585 for (unsigned i = 0; i < moments_m.size1(); ++i) {
586 for (unsigned j = 0; j <= i; ++j, ++l) {
587 moments_m(i, j) = localMoments[l] * perParticle;
588 moments_m(j, i) = moments_m(i, j);
589 }
590 }
591
592 stdTime_m = localMoments[l++] * perParticle;
593
594 for (unsigned int i = 0; i < 3; ++i, l += 2) {
595 double w1 = centroid_m[2 * i] * perParticle;
596 double w2 = moments_m(2 * i, 2 * i);
597 double w3 = localMoments[l] * perParticle;
598 double w4 = localMoments[l + 1] * perParticle;
599 double tmp = w2 - std::pow(w1, 2);
600
601 halo_m(i) = (w4 + w1 * (-4 * w3 + 3 * w1 * (tmp + w2))) / tmp;
602 halo_m(i) -= Options::haloShift;
603 }
604
605 stdKineticEnergy_m = std::sqrt(localMoments[l++] * perParticle);
606
607 totalCharge_m = localMoments[l++];
608 totalMass_m = localMoments[l++];
609
610 for (unsigned int i = 0; i < 3; ++i) {
611 sumRP(i) = moments_m(2 * i, 2 * i + 1) - meanR_m(i) * meanP_m(i);
612 stdRP_m(i) = sumRP(i) / (stdR_m(i) * stdP_m(i));
613 squaredEps(i) = std::pow(stdR_m(i) * stdP_m(i), 2) - std::pow(sumRP(i), 2);
614 normalizedEps_m(i) = std::sqrt(std::max(squaredEps(i), 0.0));
615 }
616
617 double betaGamma = std::sqrt(std::pow(meanGamma_m, 2) - 1.0);
618 geometricEps_m = normalizedEps_m / Vector_t<double, 3>(betaGamma);
619 */
620}
621
623/*
624 double data[] = {0.0, 0.0};
625 // ada for (OpalParticle const& particle : bunch) {
626 // data[0] += Util::getKineticEnergy(particle.getP(), particle.getMass());
627 // }
628 data[1] = bunch.getLocalNum();
629 ippl::Comm->allreduce(data, 2, std::plus<double>());
630
631 meanKineticEnergy_m = data[0] / data[1];
632*/
633}
634
636 size_t Np,
637 size_t Nlocal,
638 double density){
639 Np = (Np == 0) ? 1 : Np; // Explanation: see DistributionMoments::computeMeans implementation
640
642 double loc_avgVel[3] = {};
643 double avgVel[3] = {};
644 double c = Physics::c;
645
646 // From P in \beta\gamma to get v in m/s: v = (P*c)/\gamma
648 "calc moments of particle distr.", Nlocal,
649 KOKKOS_LAMBDA(
650 const int k, double& mom0, double& mom1, double& mom2){
651
652 double gamma0 = 0.0;
653 for(unsigned j=0; j<3; j++){
654 gamma0 += Pview(k)[j]*Pview(k)[j];
655 }
656 gamma0 = Kokkos::sqrt(gamma0+1.0);
657
658 mom0 += Pview(k)[0] * c / gamma0;
659 mom1 += Pview(k)[1] * c / gamma0;
660 mom2 += Pview(k)[2] * c / gamma0;
661 },
662 Kokkos::Sum<double>(loc_avgVel[0]),
663 Kokkos::Sum<double>(loc_avgVel[1]),
664 Kokkos::Sum<double>(loc_avgVel[2]));
666 ippl::Comm->barrier();
667
668 MPI_Allreduce(
669 loc_avgVel, avgVel, Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
670
671 for (unsigned i = 0; i < 3; i++) {
672 avgVel[i] = avgVel[i] / Np;
673 }
674
675 double tempAvg=0;
676 double loc_tempAvg = 0.0;
678 /*
679 for (OpalParticle const& particle_r : bunch_r) {
680 for (unsigned i = 0; i < 3; i++) {
681 tempAvg += std::pow(
682 (((particle_r.getP()[i] * Physics::c) / (Util::getGamma(particle_r.getP())))
683 - avgVel[i]),
684 2);
685 }
686 }*/
687
689 "calc moments of particle distr.", Nlocal,
690 KOKKOS_LAMBDA(
691 const int k, double& mom0){
692
693 double gamma0 = 0.0;
694 for(unsigned j=0; j<3; j++){
695 gamma0 += Pview(k)[j]*Pview(k)[j];
696 }
697 gamma0 = Kokkos::sqrt(gamma0+1.0);
698
699 mom0 += Kokkos::pow( Pview(k)[0] * c / gamma0 - avgVel[0], 2);
700 mom0 += Kokkos::pow( Pview(k)[1] * c / gamma0 - avgVel[1], 2);
701 mom0 += Kokkos::pow( Pview(k)[2] * c / gamma0 - avgVel[2], 2);
702 },
703 Kokkos::Sum<double>(loc_tempAvg));
705 ippl::Comm->barrier();
706
707 MPI_Allreduce(
708 &loc_tempAvg, &tempAvg, 1, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
709
710 // Compute the average temperature k_B T in units of kg m^2/s^2, where k_B is
711 // Boltzmann constant
712 temperature_m = (1.0 / 3.0) * Units::eV2kg * Units::GeV2eV * Physics::m_e * (tempAvg / Np);
713
715 std::sqrt((temperature_m * Physics::epsilon_0) / (density * std::pow(Physics::q_e, 2)));
716
717 computePlasmaParameter(density);
718}
719
721 // Plasma parameter: Average number of particles within the Debye sphere
722 plasmaParameter_m = (4.0 / 3.0) * Physics::pi * std::pow(debyeLength_m, 3) * density;
723}
724
726 std::fill(std::begin(centroid_m), std::end(centroid_m), 0.0);
727 meanR_m = 0.0;
728 meanP_m = 0.0;
729 stdR_m = 0.0;
730 stdP_m = 0.0;
731 stdRP_m = 0.0;
732 normalizedEps_m = 0.0;
733 geometricEps_m = 0.0;
734 halo_m = 0.0;
735
737 stdKineticEnergy_m = 0.0;
738
739 totalCharge_m = 0.0;
740 totalMass_m = 0.0;
742
751}
752
754 temperature_m = 0.0;
755 debyeLength_m = 0.0;
756 plasmaParameter_m = 0.0;
757}
758
761 // FIXME After issue 287 is resolved this shouldn't be necessary anymore
762 *gmsg << "not implemented" << endl;
763 return true;
764}
Inform * gmsg
Definition: changes.cpp:7
PartBunch< T, Dim >::ConstIterator end(PartBunch< T, Dim > const &bunch)
PartBunch< T, Dim >::ConstIterator begin(PartBunch< T, Dim > const &bunch)
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
constexpr KOKKOS_INLINE_FUNCTION auto first()
Definition: AbsorbingBC.h:10
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
Definition: Physics.h:51
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:69
constexpr double m_e
The electron rest mass in GeV.
Definition: Physics.h:78
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
constexpr double pi
The value of.
Definition: Physics.h:30
constexpr double GeV2eV
Definition: Units.h:68
constexpr double eV2kg
Definition: Units.h:110
bool computePercentiles
Definition: Options.cpp:105
double haloShift
The constant parameter C to shift halo, by < w^4 > / < w^2 > ^2 - C (w=x,y,z)
Definition: Options.cpp:101
void fence()
Definition: Ippl.cpp:103
KOKKOS_INLINE_FUNCTION Vector< T, Dim > max(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
Definition: Vector.hpp:226
RangePolicy< View::rank, typenameView::execution_space, PolicyArgs... >::policy_type getRangePolicy(const View &view, int shift=0)
void parallel_reduce(const std::string &name, const ExecPolicy &policy, const FunctorType &functor, ReducerArgument &&... reducer)
std::unique_ptr< mpi::Communicator > Comm
Definition: Ippl.h:22
void fillMembers(std::vector< double > &)
Vector_t< double, 3 > sixtyEightPercentile_m
Vector_t< double, 3 > ninetyFivePercentile_m
void computeDebyeLength(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Pview, size_t Np, size_t Nlocal, double density)
void computePlasmaParameter(double)
std::vector< Vector_t< double, 2 > >::const_iterator iterator_t
Vector_t< double, 3 > minR_m
static const double percentileFourSigmasNormalDist_m
unsigned int totalNumParticles_m
Vector_t< double, 3 > ninetyNinePercentile_m
void compute(const std::vector< OpalParticle >::const_iterator &, const std::vector< OpalParticle >::const_iterator &)
void computeMoments(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Rview, ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Pview, ippl::ParticleAttrib< double >::view_type &Mview, size_t Np, size_t Nlocal)
Vector_t< double, 3 > ninetyNine_NinetyNinePercentile_m
Vector_t< double, 3 > normalizedEps_m
Vector_t< double, 3 > normalizedEps68Percentile_m
void computeMinMaxPosition(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Rview, size_t Nlcoal)
Vector_t< double, 3 > meanP_m
double computeNormalizedEmittance(const iterator_t &begin, const iterator_t &end) const
Vector_t< double, 3 > halo_m
Vector_t< double, 3 > stdP_m
Vector_t< double, 3 > normalizedEps99Percentile_m
Vector_t< double, 3 > stdR_m
static const double percentileThreeSigmasNormalDist_m
Vector_t< double, 3 > meanR_m
void computeMeans(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Rview, ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type &Pview, ippl::ParticleAttrib< double >::view_type &Mview, size_t Np, size_t Nlocal)
void computePercentiles(const InputIt &, const InputIt &)
static const double percentileTwoSigmasNormalDist_m
Vector_t< double, 3 > normalizedEps99_99Percentile_m
bool isParticleExcluded(const OpalParticle &) const
Vector_t< double, 3 > maxR_m
Vector_t< double, 3 > stdRP_m
std::pair< double, iterator_t > determinePercentilesDetail(const iterator_t &begin, const iterator_t &end, const std::vector< int > &globalAccumulatedHistogram, const std::vector< int > &localAccumulatedHistogram, unsigned int dimension, int numRequiredParticles) const
Computes the percentile and the range of all local particles that are contained therein.
Vector_t< double, 3 > geometricEps_m
static const double percentileOneSigmaNormalDist_m
Vector_t< double, 6 > means_m
Vector_t< double, 6 > centroid_m
Vector_t< double, 3 > normalizedEps95Percentile_m
typename detail::ViewType< T, 1, Properties... >::view_type view_type
Definition: Inform.h:40
constexpr unsigned Dim