29 if (mean <= 0)
return 0;
31 double expmean = exp(-mean);
37 if (pir <= expmean)
break;
61 return static_cast<int> (em);
74 if (mean <= 0)
return 0;
76 double expmean = exp(-mean);
82 if (pir <= expmean)
break;
98 y = tan(pi*rangen.rand());
104 }
while (rangen.rand() > t);
106 return static_cast<int> (em);
118 return exp(-(mu1 + mu2)) * pow(sqrt(mu1 / mu2), k) *
xMath::BesselI(k, 2. * sqrt(mu1 * mu2));
122 double SiemensRasmussenMomentumGenerator::g(
double x,
double mass)
const {
126 double talpha = alpha(tp);
128 double en = sqrt(tp * tp + mass * mass);
129 double sh = sinh(talpha);
130 double shtalpha = 1.;
132 shtalpha = sh / talpha;
133 double ch = sqrt(1. + sh * sh);
134 return tp * tp * exp(-m_Gamma * en / m_T) * ((1. + m_T / m_Gamma / en)*shtalpha - m_T / m_Gamma / en * ch) / x;
137 double SiemensRasmussenMomentumGenerator::g2(
double x,
double tp,
double mass)
const {
140 double talpha = alpha(tp);
142 double en = sqrt(tp * tp + mass * mass);
143 double sh = sinh(talpha);
144 double shtalpha = 1.;
146 shtalpha = sh / talpha;
147 double ch = sqrt(1. + sh * sh);
148 return tp * tp * exp(-m_Gamma * en / m_T) * ((1. + m_T / m_Gamma / en)*shtalpha - m_T / m_Gamma / en * ch) / x;
151 void SiemensRasmussenMomentumGenerator::FixParameters() {
153 double l = 0., r = 1.;
154 double m1 = l + (r - l) / 3.;
155 double m2 = r - (r - l) / 3.;
158 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
165 m1 = l + (r - l) / 3.;
166 m2 = r - (r - l) / 3.;
169 m_Max = g((m1 + m2) / 2.);
172 double SiemensRasmussenMomentumGenerator::GetRandom(
double mass)
const {
177 double y0 = m_Max *
randgenMT.randDblExc();
181 if (y0 < mn * g(x0))
return -log(x0);
187 std::vector<double> ret(0);
188 double tp = GetRandom(mass);
190 double cthe = 2. *
randgenMT.rand() - 1.;
191 double sthe = sqrt(1. - cthe * cthe);
192 ret.push_back(tp*cos(tphi)*sthe);
193 ret.push_back(tp*sin(tphi)*sthe);
194 ret.push_back(tp*cthe);
204 double ThermalMomentumGenerator::g(
double x,
double mass)
const
209 double texp = exp((sqrt(mass * mass + tp * tp) - m_Mu) / m_T);
210 return tp * tp / (texp + m_Statistics) / x;
236 double ThermalMomentumGenerator::ComputeMaximum(
double mass)
const
239 double l = 0., r = 1.;
240 double m1 = l + (r - l) / 3.;
241 double m2 = r - (r - l) / 3.;
244 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
245 if (g(m1, mass) < g(m2, mass)) {
251 m1 = l + (r - l) / 3.;
252 m2 = r - (r - l) / 3.;
255 return g((m1 + m2) / 2., mass);
265 if (mass < m_Mu && m_Statistics == -1)
266 std::cerr <<
"**WARNING** ThermalMomentumGenerator::GetP: Bose-condensation mu " << m_Mu <<
" > mass " << mass << std::endl;
270 M = ComputeMaximum(mass);
272 double prob = g(x0, mass) / M;
275 std::cerr <<
"**WARNING** ThermalMomentumGenerator::GetP: Probability exceeds unity by " << prob - 1. << std::endl;
277 if (
randgenMT.randDblExc() < prob)
return -log(x0);
284 double Tkin,
double etamax,
double mass,
int statistics,
double mu) :
285 m_FreezeoutModel(FreezeoutModel),
286 m_Tkin(Tkin), m_EtaMax(etamax), m_Mass(mass),
287 m_Generator(mass, statistics, Tkin, mu)
289 if (m_FreezeoutModel == NULL) {
296 if (m_FreezeoutModel != NULL)
297 delete m_FreezeoutModel;
310 double betar = m_FreezeoutModel->tanhetaperp(zetacand);
311 double cosheta = cosh(eta);
312 double sinheta = sinh(eta);
314 double cosphi = cos(ph);
315 double sinphi = sin(ph);
317 double vx = betar * cosphi / cosheta;
318 double vy = betar * sinphi / cosheta;
319 double vz = tanh(eta);
321 double dRdZeta = m_FreezeoutModel->dRdZeta(zetacand);
322 double dtaudZeta = m_FreezeoutModel->dtaudZeta(zetacand);
324 double coshetaperp = m_FreezeoutModel->coshetaperp(zetacand);
325 double sinhetaperp = m_FreezeoutModel->sinhetaperp(zetacand);
327 std::vector<double> dsigma_lab;
328 dsigma_lab.push_back(dRdZeta * cosheta);
329 dsigma_lab.push_back(dtaudZeta * cosphi);
330 dsigma_lab.push_back(dtaudZeta * sinphi);
331 dsigma_lab.push_back(dRdZeta * sinheta);
334 std::vector<double> dsigma_loc =
LorentzBoost(dsigma_lab, vx, vy, vz);
337 double maxWeight = 1. + std::abs(dsigma_loc[1] / dsigma_loc[0]) + std::abs(dsigma_loc[2] / dsigma_loc[0]) + std::abs(dsigma_loc[3] / dsigma_loc[0]);
344 double tp = m_Generator.GetP(mass);
347 double sthe = sqrt(1. - cthe * cthe);
348 part.
px = tp * cos(tphi) * sthe;
349 part.
py = tp * sin(tphi) * sthe;
351 part.
p0 = sqrt(mass * mass + tp * tp);
353 double p0LRF = part.
p0;
355 double dsigmamu_pmu_loc = dsigma_loc[0] * part.
p0
356 - dsigma_loc[1] * part.
px - dsigma_loc[2] * part.
py - dsigma_loc[3] * part.
pz;
359 double dsigmamu_umu_loc = dsigma_loc[0];
361 double dumu_pmu_loc = p0LRF;
363 double Weight = dsigmamu_pmu_loc / dsigmamu_umu_loc / dumu_pmu_loc / maxWeight;
366 std::cerr <<
"**WARNING** BoostInvariantHypersurfaceMomentumGenerator::GetMomentum: Weight exceeds unity by " << Weight - 1. << std::endl;
374 if (betar != 0.0 || eta != 0.0)
378 std::vector<double> ret(3, 0.);
384 double tau = m_FreezeoutModel->taufunc(zetacand);
385 double r0 = tau * cosheta;
386 double rz = tau * sinheta;
388 double Rperp = m_FreezeoutModel->Rfunc(zetacand);
389 double rx = Rperp * cosphi;
390 double ry = Rperp * sinphi;
401 if (m_FreezeoutModel->InverseZetaDistributionIsExplicit())
402 return m_FreezeoutModel->InverseZetaDistribution(rangen.rand());
405 double zetacand = rangen.rand();
407 double prob = m_FreezeoutModel->ZetaProbability(zetacand) / m_FreezeoutModel->ProbabilityMaximum();
409 if (rangen.rand() < prob)
416 double BreitWignerGenerator::f(
double x)
const {
417 return x / ((x*x - m_M * m_M)*(x*x - m_M * m_M) + m_M * m_M*m_Gamma*m_Gamma);
420 void BreitWignerGenerator::FixParameters() {
424 double l = m_Mthr, r = m_M + 2.*m_Gamma;
425 double m1 = l + (r - l) / 3.;
426 double m2 = r - (r - l) / 3.;
429 while (fabs(m2 - m1) < eps && iter < MAXITERS) {
436 m1 = l + (r - l) / 3.;
437 m2 = r - (r - l) / 3.;
440 m_Max = f((m1 + m2) / 2.);
445 if (m_Gamma < 1e-7)
return m_M;
447 double x0 = m_Mthr + (m_M + 2.*m_Gamma - m_Mthr) *
randgenMT.rand();
449 if (y0 < f(x0))
return x0;
471 if (
m_part->ZeroWidthEnforced()) {
477 double Threshold =
m_part->DecayThresholdMass();
478 double Width =
m_part->ResonanceWidth();
479 double Mass =
m_part->Mass();
481 double a = std::max(Threshold, Mass - 2.*Width);
482 double b = Mass + 2.*Width;
491 for (
int i = 0; i < iters; ++i) {
492 double tM =
m_Xmin + dM * i;
505 if (
m_part->ZeroWidthEnforced())
510 if (y0 <
f(x0))
return x0;
517 if (
m_part->ZeroWidthEnforced()) {
523 double Threshold =
m_part->DecayThresholdMass();
524 double Width =
m_part->ResonanceWidth();
525 double Mass =
m_part->Mass();
527 double a = std::max(Threshold, Mass - 2.*Width);
528 double b = Mass + 2.*Width;
530 if (
m_part->Decays().size() == 0)
531 a = Mass - 2.*Width + 1.e-6;
533 a =
m_part->DecayThresholdMassDynamical();
538 m_Xmax = b + 0.2 * (b - a);
547 for (
int i = 0; i < iters; ++i) {
548 double tM =
m_Xmin + dM * i;
575 if (nu < 0 || n < 0)
return 0.0;
577 double logret = (2. * n + nu) * log(a/2.) - a;
578 for (
int i = 1; i <= n; ++i)
579 logret -= 2. * log(i);
580 for (
int i = n + 1; i <= n + nu; ++i)
588 double hn2 = 1., hn1 = 0., hn = 0.;
589 double kn2 = 0., kn1 = 1., kn = 0.;
591 for (
int n = 1; n <= nmax; ++n) {
592 double an = 2. * (nu + n) / x;
602 if (n == nmax && nmax <= 1000 && abs(hn2 / kn2 - hn1 / kn1) > 1.e-9)
606 std::cerr <<
"**WARNING** BesselDistributionGenerator::R(x,nu): Reached maximum iterations..." << std::endl;
614 return mu(a, nu) + (1. / 4.) * a * a *
R(a, nu) * (
R(a,nu+1) -
R(a,nu));
619 double tmp =
m(a, nu) -
mu(a, nu);
620 return chi2(a, nu) + tmp * tmp;
625 double A = sqrt(a*a + nu*nu);
626 double B = sqrt(a*a + (nu+1.)*(nu+1.));
627 double tmp = 1. + a * a * (1. + B - A) / 2. / (nu + A) / (nu + 1. + B);
628 return a*a / 2. / (nu + A) + tmp * tmp;
633 if (nu < 0 || a <= 0.)
return 0;
668 for (
int i = 1; i <= X; ++i) {
669 ret *= (a / 2.)/(tm + i);
670 ret *= (a / 2.)/(tm + nu + i);
674 for (
int i = 1; i <= -X; ++i) {
675 ret *= (tm + X + i) / (a / 2.);
676 ret *= (tm + nu + X + i) / (a / 2.);
686 double pm =
pn(tm, a, nu);
687 double w = 1. + pm / 2.;
689 double U = rangen.rand();
690 double W = rangen.rand();
692 if (rangen.rand() < 0.5)
696 if (U <= w / (1. + w)) {
697 double V = rangen.rand();
701 double E = -log(rangen.randDblExc());
704 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
705 int X = S * std::lround(Y);
707 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
715 if (pratio != pratio) {
716 std::cerr <<
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye1: Float problem!" << std::endl;
720 if (W * std::min(1., exp(w - pm * Y)) <= pratio)
729 double tsig = sqrt(
sig2(a, nu));
730 double q = std::min(1. / tsig / sqrt(648.), 1. / 3.);
732 double U = rangen.rand();
733 double W = rangen.rand();
735 if (rangen.rand() < 0.5)
739 if (U <= (1. + 2. / q) / (1. + 4. / q)) {
740 double V = rangen.rand();
741 Y = V * (1. / 2. + 1. / q);
744 double E = -log(rangen.randDblExc());
745 Y = 1. / 2. + 1. / q + E / q;
747 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
748 int X = S * std::lround(Y);
750 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
758 if (pratio != pratio) {
759 std::cerr <<
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye2: Float problem!" << std::endl;
763 if (W * std::min(1., exp(1. + q/2. - q*Y)) <= pratio)
772 double tQ = sqrt(
Q2(a, nu));
773 double q = std::min(1. / tQ / sqrt(648.), 1. / 3.);
775 double U = rangen.rand();
776 double W = rangen.rand();
778 if (rangen.rand() < 0.5)
782 if (U <= (1. + 2. / q) / (1. + 4. / q)) {
783 double V = rangen.rand();
784 Y = V * (1. / 2. + 1. / q);
787 double E = -log(rangen.randDblExc());
788 Y = 1. / 2. + 1. / q + E / q;
790 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
791 int X = S * std::lround(Y);
793 int X = S * ((Y > 0.0) ? std::floor(Y + 0.5) : std::ceil(Y - 0.5));
801 if (pratio != pratio) {
802 std::cerr <<
"**WARNING** BesselDistributionGenerator::RandomBesselDevroye3: Float problem!" << std::endl;
807 if (W * std::min(1., exp(1. + q/2. - q*Y)) <= pratio)
816 while (ret <= -0.5) {
817 ret = rangen.randNorm(
mu(a,nu), sqrt(
chi2(a,nu)));
819 return static_cast<int>(ret + 0.5);
842 double sinth = sqrt(1. - costh * costh);
844 double vx =
GetBeta() * sinth * cos(ph);
845 double vy =
GetBeta() * sinth * sin(ph);
850 double tp = m_Generator.GetP(mass);
853 double sthe = sqrt(1. - cthe * cthe);
854 part.
px = tp * cos(tphi) * sthe;
855 part.
py = tp * sin(tphi) * sthe;
857 part.
p0 = sqrt(mass * mass + tp * tp);
862 std::vector<double> ret(7);
869 ret[4] =
GetR() * sinth * cos(ph);
870 ret[5] =
GetR() * sinth * sin(ph);
871 ret[6] =
GetR() * costh;
886 namespace RandomGenerators {
888 void SSHMomentumGenerator::FixParameters() {
891 double l = 0., r = 1.;
892 double m1 = l + (r - l) / 3.;
893 double m2 = r - (r - l) / 3.;
896 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
903 m1 = l + (r - l) / 3.;
904 m2 = r - (r - l) / 3.;
907 m_MaxPt = g((m1 + m2) / 2.);
911 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
912 m_dndpt.add_val(x, g(x));
920 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
925 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
926 double m1 = l + (r - l) / 3.;
927 double m2 = r - (r - l) / 3.;
930 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
931 if (m_distr.dndy(m1, pt) < m_distr.dndy(m2, pt)) {
937 m1 = l + (r - l) / 3.;
938 m2 = r - (r - l) / 3.;
941 m_MaxYs.push_back(m_distr.dndy((m1 + m2) / 2., pt));
943 m_dndy.push_back(SplineFunction());
945 for (
double ty = -4. - m_EtaMax + 0.5 * dy; ty <= 4. + m_EtaMax; ty += dy) {
946 m_dndy[m_dndy.size() - 1].add_val(ty, m_distr.dndy(ty, pt));
952 void SSHMomentumGenerator::FixParameters2() {
955 double l = 0., r = 1.;
956 double m1 = l + (r - l) / 3.;
957 double m2 = r - (r - l) / 3.;
960 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
967 m1 = l + (r - l) / 3.;
968 m2 = r - (r - l) / 3.;
971 m_MaxPt = g((m1 + m2) / 2.);
975 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
976 m_dndpt.add_val(x, g(x));
984 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
989 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
990 double m1 = l + (r - l) / 3.;
991 double m2 = r - (r - l) / 3.;
994 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
995 if (m_distr.dndysingle(m1, pt) < m_distr.dndysingle(m2, pt)) {
1001 m1 = l + (r - l) / 3.;
1002 m2 = r - (r - l) / 3.;
1005 m_MaxYs.push_back(m_distr.dndysingle((m1 + m2) / 2., pt));
1007 m_dndy.push_back(SplineFunction());
1009 for (
double ty = -4. + 0.5 * dy; ty <= 4.; ty += dy) {
1010 m_dndy[m_dndy.size() - 1].add_val(ty, m_distr.dndysingle(ty, pt));
1017 void SSHMomentumGenerator::FindMaximumPt() {
1020 double l = 0., r = 1.;
1021 double m1 = l + (r - l) / 3.;
1022 double m2 = r - (r - l) / 3.;
1025 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
1026 if (g(m1) < g(m2)) {
1032 m1 = l + (r - l) / 3.;
1033 m2 = r - (r - l) / 3.;
1036 m_MaxPt = g((m1 + m2) / 2.);
1040 for (
double x = 0.5 * dx; x <= 1.; x += dx) {
1041 m_dndpt.add_val(x, g(x));
1045 void SSHMomentumGenerator::FindMaximumY(
double pt) {
1047 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
1048 double m1 = l + (r - l) / 3.;
1049 double m2 = r - (r - l) / 3.;
1052 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
1053 if (m_distr.dndy(m1, pt) < m_distr.dndy(m2, pt)) {
1059 m1 = l + (r - l) / 3.;
1060 m2 = r - (r - l) / 3.;
1063 m_MaxY = m_distr.dndy((m1 + m2) / 2., pt);
1066 void SSHMomentumGenerator::FindMaximumY2(
double pt) {
1068 double l = -4. - m_EtaMax, r = 4. + m_EtaMax;
1069 double m1 = l + (r - l) / 3.;
1070 double m2 = r - (r - l) / 3.;
1073 while (fabs(m2 - m1) > eps && iter < MAXITERS) {
1074 if (m_distr.dndysingle(m1, pt) < m_distr.dndysingle(m2, pt)) {
1080 m1 = l + (r - l) / 3.;
1081 m2 = r - (r - l) / 3.;
1084 m_MaxY = m_distr.dndysingle((m1 + m2) / 2., pt);
1087 std::pair<double, double> SSHMomentumGenerator::GetRandom(
double mass) {
1088 double tpt = 0., ty = 0.;
1091 double y0 = m_MaxPt *
randgenMT.randDblExc();
1098 int ind = (int)(exp(-tpt) / m_dPt);
1099 if (ind < 0) ind = 0;
1100 if (ind >=
static_cast<int>(m_dndy.size())) ind = m_dndy.size() - 1;
1101 double x0 = -4. - m_EtaMax + (8. + 2. * m_EtaMax) *
randgenMT.randDblExc();
1102 double y0 = m_MaxYs[ind] *
randgenMT.randDblExc();
1103 if (y0 < m_dndy[ind].f(x0)) {
1108 return std::make_pair(tpt, ty);
1111 std::pair<double, double> SSHMomentumGenerator::GetRandom2(
double mass)
const {
1112 double tpt = 0., ty = 0., teta = 0.;
1115 double y0 = m_MaxPt *
randgenMT.randDblExc();
1122 int ind = (int)(exp(-tpt) / m_dPt);
1123 if (ind < 0) ind = 0;
1124 if (ind >=
static_cast<int>(m_dndy.size())) ind = m_dndy.size() - 1;
1125 double x0 = -4. + (8.) *
randgenMT.randDblExc();
1126 double y0 = m_MaxYs[ind] *
randgenMT.randDblExc();
1128 if (y0 < m_dndy[ind].f(x0)) {
1130 teta = -m_EtaMax + 2. * m_EtaMax *
randgenMT.randDblExc();
1134 return std::make_pair(tpt, ty - teta);
1138 std::vector<double> ret(0);
1139 std::pair<double, double> pty = GetRandom2(mass);
1140 double tpt = pty.first;
1141 double ty = pty.second;
1143 ret.push_back(tpt * cos(tphi));
1144 ret.push_back(tpt * sin(tphi));
1145 ret.push_back(sqrt(tpt * tpt + m_Mass * m_Mass) * sinh(ty));
Base class implementing a longitudinally boost-invariant azimuthally symmetric freeze-out parametriza...
virtual std::vector< double > GetMomentum(double mass=-1.) const
BoostInvariantMomentumGenerator(BoostInvariantFreezeoutParametrization *FreezeoutModel=NULL, double Tkin=0.100, double etamax=3.0, double mass=0.938, int statistics=0, double mu=0)
Construct a new BoostInvariantMomentumGenerator object.
virtual double GetRandomZeta(MTRand &rangen=RandomGenerators::randgenMT) const
Samples zeta for use in Monte Carlo event generator.
virtual ~BoostInvariantMomentumGenerator()
BoostInvariantMomentumGenerator desctructor.
void SetParameters(double M, double gamma, double mthr)
Set the Breit-Wigner spectral function parameters.
double GetRandom() const
Samples the resonance mass from a relativistic Breit-Wigner distribution with a constant width.
std::vector< double > GetMomentum(double mass=-1.) const
virtual std::vector< double > GetMomentum(double mass=-1.) const
virtual std::vector< double > GetMomentum(double mass=-1.) const
virtual void FixParameters()
Computes some auxiliary stuff needed for sampling.
void SetParameters(ThermalParticle *part, double T, double Mu)
Sets the parameters of the distribution.
double GetRandom() const
Samples the mass.
virtual double f(double M) const
Unnormalized resonance mass probability density.
virtual double f(double M) const
Unnormalized resonance mass probability density.
virtual void FixParameters()
Computes some auxiliary stuff needed for sampling.
double GetP(double mass=-1.) const
Samples the momentum of a particle.
Class containing all information about a particle specie.
SimpleParticle LorentzBoostMomentumOnly(const SimpleParticle &part, double vx, double vy, double vz)
Lorentz boost of the 4-momentum of a particle.
Contains random generator functions used in the Monte Carlo Thermal Event Generator.
double SkellamProbability(int k, double mu1, double mu2)
Probability of a Skellam distributed random variable with Poisson means mu1 and mu2 to have the value...
int RandomPoisson(double mean)
Generates random integer distributed by Poisson with specified mean Uses randgenMT.
MTRand randgenMT
The Mersenne Twister random number generator.
void SetSeed(const unsigned int seed)
Set the seed of the random number generator randgenMT.
std::mt19937 rng_std
The Mersenne Twister random number generator from STD library.
constexpr double Pi()
Pi constant.
double BesselIexp(int n, double x)
Modified Bessel function I_n(x), divided by exponential factor.
double LogGamma(double x)
Computes the logarithm of the Gamma function.
double BesselI(int n, double x)
Integer order modified Bessel function I_n(x)
The main namespace where all classes and functions of the Thermal-FIST library reside.
std::vector< double > LorentzBoost(const std::vector< double > &fourvector, double vx, double vy, double vz)
Performs a Lorentz boost on a four-vector.
static double chi2(double a, int nu)
static int RandomBesselNormal(double a, int nu, MTRand &rangen)
static int RandomBesselDevroye1(double a, int nu, MTRand &rangen)
static int RandomBesselDevroye3(double a, int nu, MTRand &rangen)
static double pmXmOverpm(int X, int tm, double a, int nu)
static double mu(double a, int nu)
static double Q2(double a, int nu)
static int RandomBesselCombined(double a, int nu, MTRand &rangen)
static int RandomBesselPoisson(double a, int nu, MTRand &rangen)
static int m(double a, int nu)
static int RandomBesselDevroye2(double a, int nu, MTRand &rangen)
static double pn(int n, double a, int nu)
static double R(double x, int nu)
static double sig2(double a, int nu)
Structure holding information about a single particle in the event generator.
double pz
3-momentum components (in GeV)
Contains some extra mathematical functions used in the code.