OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestLossDataSink.cpp
Go to the documentation of this file.
1
56#include <gtest/gtest.h>
57
58#include "Ippl.h"
59
60#include <cmath>
61#include <cstddef>
62#include <utility>
63#include <vector>
64
65#define private public
67#undef private
68
70#include "Utilities/Options.h"
71
72namespace {
73
74 Vector_t<double, 3> makeVector(double x, double y, double z) {
76 v(0) = x;
77 v(1) = y;
78 v(2) = z;
79 return v;
80 }
81
82 OpalParticle makeParticle(
83 std::size_t id, const Vector_t<double, 3>& r, const Vector_t<double, 3>& p,
84 double time = 0.0, double charge = -1.0e-17, double mass = 0.51099895) {
85 return OpalParticle(id, r, p, time, charge, mass);
86 }
87
88 class LossDataSinkTest : public ::testing::Test {
89 protected:
90 static void SetUpTestSuite() {
91 int argc = 0;
92 char** argv = nullptr;
93 ippl::initialize(argc, argv);
94 }
95
96 static void TearDownTestSuite() { ippl::finalize(); }
97
98 void SetUp() override {
99 oldComputePercentiles_m = Options::computePercentiles;
101 }
102
103 void TearDown() override { Options::computePercentiles = oldComputePercentiles_m; }
104
105 private:
106 bool oldComputePercentiles_m = false;
107 };
108
109 TEST_F(LossDataSinkTest, AddParticleRejectsTurnInformationAfterPlainParticle) {
110 LossDataSink sink;
111
112 sink.addParticle(makeParticle(1, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0)));
113
114 EXPECT_THROW(
115 sink.addParticle(
116 makeParticle(2, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0)),
117 std::make_pair(3, static_cast<short>(4))),
119 }
120
121 TEST_F(LossDataSinkTest, AddParticleRejectsPlainParticleAfterTurnInformation) {
122 LossDataSink sink;
123
124 sink.addParticle(
125 makeParticle(1, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0)),
126 std::make_pair(3, static_cast<short>(4)));
127
128 EXPECT_THROW(
129 sink.addParticle(
130 makeParticle(2, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0))),
132 }
133
134 TEST_F(LossDataSinkTest, ComputeStatisticsSingleParticle) {
135 LossDataSink sink;
136
137 const Vector_t<double, 3> r = makeVector(1.0, -2.0, 3.0);
138 const Vector_t<double, 3> p = makeVector(0.1, -0.2, 4.0);
139
140 sink.addParticle(makeParticle(1, r, p, 5.0, -2.0e-17, 0.51099895));
141
142 const auto stats = sink.computeStatistics(1);
143
144 ASSERT_EQ(stats.size(), 1u);
145
146 const SetStatistics& stat = *stats.begin();
147
148 EXPECT_EQ(stat.nTotal_m, 1u);
149
150 EXPECT_DOUBLE_EQ(stat.rmean_m(0), 1.0);
151 EXPECT_DOUBLE_EQ(stat.rmean_m(1), -2.0);
152 EXPECT_DOUBLE_EQ(stat.rmean_m(2), 3.0);
153
154 EXPECT_DOUBLE_EQ(stat.pmean_m(0), 0.1);
155 EXPECT_DOUBLE_EQ(stat.pmean_m(1), -0.2);
156 EXPECT_DOUBLE_EQ(stat.pmean_m(2), 4.0);
157
158 EXPECT_DOUBLE_EQ(stat.rrms_m(0), 0.0);
159 EXPECT_DOUBLE_EQ(stat.rrms_m(1), 0.0);
160 EXPECT_DOUBLE_EQ(stat.rrms_m(2), 0.0);
161
162 EXPECT_DOUBLE_EQ(stat.prms_m(0), 0.0);
163 EXPECT_DOUBLE_EQ(stat.prms_m(1), 0.0);
164 EXPECT_DOUBLE_EQ(stat.prms_m(2), 0.0);
165
166 EXPECT_DOUBLE_EQ(stat.tmean_m, 5.0);
167 EXPECT_DOUBLE_EQ(stat.trms_m, 0.0);
168
169 EXPECT_DOUBLE_EQ(stat.totalCharge_m, -2.0e-17);
170 EXPECT_DOUBLE_EQ(stat.totalMass_m, 0.51099895);
171 }
172
173 TEST_F(LossDataSinkTest, MaxRUsesMaximumAbsoluteExtent) {
174 LossDataSink sink;
175
176 sink.addParticle(makeParticle(1, makeVector(-2.0, 5.0, -7.0), makeVector(0.0, 0.0, 1.0)));
177
178 sink.addParticle(makeParticle(2, makeVector(1.0, -6.0, 4.0), makeVector(0.0, 0.0, 1.0)));
179
180 const auto stats = sink.computeStatistics(1);
181
182 ASSERT_EQ(stats.size(), 1u);
183
184 const SetStatistics& stat = *stats.begin();
185
186 EXPECT_DOUBLE_EQ(stat.rmin_m(0), -2.0);
187 EXPECT_DOUBLE_EQ(stat.rmax_m(0), 1.0);
188 EXPECT_DOUBLE_EQ(stat.maxR_m(0), 2.0);
189
190 EXPECT_DOUBLE_EQ(stat.rmin_m(1), -6.0);
191 EXPECT_DOUBLE_EQ(stat.rmax_m(1), 5.0);
192 EXPECT_DOUBLE_EQ(stat.maxR_m(1), 6.0);
193
194 EXPECT_DOUBLE_EQ(stat.rmin_m(2), -7.0);
195 EXPECT_DOUBLE_EQ(stat.rmax_m(2), 4.0);
196 EXPECT_DOUBLE_EQ(stat.maxR_m(2), 7.0);
197 }
198
199 TEST_F(LossDataSinkTest, MeanAndRmsTimeAreComputedCorrectly) {
200 LossDataSink sink;
201
202 sink.addParticle(
203 makeParticle(1, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 1.0));
204
205 sink.addParticle(
206 makeParticle(2, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 3.0));
207
208 const auto stats = sink.computeStatistics(1);
209
210 ASSERT_EQ(stats.size(), 1u);
211
212 const SetStatistics& stat = *stats.begin();
213
214 EXPECT_DOUBLE_EQ(stat.tmean_m, 2.0);
215 EXPECT_DOUBLE_EQ(stat.trms_m, 1.0);
216 }
217
218 TEST_F(LossDataSinkTest, StdKineticEnergyIsStableForIdenticalParticles) {
219 LossDataSink sink;
220
221 const Vector_t<double, 3> r = makeVector(0.0, 0.0, 0.0);
222 const Vector_t<double, 3> p = makeVector(0.0, 0.0, 13.87990113);
223
224 constexpr std::size_t numParticles = 10000;
225
226 for (std::size_t i = 0; i < numParticles; ++i) {
227 sink.addParticle(makeParticle(i, r, p, 1.0, -1.5e-17, 0.51099895));
228 }
229
230 const auto stats = sink.computeStatistics(1);
231
232 ASSERT_EQ(stats.size(), 1u);
233
234 const SetStatistics& stat = *stats.begin();
235
236 EXPECT_EQ(stat.nTotal_m, numParticles);
237 EXPECT_NEAR(stat.meanKineticEnergy_m, 6.6, 1.0e-6);
238 EXPECT_NEAR(stat.stdKineticEnergy_m, 0.0, 1.0e-12);
239 }
240
241 TEST_F(LossDataSinkTest, SplitSetsClearsPreviousStateForSingleSet) {
242 LossDataSink sink;
243
244 sink.startSet_m = {0, 1, 2};
245
246 sink.addParticle(
247 makeParticle(1, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 1.0));
248
249 sink.splitSets(1);
250
251 EXPECT_TRUE(sink.startSet_m.empty());
252 }
253
254 TEST_F(LossDataSinkTest, SplitSetsCreatesMonotonicBoundaries) {
255 LossDataSink sink;
256
257 sink.addParticle(
258 makeParticle(1, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 0.0));
259
260 sink.addParticle(
261 makeParticle(2, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 1.0));
262
263 sink.addParticle(
264 makeParticle(3, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 10.0));
265
266 sink.addParticle(
267 makeParticle(4, makeVector(0.0, 0.0, 0.0), makeVector(0.0, 0.0, 1.0), 11.0));
268
269 sink.splitSets(2);
270
271 ASSERT_EQ(sink.startSet_m.size(), 3u);
272
273 EXPECT_EQ(sink.startSet_m.front(), 0u);
274 EXPECT_EQ(sink.startSet_m.back(), sink.particles_m.size());
275
276 EXPECT_LE(sink.startSet_m[0], sink.startSet_m[1]);
277 EXPECT_LE(sink.startSet_m[1], sink.startSet_m[2]);
278
279 EXPECT_EQ(sink.startSet_m[1], 2u);
280 }
281
282 TEST_F(LossDataSinkTest, KineticEnergyUsesParticleMass) {
283 LossDataSink sink;
284
285 const auto r = makeVector(0.0, 0.0, 0.0);
286 const auto p = makeVector(0.0, 0.0, 13.87990113);
287
288 sink.addParticle(makeParticle(1, r, p, 1.0, -1.0e-17, 0.51099895));
289
290 const auto stats = sink.computeStatistics(1);
291 ASSERT_EQ(stats.size(), 1u);
292
293 const SetStatistics& stat = *stats.begin();
294
295 EXPECT_NEAR(stat.meanKineticEnergy_m, 6.6, 1.0e-6);
296 EXPECT_NEAR(stat.totalMass_m, 0.51099895, 1.0e-12);
297 }
298
299} // namespace
ippl::Vector< T, Dim > Vector_t
TEST_F(MonitorTest, GetType)
std::set< SetStatistics > computeStatistics(unsigned int numSets)
void addParticle(const OpalParticle &, const std::optional< std::pair< int, short int > > &turnBunchNumPair=std::nullopt)
void splitSets(unsigned int numSets)
std::vector< OpalParticle > particles_m
std::vector< unsigned long > startSet_m
bool computePercentiles
Definition Options.cpp:107
double stdKineticEnergy_m
Vector_t< double, 3 > maxR_m
Vector_t< double, 3 > rrms_m
Vector_t< double, 3 > rmax_m
Vector_t< double, 3 > prms_m
double meanKineticEnergy_m
double totalMass_m
double totalCharge_m
unsigned long nTotal_m
Vector_t< double, 3 > pmean_m
Vector_t< double, 3 > rmin_m
Vector_t< double, 3 > rmean_m