Belle II Software development
BBBrem.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <generators/bbbrem/BBBrem.h>
10#include <framework/logging/Logger.h>
11#include <framework/gearbox/Const.h>
12#include <mdst/dataobjects/MCParticleGraph.h>
13
14#include <TRandom3.h>
15//#include <cmath>
16
17using namespace std;
18using namespace Belle2;
19
20
21void BBBrem::init(double cmsEnergy, double minPhotonEFrac, bool unweighted, double maxWeight, int densitymode,
22 double densityparameter)
23{
24 m_cmsEnergy = cmsEnergy;
25 m_photonEFrac = minPhotonEFrac;
26
27 m_unweighted = unweighted;
28 m_maxWeight = maxWeight;
29 m_densityCorrectionMode = densitymode;
30 m_densityCorrectionParameter = densityparameter;
31
35 m_weightCount = 0;
36
37 if ((minPhotonEFrac <= 0.0) || (minPhotonEFrac >= 1.0)) {
38 B2ERROR("BBBrem: The minimum photon energy fraction has to be in the range ]0,1[ !");
39 return;
40 }
41
42 B2DEBUG(100, "BBBrem: Center of mass energy: " << cmsEnergy);
43 B2DEBUG(100, "BBBrem: Minimum photon energy: " << minPhotonEFrac << " * beam energy");
44
45 //Initialize the constants (in order to be consistent with the FORTRAN source code)
48
49 //Initialize the derived constants
50 s = cmsEnergy * cmsEnergy;
51 rme2 = rme * rme;
52 rme2s = rme2 / s;
53 rls = -log(rme2s);
54 z0 = minPhotonEFrac / (1.0 - minPhotonEFrac);
55
56 //Approximate total cross section
57 a1 = log((1.0 + z0) / z0);
58// a2 = (log(1.0 + z0)) / z0;
59// Expression 'log(1 + x)' is replaced by 'log1p(x)' to avoid loss of precision.
60 a2 = (log1p(z0)) / z0;
61 ac = a1 / (a1 + a2);
62 sigapp = 8.0 * (alpha * alpha * alpha) / rme2 * (-log(rme2s)) * (a1 + a2) * tomb;
63 B2DEBUG(100, "BBBrem: Approximate cross section: " << sigapp << " millibarn");
64
65 //Initial-state momenta
66 eb = 0.5 * cmsEnergy;
67 pb = sqrt(eb * eb - rme2);
68 rin2pb = 0.5 / pb;
69 p1[0] = 0.0;
70 p1[1] = 0.0;
71 p1[2] = -pb;
72 p1[3] = eb;
73 q1[0] = 0.0;
74 q1[1] = 0.0;
75 q1[2] = pb;
76 q1[3] = eb;
77}
78
79
80double BBBrem::generateEvent(MCParticleGraph& mcGraph, ROOT::Math::XYZVector vertex, ROOT::Math::LorentzRotation boost)
81{
82
83 if (m_unweighted) {
84 double ran = 0.0;
85 do {
88 if (weight > m_maxWeight) {
89 B2INFO("BBBrem: OVERWEIGHT, w=" << weight << ", nw=" << m_weightCountOver << ", sumw=" << m_sumWeightDeliveredOver);
93 }
97
98 ran = gRandom->Uniform();
99 } while (weight <= ran * m_maxWeight);
100 } else {
106 }
107
108 //Store the incoming particles as virtual particles, the outgoing particles as real particles
109 storeParticle(mcGraph, p1, 11, vertex, boost, false, true);
110 storeParticle(mcGraph, q1, -11, vertex, boost, false, true);
111
112 // BBBrem emits gammma only from electron(p1)
113 // To emit gamma from positron we need to swap electron and positron here
114 bool swapflag = (gRandom->Uniform() > 0.5) ? true : false;
115 if (swapflag) {
116 double tmp[4];
117 for (int i = 0; i < 4; i++) tmp[i] = p2[i];
118 for (int i = 0; i < 4; i++) p2[i] = q2[i];
119 for (int i = 0; i < 4; i++) q2[i] = tmp[i];
120 p2[2] = -p2[2];
121 q2[2] = -q2[2];
122 qk[2] = -qk[2];
123 }
124
125 //Store the outgoing particles as real particles
126 storeParticle(mcGraph, p2, 11, vertex, boost, false, false);
127 storeParticle(mcGraph, q2, -11, vertex, boost, false, false);
128 storeParticle(mcGraph, qk, 22, vertex, boost, false, false);
129
130 if (!m_unweighted) return weight;
131 return 1.0;
132}
133
134
136{
137 if (m_weightCount > 0.0) {
141
142 if (m_unweighted) {
146 }
147 }
148}
149
150
151//=========================================================================
152// Protected methods
153//=========================================================================
154
156{
157 //Generate z
158 double z;
159 if (gRandom->Uniform() < ac) {
160 double temp1 = gRandom->Uniform();
161// z = 1.0 / (temp1 * (exp(a1 * gRandom->Uniform()) - 1.0));
162// Expression 'exp(x) - 1' is replaced by 'expm1(x)' to avoid loss of precision.
163 z = 1.0 / (temp1 * (expm1(a1 * gRandom->Uniform())));
164 } else {
165 z = z0 / gRandom->Uniform();
166 }
167
168 //Bounds on t
169 double y = rme2s * z;
170 double q0 = eb * y;
171 double temp1 = pb * pb - eb * q0;
172 double temp2 = temp1 * temp1 - rme2 - q0 * q0;
173
174 //If temp2<0 (very very rare): set weight to 0
175 if (temp2 < 0.0) {
176 B2WARNING("BBBrem: y too large: delta_t^2 = " << temp2 << " !!!");
177 weight = 0.0;
178 } else {
179 double tmin = -2.0 * (temp1 + sqrt(temp2));
180 double tmax = rme2 * s * y * y / tmin;
181
182 //Generate t
183 double sy = s * y;
184 double w2 = sy + rme2;
185 temp1 = sy + tmax;
186 double rlamx = sqrt(temp1 * temp1 - 4.0 * w2 * tmax);
187
188 if (temp1 <= 0.0) {
189 temp1 = rlamx - temp1;
190 } else {
191 temp1 = -4.0 * w2 * tmax / (rlamx + temp1);
192 }
193
194 double t = 0.0;
195 do {
196 double b;
197// b = exp(gRandom->Uniform() * log(1.0 + 2.0 * sy / temp1));
198// Expression 'log(1 + x)' is replaced by 'log1p(x)' to avoid loss of precision.
199 b = exp(gRandom->Uniform() * log1p(2.0 * sy / temp1));
200 t = -b * z * z * rme2 / ((b - 1) * (b * z + b - 1));
201 } while (t <= tmin);
202
203 //Generate cgam
204 double rlam = sqrt((sy - t) * (sy - t) - 4 * rme2 * t);
205 double eps = 4 * rme2 * w2 / (rlam * (rlam + w2 + rme2 - t));
206 double rl = log((2 + eps) / eps);
207// double vgam = eps * (exp(gRandom->Uniform() * rl) - 1.0);
208// Expression 'exp(x) - 1' is replaced by 'expm1(x)' to avoid loss of precision.
209 double vgam = eps * (expm1(gRandom->Uniform() * rl));
210 double cgam = 1.0 - vgam;
211 double sgam = sqrt(vgam * (2 - vgam));
212
213 //Generate azimuthal angles
214 double phi = twopi * gRandom->Uniform();
215 double phig = twopi * gRandom->Uniform();
216
217 //Construct momentum transfer q(mu)
218 double ql = (2.0 * eb * q0 - t) * rin2pb;
219 double qt = sqrt((tmax - t) * (t - tmin)) * rin2pb;
220 double q[4];
221 q[0] = qt * sin(phi);
222 q[1] = qt * cos(phi);
223 q[2] = ql;
224 q[3] = q0;
225
226 //Construct momentum of outgoing positron in lab frame
227 q2[0] = q1[0] - q[0];
228 q2[1] = q1[1] - q[1];
229 q2[2] = q1[2] - q[2];
230 q2[3] = q1[3] - q[3];
231
232 //Find euler angles of p1(mu) in cm frame
233 double r0 = eb + q0;
234 double w = sqrt(w2);
235 double rin2w = 0.5 / w;
236 double rinr0w = 1.0 / (r0 + w);
237 double eta = -(sy + 2 * w * q0 + t) * rin2w * rinr0w;
238 double phat1 = -q[0] * (1 + eta);
239 double phat2 = -q[1] * (1 + eta);
240 double phat3 = pb * eta - ql * (1 + eta);
241 double phatl = rlam * rin2w;
242 double phatt = sqrt(phat1 * phat1 + phat2 * phat2);
243 double sfhat = phat1 / phatt;
244 double cfhat = phat2 / phatt;
245 double sthat = phatt / phatl;
246 double vthat;
247 if (phat3 > 0.0) {
248 vthat = sthat * sthat / (1 - sqrt(1 - sthat * sthat));
249 } else {
250 vthat = sthat * sthat / (1 + sqrt(1 - sthat * sthat));
251 }
252 double cthat = vthat - 1.0;
253
254 //Rotate using these euler angles to get the qk direction in the cm
255 double sfg = sin(phig);
256 double cfg = cos(phig);
257 temp1 = sgam * sfg;
258 temp2 = cthat * sgam * cfg + sthat * cgam;
259 double veg = vthat + vgam - vthat * vgam - sthat * sgam * cfg;
260 double qkhat[4];
261 qkhat[3] = sy * rin2w;
262 qkhat[0] = qkhat[3] * (cfhat * temp1 + sfhat * temp2);
263 qkhat[1] = qkhat[3] * (-sfhat * temp1 + cfhat * temp2);
264 qkhat[2] = qkhat[3] * (veg - 1.0);
265
266 //Boost the photon momentum to the lab frame
267 temp1 = pb * qkhat[2];
268 if (temp1 > 0.0) {
269 temp2 = (rme2 * qkhat[3] * qkhat[3] + pb * pb * (qkhat[0] * qkhat[0] + qkhat[1] * qkhat[1])) / (eb * qkhat[3] + temp1);
270 } else {
271 temp2 = eb * qkhat[3] - temp1;
272 }
273
274 qk[3] = (temp2 + qkhat[3] * q[3] + qkhat[0] * q[0] + qkhat[1] * q[1] + qkhat[2] * q[2]) / w;
275 temp1 = (qk[3] + qkhat[3]) * rinr0w;
276 qk[0] = qkhat[0] + temp1 * q[0];
277 qk[1] = qkhat[1] + temp1 * q[1];
278 qk[2] = qkhat[2] + temp1 * (-pb + ql);
279
280 //Construct p2 by momentum conservation
281 p2[0] = -q2[0] - qk[0];
282 p2[1] = -q2[1] - qk[1];
283 p2[2] = -q2[2] - qk[2];
284 p2[3] = -q2[3] - qk[3] + m_cmsEnergy;
285
286 //Impose cut on the photon energy: qk[3]>eb*rk0
287 if (qk[3] < eb * m_photonEFrac) {
288 weight = 0.0;
289 } else {
290 //The event is now accepted: compute matrix element and weight
291 //Compute fudge factor c1
292// double c1 = log(1 + z) / log((2 + eps) / eps);
293// Expression 'log(1 + x)' is replaced by 'log1p(x)' to avoid loss of precision.
294 double c1 = log1p(z) / log((2.0 + eps) / eps);
295
296 //Compute fudge factor c2
297 temp1 = sy - tmax;
298 double vnumx = sqrt(temp1 * temp1 - 4.0 * rme2 * tmax) + temp1;
299 temp1 = sy + tmax;
300
301 double vdenx;
302 if (temp1 < 0.0) {
303 vdenx = sqrt(temp1 * temp1 - 4.0 * w2 * tmax) - temp1;
304 } else {
305 vdenx = -4.0 * w2 * tmax / (sqrt(temp1 * temp1 - 4.0 * w2 * tmax) + temp1);
306 }
307 temp1 = sy - tmin;
308 double vnumn = sqrt(temp1 * temp1 - 4.0 * rme2 * tmin) + temp1;
309 temp1 = sy + tmin;
310
311 double vdenn;
312 if (temp1 < 0.0) {
313 vdenn = sqrt(temp1 * temp1 - 4.0 * w2 * tmin) - temp1;
314 } else {
315 vdenn = -4.0 * w2 * tmin / (sqrt(temp1 * temp1 - 4.0 * w2 * tmin) + temp1);
316 }
317 double c2 = 2.0 * rls / log((vnumx * vdenn) / (vdenx * vnumn));
318
319 //Compute vector (small) r in cm frame, and (big) z
320 double rlabl = (t - 2.0 * rme2 * y) * rin2pb;
321 double rhat4 = -(2.0 * rme2 * y + (1 - y) * t) * rin2w;
322 double etar = rhat4 * rinr0w;
323 double rhat1 = -q[0] * (1 + etar);
324 double rhat2 = -q[1] * (1 + etar);
325 double rhat3 = rlabl + (pb - ql) * etar;
326 double zz = s * (rhat4 * qkhat[3] - rhat1 * qkhat[0] - rhat2 * qkhat[1] - rhat3 * qkhat[2]);
327
328 //The other invariants
329 double s1 = 4.0 * eb * (eb - qk[3]);
330 double d1 = sy * rlam * (eps + vgam) * rin2w * rin2w;
331 double d2 = 0.5 * sy;
332
333 //The exact matrix element
334 //Kleiss-burkhardt cross section multiplied by t^2
335 double rind1 = 1.0 / d1;
336 double rind12 = rind1 * rind1;
337 double rind2 = 1.0 / d2;
338 double rind22 = rind2 * rind2;
339 temp1 = s + t - 2 * d2;
340 temp2 = s1 + t + 2 * d1;
341 double aa0 = (s * s + s1 * s1 + temp1 * temp1 + temp2 * temp2) * rind1 * rind2 * (-t);
342 double aa1 = -4.0 * rme2 * zz * zz * rind12 * rind22;
343 double aa2 = -8.0 * rme2 * (d1 * d1 + d2 * d2) * rind1 * rind2;
344 double aa3 = 16.0 * rme2 * rme2 * (d1 - d2) * zz * rind12 * rind22;
345 double aa4 = -16.0 * rme2 * rme2 * rme2 * (d1 - d2) * (d1 - d2) * rind12 * rind22;
346 double rmex = aa0 + aa1 + aa2 + aa3 + aa4;
347
348 //The approximate matrix element without c1,2, multiplied by t^2
349 double rmap = 4.0 * s * s * rind1 * rind2 * (-t) * c1 * c2;
350
351 //The weight
352 weight = rmex / rmap * sigapp;
353
354 //Isnan check (not sure if this is ok)
355 if (std::isnan(weight)) {
356 B2WARNING("BBBrem: Weight is nan! Setting the weight to zero.");
357 weight = 0.0;
358 }
359
360
361 //========================================================
362 // beam size effect (or density effect)
363 // ref: arxiv:hep-ph/9401333
364
365 // tc = (hbarc/simga_y)^2
366// double tc = 1.68e-17; //SuperKEKB LER (sigma_y*=48nm)
367 //double tc = 9.81e-18; //SuperKEKB HER (sigma_y*=63nm)
369// int cutflag = 0 ; // 0: no cut, 1: hard cut, 2: soft cut
370 if (m_densityCorrectionMode == 1) {
371 if (abs(t) < tc) weight = 0.0;
372 } else if (m_densityCorrectionMode == 2) {
373 if (t != tc) weight *= t * t / (t - tc) / (t - tc); // t<0<tc, always t!=tc
374 }
375 //========================================================
376
377 }
378 }
379}
380
381
382void BBBrem::storeParticle(MCParticleGraph& mcGraph, const double* mom, int pdg, ROOT::Math::XYZVector vertex,
383 ROOT::Math::LorentzRotation boost,
384 bool isVirtual, bool isInitial)
385{
386
387 // RG 6/25/14 Add new flag for ISR "c_Initial"
389 if (isVirtual) {
391 } else if (isInitial) {
393 }
394
395 //all particles from a generator are primary
397
398 //all non virtual photons from BBBREM are ISR or FSR
399 if (pdg == 22 && !isVirtual) {
402 }
403
404 part.setPDG(pdg);
405 part.setFirstDaughter(0);
406 part.setLastDaughter(0);
407 part.setMomentum(ROOT::Math::XYZVector(mom[0], mom[1],
408 -mom[2])); //Switch direction, because electrons fly into the +z direction at Belle II
409 part.setEnergy(mom[3]);
410 part.setMassFromPDG();
411// part.setDecayVertex(0.0, 0.0, 0.0);
412
413 //set the production vertex of non initial particles
414 if (!isInitial) {
415 ROOT::Math::XYZVector v3 = part.getProductionVertex();
416 v3 = v3 + vertex;
417 part.setProductionVertex(v3);
418 part.setValidVertex(true);
419 }
420
421 //If boosting is enable boost the particles to the lab frame
422 ROOT::Math::PxPyPzEVector p4 = part.get4Vector();
423 p4 = boost * p4;
424 part.set4Vector(p4);
425}
double rme2
variable
Definition: BBBrem.h:184
long m_weightCountOver
Internal overweighted event counter.
Definition: BBBrem.h:139
double sigapp
variable
Definition: BBBrem.h:191
double rme2s
variable
Definition: BBBrem.h:185
double alpha
variable
Definition: BBBrem.h:181
double m_maxWeightDelivered
The maximum weight given by the BBBrem generation.
Definition: BBBrem.h:141
void storeParticle(MCParticleGraph &mcGraph, const double *mom, int pdg, ROOT::Math::XYZVector vertex, ROOT::Math::LorentzRotation boost, bool isVirtual=false, bool isInitial=false)
Store a single generated particle into the MonteCarlo graph.
Definition: BBBrem.cc:382
double rme
in MeV
Definition: BBBrem.h:182
double m_crossSection
The cross-section in millibarns.
Definition: BBBrem.h:149
bool m_unweighted
True if BBBrem should produce unweighted events.
Definition: BBBrem.h:137
double m_cmsEnergy
Center of mass energy (sqrt(s)).
Definition: BBBrem.h:146
double rin2pb
variable
Definition: BBBrem.h:194
double m_densityCorrectionParameter
Density correction parameter tc.
Definition: BBBrem.h:155
static constexpr double twopi
2*pi.
Definition: BBBrem.h:178
void calcOutgoingLeptonsAndWeight()
Calculate the outgoing leptons and the event weight for one single radiative Bhabha scattering.
Definition: BBBrem.cc:155
long m_weightCount
Internal weighted event counter.
Definition: BBBrem.h:138
double pb
variable
Definition: BBBrem.h:193
double a1
variable
Definition: BBBrem.h:188
static constexpr double tomb
Conversion factor (hc)^2.
Definition: BBBrem.h:177
double m_sumWeightDeliveredOver
The sum of all overweights.
Definition: BBBrem.h:144
void term()
Terminates the generator.
Definition: BBBrem.cc:135
double m_maxWeight
The maximum weight.
Definition: BBBrem.h:140
double z0
variable
Definition: BBBrem.h:187
double p2[4]
variable
Definition: BBBrem.h:196
double generateEvent(MCParticleGraph &mcGraph, ROOT::Math::XYZVector vertex, ROOT::Math::LorentzRotation boost)
Generates one single event.
Definition: BBBrem.cc:80
double p1[4]
variable
Definition: BBBrem.h:195
double m_sumWeightDelivered
The sum of all weights returned by the BBBrem generation.
Definition: BBBrem.h:142
double eb
variable
Definition: BBBrem.h:192
double weight
variable
Definition: BBBrem.h:200
double q1[4]
variable
Definition: BBBrem.h:197
void init(double cmsEnergy, double minPhotonEFrac, bool unweighted=true, double maxWeight=2000.0, int densitymode=1, double densityparameter=1.68e-17)
Initializes the generator.
Definition: BBBrem.cc:21
double m_crossSectionError
The error on the cross-section in millibarns.
Definition: BBBrem.h:150
double m_sumWeightDeliveredSqrOver
The square of the sum of all overweights.
Definition: BBBrem.h:145
double ac
variable
Definition: BBBrem.h:190
double q2[4]
variable
Definition: BBBrem.h:198
double a2
variable
Definition: BBBrem.h:189
double m_sumWeightDeliveredSqr
The square of the sum of all weights returned by the BBBrem generation.
Definition: BBBrem.h:143
double qk[4]
variable
Definition: BBBrem.h:199
double m_photonEFrac
Minimum photon energy fraction.
Definition: BBBrem.h:147
int m_densityCorrectionMode
Mode for bunch density correction.
Definition: BBBrem.h:154
double m_crossSectionErrorOver
The overweight bias error on the cross-section in millibarns.
Definition: BBBrem.h:152
double s
variable
Definition: BBBrem.h:183
double rls
variable
Definition: BBBrem.h:186
double m_crossSectionOver
The overweight bias cross-section in millibarns.
Definition: BBBrem.h:151
static const double electronMass
electron mass
Definition: Const.h:685
static const double fineStrConst
The fine structure constant.
Definition: Const.h:698
Class to represent Particle data in graph.
void setFirstDaughter(int daughter)
Set the 1-based index of the first daughter, 0 means no daughters.
void setLastDaughter(int daughter)
Set the 1-based index of the last daughter, 0 means no daughters.
Class to build, validate and sort a particle decay chain.
@ c_IsFSRPhoton
bit 7: Particle is from finial state radiation
Definition: MCParticle.h:61
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
Definition: MCParticle.h:57
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
Definition: MCParticle.h:55
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
Definition: MCParticle.h:59
void addStatus(unsigned short int bitmask)
Add bitmask to current status.
Definition: MCParticle.h:353
void setEnergy(float energy)
Set energy.
Definition: MCParticle.h:372
ROOT::Math::XYZVector getProductionVertex() const
Return production vertex position.
Definition: MCParticle.h:189
void setValidVertex(bool valid)
Set indication wether vertex and time information is valid or just default.
Definition: MCParticle.h:378
void setProductionVertex(const ROOT::Math::XYZVector &vertex)
Set production vertex position.
Definition: MCParticle.h:396
ROOT::Math::PxPyPzEVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:207
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:335
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:438
void setMomentum(const ROOT::Math::XYZVector &momentum)
Set particle momentum.
Definition: MCParticle.h:417
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:346
void setMassFromPDG()
Sets the mass for the particle from the particle's PDG code.
Definition: MCParticle.cc:28
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
STL namespace.