OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestAstra1DDynamic.cpp
Go to the documentation of this file.
1
44#include <gtest/gtest.h>
45
47#include "Fields/Fieldmap.h"
48#include "Ippl.h"
49#include "PartBunch/PartBunch.h"
50#include "Physics/Physics.h"
51#include "Physics/Units.h"
53
54#include <cmath>
55#include <filesystem>
56#include <fstream>
57#include <iomanip>
58#include <string>
59#include <vector>
60
61namespace {
62
63 // ---------------------------------------------------------------------------
64 // Helper: write 1D Astra dynamic fieldmap
65 // Format:
66 // 1DDynamic accuracy [TRUE|FALSE]
67 // freq_MHz
68 // z Ez
69 // z Ez
70 // ...
71 //
72 // z is written in meters.
73 // Ez is written in MV/m.
74 // ---------------------------------------------------------------------------
75 std::string writeAstra1DFieldmap(
76 const std::string& path, const std::vector<double>& z_m,
77 const std::vector<double>& ez_MVpm, int accuracy = 8, double freq_MHz = 100.0,
78 bool normalize = true) {
79 EXPECT_EQ(z_m.size(), ez_MVpm.size());
80
81 std::ofstream f(path);
82 f << "AstraDynamic " << accuracy << " " << (normalize ? "TRUE" : "FALSE") << "\n";
83 f << freq_MHz << "\n";
84
85 for (size_t i = 0; i < z_m.size(); ++i) {
86 f << z_m[i] << " " << ez_MVpm[i] << "\n";
87 }
88
89 return path;
90 }
91
92 // ---------------------------------------------------------------------------
93 // Helper: constant 1D map
94 // ---------------------------------------------------------------------------
95 std::string writeConstantAstra1DFieldmap(
96 const std::string& path, double zbegin_m, double zend_m, int nz, double ez_MVpm,
97 int accuracy = 8, double freq_MHz = 100.0, bool normalize = true) {
98 std::vector<double> z(nz);
99 std::vector<double> ez(nz, ez_MVpm);
100
101 const double dz = (zend_m - zbegin_m) / (nz - 1);
102 for (int i = 0; i < nz; ++i) {
103 z[i] = zbegin_m + i * dz;
104 }
105
106 return writeAstra1DFieldmap(path, z, ez, accuracy, freq_MHz, normalize);
107 }
108
109} // namespace
110
111// ===========================================================================
112// Fixture
113// ===========================================================================
114class Astra1DDynamicTest : public ::testing::Test {
115protected:
116 static void SetUpTestSuite() {
117 int argc = 0;
118 char** argv = nullptr;
119 ippl::initialize(argc, argv);
120 }
121
122 static void TearDownTestSuite() {
123 Fieldmap::clearDictionary();
124 ippl::finalize();
125 }
126
127 void SetUp() override {
128 tmpDir_ = std::filesystem::temp_directory_path() / "opalx_astra1d_test";
129 std::filesystem::create_directories(tmpDir_);
130 }
131
132 void TearDown() override {
133 Fieldmap::clearDictionary();
134 std::filesystem::remove_all(tmpDir_);
135 }
136
137 std::string tmpFile(const std::string& name) const { return (tmpDir_ / name).string(); }
138
139 std::filesystem::path tmpDir_;
140};
141
142// ===========================================================================
143// Test: Parse fieldmap and verify field dimensions
144// ===========================================================================
145TEST_F(Astra1DDynamicTest, ParseAndDimensions) {
146 const double zb = 0.0;
147 const double ze = 0.10;
148 const double freq = 100.0;
149 const int nz = 5;
150
151 std::string fname =
152 writeConstantAstra1DFieldmap(tmpFile("parse.map"), zb, ze, nz, 1.0, 8, freq, true);
153
154 Fieldmap* fm = Fieldmap::getFieldmap(fname);
155 ASSERT_NE(fm, nullptr);
156 EXPECT_EQ(fm->getType(), TAstraDynamic);
157
158 Fieldmap::readMap(fname);
159
160 double zBegin = 0.0, zEnd = 0.0;
161 fm->getFieldDimensions(zBegin, zEnd);
162
163 EXPECT_NEAR(zBegin, zb, 1e-12);
164 EXPECT_NEAR(zEnd, ze, 1e-12);
165}
166
167// ===========================================================================
168// Test: Frequency parsing and conversion
169// ===========================================================================
170TEST_F(Astra1DDynamicTest, FrequencyParsing) {
171 const double freq = 100.0;
172
173 std::string fname =
174 writeConstantAstra1DFieldmap(tmpFile("freq.map"), 0.0, 0.10, 5, 1.0, 8, freq, true);
175
176 auto* fm = dynamic_cast<Astra1DDynamic*>(Fieldmap::getFieldmap(fname));
177 ASSERT_NE(fm, nullptr);
178
179 Fieldmap::readMap(fname);
180
181 const double expected = freq * Physics::two_pi * Units::MHz2Hz;
182 EXPECT_NEAR(fm->getFrequency(), expected, 1e-6);
183}
184
185// ===========================================================================
186// Test: isInside() helper
187// ===========================================================================
189 std::string fname =
190 writeConstantAstra1DFieldmap(tmpFile("inside.map"), 0.0, 0.10, 5, 1.0, 8, 100.0, true);
191
192 auto* fm = dynamic_cast<Astra1DDynamic*>(Fieldmap::getFieldmap(fname));
193 ASSERT_NE(fm, nullptr);
194
195 EXPECT_TRUE(fm->isInside({0.0, 0.0, 0.00}));
196 EXPECT_TRUE(fm->isInside({0.0, 0.0, 0.05}));
197 EXPECT_FALSE(fm->isInside({0.0, 0.0, 0.10}));
198 EXPECT_FALSE(fm->isInside({0.0, 0.0, -0.01}));
199}
200
201// ===========================================================================
202// Test: Uniform field – on-axis field strength
203// ===========================================================================
204TEST_F(Astra1DDynamicTest, UniformFieldStrengthOnAxis) {
205 // With normalization = true and uniform Ez = 3 MV/m,
206 // the reconstructed on-axis field follows the current Astra1DDynamic
207 // Fourier/mirroring convention, which for nz samples gives a factor
208 // (nz - 1) / nz on a uniform input field.
209
210 const int nz = 9;
211
212 std::string fname = writeConstantAstra1DFieldmap(
213 tmpFile("uniform.map"), 0.0, 0.10, nz, 3.0, 8, 100.0, true);
214
215 Fieldmap* fm = Fieldmap::getFieldmap(fname);
216 ASSERT_NE(fm, nullptr);
217
218 Fieldmap::readMap(fname);
219
220 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
221 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
222 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
223
224 bool outside = fm->getFieldstrength(R, E, B);
225
226 EXPECT_FALSE(outside);
227
228 EXPECT_NEAR(E[0], 0.0, 1e-10);
229 EXPECT_NEAR(E[1], 0.0, 1e-10);
230
231 // const double expected_scale = static_cast<double>(nz - 1) / nz;
232 EXPECT_NEAR(E[2], 1.0e6, 1e-4);
233
234 // on-axis, transverse magnetic field projects to zero
235 EXPECT_NEAR(B[0], 0.0, 1e-10);
236 EXPECT_NEAR(B[1], 0.0, 1e-10);
237 EXPECT_NEAR(B[2], 0.0, 1e-10);
238}
239
240// ===========================================================================
241// Test: No normalization
242// ===========================================================================
243TEST_F(Astra1DDynamicTest, NoNormalization) {
244 const int nz = 9;
245
246 std::string fname = writeConstantAstra1DFieldmap(
247 tmpFile("nonorm.map"), 0.0, 0.10, nz, 3.0, 8, 100.0, false);
248
249 Fieldmap* fm = Fieldmap::getFieldmap(fname);
250 ASSERT_NE(fm, nullptr);
251
252 Fieldmap::readMap(fname);
253
254 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
255 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
256 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
257
258 bool outside = fm->getFieldstrength(R, E, B);
259
260 EXPECT_FALSE(outside);
261
262 // const double expected_scale = static_cast<double>(nz - 1) / nz;
263 EXPECT_NEAR(E[2], 3.0e6, 1e-3);
264}
265
266// ===========================================================================
267// Test: Outside z range returns outside flag and no modification
268// ===========================================================================
269TEST_F(Astra1DDynamicTest, OutsideZRange) {
270 std::string fname =
271 writeConstantAstra1DFieldmap(tmpFile("outside.map"), 0.0, 0.10, 9, 1.0, 8, 100.0, true);
272
273 Fieldmap* fm = Fieldmap::getFieldmap(fname);
274 ASSERT_NE(fm, nullptr);
275
276 Fieldmap::readMap(fname);
277
278 {
279 Vector_t<double, 3> R = {0.0, 0.0, -0.01};
280 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
281 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
282
283 bool outside = fm->getFieldstrength(R, E, B);
284
285 EXPECT_TRUE(outside);
286 EXPECT_NEAR(E[0], 1.0, 1e-15);
287 EXPECT_NEAR(E[1], 2.0, 1e-15);
288 EXPECT_NEAR(E[2], 3.0, 1e-15);
289 EXPECT_NEAR(B[0], 4.0, 1e-15);
290 EXPECT_NEAR(B[1], 5.0, 1e-15);
291 EXPECT_NEAR(B[2], 6.0, 1e-15);
292 }
293
294 {
295 Vector_t<double, 3> R = {0.0, 0.0, 0.10};
296 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
297 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
298
299 bool outside = fm->getFieldstrength(R, E, B);
300
301 EXPECT_TRUE(outside);
302 EXPECT_NEAR(E[0], 1.0, 1e-15);
303 EXPECT_NEAR(E[1], 2.0, 1e-15);
304 EXPECT_NEAR(E[2], 3.0, 1e-15);
305 EXPECT_NEAR(B[0], 4.0, 1e-15);
306 EXPECT_NEAR(B[1], 5.0, 1e-15);
307 EXPECT_NEAR(B[2], 6.0, 1e-15);
308 }
309}
310
311// ===========================================================================
312// Test: Accumulation semantics – E and B are accumulated, not overwritten
313// ===========================================================================
314TEST_F(Astra1DDynamicTest, FieldAccumulation) {
315 const int nz = 9;
316
317 std::string fname =
318 writeConstantAstra1DFieldmap(tmpFile("accum.map"), 0.0, 0.10, nz, 1.0, 8, 100.0, true);
319
320 Fieldmap* fm = Fieldmap::getFieldmap(fname);
321 ASSERT_NE(fm, nullptr);
322
323 Fieldmap::readMap(fname);
324
325 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
326 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
327 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
328
329 fm->getFieldstrength(R, E, B);
330
331 EXPECT_NEAR(E[0], 1.0, 1e-10);
332 EXPECT_NEAR(E[1], 2.0, 1e-10);
333
334 // const double expected_scale = static_cast<double>(nz - 1) / nz;
335 EXPECT_NEAR(E[2], 3.0 + 1.0e6, 1e-4);
336
337 // on-axis, no transverse magnetic contribution
338 EXPECT_NEAR(B[0], 4.0, 1e-10);
339 EXPECT_NEAR(B[1], 5.0, 1e-10);
340 EXPECT_NEAR(B[2], 6.0, 1e-10);
341}
342
343// ===========================================================================
344// Test: getFieldDerivative for constant field should be zero on-axis
345// ===========================================================================
346TEST_F(Astra1DDynamicTest, FieldDerivativeConstantField) {
347 std::string fname =
348 writeConstantAstra1DFieldmap(tmpFile("deriv.map"), 0.0, 0.10, 9, 2.0, 8, 100.0, true);
349
350 auto* fm = dynamic_cast<Astra1DDynamic*>(Fieldmap::getFieldmap(fname));
351 ASSERT_NE(fm, nullptr);
352
353 Fieldmap::readMap(fname);
354
355 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
356 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
357 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
358
359 bool outside = fm->getFieldDerivative(R, E, B, DZ);
360
361 EXPECT_FALSE(outside);
362 EXPECT_NEAR(E[2], 0.0, 1e-6);
363}
364
365// ===========================================================================
366// Test: getOnaxisEz returns the normalized raw on-axis profile
367// for the legacy 2-token Astra1D header format.
368// ===========================================================================
369TEST_F(Astra1DDynamicTest, GetOnaxisEzReturnsNormalizedRawProfile) {
370 const int nz = 9;
371 const std::string fname = tmpFile("onaxis_legacy.map");
372
373 {
374 std::ofstream out(fname);
375 ASSERT_TRUE(out.good());
376
377 // Legacy 2-token header accepted by both:
378 // - Fieldmap::getFieldmap()
379 // - current Astra1DDynamic::getOnaxisEz()
380 out << "AstraDynamic 8\n";
381 out << "100.0\n";
382
383 for (int i = 0; i < nz; ++i) {
384 const double z = 0.10 * double(i) / double(nz - 1);
385 out << std::setprecision(16) << z << " " << 3.0 << "\n";
386 }
387 }
388
389 auto* fm = dynamic_cast<Astra1DDynamic*>(Fieldmap::getFieldmap(fname));
390 ASSERT_NE(fm, nullptr);
391
392 ASSERT_NO_THROW(Fieldmap::readMap(fname));
393
394 std::vector<std::pair<double, double>> F;
395 ASSERT_NO_THROW(fm->getOnaxisEz(F));
396
397 ASSERT_EQ(F.size(), nz);
398
399 EXPECT_NEAR(F.front().first, 0.0, 1e-12);
400 EXPECT_NEAR(F.back().first, 0.10, 1e-12);
401
402 for (int i = 0; i < nz; ++i) {
403 EXPECT_NEAR(F[i].second, 1.0, 1e-12);
404 }
405}
406
407// ===========================================================================
408// Test: computeField static function directly with host view
409// ===========================================================================
410TEST_F(Astra1DDynamicTest, ComputeFieldStaticConstantCoefficient) {
411 // accuracy = 2 => coefficients [a0, a1, b1]
412 // choose only a0 = 1.0, so ez = 1.0 everywhere
413 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
414 coefs(0) = 1.0;
415 coefs(1) = 0.0;
416 coefs(2) = 0.0;
417
418 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
419 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
420 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
421
422 Astra1DDynamic::computeField(
423 R, E, B, coefs,
424 0.0, // zbegin
425 0.20, // length
426 1.0, // xlrep
427 2 // accuracy
428 );
429
430 EXPECT_NEAR(E[0], 0.0, 1e-12);
431 EXPECT_NEAR(E[1], 0.0, 1e-12);
432 EXPECT_NEAR(E[2], 1.0, 1e-12);
433
434 EXPECT_NEAR(B[0], 0.0, 1e-12);
435 EXPECT_NEAR(B[1], 0.0, 1e-12);
436}
437
438// ===========================================================================
439// Test: swap() does not crash
440// ===========================================================================
442 std::string fname =
443 writeConstantAstra1DFieldmap(tmpFile("swap.map"), 0.0, 0.10, 5, 1.0, 8, 100.0, true);
444
445 auto* fm = dynamic_cast<Astra1DDynamic*>(Fieldmap::getFieldmap(fname));
446 ASSERT_NE(fm, nullptr);
447
448 EXPECT_NO_THROW(fm->swap());
449}
450
451// ===========================================================================
452// Test: getInfo does not crash
453// ===========================================================================
454TEST_F(Astra1DDynamicTest, GetInfoNoCrash) {
455 std::string fname =
456 writeConstantAstra1DFieldmap(tmpFile("info.map"), 0.0, 0.10, 5, 1.0, 8, 100.0, true);
457
458 Fieldmap* fm = Fieldmap::getFieldmap(fname);
459 ASSERT_NE(fm, nullptr);
460
461 Inform msg("test");
462 EXPECT_NO_THROW(fm->getInfo(&msg));
463}
464
465// ===========================================================================
466// Test: Missing file
467// ===========================================================================
469 std::string fname = tmpFile("nonexistent.map");
470 EXPECT_THROW(Fieldmap::getFieldmap(fname), GeneralOpalException);
471}
472
473// ===========================================================================
474// Test: Dictionary caching
475// ===========================================================================
476TEST_F(Astra1DDynamicTest, DictionaryCaching) {
477 std::string fname =
478 writeConstantAstra1DFieldmap(tmpFile("cache.map"), 0.0, 0.10, 5, 1.0, 8, 100.0, true);
479
480 Fieldmap* fm1 = Fieldmap::getFieldmap(fname);
481 Fieldmap* fm2 = Fieldmap::getFieldmap(fname);
482
483 EXPECT_EQ(fm1, fm2);
484}
485
486// ===========================================================================
487// Test: readMap / freeMap cycle
488// ===========================================================================
489TEST_F(Astra1DDynamicTest, ReadFreeCycle) {
490 std::string fname =
491 writeConstantAstra1DFieldmap(tmpFile("cycle.map"), 0.0, 0.10, 9, 1.0, 8, 100.0, true);
492
493 Fieldmap* fm = Fieldmap::getFieldmap(fname);
494 ASSERT_NE(fm, nullptr);
495
496 fm->readMap();
497
498 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
499 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
500 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
501
502 fm->getFieldstrength(R, E, B);
503 EXPECT_NE(E[2], 0.0);
504
505 fm->freeMap();
506 fm->readMap();
507
508 E = {0.0, 0.0, 0.0};
509 B = {0.0, 0.0, 0.0};
510
511 fm->getFieldstrength(R, E, B);
512 EXPECT_NE(E[2], 0.0);
513}
514
515// ===========================================================================
516// Test: applyTravelingWave entry region
517// ===========================================================================
518TEST_F(Astra1DDynamicTest, ComputeTravelingWaveFieldEntryRegion) {
519 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
520 coefs(0) = 1.0;
521 coefs(1) = 0.0;
522 coefs(2) = 0.0;
523
524 Vector_t<double, 3> R = {0.0, 0.0, -0.01};
525 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
526 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
527
528 Astra1DDynamic::computeTravelingWaveField(
529 R, E, B, coefs,
530 0.0, // zbegin
531 0.10, // zend
532 0.20, // length
533 1.0, // xlrep
534 2, // accuracy
535 2.0, 0.0, // entry
536 0.0, 0.0, // core1
537 0.0, 0.0, // core2
538 0.0, 0.0, // exit
539 0.05, // startCoreField
540 0.20, // startExitField
541 0.0, // mappedStartExitField
542 0.10, // periodLength
543 0.05, // cellLength
544 0.30 // elementLength
545 );
546
547 EXPECT_NEAR(E[2], 2.0, 1e-12);
548}
549
550// ===========================================================================
551// Test: computeTravelingWaveField core region accumulates two contributions
552// ===========================================================================
553TEST_F(Astra1DDynamicTest, ComputeTravelingWaveFieldCoreRegion) {
554 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
555 coefs(0) = 1.0;
556 coefs(1) = 0.0;
557 coefs(2) = 0.0;
558
559 Vector_t<double, 3> R = {0.0, 0.0, 0.03};
560 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
561 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
562
563 // Consistent geometry for a fieldmap spanning z in [0.0, 0.10)
564 const double periodLength = 0.05;
565 const double startCoreField = 0.025;
566 const double cellLength = 0.05;
567 const double startExitField = 0.125;
568 const double mappedStartExit = 0.05;
569 const double elementLength = 0.175;
570
571 Astra1DDynamic::computeTravelingWaveField(
572 R, E, B, coefs,
573 0.0, // zbegin
574 0.10, // zend
575 0.20, // length
576 1.0, // xlrep
577 2, // accuracy
578 0.0, 0.0, // entry
579 1.5, 0.0, // core1
580 2.5, 0.0, // core2
581 0.0, 0.0, // exit
582 startCoreField, startExitField, mappedStartExit, periodLength, cellLength,
583 elementLength);
584
585 // Uniform constant coefficient => each core contribution gives Ez = 1
586 EXPECT_NEAR(E[2], 4.0, 1e-12);
587}
588
589// ===========================================================================
590// Test: computeTravelingWaveField exit region
591// ===========================================================================
592TEST_F(Astra1DDynamicTest, ComputeTravelingWaveFieldExitRegion) {
593 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
594 coefs(0) = 1.0;
595 coefs(1) = 0.0;
596 coefs(2) = 0.0;
597
598 Vector_t<double, 3> R = {0.0, 0.0, 0.11};
599 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
600 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
601
602 // Same consistent TW geometry as above
603 const double periodLength = 0.05;
604 const double startCoreField = 0.025;
605 const double cellLength = 0.05;
606 const double startExitField = 0.125;
607 const double mappedStartExit = 0.05;
608 const double elementLength = 0.175;
609
610 Astra1DDynamic::computeTravelingWaveField(
611 R, E, B, coefs,
612 0.0, // zbegin
613 0.10, // zend
614 0.20, // length
615 1.0, // xlrep
616 2, // accuracy
617 0.0, 0.0, // entry
618 0.0, 0.0, // core1
619 0.0, 0.0, // core2
620 3.0, 0.0, // exit
621 startCoreField, startExitField, mappedStartExit, periodLength, cellLength,
622 elementLength);
623
624 EXPECT_NEAR(E[2], 3.0, 1e-12);
625}
626
627// ===========================================================================
628// Test: applyTravelingWave does nothing outside TW longitudinal range
629// ===========================================================================
630TEST_F(Astra1DDynamicTest, ComputeTravelingWaveFieldOutsideRange) {
631 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
632 coefs(0) = 1.0;
633 coefs(1) = 0.0;
634 coefs(2) = 0.0;
635
636 Vector_t<double, 3> R = {0.0, 0.0, -0.06};
637 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
638 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
639
640 Astra1DDynamic::computeTravelingWaveField(
641 R, E, B, coefs, 0.0, 0.10, 0.20, 1.0, 2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.05,
642 0.20, 0.0, 0.10, 0.05, 0.30);
643
644 EXPECT_NEAR(E[0], 1.0, 1e-12);
645 EXPECT_NEAR(E[1], 2.0, 1e-12);
646 EXPECT_NEAR(E[2], 3.0, 1e-12);
647 EXPECT_NEAR(B[0], 4.0, 1e-12);
648 EXPECT_NEAR(B[1], 5.0, 1e-12);
649 EXPECT_NEAR(B[2], 6.0, 1e-12);
650}
651
652// ===========================================================================
653// Test: computeRFField applies RF scaling inside longitudinal range
654// ===========================================================================
655TEST_F(Astra1DDynamicTest, ComputeRFFieldInsideRange) {
656 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
657 coefs(0) = 1.0;
658 coefs(1) = 0.0;
659 coefs(2) = 0.0;
660
661 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
662 Vector_t<double, 3> E = {0.0, 0.0, 0.0};
663 Vector_t<double, 3> B = {0.0, 0.0, 0.0};
664
665 Astra1DDynamic::computeRFField(
666 R, E, B, coefs,
667 0.0, // zbegin
668 0.10, // zend
669 0.20, // length
670 1.0, // xlrep
671 2, // accuracy
672 2.0, // electricScale
673 0.0, // magneticScale
674 0.0, // startField
675 0.10 // endField
676 );
677
678 EXPECT_NEAR(E[0], 0.0, 1e-12);
679 EXPECT_NEAR(E[1], 0.0, 1e-12);
680 EXPECT_NEAR(E[2], 2.0, 1e-12);
681
682 EXPECT_NEAR(B[0], 0.0, 1e-12);
683 EXPECT_NEAR(B[1], 0.0, 1e-12);
684 EXPECT_NEAR(B[2], 0.0, 1e-12);
685}
686
687// ===========================================================================
688// Test: computeRFField does nothing outside RFCavity longitudinal range
689// ===========================================================================
690TEST_F(Astra1DDynamicTest, ComputeRFFieldOutsideStartEndRange) {
691 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
692 coefs(0) = 1.0;
693 coefs(1) = 0.0;
694 coefs(2) = 0.0;
695
696 Vector_t<double, 3> R = {0.0, 0.0, 0.05};
697 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
698 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
699
700 Astra1DDynamic::computeRFField(
701 R, E, B, coefs,
702 0.0, // zbegin
703 0.10, // zend
704 0.20, // length
705 1.0, // xlrep
706 2, // accuracy
707 2.0, // electricScale
708 3.0, // magneticScale
709 0.06, // startField
710 0.10 // endField
711 );
712
713 EXPECT_NEAR(E[0], 1.0, 1e-12);
714 EXPECT_NEAR(E[1], 2.0, 1e-12);
715 EXPECT_NEAR(E[2], 3.0, 1e-12);
716
717 EXPECT_NEAR(B[0], 4.0, 1e-12);
718 EXPECT_NEAR(B[1], 5.0, 1e-12);
719 EXPECT_NEAR(B[2], 6.0, 1e-12);
720}
721
722// ===========================================================================
723// Test: computeRFField does nothing outside fieldmap z range
724// ===========================================================================
725TEST_F(Astra1DDynamicTest, ComputeRFFieldOutsideFieldmapRange) {
726 Kokkos::View<double*, Kokkos::HostSpace> coefs("coefs", 3);
727 coefs(0) = 1.0;
728 coefs(1) = 0.0;
729 coefs(2) = 0.0;
730
731 Vector_t<double, 3> R = {0.0, 0.0, 0.11};
732 Vector_t<double, 3> E = {1.0, 2.0, 3.0};
733 Vector_t<double, 3> B = {4.0, 5.0, 6.0};
734
735 Astra1DDynamic::computeRFField(
736 R, E, B, coefs,
737 0.0, // zbegin
738 0.10, // zend
739 0.20, // length
740 1.0, // xlrep
741 2, // accuracy
742 2.0, // electricScale
743 3.0, // magneticScale
744 0.0, // startField
745 0.20 // endField
746 );
747
748 EXPECT_NEAR(E[0], 1.0, 1e-12);
749 EXPECT_NEAR(E[1], 2.0, 1e-12);
750 EXPECT_NEAR(E[2], 3.0, 1e-12);
751
752 EXPECT_NEAR(B[0], 4.0, 1e-12);
753 EXPECT_NEAR(B[1], 5.0, 1e-12);
754 EXPECT_NEAR(B[2], 6.0, 1e-12);
755}
ippl::Vector< T, Dim > Vector_t
@ TAstraDynamic
Definition Fieldmap.h:17
@ DZ
Definition Fieldmap.h:54
Template PIC bunch: IPPL PicManager, shared field mesh/solver, and multiple particle containers.
TEST_F(Astra1DDynamicTest, ParseAndDimensions)
std::string tmpFile(const std::string &name) const
static void TearDownTestSuite()
std::filesystem::path tmpDir_
Abstract base class for all field maps. It acts as a factory for creating specific field map types ba...
Definition Fieldmap.h:62
virtual bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const =0
Get the field strength at a given point.
virtual void getInfo(Inform *msg)=0
Print info about the field map.
virtual void getFieldDimensions(double &zBegin, double &zEnd) const =0
Get the longitudinal dimensions of the field.
MapType getType()
Definition Fieldmap.h:206
static void freeMap(std::string Filename)
Decrease reference count or delete field map if unused.
Definition Fieldmap.cpp:311
static void readMap(std::string Filename)
Trigger the actual reading of the field map data.
Definition Fieldmap.cpp:301
constexpr double two_pi
The value of.
Definition Physics.h:40
constexpr double MHz2Hz
Definition Units.h:113