OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
LinearBreitWheelerBenchmark.cpp
Go to the documentation of this file.
2#include "Utilities/Options.h"
3
4#include <cstdlib>
5#include <filesystem>
6#include <fstream>
7#include <iostream>
8#include <stdexcept>
9#include <string>
10
11namespace {
21 struct CliOptions {
22 std::filesystem::path output = "opalx-linear-breit-wheeler-spectrum.csv";
23 std::string particle = "electron";
24 std::string observable = "energy";
25 bool joint = false;
26 bool finitePhotonBeam = false;
27 std::size_t samples = 250000;
28 int seed = 13579;
29 double wavelength_m = 1.0e-9;
30 double highEnergyPhotonEnergyGeV = 0.5;
31 double photonSigmaThetaRad = 1.0e-3;
32 double photonRelativeEnergySpread = 0.0;
33 double photonSigmaPositionM = 0.0;
34 double photonSigmaSM = 0.0;
35 double laserRayleighM = 1.0e-6;
36 double laserSigmaTM = 5.0e-12 * Physics::c;
37 bool overlapWeighting = false;
38 std::size_t bins = 80;
39 double minValue = 0.0;
40 double maxValue = 0.5;
41 double thetaMaxRad = 0.0045;
42 };
43
44 CliOptions parseArguments(int argc, char** argv) {
45 CliOptions options;
46 for (int i = 1; i < argc; ++i) {
47 const std::string arg(argv[i]);
48 if (arg == "--particle") {
49 options.particle = argv[++i];
50 } else if (arg == "--observable") {
51 options.observable = argv[++i];
52 } else if (arg == "--joint") {
53 options.joint = true;
54 } else if (arg == "--finite-photon-beam") {
55 options.finitePhotonBeam = true;
56 } else if (arg == "--samples") {
57 options.samples = static_cast<std::size_t>(std::stoull(argv[++i]));
58 } else if (arg == "--seed") {
59 options.seed = std::stoi(argv[++i]);
60 } else if (arg == "--wavelength") {
61 options.wavelength_m = std::stod(argv[++i]);
62 } else if (arg == "--high-energy-photon") {
63 options.highEnergyPhotonEnergyGeV = std::stod(argv[++i]);
64 } else if (arg == "--photon-sigma-theta") {
65 options.photonSigmaThetaRad = std::stod(argv[++i]);
66 } else if (arg == "--photon-relative-energy-spread") {
67 options.photonRelativeEnergySpread = std::stod(argv[++i]);
68 } else if (arg == "--photon-sigma-position") {
69 options.photonSigmaPositionM = std::stod(argv[++i]);
70 } else if (arg == "--photon-sigma-s") {
71 options.photonSigmaSM = std::stod(argv[++i]);
72 } else if (arg == "--laser-rayleigh") {
73 options.laserRayleighM = std::stod(argv[++i]);
74 } else if (arg == "--laser-sigma-t") {
75 options.laserSigmaTM = std::stod(argv[++i]);
76 } else if (arg == "--overlap-weighting") {
77 options.overlapWeighting = true;
78 } else if (arg == "--bins") {
79 options.bins = static_cast<std::size_t>(std::stoull(argv[++i]));
80 } else if (arg == "--min") {
81 options.minValue = std::stod(argv[++i]);
82 } else if (arg == "--max") {
83 options.maxValue = std::stod(argv[++i]);
84 } else if (arg == "--theta-max") {
85 options.thetaMaxRad = std::stod(argv[++i]);
86 } else if (arg == "-h" || arg == "--help") {
87 std::cout << "Usage: LinearBreitWheelerBenchmark [output.csv] [--particle "
88 "electron|positron]"
89 << " [--observable energy|theta] [--joint] [--finite-photon-beam] "
90 "[--overlap-weighting] [--samples N] [--seed S] [--bins N]"
91 << " [--high-energy-photon E] [--photon-sigma-theta S] "
92 "[--photon-relative-energy-spread S]"
93 << " [--photon-sigma-position S] [--photon-sigma-s S] [--laser-rayleigh "
94 "S] [--laser-sigma-t S]"
95 << " [--min V] [--max V] [--theta-max V]\n";
96 std::exit(0);
97 } else if (!arg.empty() && arg[0] == '-') {
98 throw std::runtime_error("Unknown option: " + arg);
99 } else {
100 options.output = arg;
101 }
102 }
103 return options;
104 }
105
106 Vector_t<double, 3> makeDirection(double x, double y, double z) {
107 Vector_t<double, 3> value(0.0);
108 value(0) = x;
109 value(1) = y;
110 value(2) = z;
111 return value;
112 }
113
114 LinearBreitWheelerBenchmark::FinalState parseFinalState(const std::string& particle) {
115 if (particle == "positron") {
117 }
119 }
120
121 LinearBreitWheelerBenchmark::Observable parseObservable(const std::string& observable) {
122 if (observable == "theta") {
124 }
126 }
127} // namespace
128
129int main(int argc, char** argv) {
130 const CliOptions options = parseArguments(argc, argv);
131 const int previousSeed = Options::seed;
132 Options::seed = options.seed;
133
134 const auto state = parseFinalState(options.particle);
135
136 if (options.joint) {
137 if (options.finitePhotonBeam) {
139 config.centralHighEnergyPhotonEnergyGeV = options.highEnergyPhotonEnergyGeV;
140 config.wavelength_m = options.wavelength_m;
141 config.referenceHighEnergyDirection = makeDirection(0.0, 0.0, 1.0);
142 config.laserDirection = makeDirection(0.0, 0.0, -1.0);
143 config.sigmaThetaXRad = options.photonSigmaThetaRad;
144 config.sigmaThetaYRad = options.photonSigmaThetaRad;
145 config.relativeEnergySpread = options.photonRelativeEnergySpread;
146 config.sigmaX_m = options.photonSigmaPositionM;
147 config.sigmaY_m = options.photonSigmaPositionM;
148 config.sigmaS_m = options.photonSigmaSM;
149 config.laserRayleighX_m = options.laserRayleighM;
150 config.laserRayleighY_m = options.laserRayleighM;
151 config.laserSigmaT_m = options.laserSigmaTM;
152 config.overlapWeighting = options.overlapWeighting;
153 config.energyBins = options.bins;
154 config.thetaBins = options.bins;
155 config.energyMinGeV = options.minValue;
156 config.energyMaxGeV = options.maxValue;
157 config.thetaMinRad = 0.0;
158 config.thetaMaxRad = options.thetaMaxRad;
159
160 const auto histogram =
162 config, state, options.samples);
164 } else {
166 config.highEnergyPhotonEnergyGeV = options.highEnergyPhotonEnergyGeV;
167 config.wavelength_m = options.wavelength_m;
168 config.highEnergyDirection = makeDirection(0.0, 0.0, 1.0);
169 config.laserDirection = makeDirection(0.0, 0.0, -1.0);
170 config.energyBins = options.bins;
171 config.thetaBins = options.bins;
172 config.energyMinGeV = options.minValue;
173 config.energyMaxGeV = options.maxValue;
174 config.thetaMinRad = 0.0;
175 config.thetaMaxRad = options.thetaMaxRad;
176
178 config, state, options.samples);
180 }
181 Options::seed = previousSeed;
182 std::cout << "Wrote OPALX linear Breit-Wheeler joint benchmark to " << options.output
183 << '\n';
184 return 0;
185 }
186
187 const auto observable = parseObservable(options.observable);
189
190 std::ofstream output(options.output);
191 output << "# value,weight\n";
192
193 if (options.finitePhotonBeam) {
194 const double laserPhotonEnergyGeV =
197 config.centralHighEnergyPhotonEnergyGeV = options.highEnergyPhotonEnergyGeV;
198 config.wavelength_m = options.wavelength_m;
199 config.referenceHighEnergyDirection = makeDirection(0.0, 0.0, 1.0);
200 config.laserDirection = makeDirection(0.0, 0.0, -1.0);
201 config.sigmaThetaXRad = options.photonSigmaThetaRad;
202 config.sigmaThetaYRad = options.photonSigmaThetaRad;
203 config.relativeEnergySpread = options.photonRelativeEnergySpread;
204 config.sigmaX_m = options.photonSigmaPositionM;
205 config.sigmaY_m = options.photonSigmaPositionM;
206 config.sigmaS_m = options.photonSigmaSM;
207 config.laserRayleighX_m = options.laserRayleighM;
208 config.laserRayleighY_m = options.laserRayleighM;
209 config.laserSigmaT_m = options.laserSigmaTM;
210 config.overlapWeighting = options.overlapWeighting;
211
212 for (std::size_t i = 0; i < options.samples; ++i) {
213 const auto beamState =
214 config.overlapWeighting
216 config, engine)
219 config.sigmaThetaYRad, config.sigmaX_m, config.sigmaY_m,
221 config.relativeEnergySpread, engine);
222 constexpr double overlapWeight = 1.0;
224 beamState.energyGeV, laserPhotonEnergyGeV, beamState.direction,
225 config.laserDirection);
226 const auto event = Physics::LinearBreitWheeler::sampleEvent(kernel, engine);
227 const double value =
228 LinearBreitWheelerBenchmark::sampledObservable(event, state, observable);
229 output << value << ',' << overlapWeight << '\n';
230 }
231 } else {
232 const double laserPhotonEnergyGeV =
235 options.highEnergyPhotonEnergyGeV, laserPhotonEnergyGeV,
236 makeDirection(0.0, 0.0, 1.0), makeDirection(0.0, 0.0, -1.0));
237 for (std::size_t i = 0; i < options.samples; ++i) {
238 const auto event = Physics::LinearBreitWheeler::sampleEvent(kernel, engine);
239 const double value =
240 LinearBreitWheelerBenchmark::sampledObservable(event, state, observable);
241 output << value << ",1\n";
242 }
243 }
244
245 Options::seed = previousSeed;
246 std::cout << "Wrote OPALX linear Breit-Wheeler sampled benchmark to " << options.output << '\n';
247 return 0;
248}
ippl::Vector< T, Dim > Vector_t
int main(int argc, char **argv)
double sampledObservable(const Physics::LinearBreitWheeler::SampledEvent &event, FinalState state, Observable observable)
JointHistogram sampleFinitePhotonBeamJointHistogram(const FinitePhotonBeamJointConfig &config, FinalState state, std::size_t sampleCount, std::uint64_t streamIndex=0)
Sample the joint Breit-Wheeler laboratory distribution in energy and polar angle.
void writeJointHistogramCSV(const JointHistogram &histogram, const std::filesystem::path &outputPath)
SampledPhotonBeamState samplePhotonBeamState(const Vector_t< double, 3 > &referenceDirection, double sigmaThetaXRad, double sigmaThetaYRad, double sigmaX_m, double sigmaY_m, double sigmaS_m, double centralEnergyGeV, double relativeEnergySpread, std::mt19937_64 &engine)
JointHistogram sampleJointHistogram(const JointHistogramConfig &config, FinalState state, std::size_t sampleCount, std::uint64_t streamIndex=0)
SampledPhotonBeamState sampleOverlapPhotonBeamState(const FinitePhotonBeamConfig &config, std::mt19937_64 &engine)
Configuration for folding the linear Breit-Wheeler kernel over a finite incoming photon beam.
int seed
The current random seed.
Definition Options.cpp:37
SampledEvent sampleEvent(const SamplingKernel &kernel, std::mt19937_64 &engine)
Sample one unpolarized linear Breit-Wheeler event.
SamplingKernel makeSamplingKernel(double highEnergyPhotonEnergyGeV, double laserPhotonEnergyGeV, const Vector_t< double, 3 > &highEnergyDirection, const Vector_t< double, 3 > &laserDirection)
Build a cached sampling kernel for repeated sampled events.
std::mt19937_64 makeHostRandomEngine(std::uint64_t streamIndex)
Build a deterministic host RNG from Options::seed.
double photonEnergyFromWavelengthGeV(double wavelength_m)
Convert a laser wavelength to a single-photon energy.
constexpr double c
The velocity of light in m/s.
Definition Physics.h:60