18 double ThreeBodym12F2(
double m12,
double M,
double m1,
double m2,
double m3) {
19 double m12k = m12 * m12;
20 return (m12k - (m1 + m2)*(m1 + m2)) * (m12k - (m1 - m2)*(m1 - m2)) * (M*M - (m12 + m3)*(m12 + m3)) * (M*M - (m12 - m3)*(m12 - m3)) / m12k;
25 double l = m1_ + m2_, r = M - m3_;
26 double m1 = 0., m2 = 0.;
27 m1 = l + (r - l) / 3.;
28 m2 = r - (r - l) / 3.;
29 while ((m2 - m1) > 1e-8) {
38 m1 = l + (r - l) / 3.;
39 m2 = r - (r - l) / 3.;
67 double v2 = vx * vx + vy * vy + vz * vz;
70 double gamma = 1. / sqrt(1. - v2);
71 ret.
p0 = gamma * part.
p0 - gamma * (vx * part.
px + vy * part.
py + vz * part.
pz);
72 ret.
px = -gamma * vx * part.
p0 + (1. + (gamma - 1.) * vx * vx / v2) * part.
px +
73 (gamma - 1.) * vx * vy / v2 * part.
py + (gamma - 1.) * vx * vz / v2 * part.
pz;
74 ret.
py = -gamma * vy * part.
p0 + (1. + (gamma - 1.) * vy * vy / v2) * part.
py +
75 (gamma - 1.) * vy * vx / v2 * part.
px + (gamma - 1.) * vy * vz / v2 * part.
pz;
76 ret.
pz = -gamma * vz * part.
p0 + (1. + (gamma - 1.) * vz * vz / v2) * part.
pz +
77 (gamma - 1.) * vz * vx / v2 * part.
px + (gamma - 1.) * vz * vy / v2 * part.
py;
86 double v2 = vx * vx + vy * vy + vz * vz;
89 double gamma = 1. / sqrt(1. - v2);
90 ret.
p0 = gamma * part.
p0 - gamma * (vx * part.
px + vy * part.
py + vz * part.
pz);
91 ret.
px = -gamma * vx * part.
p0 + (1. + (gamma - 1.) * vx * vx / v2) * part.
px +
92 (gamma - 1.) * vx * vy / v2 * part.
py + (gamma - 1.) * vx * vz / v2 * part.
pz;
93 ret.
py = -gamma * vy * part.
p0 + (1. + (gamma - 1.) * vy * vy / v2) * part.
py +
94 (gamma - 1.) * vy * vx / v2 * part.
px + (gamma - 1.) * vy * vz / v2 * part.
pz;
95 ret.
pz = -gamma * vz * part.
p0 + (1. + (gamma - 1.) * vz * vz / v2) * part.
pz +
96 (gamma - 1.) * vz * vx / v2 * part.
px + (gamma - 1.) * vz * vy / v2 * part.
py;
98 ret.
r0 = gamma * part.
r0 - gamma * (vx * part.
rx + vy * part.
ry + vz * part.
rz);
99 ret.
rx = -gamma * vx * part.
r0 + (1. + (gamma - 1.) * vx * vx / v2) * part.
rx +
100 (gamma - 1.) * vx * vy / v2 * part.
ry + (gamma - 1.) * vx * vz / v2 * part.
rz;
101 ret.
ry = -gamma * vy * part.
r0 + (1. + (gamma - 1.) * vy * vy / v2) * part.
ry +
102 (gamma - 1.) * vy * vx / v2 * part.
rx + (gamma - 1.) * vy * vz / v2 * part.
rz;
103 ret.
rz = -gamma * vz * part.
r0 + (1. + (gamma - 1.) * vz * vz / v2) * part.
rz +
104 (gamma - 1.) * vz * vx / v2 * part.
rx + (gamma - 1.) * vz * vy / v2 * part.
ry;
112 std::vector<SimpleParticle> ret(0);
113 ret.push_back(Mother);
114 ret.push_back(Mother);
120 double vx = Mother.
px / Mother.
p0;
121 double vy = Mother.
py / Mother.
p0;
122 double vz = Mother.
pz / Mother.
p0;
125 double ten1 = (Mo.
m*Mo.
m - m2 * m2 + m1 * m1) / 2. / Mo.
m;
126 double tp = sqrt(ten1*ten1 - m1 * m1);
129 double sthe = sqrt(1. - cthe * cthe);
130 ret[0].px = tp * cos(tphi) * sthe;
131 ret[0].py = tp * sin(tphi) * sthe;
132 ret[0].pz = tp * cthe;
134 ret[1].px = -ret[0].px;
135 ret[1].py = -ret[0].py;
136 ret[1].pz = -ret[0].pz;
137 ret[1].p0 = sqrt(m2*m2 + ret[1].px*ret[1].px + ret[1].py*ret[1].py + ret[1].pz*ret[1].pz);
139 double ten2 = ret[1].p0;
146 ret[0].MotherPDGID = Mother.
PDGID;
147 ret[1].MotherPDGID = Mother.
PDGID;
149 ret[0].epoch = Mother.
epoch + 1;
150 ret[1].epoch = Mother.
epoch + 1;
152 for (
size_t i = 0; i < ret.size(); ++i)
153 if (ret[i].px != ret[i].px) {
154 std::cerr <<
"**WARNING** Issue in a two-body decay!" << std::endl;
158 if (abs(Mother.
p0 - (ret[0].p0 + ret[1].p0)) > 1.e-9) {
159 std::cerr <<
"Two-body decay energy conservation issue: " << Mother.
p0 - (ret[0].p0 + ret[1].p0) <<
" " << sqrt(vx*vx+vy*vy+vz*vz) << std::endl;
160 std::cerr << Mother.
m <<
" " << ten1 + ten2 << std::endl;
168 std::vector<SimpleParticle> ret(0);
169 if (masses.size() < 1)
return ret;
172 if (masses.size() == 1)
174 masses.push_back(0.);
178 if (masses.size() > 3) {
184 double tmasssum = 0.;
185 for (
size_t i = 0; i < masses.size(); ++i)
186 tmasssum += masses[i];
190 if (Mother2.
m < tmasssum) {
191 Mother2.
m = tmasssum + 1.e-7;
192 Mother2.
p0 = sqrt(Mother2.
px * Mother2.
px + Mother2.
py * Mother2.
py + Mother2.
pz * Mother2.
pz + Mother2.
m * Mother2.
m);
195 if (masses.size() == 2)
return TwoBodyDecay(Mother2, masses[0], pdgs[0], masses[1], pdgs[1]);
197 for (
size_t i = 0; i < masses.size() - 1; ++i) tmin += masses[i];
198 double tmax = Mother2.
m - masses[masses.size() - 1];
200 if (masses.size() == 3) {
207 std::vector<SimpleParticle> ret1 =
TwoBodyDecay(Mother2, mijk, 11111, masses[masses.size() - 1], pdgs[pdgs.size() - 1]);
208 ret.push_back(ret1[1]);
209 masses.resize(masses.size() - 1);
210 pdgs.resize(pdgs.size() - 1);
212 for (
size_t i = 0; i < ret1.size(); ++i)
213 ret.push_back(ret1[i]);
215 for (
size_t i = 0; i < ret.size(); ++i) {
216 ret[i].MotherPDGID = Mother.
PDGID;
217 ret[i].epoch = Mother.
epoch + 1;
221 for (
int i = 0; i < ret.size(); ++i)
222 if (ret[i].px != ret[i].px) std::cerr <<
"**WARNING** NaN in NBodyDecay procedure output!" << std::endl;
230 if (masses.size() != pdgs.size()) {
231 std::cerr <<
"**WARNING** ShuffleDecayProducts(): size of masses does not match size of pdgs!" << std::endl;
234 int N = masses.size();
235 for (
int i = N - 1; i >= 1; --i) {
237 std::swap(masses[j], masses[i]);
238 std::swap(pdgs[j], pdgs[i]);
244 double totP0 = part1.
p0 + part2.
p0;
245 double totPx = part1.
px + part2.
px;
246 double totPy = part1.
py + part2.
py;
247 double totPz = part1.
pz + part2.
pz;
249 double vx = totPx / totP0;
250 double vy = totPy / totP0;
251 double vz = totPz / totP0;
256 if (npart1.
r0 < npart2.
r0)
257 std::swap(npart1, npart2);
259 npart2.
rx += npart2.
px / npart2.
p0 * (npart1.
r0 - npart2.
r0);
260 npart2.
ry += npart2.
py / npart2.
p0 * (npart1.
r0 - npart2.
r0);
261 npart2.
rz += npart2.
pz / npart2.
p0 * (npart1.
r0 - npart2.
r0);
262 npart2.
r0 = npart1.
r0;
264 return (npart1.
rx - npart2.
rx) * (npart1.
rx - npart2.
rx)
265 + (npart1.
ry - npart2.
ry) * (npart1.
ry - npart2.
ry)
266 + (npart1.
rz - npart2.
rz) * (npart1.
rz - npart2.
rz);
271 double mult1 = part.
rx * part.
px + part.
ry * part.
py + part.
rz * part.
pz;
272 double mult2 = part.
px * part.
px + part.
py * part.
py + part.
pz * part.
pz;
273 double retx = part.
rx - part.
px * mult1 / mult2;
274 double rety = part.
ry - part.
py * mult1 / mult2;
275 double retz = part.
rz - part.
pz * mult1 / mult2;
277 double ret = retx * retx + rety * rety + retz * retz;
Contains functions for Monte Carlo generation of decays.
SimpleParticle LorentzBoostMomentaAndCoordinates(const SimpleParticle &part, double vx, double vy, double vz)
Lorentz boost of the 4-coordinate and 4-momentum of a particle.
double ComputeDCA(const SimpleParticle &part)
Computes the distance of closest approach (DCA) to the origin.
double ThreeBodym12F2(double m12, double M, double m1, double m2, double m3)
Square of the probability density function used in a three-body decay (unnormalized)
std::vector< SimpleParticle > TwoBodyDecay(const SimpleParticle &Mother, double m1, long long pdg1, double m2, long long pdg2)
Samples the decay products of a two-body decay.
double ParticleDistanceSquared(const SimpleParticle &part1, const SimpleParticle &part2)
Return the square of the distance between particles at equal time.
void ShuffleDecayProducts(std::vector< double > &masses, std::vector< long long > &pdgs)
Shuffles the decay products.
SimpleParticle LorentzBoostMomentumOnly(const SimpleParticle &part, double vx, double vy, double vz)
Lorentz boost of the 4-momentum of a particle.
double GetRandomThreeBodym12(double M, double m1, double m2, double m3, double fm12max)
Sample the invariant mass of the leading two daughter particles in a three-body decay.
double TernaryThreeBodym12Maximum(double M, double m1, double m2, double m3)
Determines the maximum of the probability density function used in a three-body decay.
SimpleParticle LorentzBoost(const SimpleParticle &part, double vx, double vy, double vz)
Lorentz boost of the 4-momentum and 4-coordinate of a particle.
int threebodysucc
Used for debugging the succes rate in the rejection sampling of .
std::vector< SimpleParticle > ManyBodyDecay(const SimpleParticle &Mother, std::vector< double > masses, std::vector< long long > pdgs)
Samples the decay products of a many-body decay.
MTRand randgenMT
The Mersenne Twister random number generator.
constexpr double Pi()
Pi constant.
The main namespace where all classes and functions of the Thermal-FIST library reside.
Structure holding information about a single particle in the event generator.
double rz
Space-time coordinates.
double pz
3-momentum components (in GeV)
int epoch
0 - primary particle, 1 - after decay of primary particles, 2 - after a cascade of two decays and so ...
Contains some extra mathematical functions used in the code.