OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
LinearCompton.cpp
Go to the documentation of this file.
2
3#include "Physics/Physics.h"
5#include "Utilities/Options.h"
6
7#include <algorithm>
8#include <cmath>
9#include <cstdint>
10#include <limits>
11#include <random>
12#include <string>
13
14namespace {
15 Vector_t<double, 3> normalizeDirection(
16 const Vector_t<double, 3>& direction, const char* where, const char* argument) {
17 const double norm = std::sqrt(dot(direction, direction));
18 if (norm <= 0.0) {
19 throw OpalException(
20 where, std::string("\"") + argument + "\" must be a non-zero vector.");
21 }
22
23 return direction / norm;
24 }
25
26 double clampCosine(double value) { return std::max(-1.0, std::min(1.0, value)); }
27
28 void ensureStrictlyPositive(double value, const char* where, const char* argument) {
29 if (value <= 0.0) {
30 throw OpalException(where, std::string("\"") + argument + "\" must be greater than 0.");
31 }
32 }
33
34 void ensureCosineRange(double cosine, const char* where, const char* argument) {
35 if (cosine < -1.0 - 1.0e-12 || cosine > 1.0 + 1.0e-12) {
36 throw OpalException(where, std::string("\"") + argument + "\" must lie in [-1, 1].");
37 }
38 }
39
40 Vector_t<double, 3> chooseReferenceDirection(const Vector_t<double, 3>& direction) {
41 Vector_t<double, 3> reference(0.0);
42 reference(0) = 1.0;
43 if (std::abs(direction(0)) > 0.9) {
44 reference(0) = 0.0;
45 reference(1) = 1.0;
46 }
47 return reference;
48 }
49
50 Vector_t<double, 3> scatteringPlaneAxis(
51 const Vector_t<double, 3>& incomingDirectionERF,
52 const Vector_t<double, 3>& boostDirectionLab, const char* where) {
54 boostDirectionLab
55 - dot(boostDirectionLab, incomingDirectionERF) * incomingDirectionERF;
56 const double axisNorm = std::sqrt(dot(axis, axis));
57 if (axisNorm > 1.0e-14) {
58 return axis / axisNorm;
59 }
60
61 axis = cross(incomingDirectionERF, chooseReferenceDirection(incomingDirectionERF));
62 return normalizeDirection(axis, where, "scatteringPlaneAxis");
63 }
64
65 Vector_t<double, 3> scatteredDirectionERF(
66 const Vector_t<double, 3>& incomingDirectionERF,
67 const Vector_t<double, 3>& boostDirectionLab, double scatteringCosineERF,
68 double azimuthERF, const char* where) {
69 ensureCosineRange(scatteringCosineERF, where, "scatteringCosineERF");
70 const double clampedCosine = clampCosine(scatteringCosineERF);
71 const double sinTheta = std::sqrt(std::max(0.0, 1.0 - clampedCosine * clampedCosine));
72 const Vector_t<double, 3> axis1 =
73 scatteringPlaneAxis(incomingDirectionERF, boostDirectionLab, where);
74 const Vector_t<double, 3> axis2 =
75 normalizeDirection(cross(incomingDirectionERF, axis1), where, "axis2");
76 return normalizeDirection(
77 clampedCosine * incomingDirectionERF
78 + sinTheta * (std::cos(azimuthERF) * axis1 + std::sin(azimuthERF) * axis2),
79 where, "scatteredDirectionERF");
80 }
81
82 std::uint64_t deterministicHostSeed() {
83 return Options::seed >= 0 ? static_cast<std::uint64_t>(Options::seed) : 123456789ULL;
84 }
85
86 std::uint64_t mixSeed(std::uint64_t seed, std::uint64_t streamIndex) {
87 const std::uint64_t golden = 0x9E3779B97F4A7C15ULL;
88 std::uint64_t mixed = seed + golden * (streamIndex + 1ULL);
89 mixed ^= (mixed >> 30);
90 mixed *= 0xBF58476D1CE4E5B9ULL;
91 mixed ^= (mixed >> 27);
92 mixed *= 0x94D049BB133111EBULL;
93 mixed ^= (mixed >> 31);
94 return mixed;
95 }
96
97 double rejectionUpperBoundSolidAngleERF(double incomingPhotonEnergyERFGeV) {
98 constexpr int samples = 4096;
99 double upperBound = 0.0;
100 for (int i = 0; i <= samples; ++i) {
101 const double mu = -1.0 + 2.0 * static_cast<double>(i) / static_cast<double>(samples);
102 upperBound = std::max(
104 incomingPhotonEnergyERFGeV, mu));
105 }
106
107 return std::max(upperBound * 1.0001, std::numeric_limits<double>::min());
108 }
109} // namespace
110
111namespace Physics {
112 namespace LinearCompton {
113
114 double photonEnergyFromWavelengthGeV(double wavelength_m) {
115 constexpr const char* where = "Physics::LinearCompton::photonEnergyFromWavelengthGeV()";
116 ensureStrictlyPositive(wavelength_m, where, "wavelength_m");
117 return Physics::two_pi * Physics::h_bar * Physics::c / wavelength_m;
118 }
119
120 double electronGamma(double electronTotalEnergyGeV) {
121 constexpr const char* where = "Physics::LinearCompton::electronGamma()";
122 if (electronTotalEnergyGeV <= Physics::m_e) {
123 throw OpalException(
124 where,
125 "Electron total energy must be larger than the electron rest energy.");
126 }
127
128 return electronTotalEnergyGeV / Physics::m_e;
129 }
130
131 double electronBeta(double electronTotalEnergyGeV) {
132 const double gamma = electronGamma(electronTotalEnergyGeV);
133 return std::sqrt(1.0 - 1.0 / (gamma * gamma));
134 }
135
137 double electronTotalEnergyGeV, double laserPhotonEnergyGeV,
138 const Vector_t<double, 3>& beamDirection,
139 const Vector_t<double, 3>& laserDirection) {
140 constexpr const char* where =
141 "Physics::LinearCompton::restFrameIncomingPhotonEnergyGeV()";
142 ensureStrictlyPositive(laserPhotonEnergyGeV, where, "laserPhotonEnergyGeV");
143
144 const double gamma = electronGamma(electronTotalEnergyGeV);
145 const double beta = electronBeta(electronTotalEnergyGeV);
146 const Vector_t<double, 3> normalizedBeamDirection =
147 normalizeDirection(beamDirection, where, "beamDirection");
148 const Vector_t<double, 3> normalizedLaserDirection =
149 normalizeDirection(laserDirection, where, "laserDirection");
150 const double cosAlpha =
151 clampCosine(dot(normalizedBeamDirection, normalizedLaserDirection));
152
153 return gamma * laserPhotonEnergyGeV * (1.0 - beta * cosAlpha);
154 }
155
157 double electronTotalEnergyGeV, const Vector_t<double, 3>& beamDirection,
158 const Vector_t<double, 3>& laserDirection) {
159 constexpr const char* where =
160 "Physics::LinearCompton::restFrameIncomingPhotonDirection()";
161 const double gamma = electronGamma(electronTotalEnergyGeV);
162 const double beta = electronBeta(electronTotalEnergyGeV);
163 const Vector_t<double, 3> normalizedBeamDirection =
164 normalizeDirection(beamDirection, where, "beamDirection");
165 const Vector_t<double, 3> normalizedLaserDirection =
166 normalizeDirection(laserDirection, where, "laserDirection");
167 const double cosAlpha =
168 clampCosine(dot(normalizedBeamDirection, normalizedLaserDirection));
169 const double denominator = 1.0 - beta * cosAlpha;
170 const Vector_t<double, 3> transverseComponent =
171 normalizedLaserDirection - cosAlpha * normalizedBeamDirection;
172 const Vector_t<double, 3> directionERF =
173 transverseComponent / (gamma * denominator)
174 + ((cosAlpha - beta) / denominator) * normalizedBeamDirection;
175 return normalizeDirection(directionERF, where, "directionERF");
176 }
177
179 double electronTotalEnergyGeV, const Vector_t<double, 3>& beamDirection,
180 const Vector_t<double, 3>& laserDirection, double scatteringCosineERF,
181 double azimuthERF) {
182 constexpr const char* where = "Physics::LinearCompton::labPhotonDirection()";
183 const double gamma = electronGamma(electronTotalEnergyGeV);
184 const double beta = electronBeta(electronTotalEnergyGeV);
185 const Vector_t<double, 3> normalizedBeamDirection =
186 normalizeDirection(beamDirection, where, "beamDirection");
187 const Vector_t<double, 3> incomingDirectionERF = restFrameIncomingPhotonDirection(
188 electronTotalEnergyGeV, beamDirection, laserDirection);
189 const Vector_t<double, 3> outgoingDirectionERF = scatteredDirectionERF(
190 incomingDirectionERF, normalizedBeamDirection, scatteringCosineERF, azimuthERF,
191 where);
192 const double parallelCosine = dot(outgoingDirectionERF, normalizedBeamDirection);
193 const Vector_t<double, 3> transverseDirection =
194 outgoingDirectionERF - parallelCosine * normalizedBeamDirection;
195 const Vector_t<double, 3> boostedDirection =
196 transverseDirection + gamma * (parallelCosine + beta) * normalizedBeamDirection;
197 return normalizeDirection(boostedDirection, where, "boostedDirection");
198 }
199
200 std::mt19937_64 makeHostRandomEngine(std::uint64_t streamIndex) {
201 return std::mt19937_64(mixSeed(deterministicHostSeed(), streamIndex));
202 }
203
205 double electronTotalEnergyGeV, double laserPhotonEnergyGeV,
206 const Vector_t<double, 3>& beamDirection,
207 const Vector_t<double, 3>& laserDirection) {
208 constexpr const char* where = "Physics::LinearCompton::makeSamplingKernel()";
209 ensureStrictlyPositive(laserPhotonEnergyGeV, where, "laserPhotonEnergyGeV");
210
211 SamplingKernel kernel;
212 kernel.electronTotalEnergyGeV = electronTotalEnergyGeV;
213 kernel.laserPhotonEnergyGeV = laserPhotonEnergyGeV;
214 kernel.beamDirection = normalizeDirection(beamDirection, where, "beamDirection");
215 kernel.laserDirection = normalizeDirection(laserDirection, where, "laserDirection");
217 electronTotalEnergyGeV, laserPhotonEnergyGeV, kernel.beamDirection,
218 kernel.laserDirection);
220 rejectionUpperBoundSolidAngleERF(kernel.incomingPhotonEnergyERFGeV);
221 return kernel;
222 }
223
224 SampledEvent sampleEvent(const SamplingKernel& kernel, std::mt19937_64& engine) {
225 constexpr const char* where = "Physics::LinearCompton::sampleEvent()";
226 ensureStrictlyPositive(
227 kernel.incomingPhotonEnergyERFGeV, where, "incomingPhotonEnergyERFGeV");
228 ensureStrictlyPositive(
230 "rejectionUpperBoundSolidAngleERF");
231
232 std::uniform_real_distribution<double> cosineDistribution(-1.0, 1.0);
233 std::uniform_real_distribution<double> azimuthDistribution(0.0, Physics::two_pi);
234 std::uniform_real_distribution<double> acceptDistribution(
236
237 for (int attempt = 0; attempt < 1000000; ++attempt) {
238 const double scatteringCosineERF = cosineDistribution(engine);
239 const double differentialCrossSection = differentialCrossSectionSolidAngleERF(
240 kernel.incomingPhotonEnergyERFGeV, scatteringCosineERF);
241 if (acceptDistribution(engine) > differentialCrossSection) {
242 continue;
243 }
244
245 SampledEvent event;
246 event.scatteringCosineERF = scatteringCosineERF;
247 event.azimuthERF = azimuthDistribution(engine);
248 event.scatteredPhotonEnergyERFGeV = scatteredPhotonEnergyERFGeV(
250 event.scatteredPhotonEnergyLabGeV = labPhotonEnergyGeV(
253 event.azimuthERF);
254 event.scatteredPhotonDirectionLab = labPhotonDirection(
256 event.scatteringCosineERF, event.azimuthERF);
257 return event;
258 }
259
260 throw OpalException(
261 where, "Rejection sampler failed to accept an event within the attempt limit.");
262 }
263
264 double invariantKappa(double incomingPhotonEnergyERFGeV) {
265 constexpr const char* where = "Physics::LinearCompton::invariantKappa()";
266 ensureStrictlyPositive(incomingPhotonEnergyERFGeV, where, "incomingPhotonEnergyERFGeV");
267 return incomingPhotonEnergyERFGeV / Physics::m_e;
268 }
269
270 double invariantX(double incomingPhotonEnergyERFGeV) {
271 return 2.0 * invariantKappa(incomingPhotonEnergyERFGeV);
272 }
273
275 double electronTotalEnergyGeV, double laserPhotonEnergyGeV,
276 const Vector_t<double, 3>& beamDirection,
277 const Vector_t<double, 3>& laserDirection) {
279 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection));
280 }
281
282 double scatteredPhotonEnergyMinERFGeV(double incomingPhotonEnergyERFGeV) {
283 const double kappa = invariantKappa(incomingPhotonEnergyERFGeV);
284 return incomingPhotonEnergyERFGeV / (1.0 + 2.0 * kappa);
285 }
286
287 double scatteredPhotonEnergyMaxERFGeV(double incomingPhotonEnergyERFGeV) {
288 invariantKappa(incomingPhotonEnergyERFGeV);
289 return incomingPhotonEnergyERFGeV;
290 }
291
293 double incomingPhotonEnergyERFGeV, double scatteringCosineERF) {
294 constexpr const char* where = "Physics::LinearCompton::scatteredPhotonEnergyERFGeV()";
295 const double kappa = invariantKappa(incomingPhotonEnergyERFGeV);
296 ensureCosineRange(scatteringCosineERF, where, "scatteringCosineERF");
297 const double clampedCosine = clampCosine(scatteringCosineERF);
298 return incomingPhotonEnergyERFGeV / (1.0 + kappa * (1.0 - clampedCosine));
299 }
300
302 double incomingPhotonEnergyERFGeV, double scatteringCosineERF) {
303 constexpr const char* where =
304 "Physics::LinearCompton::differentialCrossSectionSolidAngleERF()";
305 invariantKappa(incomingPhotonEnergyERFGeV);
306 ensureCosineRange(scatteringCosineERF, where, "scatteringCosineERF");
307 const double clampedCosine = clampCosine(scatteringCosineERF);
308 const double omega2 =
309 scatteredPhotonEnergyERFGeV(incomingPhotonEnergyERFGeV, clampedCosine);
310 const double energyRatio = omega2 / incomingPhotonEnergyERFGeV;
311 const double sin2 = std::max(0.0, 1.0 - clampedCosine * clampedCosine);
312 return 0.5 * Physics::r_e * Physics::r_e * energyRatio * energyRatio
313 * (1.0 / energyRatio + energyRatio - sin2);
314 }
315
317 double incomingPhotonEnergyERFGeV, double scatteredPhotonEnergyERFGeV) {
318 constexpr const char* where =
319 "Physics::LinearCompton::differentialCrossSectionOmegaERF()";
320 const double minEnergy = scatteredPhotonEnergyMinERFGeV(incomingPhotonEnergyERFGeV);
321 const double maxEnergy = scatteredPhotonEnergyMaxERFGeV(incomingPhotonEnergyERFGeV);
322 if (scatteredPhotonEnergyERFGeV < minEnergy - 1.0e-15
323 || scatteredPhotonEnergyERFGeV > maxEnergy + 1.0e-15) {
324 throw OpalException(
325 where,
326 "\"scatteredPhotonEnergyERFGeV\" is outside the physical Compton support.");
327 }
328
329 const double clampedEnergy =
330 std::max(minEnergy, std::min(maxEnergy, scatteredPhotonEnergyERFGeV));
331 const double cosine =
332 1.0 - Physics::m_e * (1.0 / clampedEnergy - 1.0 / incomingPhotonEnergyERFGeV);
333 const double clampedCosine = clampCosine(cosine);
334 const double dsigma_dOmega = differentialCrossSectionSolidAngleERF(
335 incomingPhotonEnergyERFGeV, clampedCosine);
336 const double jacobian = Physics::m_e / (clampedEnergy * clampedEnergy);
337 return Physics::two_pi * dsigma_dOmega * jacobian;
338 }
339
340 double totalCrossSection(double incomingPhotonEnergyERFGeV) {
341 const double kappa = invariantKappa(incomingPhotonEnergyERFGeV);
342
343 // The exact closed form suffers from cancellation for kappa << 1.
344 // Use the low-energy expansion around the Thomson limit there.
345 if (kappa < 1.0e-3) {
346 return thomsonCrossSection() * (1.0 - 2.0 * kappa + 5.2 * kappa * kappa);
347 }
348
349 const double logTerm = std::log(1.0 + 2.0 * kappa);
350 const double prefactor = 2.0 * Physics::pi * Physics::r_e * Physics::r_e;
351 const double bracket =
352 ((1.0 + kappa) / (kappa * kappa))
353 * ((2.0 * (1.0 + kappa)) / (1.0 + 2.0 * kappa) - logTerm / kappa)
354 + logTerm / (2.0 * kappa)
355 - (1.0 + 3.0 * kappa) / ((1.0 + 2.0 * kappa) * (1.0 + 2.0 * kappa));
356 return prefactor * bracket;
357 }
358
360 return (8.0 / 3.0) * Physics::pi * Physics::r_e * Physics::r_e;
361 }
362
364 double electronTotalEnergyGeV, const Vector_t<double, 3>& beamDirection,
365 const Vector_t<double, 3>& laserDirection) {
366 constexpr const char* where =
367 "Physics::LinearCompton::restFrameScatteringCosineForLabForwardPhoton()";
368 const double beta = electronBeta(electronTotalEnergyGeV);
369 const Vector_t<double, 3> normalizedBeamDirection =
370 normalizeDirection(beamDirection, where, "beamDirection");
371 const Vector_t<double, 3> normalizedLaserDirection =
372 normalizeDirection(laserDirection, where, "laserDirection");
373 const double cosAlpha =
374 clampCosine(dot(normalizedBeamDirection, normalizedLaserDirection));
375 return clampCosine((cosAlpha - beta) / (1.0 - beta * cosAlpha));
376 }
377
379 double electronTotalEnergyGeV, double laserPhotonEnergyGeV,
380 const Vector_t<double, 3>& beamDirection, const Vector_t<double, 3>& laserDirection,
381 double scatteringCosineERF, double azimuthERF) {
382 constexpr const char* where = "Physics::LinearCompton::labPhotonEnergyGeV()";
383 ensureStrictlyPositive(laserPhotonEnergyGeV, where, "laserPhotonEnergyGeV");
384 ensureCosineRange(scatteringCosineERF, where, "scatteringCosineERF");
385
386 const double gamma = electronGamma(electronTotalEnergyGeV);
387 const double beta = electronBeta(electronTotalEnergyGeV);
388 const Vector_t<double, 3> normalizedBeamDirection =
389 normalizeDirection(beamDirection, where, "beamDirection");
390 const Vector_t<double, 3> incomingDirectionERF = restFrameIncomingPhotonDirection(
391 electronTotalEnergyGeV, beamDirection, laserDirection);
392 const double omega1 = restFrameIncomingPhotonEnergyGeV(
393 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection);
394 const double clampedCosine = clampCosine(scatteringCosineERF);
395 const Vector_t<double, 3> outgoingDirectionERF = scatteredDirectionERF(
396 incomingDirectionERF, normalizedBeamDirection, clampedCosine, azimuthERF,
397 where);
398 const double omega2 = scatteredPhotonEnergyERFGeV(omega1, clampedCosine);
399 return gamma * omega2
400 * (1.0 + beta * dot(outgoingDirectionERF, normalizedBeamDirection));
401 }
402
404 double electronTotalEnergyGeV, double laserPhotonEnergyGeV,
405 const Vector_t<double, 3>& beamDirection,
406 const Vector_t<double, 3>& laserDirection) {
407 const double scatteringCosine = restFrameScatteringCosineForLabForwardPhoton(
408 electronTotalEnergyGeV, beamDirection, laserDirection);
409 return labPhotonEnergyGeV(
410 electronTotalEnergyGeV, laserPhotonEnergyGeV, beamDirection, laserDirection,
411 scatteringCosine, 0.0);
412 }
413
414 } // namespace LinearCompton
415} // namespace Physics
ippl::Vector< T, Dim > Vector_t
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Definition Vector3D.cpp:89
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 electronGamma(double electronTotalEnergyGeV)
Compute the electron Lorentz factor from total energy.
Vector_t< double, 3 > labPhotonDirection(double electronTotalEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection, double scatteringCosineERF, double azimuthERF)
Laboratory-frame photon direction from electron-rest-frame scattering angles.
double scatteringCosineERF
Rest-frame polar scattering cosine .
double totalCrossSection(double incomingPhotonEnergyERFGeV)
Total unpolarized Klein-Nishina cross section.
double differentialCrossSectionSolidAngleERF(double incomingPhotonEnergyERFGeV, double scatteringCosineERF)
Unpolarized Klein-Nishina differential cross section in solid angle.
double electronTotalEnergyGeV
Incoming electron total energy in the lab frame [GeV].
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.
Vector_t< double, 3 > beamDirection
Normalized incoming electron direction in the lab frame.
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 laserPhotonEnergyGeV
Incoming laser-photon energy in the lab frame [GeV].
double thomsonCrossSection()
Thomson limit cross section.
double scatteredPhotonEnergyMaxERFGeV(double incomingPhotonEnergyERFGeV)
Maximum scattered photon energy in the electron rest frame.
Vector_t< double, 3 > laserDirection
Normalized incoming laser direction in the lab frame.
Vector_t< double, 3 > restFrameIncomingPhotonDirection(double electronTotalEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection)
Incoming laser-photon direction in the electron rest frame.
double scatteredPhotonEnergyERFGeV(double incomingPhotonEnergyERFGeV, double scatteringCosineERF)
Compute the scattered photon energy in the electron rest frame.
double electronBeta(double electronTotalEnergyGeV)
Compute the electron speed in units of c from total energy.
double restFrameIncomingPhotonEnergyGeV(double electronTotalEnergyGeV, double laserPhotonEnergyGeV, const Vector_t< double, 3 > &beamDirection, const Vector_t< double, 3 > &laserDirection)
Compute the incoming 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.
double invariantKappa(double incomingPhotonEnergyERFGeV)
Compute the dimensionless Klein-Nishina parameter .
Sampled single-photon Compton event.
Host-only cached data for repeated linear-Compton event sampling.
Definition Air.h:27
constexpr double two_pi
The value of.
Definition Physics.h:40
constexpr double h_bar
The reduced Planck constant in GeVs.
Definition Physics.h:69
constexpr double m_e
The electron rest mass in GeV.
Definition Physics.h:93
constexpr double c
The velocity of light in m/s.
Definition Physics.h:60
constexpr double pi
The value of.
Definition Physics.h:36
constexpr double r_e
The classical electron radius in m.
Definition Physics.h:96