16 std::shared_ptr<ParticleContainer_t> pc, std::shared_ptr<FieldContainer_t> fc,
48 *
gmsg <<
"* Seed = " << randInit <<
" on all ranks" << endl;
50 randInit =
static_cast<size_t>(
Options::seed + 100 * ippl::Comm->rank());
67 "Gaussian::generateParticles",
68 "EMISSIONMODEL '" +
emissionModel_m +
"' is not supported for GAUSS distributions");
85 for (
int i = 0; i < 3; i++) {
88 rmin(i) = (rmin(i) + mu[i]) *
sigmaR_m[i];
89 rmax(i) = (rmax(i) + mu[i]) *
sigmaR_m[i];
92 const double par[6] = {mu[0], sd[0], mu[1], sd[1], mu[2], sd[2]};
94 using Dist_t = ippl::random::NormalDistribution<double, 3>;
95 using sampling_t = ippl::random::InverseTransformSampling<
96 double, 3, Kokkos::DefaultExecutionSpace,
Dist_t>;
99 const int nranks = std::max(1, ippl::Comm->size());
102 :
static_cast<size_t>(
103 floor(numberOfParticles / nranks)
104 + (ippl::Comm->rank() <
static_cast<int>(
105 numberOfParticles %
static_cast<size_t>(nranks))
109 sampling_t sampling(dist, rmax, rmin, rmax, rmin, nlocal);
110 nlocal = sampling.getLocalSamplesNum();
112 const size_t nlocalCurrent =
pc_m->getLocalNum();
113 pc_m->createParticles(nlocal);
116 auto Rview = Kokkos::subview(RviewFull, std::make_pair(nlocalCurrent, nlocalCurrent + nlocal));
118 sampling.generate(Rview, rand_pool64);
121 double meanR[3], loc_meanR[3];
122 for (
int i = 0; i < 3; i++) {
127 Kokkos::parallel_reduce(
128 "calc moments of particle distr.", nlocal,
129 KOKKOS_LAMBDA(
const int k,
double& cent0,
double& cent1,
double& cent2) {
130 cent0 += Rview(k)[0];
131 cent1 += Rview(k)[1];
132 cent2 += Rview(k)[2];
134 Kokkos::Sum<double>(loc_meanR[0]), Kokkos::Sum<double>(loc_meanR[1]),
135 Kokkos::Sum<double>(loc_meanR[2]));
138 MPI_Allreduce(loc_meanR, meanR, 3, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
139 ippl::Comm->barrier();
141 for (
int i = 0; i < 3; i++) {
142 meanR[i] = meanR[i] / (1.0 * numberOfParticles);
145 Kokkos::parallel_for(
146 nlocal, KOKKOS_LAMBDA(
const int k) {
147 Rview(k)[0] -= meanR[0];
148 Rview(k)[1] -= meanR[1];
149 Rview(k)[2] -= meanR[2];
154 for (
int i = 0; i < 3; i++) {
160 auto Pview = Kokkos::subview(PviewFull, std::make_pair(nlocalCurrent, nlocalCurrent + nlocal));
162 Kokkos::parallel_for(nlocal, ippl::random::randn<double, 3>(Pview, rand_pool64, mu, sd));
166 Kokkos::parallel_for(nlocal, KOKKOS_LAMBDA(
const size_t k) { Pview(k)[2] += avrgpz; });
174 Kokkos::parallel_for(
175 nlocal, KOKKOS_LAMBDA(
const size_t k) {
182 pc_m->markMomentsDirty();
189 const double tStart = t;
190 const double tEnd = t + dt;
202 if (!(tStart <=
t0_m &&
t0_m < tEnd)) {
214 const size_t nlocalBefore =
pc_m->getLocalNum();
235 const size_t nlocalAfter =
pc_m->getLocalNum();
236 const size_t nNew = nlocalAfter - nlocalBefore;
238 const double fracDt = tEnd -
t0_m;
239 auto dtview =
pc_m->dt.getView();
240 const size_t offset = nlocalBefore;
241 Kokkos::parallel_for(
242 "Gaussian_setDt", nNew,
243 KOKKOS_LAMBDA(
const size_t j) { dtview(offset + j) = fracDt; });
ippl::Vector< T, Dim > Vector_t
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
typename Kokkos::Random_XorShift64_Pool<> GeneratorPool
ippl::random::NormalDistribution< double, 3 > Dist_t
size_t getNumParticles() const
ippl::Vector< double, 3 > getSigmaP() const
ippl::Vector< double, 3 > getSigmaR() const
ippl::Vector< double, 3 > getCutoffR() const
Vector_t< double, 3 > sigmaP_m
Vector_t< double, 3 > sigmaR_m
Standard deviations for position and momentum distributions.
void initRandomPool()
Initializes the random number generator pool.
void setCutoffR(const Vector_t< double, 3 > &cutoffR)
double avrgpz_m
Average momentum in the z-direction.
void setFixMeanR(bool fixMeanR)
bool fixMeanR_m
Flag to exactly fix the mean position of particles after sampling.
void setSigmaR(const Vector_t< double, 3 > &sigmaR)
void generateParticles(size_t &numberOfParticles, Vector_t< double, 3 > nr) override
Generates particles with a Gaussian distribution.
Vector_t< double, 3 > cutoffR_m
Cutoff multiplier for position distribution.
GeneratorPool randPool_m
Pool of random number generators for parallel sampling.
Gaussian(std::shared_ptr< ParticleContainer_t > pc, std::shared_ptr< FieldContainer_t > fc, Distribution_t *opalDist)
Constructor for the Gaussian sampler.
void emitParticles(double t, double dt) override
Time-stepped emission hook for one-shot delayed injection.
void setAvrgpz(double avrgpz)
void setSigmaP(const Vector_t< double, 3 > &sigmaP)
IpplTimings::TimerRef samperTimer_m
Timer for performance profiling.
Vector_t< double, 3 > P0_m
Vector_t< double, 3 > R0_m
Emission source offset: position R0, momentum P0, start time t0 (applied in sample step).
bool hasEmittedOnce_m
For one-shot emitters (e.g. Gaussian at delayed t0): guard to avoid double sampling.
size_t computeLocalEmitCount(size_t totalToSample) const
Computes the number of particles this rank should emit so that the global total equals totalToSample ...
std::string emissionModel_m
Distribution_t * opalDist_m
void fillPolarization(size_t startIdx, size_t count)
std::shared_ptr< ParticleContainer_t > pc_m
int seed
The current random seed.