OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestFlatTop.cpp
Go to the documentation of this file.
1#include <gtest/gtest.h>
2#include <mpi.h>
3#include <algorithm>
4#include <cmath>
5#include <memory>
6
8#include "Ippl.h"
10#include "Utility/IpplTimings.h"
11
12class FlatTopTest : public ::testing::Test {
13protected:
14 static void SetUpTestSuite() {
15 int argc = 0;
16 char** argv = nullptr;
17
18 ippl::initialize(argc, argv);
19 }
20
21 static void TearDownTestSuite() { ippl::finalize(); }
22
23 void SetUp() override {
24 // Minimal 3D grid parameters
25 nr = 64;
26 ippl::Vector<double, 3> rmin = -4.0;
27 ippl::Vector<double, 3> rmax = 4.0;
28 ippl::Vector<double, 3> origin = rmin;
29 ippl::Vector<double, 3> hr = (rmax - rmin) / ippl::Vector<double, 3>(nr);
30 std::array<bool, 3> decomp = {false, false, true};
31
32 ippl::NDIndex<3> domain;
33 for (unsigned i = 0; i < 3; i++) {
34 domain[i] = ippl::Index(this->nr[i]);
35 }
36
37 // Create FieldContainer
38 fc = std::make_shared<FieldContainer_t>(
39 hr, rmin, rmax, decomp, domain, origin, this->isAllPeriodic_m);
40
41 // Create mesh and fieldlayout
42 Mesh_t<3> mesh(domain, hr, origin);
43 FieldLayout_t<3> fl(MPI_COMM_WORLD, domain, decomp, this->isAllPeriodic_m);
44
45 // Create ParticleContainer
46 pc = std::make_shared<ParticleContainer<double, 3>>(mesh, fl);
47
48 bunchStateHandler = std::make_shared<BunchStateHandler>();
49 pc->setBunchStateHandler(bunchStateHandler);
50 }
51
52 void TearDown() override {
53 // nothing special
54 }
55
56 std::shared_ptr<ParticleContainer<double, 3>> pc;
57 std::shared_ptr<FieldContainer_t> fc;
58 std::shared_ptr<BunchStateHandler> bunchStateHandler;
59 ippl::Vector<int, 3> nr;
60 bool isAllPeriodic_m = true;
61};
62
104TEST_F(FlatTopTest, UniformDiskStatisticsAndBounds) {
105 const Vector_t<double, 3> sigmaR = {0.5, 1.0, 0.0};
106 const Vector_t<double, 3> cutoff = 4.0;
107
108 // Minimal FlatTop constructor usage
109 FlatTop sampler(
110 pc,
111 /*emitting=*/false,
112 /*sigmaTFall=*/1.0,
113 /*sigmaTRise=*/1.0, cutoff,
114 /*tPulseLengthFWHM=*/1.0, sigmaR);
115
116 const size_t nlocal = 0;
117 const size_t nNew = 100000;
118
119 pc->createParticles(nNew);
120 sampler.generateUniformDisk(nlocal, nNew, 1.0e-12);
121
122 auto Rview_d = pc->R.getView();
123 auto Pview_d = pc->P.getView();
124
125 auto Rview = Kokkos::create_mirror_view(Rview_d);
126 auto Pview = Kokkos::create_mirror_view(Pview_d);
127 Kokkos::deep_copy(Rview, Rview_d);
128 Kokkos::deep_copy(Pview, Pview_d);
129
130 double sumx = 0.0, sumy = 0.0;
131 double sumx2 = 0.0, sumy2 = 0.0;
132
133 for (size_t i = 0; i < nNew; ++i) {
134 const double x = Rview(i)[0];
135 const double y = Rview(i)[1];
136 const double z = Rview(i)[2];
137
138 // z-position must be zero
139 EXPECT_DOUBLE_EQ(z, 0.0);
140
141 // momentum must be zero
142 EXPECT_DOUBLE_EQ(Pview(i)[0], 0.0);
143 EXPECT_DOUBLE_EQ(Pview(i)[1], 0.0);
144 EXPECT_DOUBLE_EQ(Pview(i)[2], 0.0);
145
146 // inside ellipse
147 const double r2 = (x * x) / (sigmaR[0] * sigmaR[0]) + (y * y) / (sigmaR[1] * sigmaR[1]);
148
149 EXPECT_LE(r2, 1.0 + 1e-14);
150
151 sumx += x;
152 sumy += y;
153 sumx2 += x * x;
154 sumy2 += y * y;
155 }
156
157 const double meanx = sumx / nNew;
158 const double meany = sumy / nNew;
159 const double varx = sumx2 / nNew;
160 const double vary = sumy2 / nNew;
161
162 // Mean should be ~0
163 EXPECT_NEAR(meanx, 0.0, 1e-2);
164 EXPECT_NEAR(meany, 0.0, 1e-2);
165
166 // Uniform disk second moments:
167 // E[x^2] = σx^2 / 4, E[y^2] = σy^2 / 4
168 EXPECT_NEAR(varx, sigmaR[0] * sigmaR[0] / 4.0, 1e-2);
169 EXPECT_NEAR(vary, sigmaR[1] * sigmaR[1] / 4.0, 1e-2);
170}
171
252TEST_F(FlatTopTest, CountEnteringParticles_NoDomainDecomp) {
253 const Vector_t<double, 3> sigmaR = {1.0, 1.0, 0.0};
254 const Vector_t<double, 3> cutoff = {4.0, 4.0, 4.0};
255
256 FlatTop sampler(
257 pc,
258 /*emitting=*/true,
259 /*sigmaTFall=*/1.0,
260 /*sigmaTRise=*/1.0, cutoff,
261 /*tPulseLengthFWHM=*/10.0, sigmaR);
262
263 sampler.setWithDomainDecomp(false);
264
265 // total number of particles to emit over whole pulse
266 const size_t totalN = 100000;
267 sampler.allocateParticles(totalN);
268
269 // Preallocate capacity so computeLocalEmitCount can distribute totalN.
270 const int nranksConst = std::max(1, ippl::Comm->size());
271 const size_t nranksU = static_cast<size_t>(nranksConst);
272 const size_t maxLocalNum = totalN / nranksU + 2 * nranksU + 1;
273 pc->allocateParticles(maxLocalNum);
274
275 const double t0 = 2.0;
276 const double tf = 2.1;
277
278 size_t nlocal = sampler.countEnteringParticlesPerRank(t0, tf);
279
280 // --- compute expected result ---
281 double f0 = sampler.FlatTopProfile(t0);
282 double f1 = sampler.FlatTopProfile(tf);
283 double tArea = 0.5 * (f0 + f1) * (tf - t0);
284
285 double expectedTotalNewD = std::floor(totalN * tArea / sampler.getDistArea());
286 const size_t expectedTotalNew = static_cast<size_t>(expectedTotalNewD);
287
288 int nranks;
289 MPI_Comm_size(MPI_COMM_WORLD, &nranks);
290
291 int rank;
292 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
293
294 // Mirror SamplingBase::computeLocalEmitCount for equal capacities:
295 // first 'rem' ranks get one extra particle.
296 size_t base = expectedTotalNew / static_cast<size_t>(nranks);
297 size_t rem = expectedTotalNew % static_cast<size_t>(nranks);
298 size_t expectedLocal = base + ((static_cast<size_t>(rank) < rem) ? 1 : 0);
299
300 EXPECT_EQ(nlocal, expectedLocal);
301
302 size_t globalEmitted = 0;
303 MPI_Allreduce(&nlocal, &globalEmitted, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD);
304
305 EXPECT_EQ(globalEmitted, expectedTotalNew);
306}
ippl::Vector< T, Dim > Vector_t
Defines the FlatTop class used for sampling emitting particles.
ippl::FieldLayout< Dim > FieldLayout_t
Definition PBunchDefs.h:25
ippl::UniformCartesian< double, 3 > Mesh_t
Definition PBunchDefs.h:18
TEST_F(FlatTopTest, UniformDiskStatisticsAndBounds)
Testing generatiioin of uniform sampples on an elliptical disk.
std::shared_ptr< FieldContainer_t > fc
static void TearDownTestSuite()
bool isAllPeriodic_m
std::shared_ptr< BunchStateHandler > bunchStateHandler
void SetUp() override
static void SetUpTestSuite()
ippl::Vector< int, 3 > nr
std::shared_ptr< ParticleContainer< double, 3 > > pc
void TearDown() override
Implements the sampling method for the flat-top distribution. x and y coordinates are uniformly distr...
Definition FlatTop.h:33
void generateUniformDisk(size_type nlocal, size_t nNew, double dt)
Generates particles (x,y) uniformly on a disk distribution.
Definition FlatTop.cpp:88
double FlatTopProfile(double t)
Computes the flat-top profile value at a given time.
Definition FlatTop.cpp:204
void allocateParticles(size_t numberOfParticles)
Allocates memory for a given number of particles.
Definition FlatTop.cpp:350
void setWithDomainDecomp(bool withDomainDecomp) override
Sets whether to use domain decomposition.
Definition FlatTop.cpp:33
size_type countEnteringParticlesPerRank(double t0, double tf)
Counts the number of particles entering per rank in a given time interval.
Definition FlatTop.cpp:263
double getDistArea()
Returns the total area of the distribution.
Definition FlatTop.h:103