Thermal-FIST 1.5
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
ThermalParticle.cpp
Go to the documentation of this file.
1/*
2 * Thermal-FIST package
3 *
4 * Copyright (c) 2014-2019 Volodymyr Vovchenko
5 *
6 * GNU General Public License (GPLv3 or later)
7 */
9
10#include <fstream>
11#include <iostream>
12#include <sstream>
13#include <cmath>
14#include <cstdlib>
15#include <algorithm>
16
17#include "HRGBase/Utility.h"
18#include "HRGBase/xMath.h"
21
22using namespace std;
23
24namespace thermalfist {
25
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.),
30 m_ResonanceWidthShape(ThermalParticle::RelativisticBreitWigner), m_ResonanceWidthIntegrationType(ThermalParticle::ZeroWidth), m_GeneralizedDensity(NULL),
31 m_IGFExtraConfig()
32 {
35
37
39 if (m_Mass < 1.000) SetClusterExpansionOrder(5);
40 if (m_Mass < 0.200) SetClusterExpansionOrder(10);
41
43 //SetResonanceWidthIntegrationType(BWTwoGamma);
45
46 m_DecayType = ParticleDecayType::Default;
47
49
51
52 }
53
54
58
60 {
61 //if (PdgId() == 223) // omega(782)
62 // return true;
63 return ((ResonanceWidth() / Mass()) < 0.01);
64 }
65
67 {
68 m_Width = width;
69 if (m_Width != 0.0) {
72 }
73 }
74
76 {
77 m_Threshold = threshold;
78 if (m_Threshold < 0.0) {
79 std::cerr << "**WARNING** Trying to set negative decay threshold for " << m_Name << ", setting to zero instead" << std::endl;
80 }
81 if (m_Width != 0.0) FillCoefficients();
82 }
83
85 {
86 m_ThresholdDynamical = threshold;
87 if (m_ThresholdDynamical < 0.0) {
88 std::cerr << "**WARNING** Trying to set negative dynamical decay threshold for " << m_Name << ", setting to zero instead" << std::endl;
89 }
90 }
91
93 {
94 double Thr = m_Mass + m_Width;
95 for (size_t i = 0; i < m_Decays.size(); ++i) {
96 Thr = min(Thr, m_Decays[i].mM0);
97 }
98 m_ThresholdDynamical = Thr;
99 }
100
102 {
103 if (shape != m_ResonanceWidthShape) {
104 m_ResonanceWidthShape = shape;
106 }
107 }
108
110 {
111 m_ResonanceWidthIntegrationType = type;
115 }
116
118 {
119 return MassDistribution(m, m_Width);
120 }
121
122 double ThermalParticle::MassDistribution(double m, double width) const
123 {
124 if (width < 0.) width = m_Width;
125
126 // Zero if outside the interval
127 //if (m_ResonanceWidthIntegrationType == BWTwoGamma) {
128 // double a = max(m_Threshold, m_Mass - 2.*m_Width);
129 // double b = m_Mass + 2.*m_Width;
130 // if (m < a || m > b)
131 // return 0.;
132 //}
133
134 if (m_ResonanceWidthShape == RelativisticBreitWigner)
135 return m_Mass * width * m / ((m * m - m_Mass * m_Mass)*(m * m - m_Mass * m_Mass) + m_Mass * m_Mass*width*width);
136 else
137 return width / ((m - m_Mass)*(m - m_Mass) + width * width / 4.);
138 }
139
140 void ThermalParticle::ReadDecays(string filename) {
141 m_Decays.resize(0);
142 ifstream fin(filename.c_str());
143 if (!fin.is_open()) {
144 std::cerr << "Error: Could not open file " << filename << endl;
145 return;
146 }
147 char cc[400];
148 double tmpbr;
149 while (fin >> tmpbr) {
151 decay.mBratio = tmpbr / 100.;
152 fin.getline(cc, 350);
153 stringstream ss;
154 ss << cc;
155 int tmpid;
156 while (ss >> tmpid) {
157 decay.mDaughters.push_back(tmpid);
158 }
159 m_Decays.push_back(decay);
160 }
161 }
162
164 {
165 if (!useWidth || m_Width == 0.0 || m_Width / m_Mass < 1.e-2 || m_ResonanceWidthIntegrationType != eBW) {
166 for (size_t j = 0; j < m_Decays.size(); ++j) {
167 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
168 }
169 }
170 else {
171 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * GetAbsQ() * params.T;
172 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
173 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
174
175 for (size_t j = 0; j < m_Decays.size(); ++j) {
176 m_Decays[j].mBratioAverage = 0.;
177 }
178
179 double ret1 = 0., ret2 = 0., tmp = 0.;
180 for (size_t i = 0; i < m_xalldyn.size(); i++) {
181 tmp = m_walldyn[i];
182 double dens = IdealGasFunctions::IdealGasQuantity(IdealGasFunctions::ParticleDensity, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_xalldyn[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
183 ret1 += tmp * dens;
184 ret2 += tmp;
185
186 for (size_t j = 0; j < m_Decays.size(); ++j) {
187 const_cast<double&>(m_Decays[j].mBratioAverage) += tmp * dens * m_Decays[j].mBratioVsM[i];
188 }
189 }
190
191 for (size_t j = 0; j < m_Decays.size(); ++j) {
192 if (ret1 != 0.0)
193 m_Decays[j].mBratioAverage /= ret1;
194 else
195 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
196 }
197 }
198 }
199
200 std::vector<double> ThermalParticle::BranchingRatioWeights(const std::vector<double>& ms) const
201 {
202 std::vector<double> ret = ms;
203
204 std::vector<double> mthr, br;
205 double tsum = 0.;
206 for (size_t i = 0; i < m_Decays.size(); ++i) {
207 mthr.push_back(m_Decays[i].mM0);
208 br.push_back(m_Decays[i].mBratio);
209 tsum += m_Decays[i].mBratio;
210 }
211 if (tsum < 1.) {
212 mthr.push_back(0.);
213 br.push_back(1. - tsum);
214 }
215 else if (tsum > 1.) {
216 for (size_t i = 0; i < br.size(); ++i)
217 br[i] *= 1. / tsum;
218 }
219
220 for (size_t i = 0; i < ms.size(); ++i) {
221 double tw = 0.;
222 for (size_t j = 0; j < br.size(); ++j) {
223 if (mthr[j] <= ms[i])
224 tw += br[j];
225 }
226 ret[i] = tw;
227 }
228 return ret;
229 }
230
231 ThermalParticle ThermalParticle::GenerateAntiParticle(/*ThermalParticleSystem *TPS*/) const
232 {
233 string name = Name();
234 if (BaryonCharge() == 0 && name[name.size() - 1] == '+')
235 name[name.size() - 1] = '-';
236 else if (BaryonCharge() == 0 && name[name.size() - 1] == '-')
237 name[name.size() - 1] = '+';
238 else
239 name = "anti-" + name;
240
241 ThermalParticle ret = *this;
242 ret.SetName(name);
243 ret.SetPdgId(-PdgId());
247 ret.SetCharm(-Charm());
249 ret.SetAntiParticle(true);
250 // Decays are to be done separately from ThermalParticleSystem instance
251 // The code below is deprecated
252 /*if (TPS != NULL) {
253 ret.SetDecays(TPS->GetDecaysFromAntiParticle(Decays()));
254 ret.SetDecaysOriginal(ret.Decays());
255 }*/
256 return ret;
257 }
258
260 {
261 bool ret = true;
262
263 /*ret &= m_xlag32 == rhs.m_xlag32;
264 ret &= m_wlag32 == rhs.m_wlag32;
265 ret &= m_xleg == rhs.m_xleg;
266 ret &= m_wleg == rhs.m_wleg;
267 ret &= m_xleg32 == rhs.m_xleg32;
268 ret &= m_wleg32 == rhs.m_wleg32;*/
269
270 ret &= m_Stable == rhs.m_Stable;
271 ret &= m_AntiParticle == rhs.m_AntiParticle;
272 ret &= m_Name == rhs.m_Name;
273 ret &= m_PDGID == rhs.m_PDGID;
274 ret &= m_Degeneracy == rhs.m_Degeneracy;
275 ret &= m_Statistics == rhs.m_Statistics;
276 ret &= m_StatisticsOrig == rhs.m_StatisticsOrig;
277 ret &= m_Mass == rhs.m_Mass;
278 ret &= m_QuantumStatisticsCalculationType == rhs.m_QuantumStatisticsCalculationType;
279 ret &= m_ClusterExpansionOrder == rhs.m_ClusterExpansionOrder;
280 ret &= m_Baryon == rhs.m_Baryon;
281 ret &= m_ElectricCharge == rhs.m_ElectricCharge;
282 ret &= m_Strangeness == rhs.m_Strangeness;
283 ret &= m_Charm == rhs.m_Charm;
284 ret &= m_Quark == rhs.m_Quark;
285 ret &= m_ArbitraryCharge == rhs.m_ArbitraryCharge;
286 ret &= m_AbsQuark == rhs.m_AbsQuark;
287 ret &= m_AbsS == rhs.m_AbsS;
288 ret &= m_AbsC == rhs.m_AbsC;
289 ret &= m_Width == rhs.m_Width;
290 ret &= m_Threshold == rhs.m_Threshold;
291 ret &= m_ThresholdDynamical == rhs.m_ThresholdDynamical;
292 ret &= m_ResonanceWidthShape == rhs.m_ResonanceWidthShape;
293 ret &= m_ResonanceWidthIntegrationType == rhs.m_ResonanceWidthIntegrationType;
294 ret &= m_Weight == rhs.m_Weight;
295 ret &= m_DecayType == rhs.m_DecayType;
296 ret &= m_Decays == rhs.m_Decays;
297 ret &= m_DecaysOrig == rhs.m_DecaysOrig;
298
299 return ret;
300 }
301
303 double sum = 0.;
304 for (size_t i = 0; i < m_Decays.size(); ++i) {
305 sum += m_Decays[i].mBratio;
306 }
307 for (size_t i = 0; i < m_Decays.size(); ++i) {
308 m_Decays[i].mBratio *= 1. / sum;
309 }
311 }
312
314 {
315 //m_Decays = m_DecaysOrig;
316 for (size_t i = 0; i < m_Decays.size(); ++i) {
317 m_Decays[i].mBratio = m_DecaysOrig[i].mBratio;
318 }
320 }
321
323 double a, b;
324 if (m_ResonanceWidthIntegrationType != BWTwoGamma && m_Threshold >= 0.) {
325 a = m_Threshold;
326 b = m_Mass + 2.*m_Width;
328 m_brweight = BranchingRatioWeights(m_xleg);
329 }
330 else {
331 a = max(m_Threshold, m_Mass - 2.*m_Width);
332 b = m_Mass + 2.*m_Width;
334 m_brweight = BranchingRatioWeights(m_xleg);
335 }
336
337 // Old version
338 //if (m_Width / m_Mass<1e-1) { NumericalIntegration::GetCoefsIntegrateLegendre10(a, b, &m_xleg, &m_wleg); }
339 //else { NumericalIntegration::GetCoefsIntegrateLegendre32(a, b, &m_xleg, &m_wleg); }
340
341 // New version
342 NumericalIntegration::GetCoefsIntegrateLegendre32(0., 1., &m_xleg32, &m_wleg32);
344 }
345
346 // Mass-dependent widths
348 if (m_Width == 0.0) return;
349
350 double a, b;
351
352 if (m_Decays.size() == 0)
353 m_Threshold = m_ThresholdDynamical = m_Mass - 2.*m_Width + 1.e-6;
354
355 //a = max(m_Threshold, m_ThresholdDynamical);
356 a = m_ThresholdDynamical;
357
358 b = m_Mass + 2.*m_Width;
359 if (a >= m_Mass - 2.*m_Width) {
360 m_xlegpdyn.resize(0);
361 if (a >= m_Mass + 2.*m_Width)
362 m_xlegdyn.resize(0);
363 else
364 NumericalIntegration::GetCoefsIntegrateLegendre32(a, b, &m_xlegdyn, &m_wlegdyn);
365 }
366 else {
367 NumericalIntegration::GetCoefsIntegrateLegendre32(a, m_Mass - 2.*m_Width, &m_xlegpdyn, &m_wlegpdyn);
368 NumericalIntegration::GetCoefsIntegrateLegendre32(m_Mass - 2.*m_Width, b, &m_xlegdyn, &m_wlegdyn);
369 }
371
372 m_vallegpdyn = m_xlegpdyn;
373 m_vallegdyn = m_xlegdyn;
374 m_vallagdyn = m_xlagdyn;
375
376
377 double tsumb = 0.;
378 double tC = 0.;
379 vector<double> tCP(m_Decays.size(), 0.);
380
381 for (size_t i = 0; i < m_Decays.size(); ++i) {
382 tsumb += m_Decays[i].mBratio;
383 m_Decays[i].mBratioVsM.resize(0);
384 }
385
386 for (size_t j = 0; j < m_xlegpdyn.size(); ++j) {
387 double twid = 0.;
388
389 for (size_t i = 0; i < m_Decays.size(); ++i) {
390 twid += m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
391 }
392
393 if (tsumb < 1.)
394 twid += (1. - tsumb) * m_Width;
395
396 if (twid == 0.0) {
397 m_vallegpdyn[j] = 0.;
398 for (size_t i = 0; i < m_Decays.size(); ++i)
399 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
400 continue;
401 }
402
403 for (size_t i = 0; i < m_Decays.size(); ++i) {
404 double ttwid = m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
405 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
406 tCP[i] += m_wlegpdyn[j] * ttwid / twid * MassDistribution(m_xlegpdyn[j], twid);
407 }
408
409 tC += m_wlegpdyn[j] * MassDistribution(m_xlegpdyn[j], twid);
410 m_vallegpdyn[j] = MassDistribution(m_xlegpdyn[j], twid);
411 }
412
413 for (size_t j = 0; j < m_xlegdyn.size(); ++j) {
414 double twid = 0.;
415
416 for (size_t i = 0; i < m_Decays.size(); ++i) {
417 twid += m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
418 }
419
420 if (tsumb < 1.)
421 twid += (1. - tsumb) * m_Width;
422
423 if (twid == 0.0) {
424 m_vallegdyn[j] = 0.;
425 for (size_t i = 0; i < m_Decays.size(); ++i)
426 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
427 continue;
428 }
429
430 for (size_t i = 0; i < m_Decays.size(); ++i) {
431 double ttwid = m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
432 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
433 tCP[i] += m_wlegdyn[j] * ttwid / twid * MassDistribution(m_xlegdyn[j], twid);
434 }
435
436 tC += m_wlegdyn[j] * MassDistribution(m_xlegdyn[j], twid);
437 m_vallegdyn[j] = MassDistribution(m_xlegdyn[j], twid);
438 }
439
440 for (size_t j = 0; j < m_xlagdyn.size(); ++j) {
441 double twid = 0.;
442 double tx = m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width;
443
444 for (size_t i = 0; i < m_Decays.size(); ++i) {
445 twid += m_Decays[i].ModifiedWidth(tx) * m_Width;
446 }
447
448 if (tsumb < 1.)
449 twid += (1. - tsumb) * m_Width;
450
451 if (twid == 0.0) {
452 m_vallagdyn[j] = 0.;
453 for (size_t i = 0; i < m_Decays.size(); ++i)
454 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
455 continue;
456 }
457
458 for (size_t i = 0; i < m_Decays.size(); ++i) {
459 double ttwid = m_Decays[i].ModifiedWidth(tx) * m_Width;
460 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
461 tCP[i] += m_wlagdyn[j] * m_Width * ttwid / twid * MassDistribution(tx, twid);
462 }
463
464 tC += m_wlagdyn[j] * m_Width * MassDistribution(tx, twid);
465 m_vallagdyn[j] = m_Width * MassDistribution(tx, twid);
466 }
467
468 m_xalldyn.resize(0);
469 m_walldyn.resize(0);
470
471 for (size_t j = 0; j < m_xlegpdyn.size(); ++j) {
472 m_xalldyn.push_back(m_xlegpdyn[j]);
473 m_walldyn.push_back(m_wlegpdyn[j] * m_vallegpdyn[j] / tC);
474 }
475
476 for (size_t j = 0; j < m_xlegdyn.size(); ++j) {
477 m_xalldyn.push_back(m_xlegdyn[j]);
478 m_walldyn.push_back(m_wlegdyn[j] * m_vallegdyn[j] / tC);
479 }
480
481 for (size_t j = 0; j < m_xlagdyn.size(); ++j) {
482 m_xalldyn.push_back(m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width);
483 m_walldyn.push_back(m_wlagdyn[j] * m_vallagdyn[j] / tC);
484 }
485
486 m_densalldyn.resize(m_xalldyn.size());
487
488 double tsum = 0.;
489 for (size_t j = 0; j < m_walldyn.size(); ++j) {
490 tsum += m_walldyn[j];
491 }
492
493
494
495 }
496
497 double ThermalParticle::TotalWidtheBW(double M) const
498 {
499 //if (m_ResonanceWidthIntegrationType != eBW)
500 // return m_Width;
501 if (m_Width / m_Mass < 0.01) {
502 return m_Width;
503 }
504
505 double tsumb = 0.0;
506 for (size_t i = 0; i < m_Decays.size(); ++i) {
507 tsumb += m_Decays[i].mBratio;
508 }
509
510 double twid = 0.0;
511 for (size_t i = 0; i < m_Decays.size(); ++i) {
512 twid += m_Decays[i].ModifiedWidth(M) * m_Width;
513 }
514
515 if (tsumb < 1.)
516 twid += (1. - tsumb) * m_Width;
517
518 return twid;
519 }
520
521 std::vector<double> ThermalParticle::BranchingRatiosM(double M, bool eBW) const
522 {
523 std::vector<double> ret(m_Decays.size(), 0.);
524
525 if (!eBW || m_Width / m_Mass < 0.01) {
526 for (size_t i = 0; i < m_Decays.size(); ++i)
527 ret[i] = m_Decays[i].mBratio;
528
529 return ret;
530 }
531
532 double totwid = TotalWidtheBW(M);
533
534 for (size_t i = 0; i < m_Decays.size(); ++i) {
535 double partialwid = m_Decays[i].ModifiedWidth(M) * m_Width;
536 ret[i] = partialwid / totwid;
537 }
538
539 return ret;
540 }
541
542 double ThermalParticle::ThermalMassDistribution(double M, double T, double Mu, double width)
543 {
544 return IdealGasFunctions::IdealGasQuantity(IdealGasFunctions::ParticleDensity, m_QuantumStatisticsCalculationType, m_Statistics, T, Mu, M, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig) * MassDistribution(M, width);
545 }
546
547 double ThermalParticle::ThermalMassDistribution(double M, double T, double Mu)
548 {
549 return ThermalMassDistribution(M, T, Mu, TotalWidtheBW(M));
550 }
551
553 if (!enable) m_Statistics = 0;
554 else m_Statistics = m_StatisticsOrig;
555 }
556
557 void ThermalParticle::SetMass(double mass)
558 {
559 m_Mass = mass;
560 if (m_Width != 0.0) {
563 }
564 }
565
567 {
569 return BaryonCharge();
571 return ElectricCharge();
573 return Strangeness();
575 return Charm();
576 return 0;
577 }
578
580 return (m_Baryon == 0 && m_ElectricCharge == 0 && m_Strangeness == 0 && m_Charm == 0);
581 }
582
583
584 double ThermalParticle::Density(const ThermalModelParameters &params, IdealGasFunctions::Quantity type, bool useWidth, double mu) const {
585 if (m_GeneralizedDensity != NULL)
586 return m_GeneralizedDensity->Quantity(type, params.T, mu);
587
588 if (m_Degeneracy == 0.0)
589 return 0.0;
590
591 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * m_AbsQuark * params.T;
592 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
593 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
594
595 if (!useWidth || m_Mass == 0.0 || ZeroWidthEnforced() || m_ResonanceWidthIntegrationType == ZeroWidth) {
596 return IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_Mass, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
597 }
598
599 int ind = m_xleg.size();
600 const vector<double> &x = m_xleg, &w = m_wleg;
601 double ret1 = 0., ret2 = 0., tmp = 0.;
602
603 // Integration from m0 or M-2*Gamma to M+2*Gamma
604 if (m_ResonanceWidthIntegrationType != eBW && m_ResonanceWidthIntegrationType != eBWconstBR) {
605 for (int i = 0; i < ind; i++) {
606
607 tmp = w[i] * MassDistribution(x[i]);
608
609 if (m_ResonanceWidthIntegrationType == FullIntervalWeighted)
610 tmp *= m_brweight[i];
611 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, x[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
612
613 ret1 += tmp * dens;
614 ret2 += tmp;
615 }
616 }
617
618 // Integration from M+2*Gamma to infinity
619 if (m_ResonanceWidthIntegrationType == FullInterval || m_ResonanceWidthIntegrationType == FullIntervalWeighted) {
620 int ind2 = m_xlag32.size();
621 for (int i = 0; i < ind2; ++i) {
622 double tmass = m_Mass + 2.*m_Width + m_xlag32[i] * m_Width;
623 tmp = m_wlag32[i] * m_Width * MassDistribution(tmass);
624 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, tmass, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
625
626 ret1 += tmp * dens;
627 ret2 += tmp;
628 }
629 }
630
631 if (m_ResonanceWidthIntegrationType == eBW || m_ResonanceWidthIntegrationType == eBWconstBR) {
632 for (size_t i = 0; i < m_xalldyn.size(); i++) {
633 tmp = m_walldyn[i];
634 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_xalldyn[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
635 ret1 += tmp * dens;
636 ret2 += tmp;
637 }
638 }
639
640 return ret1 / ret2;
641 }
642
643 double ThermalParticle::DensityCluster(int n, const ThermalModelParameters & params, IdealGasFunctions::Quantity type, bool useWidth, double mu) const
644 {
645 double mn = 1.;
646 if ((abs(BaryonCharge()) & 1) && !(n & 1))
647 mn = -1.;
648
649 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * m_AbsQuark /*GetAbsQ()*/ * params.T;
650 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
651 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
652
653 //if (!useWidth || m_Width / m_Mass < 1.e-2 || m_ResonanceWidthIntegrationType == ZeroWidth) {
654 if (!useWidth || ZeroWidthEnforced() || m_ResonanceWidthIntegrationType == ZeroWidth) {
655 return mn * IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, 0, params.T / static_cast<double>(n), mu, m_Mass, m_Degeneracy, 1, m_IGFExtraConfig);
656 }
657
658 int ind = m_xleg.size();
659 const vector<double> &x = m_xleg, &w = m_wleg;
660 double ret1 = 0., ret2 = 0., tmp = 0.;
661
662 // Integration from m0 or M-2*Gamma to M+2*Gamma
663 if (m_ResonanceWidthIntegrationType != eBW && m_ResonanceWidthIntegrationType != eBWconstBR) {
664 for (int i = 0; i < ind; i++) {
665 tmp = w[i] * MassDistribution(x[i]);
666
667 if (m_ResonanceWidthIntegrationType == FullIntervalWeighted)
668 tmp *= m_brweight[i];
669
670 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, 0, params.T / static_cast<double>(n), mu, x[i], m_Degeneracy, 1, m_IGFExtraConfig);
671
672 ret1 += tmp * dens;
673 ret2 += tmp;
674 }
675 }
676
677 // Integration from M+2*Gamma to infinity
678 if (m_ResonanceWidthIntegrationType == FullInterval || m_ResonanceWidthIntegrationType == FullIntervalWeighted) {
679 int ind2 = m_xlag32.size();
680 for (int i = 0; i < ind2; ++i) {
681 double tmass = m_Mass + 2.*m_Width + m_xlag32[i] * m_Width;
682 tmp = m_wlag32[i] * m_Width * MassDistribution(tmass);
683 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, 0, params.T / static_cast<double>(n), mu, tmass, m_Degeneracy, 1, m_IGFExtraConfig);
684
685 ret1 += tmp * dens;
686 ret2 += tmp;
687 }
688 }
689
690 if (m_ResonanceWidthIntegrationType == eBW || m_ResonanceWidthIntegrationType == eBWconstBR) {
691 for (size_t i = 0; i < m_xalldyn.size(); i++) {
692 tmp = m_walldyn[i];
693 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, 0, params.T / static_cast<double>(n), mu, m_xalldyn[i], m_Degeneracy, 1, m_IGFExtraConfig);
694 ret1 += tmp * dens;
695 ret2 += tmp;
696 }
697 }
698
699 return mn * ret1 / ret2;
700 }
701
702
703 double ThermalParticle::chiDimensionfull(int index, const ThermalModelParameters& params, bool useWidth, double mu) const
704 {
705 if (index == 0) return Density(params, IdealGasFunctions::Pressure, useWidth, mu) / pow(xMath::GeVtoifm(), 3);
706 if (index == 1) return Density(params, IdealGasFunctions::ParticleDensity, useWidth, mu) / pow(xMath::GeVtoifm(), 3);
707 if (index == 2) return Density(params, IdealGasFunctions::chi2difull, useWidth, mu);
708 if (index == 3) return Density(params, IdealGasFunctions::chi3difull, useWidth, mu);
709 if (index == 4) return Density(params, IdealGasFunctions::chi4difull, useWidth, mu);
710 return 1.;
711 }
712
713 double ThermalParticle::ScaledVariance(const ThermalModelParameters &params, bool useWidth, double mu) const {
714 if (m_Degeneracy == 0.0) return 1.;
715 if (m_Statistics == 0) return 1.;
716 double dens = Density(params, IdealGasFunctions::ParticleDensity, useWidth, mu);
717 if (dens == 0.) return 1.;
718 double ret = params.T * chiDimensionfull(2, params, useWidth, mu) / chiDimensionfull(1, params, useWidth, mu);
719 if (ret != ret) ret = 1.;
720 return ret;
721 }
722
723 double ThermalParticle::Skewness(const ThermalModelParameters &params, bool useWidth, double mu) const
724 {
725 if (m_Degeneracy == 0) return 1.;
726 if (m_Statistics == 0) return 1.;
727 double dens = Density(params, IdealGasFunctions::ParticleDensity, useWidth, mu);
728 if (dens == 0.) return 1.;
729 double ret = params.T * chiDimensionfull(3, params, useWidth, mu) / chiDimensionfull(2, params, useWidth, mu);
730 if (ret != ret) ret = 1.;
731 return ret;
732 }
733
734 double ThermalParticle::Kurtosis(const ThermalModelParameters &params, bool useWidth, double mu) const
735 {
736 if (m_Degeneracy == 0) return 1.;
737 if (m_Statistics == 0) return 1.;
738 double dens = Density(params, IdealGasFunctions::ParticleDensity, useWidth, mu);
739 if (dens == 0.) return 1.;
740 double ret = params.T * params.T * chiDimensionfull(4, params, useWidth, mu) / chiDimensionfull(2, params, useWidth, mu);
741 if (ret != ret) ret = 1.;
742 return ret;
743 }
744
745 double ThermalParticle::FD(double k, double T, double mu, double m) const {
746 double arg = (sqrt(k*k + m * m) - mu) / T;
747 return 1. / (exp(arg) + 1.);
748 }
749
751 if (m_Baryon == 0) return 2. - m_AbsC - m_AbsS;
752 else return abs(m_Baryon) * 3. - m_AbsC - m_AbsS;
753 }
754
755 double ThermalParticle::GetCharge(int index) const {
756 if (index == 0) return (double)m_Baryon;
757 if (index == 1) return (double)m_ElectricCharge;
758 if (index == 2) return (double)m_Strangeness;
759 if (index == 3) return (double)m_Charm;
760 return 0.;
761 }
762
763 double ThermalParticle::GetAbsCharge(int index) const {
764 if (index == 0) return fabs((double)m_Baryon);
765 if (index == 1) return fabs((double)m_ElectricCharge);
766 if (index == 2) return m_AbsS;
767 if (index == 3) return m_AbsC;
768 return 0.;
769 }
770
771 double ThermalParticle::chi(int index, const ThermalModelParameters &params, bool useWidth, double mu) const {
772 if (index == 0) return Density(params, IdealGasFunctions::Pressure, useWidth, mu) / pow(params.T, 4) / pow(xMath::GeVtoifm(), 3);
773 if (index == 1) return Density(params, IdealGasFunctions::ParticleDensity, useWidth, mu) / pow(params.T, 3) / pow(xMath::GeVtoifm(), 3);
774 if (index == 2) return Density(params, IdealGasFunctions::chi2, useWidth, mu);
775 if (index == 3) return Density(params, IdealGasFunctions::chi3, useWidth, mu);
776 if (index == 4) return Density(params, IdealGasFunctions::chi4, useWidth, mu);
777 return 1.;
778 }
779
781 if (m_GeneralizedDensity != NULL) {
782 delete m_GeneralizedDensity;
783 m_GeneralizedDensity = NULL;
784 }
785 }
786
789 m_GeneralizedDensity = density_model;
790 }
791
792 void ThermalParticle::SetMagneticField(double B, int lmax) {
793 m_IGFExtraConfig.MagneticField.B = B;
794 m_IGFExtraConfig.MagneticField.lmax = lmax;
795 m_IGFExtraConfig.MagneticField.Q = static_cast<double>(m_ElectricCharge);
796 m_IGFExtraConfig.MagneticField.degSpin = m_Degeneracy;
797 }
798
799} // namespace thermalfist
map< string, double > params
Contains some helper functions.
static bool PrintDisclaimer()
Definition Utility.cpp:47
static bool DisclaimerPrinted
Definition Utility.h:27
Implements the possibility of a generalized calculation of the densities. For example,...
double MassDistribution(double m) const
long long PdgId() const
Particle's Particle Data Group (PDG) ID number.
void SetAntiParticle(bool antpar=true)
Set manually whether particle is an antiparticle.
void SetAbsoluteQuark(double abschg)
Set absolute light quark content |u,d|.
int BaryonCharge() const
Particle's baryon number.
double Kurtosis(const ThermalModelParameters &params, bool useWidth=0, double mu=0.) const
Computes the normalized excess kurtosis of particle number fluctuations in the ideal gas.
void FillCoefficients()
Fills coefficients for mass integration in the energy independent BW scheme.
void RestoreBranchingRatios()
Restores all branching ratios to the original values.
double Mass() const
Particle's mass [GeV].
double ArbitraryCharge() const
Arbitrary (auxiliary) charge assigned to particle.
double chiDimensionfull(int index, const ThermalModelParameters &params, bool useWidth=0, double mu=0.) const
Computes the ideal gas dimensionfull susceptibility .
int Strangeness() const
Particle's strangeness.
void SetCalculationType(IdealGasFunctions::QStatsCalculationType type)
Sets the CalculationType() method to evaluate quantum statistics.
double TotalWidtheBW(double M) const
Total width (eBW scheme) at a given mass.
void SetResonanceWidthShape(ResonanceWidthShape shape)
Set the resonance width profile to use.
void SetDecayThresholdMassDynamical(double threshold)
Set the threshold mass manually for use in the eBW scheme.
double Density(const ThermalModelParameters &params, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
Computes a specified ideal gas thermodynamic function.
void SetResonanceWidthIntegrationType(ResonanceWidthIntegration type)
Set the ResonanceWidthIntegration scheme used to treat finite resonance widths.
ResonanceWidthIntegration
Treatment of finite resonance widths.
@ FullIntervalWeighted
Energy-independent Breit-Wigner in full energy interval with weighted branching ratios.
@ eBWconstBR
Energy-dependent Breit-Wigner scheme (eBW) with constant branching ratios when evaluating feeddown.
@ eBW
Energy-dependent Breit-Wigner scheme (eBW)
@ BWTwoGamma
Energy-independent Breit-Wigner in +-2\Gamma interval.
@ FullInterval
Energy-independent Breit-Wigner in full energy interval.
@ ZeroWidth
Zero-width approximation.
void ClearGeneralizedDensity()
Clear the generalized density.
void SetArbitraryCharge(double arbchg)
Assigns arbitrary (auxiliary) charge to particle.
double FD(double k, double T, double mu, double m) const
Fermi-Dirac distribution function.
void ReadDecays(std::string filename="")
Read decays from a file and assign them to the particle.
int ElectricCharge() const
Particle's electric charge.
void SetStrangenessCharge(int chg)
Set particle's strangeness.
ResonanceWidthShape
Relativistic vs non-relativistic Breit-Wigner shape.
bool IsNeutral() const
Whether particle is neutral one.
void SetPdgId(long long PdgId)
Set particle's particle's Particle Data Group (PDG) ID number.
void SetDecayThresholdMass(double threshold)
Set the decays threshold mass.
void SetCharm(int chg)
Set particle's charm.
int Charm() const
Particle's charm.
double chi(int index, const ThermalModelParameters &params, bool useWidth=0, double mu=0.) const
Computes the ideal gas generalized susceptibility .
ThermalParticle(bool Stable=true, std::string Name="hadron", long long PDGID=0, double Deg=1., int Stat=0, double Mass=0., int Strange=0, int Baryon=0, int Charge=0, double AbsS=0., double Width=0., double Threshold=0., int Charm=0, double AbsC=0., int Quark=0)
Construct a new ThermalParticle object.
double ThermalMassDistribution(double M, double T, double Mu, double width)
Mass distribution of a resonance in a thermal environment.
void SetMass(double mass)
Set particle's mass [GeV].
double DensityCluster(int n, const ThermalModelParameters &params, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
void SetBaryonCharge(int chg)
Set particle's baryon number.
void SetMagneticField(double B=0.0, int lmax=1)
Sets the value of magnetic field and the number of Landau levels to include.
double Skewness(const ThermalModelParameters &params, bool useWidth=0, double mu=0.) const
Computes the normalized skewness of particle number fluctuations in the ideal gas.
double GetCharge(int index) const
Get the quantum number numbered by the index.
bool operator==(const ThermalParticle &rhs) const
const std::string & Name() const
Particle's name.
int ConservedCharge(ConservedCharge::Name chg) const
One of the four QCD conserved charges.
double ResonanceWidth() const
Particle's width at the pole mass (GeV)
std::vector< double > BranchingRatioWeights(const std::vector< double > &ms) const
void SetGeneralizedDensity(GeneralizedDensity *density_model)
void SetResonanceWidth(double width)
Sets the particle's width at the pole mass.
void SetName(const std::string &name)
Set particle's name.
ThermalParticle GenerateAntiParticle() const
Generates the anti-particle to the current particle specie.
void NormalizeBranchingRatios()
Normalizes all branching ratios such that they sum up to 100%.
void UseStatistics(bool enable)
Use quantum statistics.
std::vector< double > BranchingRatiosM(double M, bool eBW=true) const
(Energy-dependent) branching ratios
bool ZeroWidthEnforced() const
Whether zero-width approximation is enforced for this particle species.
void SetElectricCharge(int chg)
Set particle's electric charge.
void FillCoefficientsDynamical()
Fills coefficients for mass integration in the eBW scheme.
void CalculateThermalBranchingRatios(const ThermalModelParameters &params, bool useWidth=0, double mu=0.)
Computes average decay branching ratios by integrating over the thermal mass distribution.
double GetAbsCharge(int index) const
Get the absolute value of a quantum number.
double ScaledVariance(const ThermalModelParameters &params, bool useWidth=0, double mu=0.) const
Computes the scaled variance of particle number fluctuations in the ideal gas. Computes the scaled va...
void SetClusterExpansionOrder(int order)
Set ClusterExpansionOrder()
double IdealGasQuantity(Quantity quantity, QStatsCalculationType calctype, int statistics, double T, double mu, double m, double deg, int order=1, const IdealGasFunctionsExtraConfig &extraConfig=IdealGasFunctionsExtraConfig())
Calculation of a generic ideal gas function.
Quantity
Identifies the thermodynamic function.
void GetCoefsIntegrateLegendre10(double a, double b, std::vector< double > *x, std::vector< double > *w)
void GetCoefsIntegrateLegendre32(double a, double b, std::vector< double > *x, std::vector< double > *w)
void GetCoefsIntegrateLaguerre32(std::vector< double > *x, std::vector< double > *w)
constexpr double GeVtoifm()
A constant to transform GeV into fm .
Definition xMath.h:25
The main namespace where all classes and functions of the Thermal-FIST library reside.
Definition CosmicEoS.h:9
Name
Set of all conserved charges considered.
@ ElectricCharge
Electric charge.
Structure containing information about a single decay channel of a particle.
std::vector< long long > mDaughters
Structure containing all thermal parameters of the model.
Contains some extra mathematical functions used in the code.