OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestLinearComptonSpectrum.cpp
Go to the documentation of this file.
1
20#include "Utilities/Options.h"
21#include "gtest/gtest.h"
22
23#include <cstdlib>
24#include <filesystem>
25#include <sstream>
26#include <stdexcept>
27#include <string>
28
29namespace {
31 std::filesystem::path referenceSpectrumPath() {
32 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
33 / "cain_linear_compton_90deg_xi029_histogram.csv";
34 }
35
38 std::filesystem::path referenceJointSpectrumPath() {
39 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
40 / "cain_linear_compton_90deg_xi029_joint_histogram.csv";
41 }
42
44 std::filesystem::path referenceAngularSpectrumPath() {
45 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
46 / "cain_linear_compton_90deg_xi029_theta_histogram.csv";
47 }
48
50 std::filesystem::path referenceFiniteBeamSpectrumPath() {
51 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
52 / "cain_linear_compton_90deg_xi029_finite_beam_histogram.csv";
53 }
54
56 std::filesystem::path referenceFiniteBeamAngularSpectrumPath() {
57 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
58 / "cain_linear_compton_90deg_xi029_finite_beam_theta_histogram.csv";
59 }
60
62 std::filesystem::path referenceFiniteBeamJointSpectrumPath() {
63 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
64 / "cain_linear_compton_90deg_xi029_finite_beam_joint_histogram.csv";
65 }
66
69 std::filesystem::path referenceFiniteBeamEnergySpreadSpectrumPath() {
70 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
71 / "cain_linear_compton_90deg_xi029_finite_beam_energy_spread_histogram.csv";
72 }
73
75 std::filesystem::path referenceFiniteBeamEnergySpreadAngularSpectrumPath() {
76 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
77 / "cain_linear_compton_90deg_xi029_finite_beam_energy_spread_theta_histogram.csv";
78 }
79
82 std::filesystem::path referenceFiniteBeamEnergySpreadJointSpectrumPath() {
83 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
84 / "cain_linear_compton_90deg_xi029_finite_beam_energy_spread_joint_histogram.csv";
85 }
86
89 std::filesystem::path referenceFiniteBeamOverlapSpectrumPath() {
90 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
91 / "cain_linear_compton_90deg_xi029_finite_beam_overlap_histogram.csv";
92 }
93
95 std::filesystem::path referenceFiniteBeamOverlapAngularSpectrumPath() {
96 return std::filesystem::path(OPALX_TEST_SOURCE_DIR) / "data"
97 / "cain_linear_compton_90deg_xi029_finite_beam_overlap_theta_histogram.csv";
98 }
99
102 std::filesystem::path benchmarkExecutablePath() {
103 return std::filesystem::path(OPALX_LINEAR_COMPTON_BENCHMARK);
104 }
105
116 std::filesystem::path runFiniteBeamBenchmark(
117 const std::string& filename, bool angular, bool joint = false,
118 const std::string& extraOptions = "") {
119 const auto output = std::filesystem::temp_directory_path() / filename;
120 std::ostringstream command;
121 command << benchmarkExecutablePath().string() << ' ' << output.string()
122 << " --finite-beam --beam-particles 100000 --seed 13579";
123 if (!extraOptions.empty()) {
124 command << ' ' << extraOptions;
125 }
126 if (joint) {
127 command << " --joint";
128 } else if (angular) {
129 command << " --angular";
130 }
131
132 const int returnCode = std::system(command.str().c_str());
133 if (returnCode != 0) {
134 throw std::runtime_error(
135 "Failed to run finite-beam benchmark command: " + command.str());
136 }
137 return output;
138 }
139} // namespace
140
141TEST(TestLinearComptonSpectrum, WeakFieldSpectrumMatchesCainReference) {
143 const auto opalxSpectrum = LinearComptonBenchmark::integrateLabSpectrum(config);
144 const auto cainSpectrum = LinearComptonBenchmark::readSpectrumCSV(referenceSpectrumPath());
145
146 ASSERT_EQ(opalxSpectrum.centersGeV.size(), cainSpectrum.centersGeV.size());
147 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(opalxSpectrum), 1.0, 5.0e-4);
148 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(cainSpectrum), 1.0, 5.0e-4);
149
150 const double opalxMean = LinearComptonBenchmark::histogramMeanEnergyGeV(opalxSpectrum);
151 const double cainMean = LinearComptonBenchmark::histogramMeanEnergyGeV(cainSpectrum);
152 EXPECT_NEAR(opalxMean, cainMean, cainMean * 3.0e-2);
153
154 const double l1Distance =
155 LinearComptonBenchmark::histogramL1Distance(opalxSpectrum, cainSpectrum);
156 EXPECT_LT(l1Distance, 0.1);
157}
158
159TEST(TestLinearComptonSpectrum, WeakFieldSampledSpectrumMatchesCainReference) {
160 const int previousSeed = Options::seed;
161 Options::seed = 13579;
162
164 const auto opalxSpectrum = LinearComptonBenchmark::sampleLabSpectrum(config, 250000);
165 const auto cainSpectrum = LinearComptonBenchmark::readSpectrumCSV(referenceSpectrumPath());
166
167 ASSERT_EQ(opalxSpectrum.centersGeV.size(), cainSpectrum.centersGeV.size());
168 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(opalxSpectrum), 1.0, 1.5e-2);
169
170 const double opalxMean = LinearComptonBenchmark::histogramMeanEnergyGeV(opalxSpectrum);
171 const double cainMean = LinearComptonBenchmark::histogramMeanEnergyGeV(cainSpectrum);
172 EXPECT_NEAR(opalxMean, cainMean, cainMean * 3.5e-2);
173
174 const double l1Distance =
175 LinearComptonBenchmark::histogramL1Distance(opalxSpectrum, cainSpectrum);
176 EXPECT_LT(l1Distance, 0.14);
177
178 Options::seed = previousSeed;
179}
180
181TEST(TestLinearComptonSpectrum, WeakFieldAngularSpectrumMatchesCainReference) {
183 const auto opalxSpectrum = LinearComptonBenchmark::integrateLabAngularSpectrum(config);
184 const auto cainSpectrum = LinearComptonBenchmark::readAngleCSV(referenceAngularSpectrumPath());
185
186 ASSERT_EQ(opalxSpectrum.centersRad.size(), cainSpectrum.centersRad.size());
187 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(opalxSpectrum), 1.0, 5.0e-4);
188 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(cainSpectrum), 1.0, 5.0e-4);
189
190 const double opalxMean = LinearComptonBenchmark::angleHistogramMeanRad(opalxSpectrum);
191 const double cainMean = LinearComptonBenchmark::angleHistogramMeanRad(cainSpectrum);
192 EXPECT_NEAR(opalxMean, cainMean, cainMean * 5.0e-2);
193
194 const double l1Distance =
195 LinearComptonBenchmark::angleHistogramL1Distance(opalxSpectrum, cainSpectrum);
196 EXPECT_LT(l1Distance, 0.12);
197}
198
199TEST(TestLinearComptonSpectrum, WeakFieldSampledAngularSpectrumMatchesCainReference) {
200 const int previousSeed = Options::seed;
201 Options::seed = 13579;
202
204 const auto opalxSpectrum = LinearComptonBenchmark::sampleLabAngularSpectrum(config, 250000);
205 const auto cainSpectrum = LinearComptonBenchmark::readAngleCSV(referenceAngularSpectrumPath());
206
207 ASSERT_EQ(opalxSpectrum.centersRad.size(), cainSpectrum.centersRad.size());
208 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(opalxSpectrum), 1.0, 2.0e-2);
209
210 const double opalxMean = LinearComptonBenchmark::angleHistogramMeanRad(opalxSpectrum);
211 const double cainMean = LinearComptonBenchmark::angleHistogramMeanRad(cainSpectrum);
212 EXPECT_NEAR(opalxMean, cainMean, cainMean * 5.0e-2);
213
214 const double l1Distance =
215 LinearComptonBenchmark::angleHistogramL1Distance(opalxSpectrum, cainSpectrum);
216 EXPECT_LT(l1Distance, 0.10);
217
218 Options::seed = previousSeed;
219}
220
221TEST(TestLinearComptonSpectrum, WeakFieldJointSpectrumMatchesCainReference) {
223 const auto opalxSpectrum = LinearComptonBenchmark::integrateLabJointSpectrum(config);
224 const auto cainSpectrum = LinearComptonBenchmark::readJointCSV(referenceJointSpectrumPath());
225
226 ASSERT_EQ(opalxSpectrum.energyCentersGeV.size(), cainSpectrum.energyCentersGeV.size());
227 ASSERT_EQ(opalxSpectrum.thetaCentersRad.size(), cainSpectrum.thetaCentersRad.size());
228 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(opalxSpectrum), 1.0, 2.0e-3);
229 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(cainSpectrum), 1.0, 2.0e-3);
230
231 const double opalxMeanEnergy =
233 const double cainMeanEnergy = LinearComptonBenchmark::jointHistogramMeanEnergyGeV(cainSpectrum);
234 EXPECT_NEAR(opalxMeanEnergy, cainMeanEnergy, cainMeanEnergy * 3.0e-2);
235
236 const double opalxMeanTheta = LinearComptonBenchmark::jointHistogramMeanThetaRad(opalxSpectrum);
237 const double cainMeanTheta = LinearComptonBenchmark::jointHistogramMeanThetaRad(cainSpectrum);
238 EXPECT_NEAR(opalxMeanTheta, cainMeanTheta, cainMeanTheta * 5.0e-2);
239
240 const double l1Distance =
241 LinearComptonBenchmark::jointHistogramL1Distance(opalxSpectrum, cainSpectrum);
242 EXPECT_LT(l1Distance, 0.16);
243}
244
245TEST(TestLinearComptonSpectrum, WeakFieldSampledJointSpectrumMatchesCainReference) {
246 const int previousSeed = Options::seed;
247 Options::seed = 13579;
248
250 const auto opalxSpectrum = LinearComptonBenchmark::sampleLabJointSpectrum(config, 250000);
251 const auto cainSpectrum = LinearComptonBenchmark::readJointCSV(referenceJointSpectrumPath());
252
253 ASSERT_EQ(opalxSpectrum.energyCentersGeV.size(), cainSpectrum.energyCentersGeV.size());
254 ASSERT_EQ(opalxSpectrum.thetaCentersRad.size(), cainSpectrum.thetaCentersRad.size());
255 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(opalxSpectrum), 1.0, 1.5e-2);
256
257 const double opalxMeanEnergy =
259 const double cainMeanEnergy = LinearComptonBenchmark::jointHistogramMeanEnergyGeV(cainSpectrum);
260 EXPECT_NEAR(opalxMeanEnergy, cainMeanEnergy, cainMeanEnergy * 3.5e-2);
261
262 const double opalxMeanTheta = LinearComptonBenchmark::jointHistogramMeanThetaRad(opalxSpectrum);
263 const double cainMeanTheta = LinearComptonBenchmark::jointHistogramMeanThetaRad(cainSpectrum);
264 EXPECT_NEAR(opalxMeanTheta, cainMeanTheta, cainMeanTheta * 6.0e-2);
265
266 const double l1Distance =
267 LinearComptonBenchmark::jointHistogramL1Distance(opalxSpectrum, cainSpectrum);
268 EXPECT_LT(l1Distance, 0.09);
269
270 Options::seed = previousSeed;
271}
272
278TEST(TestLinearComptonSpectrum, FiniteBeamSpectrumMatchesCainReference) {
279 const auto output = runFiniteBeamBenchmark(
280 "opalx-linear-compton-90deg-xi029-finite-beam-histogram.csv", false);
281 const auto opalxSpectrum = LinearComptonBenchmark::readSpectrumCSV(output);
282 const auto cainSpectrum =
283 LinearComptonBenchmark::readSpectrumCSV(referenceFiniteBeamSpectrumPath());
284
285 ASSERT_EQ(opalxSpectrum.centersGeV.size(), cainSpectrum.centersGeV.size());
286 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(opalxSpectrum), 1.0, 2.0e-2);
287 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(cainSpectrum), 1.0, 5.0e-4);
288
289 const double opalxMean = LinearComptonBenchmark::histogramMeanEnergyGeV(opalxSpectrum);
290 const double cainMean = LinearComptonBenchmark::histogramMeanEnergyGeV(cainSpectrum);
291 EXPECT_NEAR(opalxMean, cainMean, cainMean * 2.0e-2);
292
293 const double l1Distance =
294 LinearComptonBenchmark::histogramL1Distance(opalxSpectrum, cainSpectrum);
295 EXPECT_LT(l1Distance, 0.05);
296}
297
298TEST(TestLinearComptonSpectrum, FiniteBeamAngularSpectrumMatchesCainReference) {
299 const auto output = runFiniteBeamBenchmark(
300 "opalx-linear-compton-90deg-xi029-finite-beam-theta-histogram.csv", true);
301 const auto opalxSpectrum = LinearComptonBenchmark::readAngleCSV(output);
302 const auto cainSpectrum =
303 LinearComptonBenchmark::readAngleCSV(referenceFiniteBeamAngularSpectrumPath());
304
305 ASSERT_EQ(opalxSpectrum.centersRad.size(), cainSpectrum.centersRad.size());
306 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(opalxSpectrum), 1.0, 2.5e-2);
307 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(cainSpectrum), 1.0, 5.0e-4);
308
309 const double opalxMean = LinearComptonBenchmark::angleHistogramMeanRad(opalxSpectrum);
310 const double cainMean = LinearComptonBenchmark::angleHistogramMeanRad(cainSpectrum);
311 EXPECT_NEAR(opalxMean, cainMean, cainMean * 2.0e-2);
312
313 const double l1Distance =
314 LinearComptonBenchmark::angleHistogramL1Distance(opalxSpectrum, cainSpectrum);
315 EXPECT_LT(l1Distance, 0.03);
316}
317
318TEST(TestLinearComptonSpectrum, FiniteBeamJointSpectrumMatchesCainReference) {
319 const auto output = runFiniteBeamBenchmark(
320 "opalx-linear-compton-90deg-xi029-finite-beam-joint-histogram.csv", false, true);
321 const auto opalxSpectrum = LinearComptonBenchmark::readJointCSV(output);
322 const auto cainSpectrum =
323 LinearComptonBenchmark::readJointCSV(referenceFiniteBeamJointSpectrumPath());
324
325 ASSERT_EQ(opalxSpectrum.energyCentersGeV.size(), cainSpectrum.energyCentersGeV.size());
326 ASSERT_EQ(opalxSpectrum.thetaCentersRad.size(), cainSpectrum.thetaCentersRad.size());
327 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(opalxSpectrum), 1.0, 2.5e-2);
328 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(cainSpectrum), 1.0, 1.0e-3);
329
330 EXPECT_NEAR(
334 EXPECT_NEAR(
338 EXPECT_LT(LinearComptonBenchmark::jointHistogramL1Distance(opalxSpectrum, cainSpectrum), 0.08);
339}
340
347TEST(TestLinearComptonSpectrum, FiniteBeamEnergySpreadSpectrumMatchesCainReference) {
348 const auto output = runFiniteBeamBenchmark(
349 "opalx-linear-compton-90deg-xi029-finite-beam-energy-spread-histogram.csv", false,
350 false, "--beam-relative-energy-spread 0.001");
351 const auto opalxSpectrum = LinearComptonBenchmark::readSpectrumCSV(output);
352 const auto cainSpectrum =
353 LinearComptonBenchmark::readSpectrumCSV(referenceFiniteBeamEnergySpreadSpectrumPath());
354
355 ASSERT_EQ(opalxSpectrum.centersGeV.size(), cainSpectrum.centersGeV.size());
356 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(opalxSpectrum), 1.0, 2.0e-2);
357 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(cainSpectrum), 1.0, 5.0e-4);
358
359 const double opalxMean = LinearComptonBenchmark::histogramMeanEnergyGeV(opalxSpectrum);
360 const double cainMean = LinearComptonBenchmark::histogramMeanEnergyGeV(cainSpectrum);
361 EXPECT_NEAR(opalxMean, cainMean, cainMean * 2.0e-2);
362
363 const double l1Distance =
364 LinearComptonBenchmark::histogramL1Distance(opalxSpectrum, cainSpectrum);
365 EXPECT_LT(l1Distance, 0.05);
366}
367
368TEST(TestLinearComptonSpectrum, FiniteBeamEnergySpreadAngularSpectrumMatchesCainReference) {
369 const auto output = runFiniteBeamBenchmark(
370 "opalx-linear-compton-90deg-xi029-finite-beam-energy-spread-theta-histogram.csv", true,
371 false, "--beam-relative-energy-spread 0.001");
372 const auto opalxSpectrum = LinearComptonBenchmark::readAngleCSV(output);
373 const auto cainSpectrum = LinearComptonBenchmark::readAngleCSV(
374 referenceFiniteBeamEnergySpreadAngularSpectrumPath());
375
376 ASSERT_EQ(opalxSpectrum.centersRad.size(), cainSpectrum.centersRad.size());
377 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(opalxSpectrum), 1.0, 2.5e-2);
378 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(cainSpectrum), 1.0, 5.0e-4);
379
380 const double opalxMean = LinearComptonBenchmark::angleHistogramMeanRad(opalxSpectrum);
381 const double cainMean = LinearComptonBenchmark::angleHistogramMeanRad(cainSpectrum);
382 EXPECT_NEAR(opalxMean, cainMean, cainMean * 2.0e-2);
383
384 const double l1Distance =
385 LinearComptonBenchmark::angleHistogramL1Distance(opalxSpectrum, cainSpectrum);
386 EXPECT_LT(l1Distance, 0.03);
387}
388
389TEST(TestLinearComptonSpectrum, FiniteBeamEnergySpreadJointSpectrumMatchesCainReference) {
390 const auto output = runFiniteBeamBenchmark(
391 "opalx-linear-compton-90deg-xi029-finite-beam-energy-spread-joint-histogram.csv", false,
392 true, "--beam-relative-energy-spread 0.001");
393 const auto opalxSpectrum = LinearComptonBenchmark::readJointCSV(output);
394 const auto cainSpectrum = LinearComptonBenchmark::readJointCSV(
395 referenceFiniteBeamEnergySpreadJointSpectrumPath());
396
397 ASSERT_EQ(opalxSpectrum.energyCentersGeV.size(), cainSpectrum.energyCentersGeV.size());
398 ASSERT_EQ(opalxSpectrum.thetaCentersRad.size(), cainSpectrum.thetaCentersRad.size());
399 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(opalxSpectrum), 1.0, 2.5e-2);
400 EXPECT_NEAR(LinearComptonBenchmark::jointHistogramArea(cainSpectrum), 1.0, 1.5e-3);
401
402 EXPECT_NEAR(
406 EXPECT_NEAR(
410 EXPECT_LT(LinearComptonBenchmark::jointHistogramL1Distance(opalxSpectrum, cainSpectrum), 0.08);
411}
412
413TEST(TestLinearComptonSpectrum, FiniteBeamOverlapSpectrumMatchesCainReference) {
414 const auto output = runFiniteBeamBenchmark(
415 "opalx-linear-compton-90deg-xi029-finite-beam-overlap-histogram.csv", false, false,
416 "--overlap-weighting --beam-sigma-longitudinal 0.000299792 --laser-rayleigh 12.5 "
417 "--laser-sigma-t 0.000299792");
418 const auto opalxSpectrum = LinearComptonBenchmark::readSpectrumCSV(output);
419 const auto cainSpectrum =
420 LinearComptonBenchmark::readSpectrumCSV(referenceFiniteBeamOverlapSpectrumPath());
421
422 ASSERT_EQ(opalxSpectrum.centersGeV.size(), cainSpectrum.centersGeV.size());
423 EXPECT_NEAR(LinearComptonBenchmark::histogramArea(opalxSpectrum), 1.0, 2.0e-2);
424 EXPECT_NEAR(
428 EXPECT_LT(LinearComptonBenchmark::histogramL1Distance(opalxSpectrum, cainSpectrum), 0.06);
429}
430
431TEST(TestLinearComptonSpectrum, FiniteBeamOverlapAngularSpectrumMatchesCainReference) {
432 const auto output = runFiniteBeamBenchmark(
433 "opalx-linear-compton-90deg-xi029-finite-beam-overlap-theta-histogram.csv", true, false,
434 "--overlap-weighting --beam-sigma-longitudinal 0.000299792 --laser-rayleigh 12.5 "
435 "--laser-sigma-t 0.000299792");
436 const auto opalxSpectrum = LinearComptonBenchmark::readAngleCSV(output);
437 const auto cainSpectrum =
438 LinearComptonBenchmark::readAngleCSV(referenceFiniteBeamOverlapAngularSpectrumPath());
439
440 ASSERT_EQ(opalxSpectrum.centersRad.size(), cainSpectrum.centersRad.size());
441 EXPECT_NEAR(LinearComptonBenchmark::angleHistogramArea(opalxSpectrum), 1.0, 2.5e-2);
442 EXPECT_NEAR(
445 LinearComptonBenchmark::angleHistogramMeanRad(cainSpectrum) * 2.0e-2);
446 EXPECT_LT(LinearComptonBenchmark::angleHistogramL1Distance(opalxSpectrum, cainSpectrum), 0.05);
447}
TEST(TestLinearComptonSpectrum, WeakFieldSpectrumMatchesCainReference)
double histogramArea(const SpectrumHistogram &histogram)
SpectrumHistogram readSpectrumCSV(const std::filesystem::path &inputPath)
double angleHistogramL1Distance(const AngleHistogram &lhs, const AngleHistogram &rhs)
JointHistogram integrateLabJointSpectrum(const JointConfig &config)
AngleHistogram readAngleCSV(const std::filesystem::path &inputPath)
double angleHistogramMeanRad(const AngleHistogram &histogram)
double jointHistogramL1Distance(const JointHistogram &lhs, const JointHistogram &rhs)
double histogramL1Distance(const SpectrumHistogram &lhs, const SpectrumHistogram &rhs)
double jointHistogramArea(const JointHistogram &histogram)
double angleHistogramArea(const AngleHistogram &histogram)
SpectrumHistogram integrateLabSpectrum(const SpectrumConfig &config)
double jointHistogramMeanThetaRad(const JointHistogram &histogram)
double histogramMeanEnergyGeV(const SpectrumHistogram &histogram)
JointHistogram sampleLabJointSpectrum(const JointConfig &config, std::size_t sampleCount, std::uint64_t streamIndex=0)
SpectrumHistogram sampleLabSpectrum(const SpectrumConfig &config, std::size_t sampleCount, std::uint64_t streamIndex=0)
AngleHistogram integrateLabAngularSpectrum(const AngleConfig &config)
JointHistogram readJointCSV(const std::filesystem::path &inputPath)
AngleHistogram sampleLabAngularSpectrum(const AngleConfig &config, std::size_t sampleCount, std::uint64_t streamIndex=0)
double jointHistogramMeanEnergyGeV(const JointHistogram &histogram)
int seed
The current random seed.
Definition Options.cpp:37