OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
DistributionMoments.cpp
Go to the documentation of this file.
1
2// Class DistributionMoments
3// Computes the statistics of particle distributions.
4//
5// Copyright (c) 2025, Paul Scherrer Institut, Villigen PSI, Switzerland
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 <limits>
22
26#include "Utilities/Options.h"
27
28const double DistributionMoments::percentileOneSigmaNormalDist_m = std::erf(1 / sqrt(2));
29const double DistributionMoments::percentileTwoSigmasNormalDist_m = std::erf(2 / sqrt(2));
30const double DistributionMoments::percentileThreeSigmasNormalDist_m = std::erf(3 / sqrt(2));
31const double DistributionMoments::percentileFourSigmasNormalDist_m = std::erf(4 / sqrt(2));
32
39
40// ---------------------------------------------------------------------------
41// computeMeans -- single Kokkos reduce for 6 centroids + Ekin + gamma
42// ---------------------------------------------------------------------------
44 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Rview,
45 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Pview,
46 ippl::ParticleAttrib<double>::view_type Mview, size_t Np, size_t Nlocal) {
47 /*
48 Np is the total number of particles (reduced over ranks). In this function, it is only used to
49 average over the number of total particles. For an empty simulation, this leads to divisions by
50 0. Since, however, some of the computed moments might be needed regardless, we compute them but
51 need to make sure that we do not divide by 0.
52 Solution: Set Np to 1 if it is 0.
53 */
54 Np = (Np == 0) ? 1 : Np;
55
56 const bool rescaleToReference = rescaleToReference_m;
57 const double referenceMassGeV = referenceMassGeV_m;
58
59 /*
60 If the storage mode is SingleValue, then the mass is a scalar value that is the same for all
61 particles. If the storage mode is Attributes, then the mass is a per-particle attribute.
62 */
63 const bool massIsScalarView = (Mview.extent(0) == 1);
64
65 // Reduce 8 quantities in a single kernel:
66 // [0..5] centroids (x, px, y, py, z, pz)
67 // [6] kinetic energy sum
68 // [7] gamma sum
69 SumArray<8> loc;
70 Kokkos::parallel_reduce(
71 "computeMeans", Nlocal,
72 KOKKOS_LAMBDA(const size_t k, SumArray<8>& upd) {
73 upd.data[0] += Rview(k)[0];
74 upd.data[1] += Pview(k)[0];
75 upd.data[2] += Rview(k)[1];
76 upd.data[3] += Pview(k)[1];
77 upd.data[4] += Rview(k)[2];
78 upd.data[5] += Pview(k)[2];
79
80 double gamma0 = Kokkos::sqrt(dot(Pview(k)) + 1.0);
81
82 const double massGeV = rescaleToReference
83 ? referenceMassGeV
84 : (massIsScalarView ? Mview(0) : Mview(k));
85 upd.data[6] += (gamma0 - 1.0) * massGeV * Units::GeV2MeV;
86 upd.data[7] += gamma0;
87 },
88 Kokkos::Sum<SumArray<8>>(loc));
89 Kokkos::fence();
90
91 double glob[8];
92 ippl::Comm->allreduce(&loc.data[0], &glob[0], 8, std::plus<double>());
93
94 for (size_t i = 0; i < 2 * Dim; ++i) {
95 centroid_m(i) = glob[i];
96 means_m(i) = centroid_m[i] / Np;
97 }
98
99 meanKineticEnergy_m = glob[6] / (1. * Np);
100 meanGamma_m = glob[7] / (1. * Np);
101
102 // gammaz reuses the pz centroid (index 5): gammaz = sqrt( (<pz>/Np)^2 + 1 )
103 double gammaz = glob[5] / (1. * Np);
104 gammaz = std::sqrt(gammaz * gammaz + 1.0);
105 meanGammaZ_m = gammaz;
106
107 for (size_t i = 0; i < Dim; ++i) {
108 meanR_m(i) = means_m[2 * i];
109 meanP_m(i) = means_m[2 * i + 1];
110 }
111}
112
113// ---------------------------------------------------------------------------
114// computeMoments -- three Kokkos reducers in a single parallel_reduce:
115// SumMatrix6x6 central moments, SumMatrix6x6 non-central moments,
116// double std kinetic energy
117// ---------------------------------------------------------------------------
119 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Rview,
120 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Pview,
121 ippl::ParticleAttrib<double>::view_type Mview, size_t Np, size_t Nlocal) {
122 // Lock the per-container slot. Null = never bound; expired = owning
123 // ParticleContainer was destroyed before this call (a bug either way).
124 auto slot = containerState_m.lock();
125 if (!slot) {
126 throw OpalException(
127 "DistributionMoments::computeMoments",
128 "ContainerState not available (expired or never bound). "
129 "Did you forget setContainerState(), or did the owning "
130 "ParticleContainer outlive its slot?");
131 }
132
133 // Short-circuit: nothing has mutated R or P since the last compute.
134 // Every caller that mutates particle state is required to call
135 // markMomentsDirty(), including PartBunch::bunchUpdate(), which calls
136 // pc->markMomentsDirty() immediately after IPPL's pc->update() so that
137 // domain-decomposition / particle migration is also covered.
138 if (!slot->momentsDirty) {
139 return;
140 }
141
142 Np = (Np == 0) ? 1 : Np; // Explanation: see DistributionMoments::computeMeans
143 // implementation
144
145 IpplTimings::TimerRef momentsTimer = IpplTimings::getTimer("computeMoments");
146 IpplTimings::startTimer(momentsTimer);
147
148 reset();
149 computeMeans(Rview, Pview, Mview, Np, Nlocal);
150
151 double meanR_loc[Dim];
152 double meanP_loc[Dim];
153 for (size_t i = 0; i < Dim; ++i) {
154 meanR_loc[i] = meanR_m[i];
155 meanP_loc[i] = meanP_m[i];
156 }
157
158 const double mekin = meanKineticEnergy_m;
159 const bool rescaleToReferenceStd = rescaleToReference_m;
160 const double referenceMassGeVStd = referenceMassGeV_m;
161 const bool massIsScalarView = (Mview.extent(0) == 1);
162
163 SumMatrix6x6 loc_cent;
164 SumMatrix6x6 loc_ncent;
165 double loc_std_ekin = 0.0;
166
167 Kokkos::parallel_reduce(
168 "computeMoments", Nlocal,
169 KOKKOS_LAMBDA(
170 const size_t k, SumMatrix6x6& cent_upd, SumMatrix6x6& ncent_upd,
171 double& ekin_upd) {
172 double cent[6];
173 cent[0] = Rview(k)[0] - meanR_loc[0];
174 cent[1] = Pview(k)[0] - meanP_loc[0];
175 cent[2] = Rview(k)[1] - meanR_loc[1];
176 cent[3] = Pview(k)[1] - meanP_loc[1];
177 cent[4] = Rview(k)[2] - meanR_loc[2];
178 cent[5] = Pview(k)[2] - meanP_loc[2];
179
180 double raw[6];
181 raw[0] = Rview(k)[0];
182 raw[1] = Pview(k)[0];
183 raw[2] = Rview(k)[1];
184 raw[3] = Pview(k)[1];
185 raw[4] = Rview(k)[2];
186 raw[5] = Pview(k)[2];
187
188 for (size_t i = 0; i < 6; ++i) {
189 for (size_t j = 0; j < 6; ++j) {
190 cent_upd.data[i][j] += cent[i] * cent[j];
191 ncent_upd.data[i][j] += raw[i] * raw[j];
192 }
193 }
194
195 double gamma0 = Kokkos::sqrt(dot(Pview(k)) + 1.0);
196 const double massGeV = rescaleToReferenceStd
197 ? referenceMassGeVStd
198 : (massIsScalarView ? Mview(0) : Mview(k));
199 double ekin0 = (gamma0 - 1.0) * massGeV * Units::GeV2MeV;
200 ekin_upd += (ekin0 - mekin) * (ekin0 - mekin);
201 },
202 Kokkos::Sum<SumMatrix6x6>(loc_cent), Kokkos::Sum<SumMatrix6x6>(loc_ncent),
203 Kokkos::Sum<double>(loc_std_ekin));
204
205 SumMatrix6x6 glob_cent, glob_ncent;
206 ippl::Comm->allreduce(&loc_cent.data[0][0], &glob_cent.data[0][0], 36, std::plus<double>());
207 ippl::Comm->allreduce(&loc_ncent.data[0][0], &glob_ncent.data[0][0], 36, std::plus<double>());
208
209 double glob_std_ekin;
210 ippl::Comm->allreduce(&loc_std_ekin, &glob_std_ekin, 1, std::plus<double>());
211
212 for (size_t i = 0; i < 2 * Dim; ++i) {
213 for (size_t j = 0; j < 2 * Dim; ++j) {
214 moments_m(i, j) = glob_cent.data[i][j] / Np;
215 notCentMoments_m(i, j) = glob_ncent.data[i][j];
216 }
217 }
218
219 for (size_t i = 0; i < Dim; ++i) {
220 stdR_m(i) = std::sqrt(moments_m(2 * i, 2 * i));
221 stdP_m(i) = std::sqrt(moments_m(2 * i + 1, 2 * i + 1));
222 }
223
224 stdKineticEnergy_m = std::sqrt(glob_std_ekin / Np);
225
226 double perParticle = 1. / (1. * Np);
227 Vector_t<double, 3> squaredEps, sumRP;
228 size_t l = 0;
229 for (size_t i = 0; i < 3; ++i, l += 2) {
230 double w1 = centroid_m[2 * i] * perParticle;
231 double w2 = moments_m(2 * i, 2 * i);
232 double w3 = notCentMoments_m(l, l) * perParticle;
233 double w4 = notCentMoments_m(l + 1, l + 1) * perParticle;
234 double tmp = w2 - std::pow(w1, 2);
235
236 halo_m(i) = (w4 + w1 * (-4 * w3 + 3 * w1 * (tmp + w2))) / tmp;
238 }
239
240 for (size_t i = 0; i < 3; ++i) {
241 sumRP(i) = notCentMoments_m(2 * i, 2 * i + 1) * perParticle - meanR_m(i) * meanP_m(i);
242 stdRP_m(i) = sumRP(i) / (stdR_m(i) * stdP_m(i));
243 squaredEps(i) = std::pow(stdR_m(i) * stdP_m(i), 2) - std::pow(sumRP(i), 2);
244 normalizedEps_m(i) = std::sqrt(std::max(squaredEps(i), 0.0));
245 }
246
247 double betaGamma = std::sqrt(std::pow(meanGamma_m, 2) - 1.0);
249
250 slot->markMomentsClean();
251 IpplTimings::stopTimer(momentsTimer);
252}
253
254// ---------------------------------------------------------------------------
255// computeMinMaxPosition -- MaxArray<3> + MinArray<3> in a single reduce
256// ---------------------------------------------------------------------------
258 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Rview, size_t Nlocal) {
259 // Identity values (lowest / max) are set by the default constructors, so
260 // ranks with Nlocal == 0 naturally contribute neutral elements to the allreduce.
261 Inform m("DistributionMoments::computeMinMaxPosition");
262 MaxArray<3> loc_max;
263 MinArray<3> loc_min;
264
265 Kokkos::parallel_reduce(
266 "computeMinMaxPosition", Nlocal,
267 KOKKOS_LAMBDA(const size_t k, MaxArray<3>& rmax, MinArray<3>& rmin) {
268 for (size_t d = 0; d < 3; ++d) {
269 const double r = Rview(k)[d];
270 if (r > rmax.data[d]) rmax.data[d] = r;
271 if (r < rmin.data[d]) rmin.data[d] = r;
272 }
273 },
274 Kokkos::Sum<MaxArray<3>>(loc_max), Kokkos::Sum<MinArray<3>>(loc_min));
275
276 double rmax[Dim], rmin[Dim];
277 ippl::Comm->allreduce(&loc_max.data[0], &rmax[0], Dim, std::greater<double>());
278 ippl::Comm->allreduce(&loc_min.data[0], &rmin[0], Dim, std::less<double>());
279
280 // Empty bunch on all ranks: min stays id_min, max stays id_max -> min > max.
281 // Use a tiny valid box so mesh/spacing remain valid (e.g. for first step before emission). The
282 // same problem arises when one dimension is 0 (e.g. flattop first timestep), then rmin>=rmax
283 // would trigger "=0". Therefore, we HAVE to check rmin>rmax instead.
284 for (size_t i = 0; i < Dim; ++i) {
285 if (rmin[i] > rmax[i]) {
286 rmin[i] = rmax[i] = 0.0;
287 m << level5 << "Min > max in dimension " << i << ". Setting to 0 (degenerate case)."
288 << endl;
289 }
290 }
291
292 for (size_t i = 0; i < Dim; ++i) {
293 minR_m(i) = rmin[i];
294 maxR_m(i) = rmax[i];
295 }
296 m << level5 << "Min/max computation done." << endl;
297}
298
299// ---------------------------------------------------------------------------
300
302 const std::vector<OpalParticle>::const_iterator& /*first*/,
303 const std::vector<OpalParticle>::const_iterator& /*last*/) {
304 throw OpalException(
305 "DistributionMoments::compute", "OpalParticle-iterator interface is not implemented.");
306}
307
308template <class InputIt>
309void DistributionMoments::computePercentiles(const InputIt& first, const InputIt& last) {
311 return;
312 }
313
314 std::vector<gsl_histogram*> histograms(3);
315 // For a normal distribution the number of exchanged data between the cores is minimized
316 // if the number of histogram bins follows the following formula. Since we can't know
317 // how many particles are in each bin for the real distribution we use this formula.
318 unsigned int numBins = 3.5 * std::pow(3, std::log10(totalNumParticles_m));
319
321 for (size_t d = 0; d < 3; ++d) {
322 maxR(d) = 1.0000001 * std::max(maxR_m[d] - meanR_m[d], meanR_m[d] - minR_m[d]);
323 histograms[d] = gsl_histogram_alloc(numBins);
324 gsl_histogram_set_ranges_uniform(histograms[d], 0.0, maxR(d));
325 }
326 for (InputIt it = first; it != last; ++it) {
327 OpalParticle const& particle = *it;
328 for (size_t d = 0; d < 3; ++d) {
329 gsl_histogram_increment(histograms[d], std::abs(particle[2 * d] - meanR_m[d]));
330 }
331 }
332
333 std::vector<int> localHistogramValues(3 * (numBins + 1)),
334 globalHistogramValues(3 * (numBins + 1));
335 for (size_t d = 0; d < 3; ++d) {
336 int j = 0;
337 size_t accumulated = 0;
338 std::generate(
339 localHistogramValues.begin() + d * (numBins + 1) + 1,
340 localHistogramValues.begin() + (d + 1) * (numBins + 1),
341 [&histograms, &d, &j, &accumulated]() {
342 accumulated += gsl_histogram_get(histograms[d], j++);
343 return accumulated;
344 });
345
346 gsl_histogram_free(histograms[d]);
347 }
348
349 ippl::Comm->allreduce(
350 localHistogramValues.data(), globalHistogramValues.data(), 3 * (numBins + 1),
351 std::plus<int>());
352
353 int numParticles68 = static_cast<int>(
355 int numParticles95 = static_cast<int>(
357 int numParticles99 = static_cast<int>(
359 int numParticles99_99 = static_cast<int>(
361
362 for (int d = 0; d < 3; ++d) {
363 unsigned int localNum = last - first, current = 0;
364 std::vector<Vector_t<double, 2>> oneDPhaseSpace(localNum);
365 for (InputIt it = first; it != last; ++it, ++current) {
366 OpalParticle const& particle = *it;
367 oneDPhaseSpace[current](0) = particle[2 * d];
368 oneDPhaseSpace[current](1) = particle[2 * d + 1];
369 }
370 std::sort(
371 oneDPhaseSpace.begin(), oneDPhaseSpace.end(),
372 [d, this](Vector_t<double, 2>& left, Vector_t<double, 2>& right) {
373 return std::abs(left[0] - meanR_m[d]) < std::abs(right[0] - meanR_m[d]);
374 });
375
376 iterator_t endSixtyEight, endNinetyFive, endNinetyNine, endNinetyNine_NinetyNine;
377 endSixtyEight = endNinetyFive = endNinetyNine = endNinetyNine_NinetyNine =
378 oneDPhaseSpace.end();
379
380 std::tie(sixtyEightPercentile_m[d], endSixtyEight) = determinePercentilesDetail(
381 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
382 localHistogramValues, d, numParticles68);
383
384 std::tie(ninetyFivePercentile_m[d], endNinetyFive) = determinePercentilesDetail(
385 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
386 localHistogramValues, d, numParticles95);
387
388 std::tie(ninetyNinePercentile_m[d], endNinetyNine) = determinePercentilesDetail(
389 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
390 localHistogramValues, d, numParticles99);
391
392 std::tie(ninetyNine_NinetyNinePercentile_m[d], endNinetyNine_NinetyNine) =
394 oneDPhaseSpace.begin(), oneDPhaseSpace.end(), globalHistogramValues,
395 localHistogramValues, d, numParticles99_99);
396
398 computeNormalizedEmittance(oneDPhaseSpace.begin(), endSixtyEight);
400 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyFive);
402 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyNine);
404 computeNormalizedEmittance(oneDPhaseSpace.begin(), endNinetyNine_NinetyNine);
405 }
406}
407
438std::pair<double, DistributionMoments::iterator_t> DistributionMoments::determinePercentilesDetail(
440 const std::vector<int>& globalAccumulatedHistogram,
441 const std::vector<int>& localAccumulatedHistogram, unsigned int dimension,
442 int numRequiredParticles) const {
443 unsigned int numBins = globalAccumulatedHistogram.size() / 3;
444 double percentile = 0.0;
445 iterator_t endPercentile = end;
446 for (unsigned int i = 1; i < numBins; ++i) {
447 unsigned int idx = dimension * numBins + i;
448 if (globalAccumulatedHistogram[idx] > numRequiredParticles) {
449 iterator_t beginBin = begin + localAccumulatedHistogram[idx - 1];
450 iterator_t endBin = begin + localAccumulatedHistogram[idx];
451 unsigned int numMissingParticles =
452 numRequiredParticles - globalAccumulatedHistogram[idx - 1];
453 unsigned int shift = 2;
454 while (numMissingParticles == 0) {
455 beginBin = begin + localAccumulatedHistogram[idx - shift];
456 numMissingParticles =
457 numRequiredParticles - globalAccumulatedHistogram[idx - shift];
458 ++shift;
459 }
460
461 std::vector<unsigned int> numParticlesInBin(ippl::Comm->size() + 1);
462 numParticlesInBin[ippl::Comm->rank() + 1] = endBin - beginBin;
463
464 ippl::Comm->allreduce(
465 &(numParticlesInBin[1]), ippl::Comm->size(), std::plus<unsigned int>());
466
467 std::partial_sum(
468 numParticlesInBin.begin(), numParticlesInBin.end(), numParticlesInBin.begin());
469
470 std::vector<double> positions(numParticlesInBin.back());
471 std::transform(
472 beginBin, endBin, positions.begin() + numParticlesInBin[ippl::Comm->rank()],
473 [&dimension, this](Vector_t<double, 2> const& particle) {
474 return std::abs(particle[0] - meanR_m[dimension]);
475 });
476 ippl::Comm->allreduce(&(positions[0]), positions.size(), std::plus<double>());
477 std::sort(positions.begin(), positions.end());
478
479 percentile = (*(positions.begin() + numMissingParticles - 1)
480 + *(positions.begin() + numMissingParticles))
481 / 2;
482 for (iterator_t it = beginBin; it != endBin; ++it) {
483 if (std::abs((*it)[0] - meanR_m[dimension]) > percentile) {
484 return std::make_pair(percentile, it);
485 }
486 }
487 endPercentile = endBin;
488 break;
489 }
490 }
491 return std::make_pair(percentile, endPercentile);
492}
493
496 const DistributionMoments::iterator_t& end) const {
497 double localStatistics[] = {0.0, 0.0, 0.0, 0.0};
498 localStatistics[0] = end - begin;
499 for (iterator_t it = begin; it < end; ++it) {
500 const Vector_t<double, 2>& rp = *it;
501 localStatistics[1] += rp(0);
502 localStatistics[2] += rp(1);
503 localStatistics[3] += rp(0) * rp(1);
504 }
505 ippl::Comm->allreduce(&(localStatistics[0]), 4, std::plus<double>());
506
507 double numParticles = localStatistics[0];
508 double perParticle = 1 / localStatistics[0];
509 double meanR = localStatistics[1] * perParticle;
510 double meanP = localStatistics[2] * perParticle;
511 double RP = localStatistics[3] * perParticle;
512
513 localStatistics[0] = 0.0;
514 localStatistics[1] = 0.0;
515 for (iterator_t it = begin; it < end; ++it) {
516 const Vector_t<double, 2>& rp = *it;
517 localStatistics[0] += std::pow(rp(0) - meanR, 2);
518 localStatistics[1] += std::pow(rp(1) - meanP, 2);
519 }
520 ippl::Comm->allreduce(&(localStatistics[0]), 2, std::plus<double>());
521
522 double stdR = std::sqrt(localStatistics[0] / numParticles);
523 double stdP = std::sqrt(localStatistics[1] / numParticles);
524 double sumRP = RP - meanR * meanP;
525 double squaredEps = std::pow(stdR * stdP, 2) - std::pow(sumRP, 2);
526 double normalizedEps = std::sqrt(std::max(squaredEps, 0.0));
527
528 return normalizedEps;
529}
530
531// ---------------------------------------------------------------------------
532
533void DistributionMoments::fillMembers(std::vector<double>& /*localMoments*/) {
534 throw OpalException(
535 "DistributionMoments::fillMembers", "Not implemented -- must not be called.");
536}
537
539 throw OpalException(
540 "DistributionMoments::computeMeanKineticEnergy",
541 "Not implemented -- must not be called.");
542}
543
544// ---------------------------------------------------------------------------
545// computeDebyeLength -- SumArray<3> for avg velocity, scalar for temperature
546// ---------------------------------------------------------------------------
548 ippl::ParticleAttrib<Vector_t<double, 3>>::view_type Pview, size_t Np, size_t Nlocal,
549 double density) {
550 Np = (Np == 0) ? 1 : Np;
551
553 const double c = Physics::c;
554
555 // v = (P * c) / gamma --> average velocity per component
556 SumArray<3> loc_vel;
557 Kokkos::parallel_reduce(
558 "computeDebyeLength avgVel", Nlocal,
559 KOKKOS_LAMBDA(const size_t k, SumArray<3>& upd) {
560 double gamma0 = Kokkos::sqrt(dot(Pview(k)) + 1.0);
561
562 upd.data[0] += Pview(k)[0] * c / gamma0;
563 upd.data[1] += Pview(k)[1] * c / gamma0;
564 upd.data[2] += Pview(k)[2] * c / gamma0;
565 },
566 Kokkos::Sum<SumArray<3>>(loc_vel));
567 Kokkos::fence();
568
569 double avgVel[3];
570 ippl::Comm->allreduce(&loc_vel.data[0], &avgVel[0], Dim, std::plus<double>());
571
572 for (unsigned i = 0; i < 3; ++i)
573 avgVel[i] /= Np;
574
575 double loc_tempAvg = 0.0;
576 Kokkos::parallel_reduce(
577 "computeDebyeLength temperature", Nlocal,
578 KOKKOS_LAMBDA(const size_t k, double& mom0) {
579 double gamma0 = Kokkos::sqrt(dot(Pview(k)) + 1.0);
580
581 mom0 += Kokkos::pow(Pview(k)[0] * c / gamma0 - avgVel[0], 2);
582 mom0 += Kokkos::pow(Pview(k)[1] * c / gamma0 - avgVel[1], 2);
583 mom0 += Kokkos::pow(Pview(k)[2] * c / gamma0 - avgVel[2], 2);
584 },
585 Kokkos::Sum<double>(loc_tempAvg));
586 Kokkos::fence();
587
588 double tempAvg;
589 ippl::Comm->allreduce(&loc_tempAvg, &tempAvg, 1, std::plus<double>());
590
591 // k_B T in units of kg m^2/s^2
592 temperature_m = (1.0 / 3.0) * Units::eV2kg * Units::GeV2eV * Physics::m_e * (tempAvg / Np);
593
595 std::sqrt((temperature_m * Physics::epsilon_0) / (density * std::pow(Physics::q_e, 2)));
596
597 computePlasmaParameter(density);
598}
599
601 plasmaParameter_m = (4.0 / 3.0) * Physics::pi * std::pow(debyeLength_m, 3) * density;
602}
603
604// ---------------------------------------------------------------------------
605
607 std::fill(std::begin(centroid_m), std::end(centroid_m), 0.0);
608 meanR_m = 0.0;
609 meanP_m = 0.0;
610 stdR_m = 0.0;
611 stdP_m = 0.0;
612 stdRP_m = 0.0;
613 normalizedEps_m = 0.0;
614 geometricEps_m = 0.0;
615 halo_m = 0.0;
616
618 stdKineticEnergy_m = 0.0;
619
620 totalCharge_m = 0.0;
621 totalMass_m = 0.0;
623
632}
633
639
641 throw OpalException(
642 "DistributionMoments::isParticleExcluded", "Not implemented -- must not be called.");
643}
ippl::Vector< T, Dim > Vector_t
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
void gsl_histogram_free(gsl_histogram *h)
Free a histogram allocated by gsl_histogram_alloc.
void gsl_histogram_increment(gsl_histogram *h, double x)
Increment the bin containing x by 1.
void gsl_histogram_set_ranges_uniform(gsl_histogram *h, double xmin, double xmax)
Set uniform bin edges over .
gsl_histogram * gsl_histogram_alloc(size_t n)
Allocate a 1D histogram with n bins.
matrix_t< 6, 6 > matrix6x6_t
Definition Matrix.h:97
constexpr unsigned Dim
Definition OPALTypes.h:7
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:95
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)
std::vector< Vector_t< double, 2 > >::const_iterator iterator_t
Vector_t< double, 3 > minR_m
static const double percentileFourSigmasNormalDist_m
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)
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 computeMinMaxPosition(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type Rview, size_t Nlcoal)
Vector_t< double, 3 > ninetyNinePercentile_m
void compute(const std::vector< OpalParticle >::const_iterator &, const std::vector< OpalParticle >::const_iterator &)
Vector_t< double, 3 > ninetyNine_NinetyNinePercentile_m
Vector_t< double, 3 > normalizedEps_m
Vector_t< double, 3 > normalizedEps68Percentile_m
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 computePercentiles(const InputIt &, const InputIt &)
static const double percentileTwoSigmasNormalDist_m
Vector_t< double, 3 > normalizedEps99_99Percentile_m
bool isParticleExcluded(const OpalParticle &) const
std::weak_ptr< BunchStateHandler::ContainerState > containerState_m
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
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
bool computePercentiles
Definition Options.cpp:107
double haloShift
The constant parameter C to shift halo, by < w^4 > / < w^2 > ^2 - C (w=x,y,z)
Definition Options.cpp:103
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
Definition Physics.h:66
constexpr double q_e
The elementary charge in As.
Definition Physics.h:84
constexpr double m_e
The electron rest mass in GeV.
Definition Physics.h:93
constexpr double c
The velocity of light in m/s.
Definition Physics.h:60
constexpr double pi
The value of.
Definition Physics.h:36
constexpr double GeV2MeV
Definition Units.h:80
constexpr double GeV2eV
Definition Units.h:68
constexpr double eV2kg
Definition Units.h:110