OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestLinearCompton.cpp
Go to the documentation of this file.
1
33#include "Physics/Physics.h"
34#include "Utilities/Options.h"
35#include "gtest/gtest.h"
36
37#include <cmath>
38
39namespace {
40 double integrateSpectrumCompositeSimpson(
41 double incomingPhotonEnergyERFGeV, double minEnergy, double maxEnergy, int panels) {
42 const double h = (maxEnergy - minEnergy) / panels;
44 incomingPhotonEnergyERFGeV, minEnergy)
46 incomingPhotonEnergyERFGeV, maxEnergy);
47
48 for (int i = 1; i < panels; ++i) {
49 const double energy = minEnergy + i * h;
50 const double weight = (i % 2 == 0) ? 2.0 : 4.0;
51 sum += weight
53 incomingPhotonEnergyERFGeV, energy);
54 }
55
56 return sum * h / 3.0;
57 }
58} // namespace
59
60TEST(TestLinearCompton, ThomsonLimitRecoveredAtLowEnergy) {
61 const double incomingPhotonEnergyERFGeV = 1.0e-9;
62 const double sigmaKN = Physics::LinearCompton::totalCrossSection(incomingPhotonEnergyERFGeV);
63 const double sigmaThomson = Physics::LinearCompton::thomsonCrossSection();
64
65 EXPECT_NEAR(sigmaKN / sigmaThomson, 1.0, 1.0e-5);
66}
67
68TEST(TestLinearCompton, EnergySupportMatchesComptonEndpoints) {
69 const double incomingPhotonEnergyERFGeV = 2.5e-4;
70 const double minEnergy =
72 const double maxEnergy =
74
75 EXPECT_DOUBLE_EQ(maxEnergy, incomingPhotonEnergyERFGeV);
76 EXPECT_NEAR(
77 Physics::LinearCompton::scatteredPhotonEnergyERFGeV(incomingPhotonEnergyERFGeV, 1.0),
78 maxEnergy, 1.0e-15);
79 EXPECT_NEAR(
80 Physics::LinearCompton::scatteredPhotonEnergyERFGeV(incomingPhotonEnergyERFGeV, -1.0),
81 minEnergy, 1.0e-15);
82 EXPECT_LT(minEnergy, maxEnergy);
83}
84
85TEST(TestLinearCompton, DifferentialSpectrumIntegratesToTotalCrossSection) {
86 const double incomingPhotonEnergyERFGeV = 2.0e-4;
87 const double minEnergy =
89 const double maxEnergy =
91 const double integral = integrateSpectrumCompositeSimpson(
92 incomingPhotonEnergyERFGeV, minEnergy, maxEnergy, 20000);
93
94 const double sigmaKN = Physics::LinearCompton::totalCrossSection(incomingPhotonEnergyERFGeV);
95 EXPECT_NEAR(integral, sigmaKN, sigmaKN * 2.0e-6);
96}
97
98TEST(TestLinearCompton, NinetyDegreeLabForwardBenchmarkMatchesExactFormula) {
99 const double electronTotalEnergyGeV = 1.0;
100 const double wavelength_m = 1.03e-6;
101 const double laserPhotonEnergyGeV =
103
104 Vector_t<double, 3> beamDirection(0.0);
105 beamDirection(2) = 1.0;
106 Vector_t<double, 3> laserDirection(0.0);
107 laserDirection(0) = 1.0;
108
109 const double electronMomentumGeV = std::sqrt(
110 electronTotalEnergyGeV * electronTotalEnergyGeV - Physics::m_e * Physics::m_e);
111 const double expectedInvariantX =
112 2.0 * laserPhotonEnergyGeV * electronTotalEnergyGeV / (Physics::m_e * Physics::m_e);
113 const double stableEnergyMinusMomentum =
114 Physics::m_e * Physics::m_e / (electronTotalEnergyGeV + electronMomentumGeV);
115 const double expectedForwardPhotonEnergyGeV =
116 laserPhotonEnergyGeV * electronTotalEnergyGeV
117 / (stableEnergyMinusMomentum + laserPhotonEnergyGeV);
118
119 EXPECT_NEAR(
121 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection),
122 expectedInvariantX, expectedInvariantX * 1.0e-12);
123 EXPECT_NEAR(
125 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection),
126 expectedForwardPhotonEnergyGeV, expectedForwardPhotonEnergyGeV * 1.0e-12);
127}
128
129TEST(TestLinearCompton, ExplicitLabPhotonEnergyMatchesForwardHelper) {
130 const double electronTotalEnergyGeV = 1.0;
131 const double wavelength_m = 1.03e-6;
132 const double laserPhotonEnergyGeV =
134
135 Vector_t<double, 3> beamDirection(0.0);
136 beamDirection(2) = 1.0;
137 Vector_t<double, 3> laserDirection(0.0);
138 laserDirection(0) = 1.0;
139
140 const double scatteringCosine =
142 electronTotalEnergyGeV, beamDirection, laserDirection);
143
144 EXPECT_NEAR(
146 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection,
147 scatteringCosine, 0.0),
149 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection),
150 1.0e-12);
151}
152
153TEST(TestLinearCompton, SampledEventsRespectKinematicBounds) {
154 const int previousSeed = Options::seed;
155 Options::seed = 20260403;
156
157 const double electronTotalEnergyGeV = 1.0;
158 const double wavelength_m = 1.03e-6;
159 const double laserPhotonEnergyGeV =
161
162 Vector_t<double, 3> beamDirection(0.0);
163 beamDirection(2) = 1.0;
164 Vector_t<double, 3> laserDirection(0.0);
165 laserDirection(0) = 1.0;
166
168 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection);
170 const auto event = Physics::LinearCompton::sampleEvent(kernel, engine);
171
173 kernel.incomingPhotonEnergyERFGeV);
175 kernel.incomingPhotonEnergyERFGeV);
176 const double directionNorm =
177 std::sqrt(dot(event.scatteredPhotonDirectionLab, event.scatteredPhotonDirectionLab));
178
179 EXPECT_GE(event.scatteringCosineERF, -1.0);
180 EXPECT_LE(event.scatteringCosineERF, 1.0);
181 EXPECT_GE(event.azimuthERF, 0.0);
182 EXPECT_LT(event.azimuthERF, Physics::two_pi);
183 EXPECT_GE(event.scatteredPhotonEnergyERFGeV, minERF);
184 EXPECT_LE(event.scatteredPhotonEnergyERFGeV, maxERF);
185 EXPECT_GT(event.scatteredPhotonEnergyLabGeV, 0.0);
186 EXPECT_NEAR(directionNorm, 1.0, 1.0e-12);
187
188 Options::seed = previousSeed;
189}
190
191TEST(TestLinearCompton, FixedSeedProducesDeterministicSampleSequence) {
192 const int previousSeed = Options::seed;
193 Options::seed = 424242;
194
195 const double electronTotalEnergyGeV = 1.0;
196 const double wavelength_m = 1.03e-6;
197 const double laserPhotonEnergyGeV =
199
200 Vector_t<double, 3> beamDirection(0.0);
201 beamDirection(2) = 1.0;
202 Vector_t<double, 3> laserDirection(0.0);
203 laserDirection(0) = 1.0;
204
206 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection);
209
210 for (int i = 0; i < 8; ++i) {
211 const auto event1 = Physics::LinearCompton::sampleEvent(kernel, engine1);
212 const auto event2 = Physics::LinearCompton::sampleEvent(kernel, engine2);
213 EXPECT_DOUBLE_EQ(event1.scatteringCosineERF, event2.scatteringCosineERF);
214 EXPECT_DOUBLE_EQ(event1.azimuthERF, event2.azimuthERF);
215 EXPECT_DOUBLE_EQ(event1.scatteredPhotonEnergyERFGeV, event2.scatteredPhotonEnergyERFGeV);
216 EXPECT_DOUBLE_EQ(event1.scatteredPhotonEnergyLabGeV, event2.scatteredPhotonEnergyLabGeV);
217 for (int axis = 0; axis < 3; ++axis) {
218 EXPECT_DOUBLE_EQ(
219 event1.scatteredPhotonDirectionLab(axis),
220 event2.scatteredPhotonDirectionLab(axis));
221 }
222 }
223
224 Options::seed = previousSeed;
225}
ippl::Vector< T, Dim > Vector_t
TEST(TestLinearCompton, ThomsonLimitRecoveredAtLowEnergy)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:95
int seed
The current random seed.
Definition Options.cpp:37
double differentialCrossSectionOmegaERF(double incomingPhotonEnergyERFGeV, double scatteredPhotonEnergyERFGeV)
Unpolarized Klein-Nishina differential cross section in the scattered-photon energy.
double restFrameScatteringCosineForLabForwardPhoton(double electronTotalEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection)
Rest-frame scattering cosine corresponding to a lab-forward photon.
SamplingKernel makeSamplingKernel(double electronTotalEnergyGeV, double laserPhotonEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection)
Build a cached sampling kernel for repeated event generation.
double labForwardPhotonEnergyGeV(double electronTotalEnergyGeV, double laserPhotonEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection)
Forward scattered photon energy in the laboratory frame.
double totalCrossSection(double incomingPhotonEnergyERFGeV)
Total unpolarized Klein-Nishina cross section.
std::mt19937_64 makeHostRandomEngine(std::uint64_t streamIndex)
Create a deterministic host-side random engine for Monte Carlo validation.
SampledEvent sampleEvent(const SamplingKernel &kernel, std::mt19937_64 &engine)
Sample one unpolarized linear-Compton event on the host.
double invariantX(double incomingPhotonEnergyERFGeV)
Compute CAIN's linear-Compton invariant .
double labPhotonEnergyGeV(double electronTotalEnergyGeV, double laserPhotonEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection, double scatteringCosineERF, double azimuthERF)
Laboratory-frame photon energy from electron-rest-frame scattering angles.
double thomsonCrossSection()
Thomson limit cross section.
double scatteredPhotonEnergyMaxERFGeV(double incomingPhotonEnergyERFGeV)
Maximum scattered photon energy in the electron rest frame.
double scatteredPhotonEnergyERFGeV(double incomingPhotonEnergyERFGeV, double scatteringCosineERF)
Compute the scattered photon energy in the electron rest frame.
double photonEnergyFromWavelengthGeV(double wavelength_m)
Convert a laser wavelength to a single-photon energy.
double scatteredPhotonEnergyMinERFGeV(double incomingPhotonEnergyERFGeV)
Minimum scattered photon energy in the electron rest frame.
constexpr double two_pi
The value of.
Definition Physics.h:40
constexpr double m_e
The electron rest mass in GeV.
Definition Physics.h:93