9 #include <generators/bbbrem/BBBrem.h>
10 #include <framework/logging/Logger.h>
11 #include <framework/gearbox/Const.h>
12 #include <mdst/dataobjects/MCParticleGraph.h>
21 void BBBrem::init(
double cmsEnergy,
double minPhotonEFrac,
bool unweighted,
double maxWeight,
int densitymode,
22 double densityparameter)
24 m_cmsEnergy = cmsEnergy;
25 m_photonEFrac = minPhotonEFrac;
27 m_unweighted = unweighted;
28 m_maxWeight = maxWeight;
29 m_densityCorrectionMode = densitymode;
30 m_densityCorrectionParameter = densityparameter;
32 m_maxWeightDelivered = 0.0;
33 m_sumWeightDelivered = 0.0;
34 m_sumWeightDeliveredSqr = 0.0;
37 if ((minPhotonEFrac <= 0.0) || (minPhotonEFrac >= 1.0)) {
38 B2ERROR(
"BBBrem: The minimum photon energy fraction has to be in the range ]0,1[ !");
42 B2DEBUG(100,
"BBBrem: Center of mass energy: " << cmsEnergy);
43 B2DEBUG(100,
"BBBrem: Minimum photon energy: " << minPhotonEFrac <<
" * beam energy");
46 alpha = Const::fineStrConst;
47 rme = Const::electronMass;
50 s = cmsEnergy * cmsEnergy;
54 z0 = minPhotonEFrac / (1.0 - minPhotonEFrac);
57 a1 = log((1.0 + z0) / z0);
60 a2 = (log1p(z0)) / z0;
62 sigapp = 8.0 * (alpha * alpha * alpha) / rme2 * (-log(rme2s)) * (a1 + a2) * tomb;
63 B2DEBUG(100,
"BBBrem: Approximate cross section: " << sigapp <<
" millibarn");
67 pb =
sqrt(eb * eb - rme2);
80 double BBBrem::generateEvent(
MCParticleGraph& mcGraph, ROOT::Math::XYZVector vertex, ROOT::Math::LorentzRotation boost)
86 calcOutgoingLeptonsAndWeight();
87 if (weight > m_maxWeightDelivered) m_maxWeightDelivered = weight;
88 if (weight > m_maxWeight) {
89 B2INFO(
"BBBrem: OVERWEIGHT, w=" << weight <<
", nw=" << m_weightCountOver <<
", sumw=" << m_sumWeightDeliveredOver);
91 m_sumWeightDeliveredOver = m_sumWeightDeliveredOver + (weight - m_maxWeight);
92 m_sumWeightDeliveredSqrOver = m_sumWeightDeliveredSqrOver + (weight - m_maxWeight) * (weight - m_maxWeight);
95 m_sumWeightDelivered += weight;
96 m_sumWeightDeliveredSqr += weight * weight;
98 ran = gRandom->Uniform();
99 }
while (weight <= ran * m_maxWeight);
101 calcOutgoingLeptonsAndWeight();
102 if (weight > m_maxWeightDelivered) m_maxWeightDelivered = weight;
104 m_sumWeightDelivered += weight;
105 m_sumWeightDeliveredSqr += weight * weight;
109 storeParticle(mcGraph, p1, 11, vertex, boost,
false,
true);
110 storeParticle(mcGraph, q1, -11, vertex, boost,
false,
true);
114 bool swapflag = (gRandom->Uniform() > 0.5) ?
true :
false;
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];
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);
130 if (!m_unweighted)
return weight;
137 if (m_weightCount > 0.0) {
138 m_crossSection = m_sumWeightDelivered / m_weightCount;
139 m_crossSectionError =
sqrt(m_sumWeightDeliveredSqr - m_sumWeightDelivered * m_sumWeightDelivered / m_weightCount) /
143 m_crossSectionOver = m_sumWeightDeliveredOver / m_weightCount;
144 m_crossSectionErrorOver =
sqrt(abs(((m_sumWeightDeliveredSqrOver) / m_weightCount - m_crossSectionOver * m_crossSectionOver) /
155 void BBBrem::calcOutgoingLeptonsAndWeight()
159 if (gRandom->Uniform() < ac) {
160 double temp1 = gRandom->Uniform();
163 z = 1.0 / (temp1 * (expm1(a1 * gRandom->Uniform())));
165 z = z0 / gRandom->Uniform();
169 double y = rme2s * z;
171 double temp1 = pb * pb - eb * q0;
172 double temp2 = temp1 * temp1 - rme2 - q0 * q0;
176 B2WARNING(
"BBBrem: y too large: delta_t^2 = " << temp2 <<
" !!!");
179 double tmin = -2.0 * (temp1 +
sqrt(temp2));
180 double tmax = rme2 * s * y * y / tmin;
184 double w2 = sy + rme2;
186 double rlamx =
sqrt(temp1 * temp1 - 4.0 * w2 * tmax);
189 temp1 = rlamx - temp1;
191 temp1 = -4.0 * w2 * tmax / (rlamx + temp1);
199 b = exp(gRandom->Uniform() * log1p(2.0 * sy / temp1));
200 t = -b * z * z * rme2 / ((b - 1) * (b * z + b - 1));
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);
209 double vgam = eps * (expm1(gRandom->Uniform() * rl));
210 double cgam = 1.0 - vgam;
211 double sgam =
sqrt(vgam * (2 - vgam));
214 double phi = twopi * gRandom->Uniform();
215 double phig = twopi * gRandom->Uniform();
218 double ql = (2.0 * eb * q0 - t) * rin2pb;
219 double qt =
sqrt((tmax - t) * (t - tmin)) * rin2pb;
221 q[0] = qt * sin(phi);
222 q[1] = qt * cos(phi);
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];
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;
248 vthat = sthat * sthat / (1 -
sqrt(1 - sthat * sthat));
250 vthat = sthat * sthat / (1 +
sqrt(1 - sthat * sthat));
252 double cthat = vthat - 1.0;
255 double sfg = sin(phig);
256 double cfg = cos(phig);
258 temp2 = cthat * sgam * cfg + sthat * cgam;
259 double veg = vthat + vgam - vthat * vgam - sthat * sgam * cfg;
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);
267 temp1 = pb * qkhat[2];
269 temp2 = (rme2 * qkhat[3] * qkhat[3] + pb * pb * (qkhat[0] * qkhat[0] + qkhat[1] * qkhat[1])) / (eb * qkhat[3] + temp1);
271 temp2 = eb * qkhat[3] - temp1;
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);
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;
287 if (qk[3] < eb * m_photonEFrac) {
294 double c1 = log1p(z) / log((2.0 + eps) / eps);
298 double vnumx =
sqrt(temp1 * temp1 - 4.0 * rme2 * tmax) + temp1;
303 vdenx =
sqrt(temp1 * temp1 - 4.0 * w2 * tmax) - temp1;
305 vdenx = -4.0 * w2 * tmax / (
sqrt(temp1 * temp1 - 4.0 * w2 * tmax) + temp1);
308 double vnumn =
sqrt(temp1 * temp1 - 4.0 * rme2 * tmin) + temp1;
313 vdenn =
sqrt(temp1 * temp1 - 4.0 * w2 * tmin) - temp1;
315 vdenn = -4.0 * w2 * tmin / (
sqrt(temp1 * temp1 - 4.0 * w2 * tmin) + temp1);
317 double c2 = 2.0 * rls / log((vnumx * vdenn) / (vdenx * vnumn));
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]);
329 double s1 = 4.0 * eb * (eb - qk[3]);
330 double d1 = sy * rlam * (eps + vgam) * rin2w * rin2w;
331 double d2 = 0.5 * sy;
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;
349 double rmap = 4.0 * s * s * rind1 * rind2 * (-t) * c1 * c2;
352 weight = rmex / rmap * sigapp;
355 if (std::isnan(weight)) {
356 B2WARNING(
"BBBrem: Weight is nan! Setting the weight to zero.");
368 double tc = m_densityCorrectionParameter;
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);
382 void BBBrem::storeParticle(
MCParticleGraph& mcGraph,
const double* mom,
int pdg, ROOT::Math::XYZVector vertex,
383 ROOT::Math::LorentzRotation boost,
384 bool isVirtual,
bool isInitial)
390 part.setStatus(MCParticle::c_IsVirtual);
391 }
else if (isInitial) {
392 part.setStatus(MCParticle::c_Initial);
396 part.addStatus(MCParticle::c_PrimaryParticle);
399 if (pdg == 22 && !isVirtual) {
400 part.addStatus(MCParticle::c_IsISRPhoton);
401 part.addStatus(MCParticle::c_IsFSRPhoton);
405 part.setFirstDaughter(0);
406 part.setLastDaughter(0);
407 part.setMomentum(ROOT::Math::XYZVector(mom[0], mom[1],
409 part.setEnergy(mom[3]);
410 part.setMassFromPDG();
415 ROOT::Math::XYZVector v3 = part.getProductionVertex();
417 part.setProductionVertex(v3);
418 part.setValidVertex(
true);
422 ROOT::Math::PxPyPzEVector p4 = part.get4Vector();
Class to represent Particle data in graph.
Class to build, validate and sort a particle decay chain.
double sqrt(double a)
sqrt for double
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.