OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
Gaussian.cpp
Go to the documentation of this file.
1#include "Distribution.h"
2#include "SamplingBase.hpp"
3#include "Gaussian.h"
4#include <memory>
5#include <cmath>
6
14Gaussian::Gaussian(std::shared_ptr<ParticleContainer_t> &pc,
15 std::shared_ptr<FieldContainer_t> &fc,
16 std::shared_ptr<Distribution_t> &opalDist)
17 : SamplingBase(pc, fc, opalDist) {
18 samperTimer_m = IpplTimings::getTimer("SamplingTimer");
20 setSigmaP(opalDist->getSigmaP());
21 setSigmaR(opalDist->getSigmaR());
22 setAvrgpz(opalDist->getAvrgpz());
23 setCutoffR(opalDist->getCutoffR());
24}
25
26Gaussian::Gaussian(std::shared_ptr<ParticleContainer_t> pc,
27 const Vector_t<double, 3>& sigmaR,
28 const Vector_t<double, 3>& sigmaP,
29 double avrgpz, const Vector_t<double, 3>& cutoffR,
30 bool fixMeanR)
31 : SamplingBase(pc) {
32 setSigmaR(sigmaR);
33 setSigmaP(sigmaP);
34 setAvrgpz(avrgpz);
35 setCutoffR(cutoffR);
36 setFixMeanR(fixMeanR);
37
38 samperTimer_m = IpplTimings::getTimer("SamplingTimer");
40}
41
43 extern Inform* gmsg;
44 size_t randInit;
45
46 if (Options::seed == -1) {
47 randInit = 1234567;
48 *gmsg << "* Seed = " << randInit << " on all ranks" << endl;
49 } else {
50 randInit = static_cast<size_t>(Options::seed + 100 * ippl::Comm->rank());
51 }
52
53 GeneratorPool rand_pool64(randInit);
54 randPool_m = rand_pool64;
55 return;
56}
57
64void Gaussian::generateParticles(size_t& numberOfParticles, Vector_t<double, 3> nr) {
65 extern Inform* gmsg;
66 auto rand_pool64 = randPool_m;
67
68 IpplTimings::startTimer(samperTimer_m);
69
70 double mu[3], sd[3];
71
74
75 for (int i = 0; i < 3; i++) {
76 mu[i] = 0.0;
77 sd[i] = sigmaR_m[i];
78 rmin(i) = (rmin(i) + mu[i]) * sigmaR_m[i];
79 rmax(i) = (rmax(i) + mu[i]) * sigmaR_m[i];
80 }
81
82 view_type &Rview = pc_m->R.getView();
83 const double par[6] = {mu[0], sd[0], mu[1], sd[1], mu[2], sd[2]};
84
85 using Dist_t = ippl::random::NormalDistribution<double, 3>;
86 using sampling_t = ippl::random::InverseTransformSampling<double, 3, Kokkos::DefaultExecutionSpace, Dist_t>;
87 Dist_t dist(par);
88
89 MPI_Comm comm = MPI_COMM_WORLD;
90 int nranks, rank;
91 MPI_Comm_size(comm, &nranks);
92 MPI_Comm_rank(comm, &rank);
93
94 size_t nlocal = floor(numberOfParticles / nranks);
95 size_t remaining = numberOfParticles - nlocal * nranks;
96
97 if (remaining > 0 && rank == 0) {
98 nlocal += remaining;
99 }
100
101 sampling_t sampling(dist, rmax, rmin, rmax, rmin, nlocal);
102 nlocal = sampling.getLocalSamplesNum();
103 pc_m->create(nlocal);
104 sampling.generate(Rview, rand_pool64);
105
106 if (fixMeanR_m) {
107
108 double meanR[3], loc_meanR[3];
109 for(int i=0; i<3; i++){
110 meanR[i] = 0.0;
111 loc_meanR[i] = 0.0;
112 }
113
114 Kokkos::parallel_reduce(
115 "calc moments of particle distr.", nlocal,
116 KOKKOS_LAMBDA(
117 const int k, double& cent0, double& cent1, double& cent2) {
118 cent0 += Rview(k)[0];
119 cent1 += Rview(k)[1];
120 cent2 += Rview(k)[2];
121 },
122 Kokkos::Sum<double>(loc_meanR[0]), Kokkos::Sum<double>(loc_meanR[1]), Kokkos::Sum<double>(loc_meanR[2]));
123 Kokkos::fence();
124
125 MPI_Allreduce(loc_meanR, meanR, 3, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
126 ippl::Comm->barrier();
127
128 for(int i=0; i<3; i++){
129 meanR[i] = meanR[i]/(1.0*numberOfParticles);
130 }
131
132 Kokkos::parallel_for(
133 nlocal, KOKKOS_LAMBDA(
134 const int k) {
135 Rview(k)[0] -= meanR[0];
136 Rview(k)[1] -= meanR[1];
137 Rview(k)[2] -= meanR[2];
138 }
139 );
140 Kokkos::fence();
141 }
142
143 for (int i = 0; i < 3; i++) {
144 mu[i] = 0.0;
145 sd[i] = sigmaP_m[i];
146 }
147
148 view_type &Pview = pc_m->P.getView();
149 Kokkos::parallel_for(
150 nlocal,
151 ippl::random::randn<double, 3>(Pview, rand_pool64, mu, sd)
152 );
153 Kokkos::fence();
154
155 double avrgpz = avrgpz_m;
156 Kokkos::parallel_for(
157 nlocal,
158 KOKKOS_LAMBDA(const int k) {
159 Pview(k)[2] += avrgpz;
160 }
161 );
162 Kokkos::fence();
163
164 IpplTimings::stopTimer(samperTimer_m);
165}
166
Inform * gmsg
Definition changes.cpp:7
ippl::Vector< T, Dim > Vector_t
typename Kokkos::Random_XorShift64_Pool<> GeneratorPool
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
ippl::random::NormalDistribution< double, 3 > Dist_t
Definition Gaussian.h:17
const int nr
int seed
The current random seed.
Definition Options.cpp:37
Vector_t< double, 3 > sigmaP_m
Definition Gaussian.h:130
Vector_t< double, 3 > sigmaR_m
Standard deviations for position and momentum distributions.
Definition Gaussian.h:129
void initRandomPool()
Initializes the random number generator pool.
Definition Gaussian.cpp:42
void setCutoffR(const Vector_t< double, 3 > &cutoffR)
Definition Gaussian.h:93
double avrgpz_m
Average momentum in the z-direction.
Definition Gaussian.h:135
void setFixMeanR(bool fixMeanR)
Definition Gaussian.h:107
bool fixMeanR_m
Flag to exactly fix the mean position of particles after sampling.
Definition Gaussian.h:145
void setSigmaR(const Vector_t< double, 3 > &sigmaR)
Definition Gaussian.h:81
void generateParticles(size_t &numberOfParticles, Vector_t< double, 3 > nr) override
Generates particles with a Gaussian distribution.
Definition Gaussian.cpp:64
Vector_t< double, 3 > cutoffR_m
Cutoff multiplier for position distribution.
Definition Gaussian.h:140
GeneratorPool randPool_m
Pool of random number generators for parallel sampling.
Definition Gaussian.h:124
Gaussian(std::shared_ptr< ParticleContainer_t > &pc, std::shared_ptr< FieldContainer_t > &fc, std::shared_ptr< Distribution_t > &opalDist)
Constructor for the Gaussian sampler.
Definition Gaussian.cpp:14
void setAvrgpz(double avrgpz)
Definition Gaussian.h:89
void setSigmaP(const Vector_t< double, 3 > &sigmaP)
Definition Gaussian.h:85
IpplTimings::TimerRef samperTimer_m
Timer for performance profiling.
Definition Gaussian.h:46
SamplingBase(std::shared_ptr< ParticleContainer_t > &pc, std::shared_ptr< FieldContainer_t > &fc, std::shared_ptr< Distribution_t > &dist)
std::shared_ptr< ParticleContainer_t > pc_m