26 ThermalParticle::ThermalParticle(
bool Stable, std::string Name,
long long PDGID,
double Deg,
int Stat,
double Mass,
27 int Strange,
int Baryon,
int Charge,
double AbsS,
double Width,
double Threshold,
int Charm,
double AbsC,
int Quark) :
28 m_Stable(Stable), m_AntiParticle(false), m_Name(Name), m_PDGID(PDGID), m_Degeneracy(Deg), m_Statistics(Stat), m_StatisticsOrig(Stat), m_Mass(Mass),
29 m_Strangeness(Strange), m_Baryon(Baryon), m_ElectricCharge(Charge), m_Charm(Charm), m_ArbitraryCharge(Baryon), m_AbsS(AbsS), m_AbsC(AbsC), m_Width(Width), m_Threshold(Threshold), m_Quark(Quark), m_Weight(1.)
75 m_Threshold = threshold;
76 if (m_Threshold < 0.0) {
77 printf(
"**WARNING** Trying to set negative decay threshold for %s, setting to zero instead", m_Name.c_str());
84 m_ThresholdDynamical = threshold;
85 if (m_ThresholdDynamical < 0.0) {
86 printf(
"**WARNING** Trying to set negative dynamical decay threshold for %s, setting to zero instead", m_Name.c_str());
92 double Thr = m_Mass + m_Width;
93 for (
size_t i = 0; i < m_Decays.size(); ++i) {
94 Thr = min(Thr, m_Decays[i].mM0);
96 m_ThresholdDynamical = Thr;
101 if (shape != m_ResonanceWidthShape) {
102 m_ResonanceWidthShape = shape;
109 m_ResonanceWidthIntegrationType = type;
122 if (width < 0.) width = m_Width;
133 return m_Mass * width * m / ((m * m - m_Mass * m_Mass)*(m * m - m_Mass * m_Mass) + m_Mass * m_Mass*width*width);
135 return width / ((m - m_Mass)*(m - m_Mass) + width * width / 4.);
140 ifstream fin(filename.c_str());
144 while (fin >> tmpbr) {
147 fin.getline(cc, 350);
151 while (ss >> tmpid) {
154 m_Decays.push_back(decay);
161 if (!useWidth || m_Width == 0.0 || m_Width / m_Mass < 1.e-2 || m_ResonanceWidthIntegrationType !=
eBW) {
162 for (
size_t j = 0; j < m_Decays.size(); ++j) {
163 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
168 if (!(params.
gammaS == 1. || m_AbsS == 0.)) mu += log(params.
gammaS) * m_AbsS * params.
T;
169 if (!(params.
gammaC == 1. || m_AbsC == 0.)) mu += log(params.
gammaC) * m_AbsC * params.
T;
171 for (
size_t j = 0; j < m_Decays.size(); ++j) {
172 m_Decays[j].mBratioAverage = 0.;
175 double ret1 = 0., ret2 = 0., tmp = 0.;
176 for (
size_t i = 0; i < m_xalldyn.size(); i++) {
182 for (
size_t j = 0; j < m_Decays.size(); ++j) {
183 const_cast<double&
>(m_Decays[j].mBratioAverage) += tmp * dens * m_Decays[j].mBratioVsM[i];
187 for (
size_t j = 0; j < m_Decays.size(); ++j) {
189 m_Decays[j].mBratioAverage /= ret1;
191 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
198 std::vector<double> ret = ms;
200 std::vector<double> mthr, br;
202 for (
size_t i = 0; i < m_Decays.size(); ++i) {
203 mthr.push_back(m_Decays[i].mM0);
204 br.push_back(m_Decays[i].mBratio);
205 tsum += m_Decays[i].mBratio;
209 br.push_back(1. - tsum);
211 else if (tsum > 1.) {
212 for (
size_t i = 0; i < br.size(); ++i)
216 for (
size_t i = 0; i < ms.size(); ++i) {
218 for (
size_t j = 0; j < br.size(); ++j) {
219 if (mthr[j] <= ms[i])
229 string name =
Name();
230 if (
BaryonCharge() == 0 && name[name.size() - 1] ==
'+')
231 name[name.size() - 1] =
'-';
232 else if (
BaryonCharge() == 0 && name[name.size() - 1] ==
'-')
233 name[name.size() - 1] =
'+';
235 name =
"anti-" + name;
266 ret &= m_Stable == rhs.m_Stable;
267 ret &= m_AntiParticle == rhs.m_AntiParticle;
268 ret &= m_Name == rhs.m_Name;
269 ret &= m_PDGID == rhs.m_PDGID;
270 ret &= m_Degeneracy == rhs.m_Degeneracy;
271 ret &= m_Statistics == rhs.m_Statistics;
272 ret &= m_StatisticsOrig == rhs.m_StatisticsOrig;
273 ret &= m_Mass == rhs.m_Mass;
274 ret &= m_QuantumStatisticsCalculationType == rhs.m_QuantumStatisticsCalculationType;
275 ret &= m_ClusterExpansionOrder == rhs.m_ClusterExpansionOrder;
276 ret &= m_Baryon == rhs.m_Baryon;
277 ret &= m_ElectricCharge == rhs.m_ElectricCharge;
278 ret &= m_Strangeness == rhs.m_Strangeness;
279 ret &= m_Charm == rhs.m_Charm;
280 ret &= m_Quark == rhs.m_Quark;
281 ret &= m_ArbitraryCharge == rhs.m_ArbitraryCharge;
282 ret &= m_AbsQuark == rhs.m_AbsQuark;
283 ret &= m_AbsS == rhs.m_AbsS;
284 ret &= m_AbsC == rhs.m_AbsC;
285 ret &= m_Width == rhs.m_Width;
286 ret &= m_Threshold == rhs.m_Threshold;
287 ret &= m_ThresholdDynamical == rhs.m_ThresholdDynamical;
288 ret &= m_ResonanceWidthShape == rhs.m_ResonanceWidthShape;
289 ret &= m_ResonanceWidthIntegrationType == rhs.m_ResonanceWidthIntegrationType;
290 ret &= m_Weight == rhs.m_Weight;
291 ret &= m_DecayType == rhs.m_DecayType;
292 ret &= m_Decays == rhs.m_Decays;
293 ret &= m_DecaysOrig == rhs.m_DecaysOrig;
300 for (
size_t i = 0; i < m_Decays.size(); ++i) {
301 sum += m_Decays[i].mBratio;
303 for (
size_t i = 0; i < m_Decays.size(); ++i) {
304 m_Decays[i].mBratio *= 1. / sum;
312 for (
size_t i = 0; i < m_Decays.size(); ++i) {
313 m_Decays[i].mBratio = m_DecaysOrig[i].mBratio;
320 if (m_ResonanceWidthIntegrationType !=
BWTwoGamma && m_Threshold >= 0.) {
322 b = m_Mass + 2.*m_Width;
327 a = max(m_Threshold, m_Mass - 2.*m_Width);
328 b = m_Mass + 2.*m_Width;
344 if (m_Width == 0.0)
return;
348 if (m_Decays.size() == 0)
349 m_Threshold = m_ThresholdDynamical = m_Mass - 2.*m_Width + 1.e-6;
352 a = m_ThresholdDynamical;
354 b = m_Mass + 2.*m_Width;
355 if (a >= m_Mass - 2.*m_Width) {
356 m_xlegpdyn.resize(0);
357 if (a >= m_Mass + 2.*m_Width)
368 m_vallegpdyn = m_xlegpdyn;
369 m_vallegdyn = m_xlegdyn;
370 m_vallagdyn = m_xlagdyn;
375 vector<double> tCP(m_Decays.size(), 0.);
377 for (
size_t i = 0; i < m_Decays.size(); ++i) {
378 tsumb += m_Decays[i].mBratio;
379 m_Decays[i].mBratioVsM.resize(0);
382 for (
size_t j = 0; j < m_xlegpdyn.size(); ++j) {
385 for (
size_t i = 0; i < m_Decays.size(); ++i) {
386 twid += m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
390 twid += (1. - tsumb) * m_Width;
393 m_vallegpdyn[j] = 0.;
394 for (
size_t i = 0; i < m_Decays.size(); ++i)
395 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
399 for (
size_t i = 0; i < m_Decays.size(); ++i) {
400 double ttwid = m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
401 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
402 tCP[i] += m_wlegpdyn[j] * ttwid / twid *
MassDistribution(m_xlegpdyn[j], twid);
409 for (
size_t j = 0; j < m_xlegdyn.size(); ++j) {
412 for (
size_t i = 0; i < m_Decays.size(); ++i) {
413 twid += m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
417 twid += (1. - tsumb) * m_Width;
421 for (
size_t i = 0; i < m_Decays.size(); ++i)
422 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
426 for (
size_t i = 0; i < m_Decays.size(); ++i) {
427 double ttwid = m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
428 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
429 tCP[i] += m_wlegdyn[j] * ttwid / twid *
MassDistribution(m_xlegdyn[j], twid);
436 for (
size_t j = 0; j < m_xlagdyn.size(); ++j) {
438 double tx = m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width;
440 for (
size_t i = 0; i < m_Decays.size(); ++i) {
441 twid += m_Decays[i].ModifiedWidth(tx) * m_Width;
445 twid += (1. - tsumb) * m_Width;
449 for (
size_t i = 0; i < m_Decays.size(); ++i)
450 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
454 for (
size_t i = 0; i < m_Decays.size(); ++i) {
455 double ttwid = m_Decays[i].ModifiedWidth(tx) * m_Width;
456 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
457 tCP[i] += m_wlagdyn[j] * m_Width * ttwid / twid *
MassDistribution(tx, twid);
467 for (
size_t j = 0; j < m_xlegpdyn.size(); ++j) {
468 m_xalldyn.push_back(m_xlegpdyn[j]);
469 m_walldyn.push_back(m_wlegpdyn[j] * m_vallegpdyn[j] / tC);
472 for (
size_t j = 0; j < m_xlegdyn.size(); ++j) {
473 m_xalldyn.push_back(m_xlegdyn[j]);
474 m_walldyn.push_back(m_wlegdyn[j] * m_vallegdyn[j] / tC);
477 for (
size_t j = 0; j < m_xlagdyn.size(); ++j) {
478 m_xalldyn.push_back(m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width);
479 m_walldyn.push_back(m_wlagdyn[j] * m_vallagdyn[j] / tC);
482 m_densalldyn.resize(m_xalldyn.size());
485 for (
size_t j = 0; j < m_walldyn.size(); ++j) {
486 tsum += m_walldyn[j];
516 for (
size_t i = 0; i < m_Decays.size(); ++i) {
517 tsumb += m_Decays[i].mBratio;
521 for (
size_t i = 0; i < m_Decays.size(); ++i) {
522 twid += m_Decays[i].ModifiedWidth(M) * m_Width;
526 twid += (1. - tsumb) * m_Width;
533 std::vector<double> ret(m_Decays.size(), 0.);
535 if (!eBW || m_Width / m_Mass < 0.01) {
536 for (
size_t i = 0; i < m_Decays.size(); ++i)
537 ret[i] = m_Decays[i].mBratio;
544 for (
size_t i = 0; i < m_Decays.size(); ++i) {
545 double partialwid = m_Decays[i].ModifiedWidth(M) * m_Width;
546 ret[i] = partialwid / totwid;
563 if (!enable) m_Statistics = 0;
564 else m_Statistics = m_StatisticsOrig;
570 if (m_Width != 0.0) {
590 return (m_Baryon == 0 && m_ElectricCharge == 0 && m_Strangeness == 0 && m_Charm == 0);
595 if (!(params.
gammaq == 1.)) mu += log(params.
gammaq) * m_AbsQuark * params.
T;
596 if (!(params.
gammaS == 1. || m_AbsS == 0.)) mu += log(params.
gammaS) * m_AbsS * params.
T;
597 if (!(params.
gammaC == 1. || m_AbsC == 0.)) mu += log(params.
gammaC) * m_AbsC * params.
T;
604 int ind = m_xleg.size();
605 const vector<double> &x = m_xleg, &w = m_wleg;
606 double ret1 = 0., ret2 = 0., tmp = 0.;
609 if (m_ResonanceWidthIntegrationType !=
eBW && m_ResonanceWidthIntegrationType !=
eBWconstBR) {
610 for (
int i = 0; i < ind; i++) {
615 tmp *= m_brweight[i];
626 int ind2 = m_xlag32.size();
627 for (
int i = 0; i < ind2; ++i) {
628 double tmass = m_Mass + 2.*m_Width + m_xlag32[i] * m_Width;
637 if (m_ResonanceWidthIntegrationType ==
eBW || m_ResonanceWidthIntegrationType ==
eBWconstBR) {
638 for (
size_t i = 0; i < m_xalldyn.size(); i++) {
655 if (!(params.
gammaq == 1.)) mu += log(params.
gammaq) * m_AbsQuark * params.
T;
656 if (!(params.
gammaS == 1. || m_AbsS == 0.)) mu += log(params.
gammaS) * m_AbsS * params.
T;
657 if (!(params.
gammaC == 1. || m_AbsC == 0.)) mu += log(params.
gammaC) * m_AbsC * params.
T;
664 int ind = m_xleg.size();
665 const vector<double> &x = m_xleg, &w = m_wleg;
666 double ret1 = 0., ret2 = 0., tmp = 0.;
669 if (m_ResonanceWidthIntegrationType !=
eBW && m_ResonanceWidthIntegrationType !=
eBWconstBR) {
670 for (
int i = 0; i < ind; i++) {
674 tmp *= m_brweight[i];
685 int ind2 = m_xlag32.size();
686 for (
int i = 0; i < ind2; ++i) {
687 double tmass = m_Mass + 2.*m_Width + m_xlag32[i] * m_Width;
696 if (m_ResonanceWidthIntegrationType ==
eBW || m_ResonanceWidthIntegrationType ==
eBWconstBR) {
697 for (
size_t i = 0; i < m_xalldyn.size(); i++) {
705 return mn * ret1 / ret2;
710 if (m_Degeneracy == 0.0)
return 1.;
711 if (m_Statistics == 0)
return 1.;
713 if (dens == 0.)
return 1.;
714 double ret =
chi(2, params, useWidth, mu) /
chi(1, params, useWidth, mu);
715 if (ret != ret) ret = 1.;
721 if (m_Degeneracy == 0)
return 1.;
722 if (m_Statistics == 0)
return 1.;
724 if (dens == 0.)
return 1.;
725 double ret =
chi(3, params, useWidth, mu) /
chi(2, params, useWidth, mu);
726 if (ret != ret) ret = 1.;
732 if (m_Degeneracy == 0)
return 1.;
733 if (m_Statistics == 0)
return 1.;
735 if (dens == 0.)
return 1.;
736 double ret =
chi(4, params, useWidth, mu) /
chi(2, params, useWidth, mu);
737 if (ret != ret) ret = 1.;
742 double arg = (sqrt(k*k + m * m) - mu) / T;
743 return 1. / (exp(arg) + 1.);
747 if (m_Baryon == 0)
return 2. - m_AbsC - m_AbsS;
748 else return abs(m_Baryon) * 3. - m_AbsC - m_AbsS;
752 if (index == 0)
return (
double)m_Baryon;
753 if (index == 1)
return (
double)m_ElectricCharge;
754 if (index == 2)
return (
double)m_Strangeness;
755 if (index == 3)
return (
double)m_Charm;
760 if (index == 0)
return fabs((
double)m_Baryon);
761 if (index == 1)
return fabs((
double)m_ElectricCharge);
762 if (index == 2)
return m_AbsS;
763 if (index == 3)
return m_AbsC;
void RestoreBranchingRatios()
Restores all branching ratios to the original values.
Structure containing information about a single decay channel of a particle.
void SetAbsoluteQuark(double abschg)
Set absolute light quark content |u,d|.
static bool PrintDisclaimer()
double GeVtoifm()
A constant to transform GeV into fm .
double DensityCluster(int n, const ThermalModelParameters ¶ms, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
void SetMass(double mass)
Set particle's mass [GeV].
int Charm() const
Particle's charm.
void GetCoefsIntegrateLaguerre32(std::vector< double > *x, std::vector< double > *w)
void CalculateAndSetDynamicalThreshold()
void NormalizeBranchingRatios()
Normalizes all branching ratios such that they sum up to 100%.
double Density(const ThermalModelParameters ¶ms, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
Computes a specified ideal gas thermodynamic function.
std::vector< double > BranchingRatiosM(double M, bool eBW=true) const
(Energy-dependent) branching ratios
void SetPdgId(long long PdgId)
Set particle's particle's Particle Data Group (PDG) ID number.
Contains some helper functions.
void SetElectricCharge(int chg)
Set particle's electric charge.
static bool DisclaimerPrinted
void SetBaryonCharge(int chg)
Set particle's baryon number.
Energy-independent Breit-Wigner in +-2 interval.
long long PdgId() const
Particle's Particle Data Group (PDG) ID number.
Energy-dependent Breit-Wigner scheme (eBW)
double ResonanceWidth() const
Particle's width at the pole mass (GeV)
double IdealGasQuantity(Quantity quantity, QStatsCalculationType calctype, int statistics, double T, double mu, double m, double deg, int order=1)
Calculation of a generic ideal gas function.
Structure containing all thermal parameters of the model.
double GetCharge(int index) const
Get the quantum number numbered by the index.
void SetResonanceWidthShape(ResonanceWidthShape shape)
Set the resonance width profile to use.
double MassDistribution(double m) const
void FillCoefficientsDynamical()
Fills coefficients for mass integration in the eBW scheme.
Contains some extra mathematical functions used in the code.
void SetAntiParticle(bool antpar=true)
Set manually whether particle is an antiparticle.
double Skewness(const ThermalModelParameters ¶ms, bool useWidth=0, double mu=0.) const
Computes the normalized skewness of particle number fluctuations in the ideal gas.
double ScaledVariance(const ThermalModelParameters ¶ms, bool useWidth=0, double mu=0.) const
Computes the scaled variance of particle number fluctuations in the ideal gas. Computes the scaled va...
double Kurtosis(const ThermalModelParameters ¶ms, bool useWidth=0, double mu=0.) const
Computes the normalized excess kurtosis of particle number fluctuations in the ideal gas...
Zero-width approximation.
int BaryonCharge() const
Particle's baryon number.
void SetName(const std::string &name)
Set particle's name.
ResonanceWidthIntegration
Treatment of finite resonance widths.
std::vector< double > BranchingRatioWeights(const std::vector< double > &ms) const
Class containing all information about a particle specie.
ResonanceWidthShape
Relativistic vs non-relativistic Breit-Wigner shape.
double TotalWidtheBW(double M) const
Total width (eBW scheme) at a given mass.
const std::string & Name() const
Particle's name.
void SetCharm(int chg)
Set particle's charm.
void GetCoefsIntegrateLegendre32(double a, double b, std::vector< double > *x, std::vector< double > *w)
Energy-independent Breit-Wigner in full energy interval.
void SetClusterExpansionOrder(int order)
Set ClusterExpansionOrder()
Quantity
Identifies the thermodynamic function.
bool operator==(const ThermalParticle &rhs) const
double ThermalMassDistribution(double M, double T, double Mu, double width)
Mass distribution of a resonance in a thermal environment.
void UseStatistics(bool enable)
Use quantum statistics.
void GetCoefsIntegrateLegendre10(double a, double b, std::vector< double > *x, std::vector< double > *w)
void CalculateThermalBranchingRatios(const ThermalModelParameters ¶ms, bool useWidth=0, double mu=0.)
Computes average decay branching ratios by integrating over the thermal mass distribution.
Name
Set of all conserved charges considered.
void ReadDecays(std::string filename="")
Read decays from a file and assign them to the particle.
bool IsNeutral() const
Whether particle is neutral one.
std::vector< long long > mDaughters
double Mass() const
Particle's mass [GeV].
double FD(double k, double T, double mu, double m) const
Fermi-Dirac distribution function.
ThermalParticle GenerateAntiParticle() const
Generates the anti-particle to the current particle specie.
bool ZeroWidthEnforced() const
Whether zero-width approximation is enforced for this particle species.
void SetResonanceWidthIntegrationType(ResonanceWidthIntegration type)
Set the ResonanceWidthIntegration scheme used to treat finite resonance widths.
Energy-independent Breit-Wigner in full energy interval with weighted branching ratios.
void SetCalculationType(IdealGasFunctions::QStatsCalculationType type)
Sets the CalculationType() method to evaluate quantum statistics.
Energy-dependent Breit-Wigner scheme (eBW) with constant branching ratios when evaluating feeddown...
int ElectricCharge() const
Particle's electric charge.
void FillCoefficients()
Fills coefficients for mass integration in the energy independent BW scheme.
int Strangeness() const
Particle's strangeness.
double GetAbsCharge(int index) const
Get the absolute value of a quantum number.
int ConservedCharge(ConservedCharge::Name chg) const
One of the four QCD conserved charges.
void SetStrangenessCharge(int chg)
Set particle's strangeness.
double ArbitraryCharge() const
Arbitrary (auxiliary) charge assigned to particle.
void SetDecayThresholdMass(double threshold)
Set the decays threshold mass.
The main namespace where all classes and functions of the Thermal-FIST library reside.
void SetDecayThresholdMassDynamical(double threshold)
Set the threshold mass manually for use in the eBW scheme.
void SetArbitraryCharge(double arbchg)
Assigns arbitrary (auxiliary) charge to particle.
void SetResonanceWidth(double width)
Sets the particle's width at the pole mass.
double chi(int index, const ThermalModelParameters ¶ms, bool useWidth=0, double mu=0.) const
Computes the ideal gas generalized susceptibility .