Thermal-FIST 1.6
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 (Mass() == 0.)
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 if (!useWidth || m_Width == 0.0 || ZeroWidthEnforced() || m_ResonanceWidthIntegrationType != eBW) {
167 for (size_t j = 0; j < m_Decays.size(); ++j) {
168 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
169 }
170 }
171 else {
172 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * GetAbsQ() * params.T;
173 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
174 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
175
176 for (size_t j = 0; j < m_Decays.size(); ++j) {
177 m_Decays[j].mBratioAverage = 0.;
178 }
179
180 double ret1 = 0., ret2 = 0., tmp = 0.;
181 for (size_t i = 0; i < m_xalldyn.size(); i++) {
182 tmp = m_walldyn[i];
183 double dens = IdealGasFunctions::IdealGasQuantity(IdealGasFunctions::ParticleDensity, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_xalldyn[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
184 ret1 += tmp * dens;
185 ret2 += tmp;
186
187 for (size_t j = 0; j < m_Decays.size(); ++j) {
188 const_cast<double&>(m_Decays[j].mBratioAverage) += tmp * dens * m_Decays[j].mBratioVsM[i];
189 }
190 }
191
192 for (size_t j = 0; j < m_Decays.size(); ++j) {
193 if (ret1 != 0.0)
194 m_Decays[j].mBratioAverage /= ret1;
195 else
196 m_Decays[j].mBratioAverage = m_Decays[j].mBratio;
197 }
198 }
199 }
200
201 std::vector<double> ThermalParticle::BranchingRatioWeights(const std::vector<double>& ms) const
202 {
203 std::vector<double> ret = ms;
204
205 std::vector<double> mthr, br;
206 double tsum = 0.;
207 for (size_t i = 0; i < m_Decays.size(); ++i) {
208 mthr.push_back(m_Decays[i].mM0);
209 br.push_back(m_Decays[i].mBratio);
210 tsum += m_Decays[i].mBratio;
211 }
212 if (tsum < 1.) {
213 mthr.push_back(0.);
214 br.push_back(1. - tsum);
215 }
216 else if (tsum > 1.) {
217 for (size_t i = 0; i < br.size(); ++i)
218 br[i] *= 1. / tsum;
219 }
220
221 for (size_t i = 0; i < ms.size(); ++i) {
222 double tw = 0.;
223 for (size_t j = 0; j < br.size(); ++j) {
224 if (mthr[j] <= ms[i])
225 tw += br[j];
226 }
227 ret[i] = tw;
228 }
229 return ret;
230 }
231
232 ThermalParticle ThermalParticle::GenerateAntiParticle(/*ThermalParticleSystem *TPS*/) const
233 {
234 string name = Name();
235 if (BaryonCharge() == 0 && name[name.size() - 1] == '+')
236 name[name.size() - 1] = '-';
237 else if (BaryonCharge() == 0 && name[name.size() - 1] == '-')
238 name[name.size() - 1] = '+';
239 else
240 name = "anti-" + name;
241
242 ThermalParticle ret = *this;
243 ret.SetName(name);
244 ret.SetPdgId(-PdgId());
248 ret.SetCharm(-Charm());
250 ret.SetAntiParticle(true);
251 // Decays are to be done separately from ThermalParticleSystem instance
252 // The code below is deprecated
253 /*if (TPS != NULL) {
254 ret.SetDecays(TPS->GetDecaysFromAntiParticle(Decays()));
255 ret.SetDecaysOriginal(ret.Decays());
256 }*/
257 return ret;
258 }
259
261 {
262 bool ret = true;
263
264 /*ret &= m_xlag32 == rhs.m_xlag32;
265 ret &= m_wlag32 == rhs.m_wlag32;
266 ret &= m_xleg == rhs.m_xleg;
267 ret &= m_wleg == rhs.m_wleg;
268 ret &= m_xleg32 == rhs.m_xleg32;
269 ret &= m_wleg32 == rhs.m_wleg32;*/
270
271 ret &= m_Stable == rhs.m_Stable;
272 ret &= m_AntiParticle == rhs.m_AntiParticle;
273 ret &= m_Name == rhs.m_Name;
274 ret &= m_PDGID == rhs.m_PDGID;
275 ret &= m_Degeneracy == rhs.m_Degeneracy;
276 ret &= m_Statistics == rhs.m_Statistics;
277 ret &= m_StatisticsOrig == rhs.m_StatisticsOrig;
278 ret &= m_Mass == rhs.m_Mass;
279 ret &= m_QuantumStatisticsCalculationType == rhs.m_QuantumStatisticsCalculationType;
280 ret &= m_ClusterExpansionOrder == rhs.m_ClusterExpansionOrder;
281 ret &= m_Baryon == rhs.m_Baryon;
282 ret &= m_ElectricCharge == rhs.m_ElectricCharge;
283 ret &= m_Strangeness == rhs.m_Strangeness;
284 ret &= m_Charm == rhs.m_Charm;
285 ret &= m_Quark == rhs.m_Quark;
286 ret &= m_ArbitraryCharge == rhs.m_ArbitraryCharge;
287 ret &= m_AbsQuark == rhs.m_AbsQuark;
288 ret &= m_AbsS == rhs.m_AbsS;
289 ret &= m_AbsC == rhs.m_AbsC;
290 ret &= m_Width == rhs.m_Width;
291 ret &= m_Threshold == rhs.m_Threshold;
292 ret &= m_ThresholdDynamical == rhs.m_ThresholdDynamical;
293 ret &= m_ResonanceWidthShape == rhs.m_ResonanceWidthShape;
294 ret &= m_ResonanceWidthIntegrationType == rhs.m_ResonanceWidthIntegrationType;
295 ret &= m_Weight == rhs.m_Weight;
296 ret &= m_DecayType == rhs.m_DecayType;
297 ret &= m_Decays == rhs.m_Decays;
298 ret &= m_DecaysOrig == rhs.m_DecaysOrig;
299
300 return ret;
301 }
302
304 double sum = 0.;
305 for (size_t i = 0; i < m_Decays.size(); ++i) {
306 sum += m_Decays[i].mBratio;
307 }
308 for (size_t i = 0; i < m_Decays.size(); ++i) {
309 m_Decays[i].mBratio *= 1. / sum;
310 }
312 }
313
315 {
316 //m_Decays = m_DecaysOrig;
317 for (size_t i = 0; i < m_Decays.size(); ++i) {
318 m_Decays[i].mBratio = m_DecaysOrig[i].mBratio;
319 }
321 }
322
324 double a, b;
325 if (m_ResonanceWidthIntegrationType != BWTwoGamma && m_Threshold >= 0.) {
326 a = m_Threshold;
327 b = m_Mass + 2.*m_Width;
329 m_brweight = BranchingRatioWeights(m_xleg);
330 }
331 else {
332 a = max(m_Threshold, m_Mass - 2.*m_Width);
333 b = m_Mass + 2.*m_Width;
335 m_brweight = BranchingRatioWeights(m_xleg);
336 }
337
338 // Old version
339 //if (m_Width / m_Mass<1e-1) { NumericalIntegration::GetCoefsIntegrateLegendre10(a, b, &m_xleg, &m_wleg); }
340 //else { NumericalIntegration::GetCoefsIntegrateLegendre32(a, b, &m_xleg, &m_wleg); }
341
342 // New version
343 NumericalIntegration::GetCoefsIntegrateLegendre32(0., 1., &m_xleg32, &m_wleg32);
345 }
346
347 // Mass-dependent widths
349 if (m_Width == 0.0) return;
350
351 double a, b;
352
353 if (m_Decays.size() == 0)
354 m_Threshold = m_ThresholdDynamical = m_Mass - 2.*m_Width + 1.e-6;
355
356 //a = max(m_Threshold, m_ThresholdDynamical);
357 a = m_ThresholdDynamical;
358
359 b = m_Mass + 2.*m_Width;
360 if (a >= m_Mass - 2.*m_Width) {
361 m_xlegpdyn.resize(0);
362 if (a >= m_Mass + 2.*m_Width)
363 m_xlegdyn.resize(0);
364 else
365 NumericalIntegration::GetCoefsIntegrateLegendre32(a, b, &m_xlegdyn, &m_wlegdyn);
366 }
367 else {
368 NumericalIntegration::GetCoefsIntegrateLegendre32(a, m_Mass - 2.*m_Width, &m_xlegpdyn, &m_wlegpdyn);
369 NumericalIntegration::GetCoefsIntegrateLegendre32(m_Mass - 2.*m_Width, b, &m_xlegdyn, &m_wlegdyn);
370 }
372
373 m_vallegpdyn = m_xlegpdyn;
374 m_vallegdyn = m_xlegdyn;
375 m_vallagdyn = m_xlagdyn;
376
377
378 double tsumb = 0.;
379 double tC = 0.;
380 vector<double> tCP(m_Decays.size(), 0.);
381
382 for (size_t i = 0; i < m_Decays.size(); ++i) {
383 tsumb += m_Decays[i].mBratio;
384 m_Decays[i].mBratioVsM.resize(0);
385 }
386
387 for (size_t j = 0; j < m_xlegpdyn.size(); ++j) {
388 double twid = 0.;
389
390 for (size_t i = 0; i < m_Decays.size(); ++i) {
391 twid += m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
392 }
393
394 if (tsumb < 1.)
395 twid += (1. - tsumb) * m_Width;
396
397 if (twid == 0.0) {
398 m_vallegpdyn[j] = 0.;
399 for (size_t i = 0; i < m_Decays.size(); ++i)
400 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
401 continue;
402 }
403
404 for (size_t i = 0; i < m_Decays.size(); ++i) {
405 double ttwid = m_Decays[i].ModifiedWidth(m_xlegpdyn[j]) * m_Width;
406 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
407 tCP[i] += m_wlegpdyn[j] * ttwid / twid * MassDistribution(m_xlegpdyn[j], twid);
408 }
409
410 tC += m_wlegpdyn[j] * MassDistribution(m_xlegpdyn[j], twid);
411 m_vallegpdyn[j] = MassDistribution(m_xlegpdyn[j], twid);
412 }
413
414 for (size_t j = 0; j < m_xlegdyn.size(); ++j) {
415 double twid = 0.;
416
417 for (size_t i = 0; i < m_Decays.size(); ++i) {
418 twid += m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
419 }
420
421 if (tsumb < 1.)
422 twid += (1. - tsumb) * m_Width;
423
424 if (twid == 0.0) {
425 m_vallegdyn[j] = 0.;
426 for (size_t i = 0; i < m_Decays.size(); ++i)
427 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
428 continue;
429 }
430
431 for (size_t i = 0; i < m_Decays.size(); ++i) {
432 double ttwid = m_Decays[i].ModifiedWidth(m_xlegdyn[j]) * m_Width;
433 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
434 tCP[i] += m_wlegdyn[j] * ttwid / twid * MassDistribution(m_xlegdyn[j], twid);
435 }
436
437 tC += m_wlegdyn[j] * MassDistribution(m_xlegdyn[j], twid);
438 m_vallegdyn[j] = MassDistribution(m_xlegdyn[j], twid);
439 }
440
441 for (size_t j = 0; j < m_xlagdyn.size(); ++j) {
442 double twid = 0.;
443 double tx = m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width;
444
445 for (size_t i = 0; i < m_Decays.size(); ++i) {
446 twid += m_Decays[i].ModifiedWidth(tx) * m_Width;
447 }
448
449 if (tsumb < 1.)
450 twid += (1. - tsumb) * m_Width;
451
452 if (twid == 0.0) {
453 m_vallagdyn[j] = 0.;
454 for (size_t i = 0; i < m_Decays.size(); ++i)
455 m_Decays[i].mBratioVsM.push_back(m_Decays[i].mBratio);
456 continue;
457 }
458
459 for (size_t i = 0; i < m_Decays.size(); ++i) {
460 double ttwid = m_Decays[i].ModifiedWidth(tx) * m_Width;
461 m_Decays[i].mBratioVsM.push_back(ttwid / twid);
462 tCP[i] += m_wlagdyn[j] * m_Width * ttwid / twid * MassDistribution(tx, twid);
463 }
464
465 tC += m_wlagdyn[j] * m_Width * MassDistribution(tx, twid);
466 m_vallagdyn[j] = m_Width * MassDistribution(tx, twid);
467 }
468
469 m_xalldyn.resize(0);
470 m_walldyn.resize(0);
471
472 for (size_t j = 0; j < m_xlegpdyn.size(); ++j) {
473 m_xalldyn.push_back(m_xlegpdyn[j]);
474 m_walldyn.push_back(m_wlegpdyn[j] * m_vallegpdyn[j] / tC);
475 }
476
477 for (size_t j = 0; j < m_xlegdyn.size(); ++j) {
478 m_xalldyn.push_back(m_xlegdyn[j]);
479 m_walldyn.push_back(m_wlegdyn[j] * m_vallegdyn[j] / tC);
480 }
481
482 for (size_t j = 0; j < m_xlagdyn.size(); ++j) {
483 m_xalldyn.push_back(m_Mass + 2.*m_Width + m_xlagdyn[j] * m_Width);
484 m_walldyn.push_back(m_wlagdyn[j] * m_vallagdyn[j] / tC);
485 }
486
487 m_densalldyn.resize(m_xalldyn.size());
488
489 double tsum = 0.;
490 for (size_t j = 0; j < m_walldyn.size(); ++j) {
491 tsum += m_walldyn[j];
492 }
493
494
495
496 }
497
498 double ThermalParticle::TotalWidtheBW(double M) const
499 {
500 //if (m_ResonanceWidthIntegrationType != eBW)
501 // return m_Width;
502 if (ZeroWidthEnforced()) {
503 return m_Width;
504 }
505
506 double tsumb = 0.0;
507 for (size_t i = 0; i < m_Decays.size(); ++i) {
508 tsumb += m_Decays[i].mBratio;
509 }
510
511 double twid = 0.0;
512 for (size_t i = 0; i < m_Decays.size(); ++i) {
513 twid += m_Decays[i].ModifiedWidth(M) * m_Width;
514 }
515
516 if (tsumb < 1.)
517 twid += (1. - tsumb) * m_Width;
518
519 return twid;
520 }
521
522 std::vector<double> ThermalParticle::BranchingRatiosM(double M, bool eBW) const
523 {
524 std::vector<double> ret(m_Decays.size(), 0.);
525
526 if (!eBW || ZeroWidthEnforced()) {
527 for (size_t i = 0; i < m_Decays.size(); ++i)
528 ret[i] = m_Decays[i].mBratio;
529
530 return ret;
531 }
532
533 double totwid = TotalWidtheBW(M);
534
535 for (size_t i = 0; i < m_Decays.size(); ++i) {
536 double partialwid = m_Decays[i].ModifiedWidth(M) * m_Width;
537 ret[i] = partialwid / totwid;
538 }
539
540 return ret;
541 }
542
543 double ThermalParticle::ThermalMassDistribution(double M, double T, double Mu, double width)
544 {
545 return IdealGasFunctions::IdealGasQuantity(IdealGasFunctions::ParticleDensity, m_QuantumStatisticsCalculationType, m_Statistics, T, Mu, M, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig) * MassDistribution(M, width);
546 }
547
548 double ThermalParticle::ThermalMassDistribution(double M, double T, double Mu)
549 {
550 return ThermalMassDistribution(M, T, Mu, TotalWidtheBW(M));
551 }
552
554 if (!enable) m_Statistics = 0;
555 else m_Statistics = m_StatisticsOrig;
556 }
557
558 void ThermalParticle::SetMass(double mass)
559 {
560 m_Mass = mass;
561 if (m_Width != 0.0) {
564 }
565 }
566
568 {
570 return BaryonCharge();
572 return ElectricCharge();
574 return Strangeness();
576 return Charm();
577 return 0;
578 }
579
581 return (m_Baryon == 0 && m_ElectricCharge == 0 && m_Strangeness == 0 && m_Charm == 0);
582 }
583
584
585 double ThermalParticle::Density(const ThermalModelParameters &params, IdealGasFunctions::Quantity type, bool useWidth, double mu) const {
586 if (m_GeneralizedDensity != NULL)
587 return m_GeneralizedDensity->Quantity(type, params.T, mu);
588
589 if (m_Degeneracy == 0.0)
590 return 0.0;
591
592 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * m_AbsQuark * params.T;
593 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
594 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
595
596 if (!useWidth || m_Mass == 0.0 || ZeroWidthEnforced() || m_ResonanceWidthIntegrationType == ZeroWidth) {
597 return IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_Mass, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
598 }
599
600 int ind = m_xleg.size();
601 const vector<double> &x = m_xleg, &w = m_wleg;
602 double ret1 = 0., ret2 = 0., tmp = 0.;
603
604 // Integration from m0 or M-2*Gamma to M+2*Gamma
605 if (m_ResonanceWidthIntegrationType != eBW && m_ResonanceWidthIntegrationType != eBWconstBR) {
606 for (int i = 0; i < ind; i++) {
607
608 tmp = w[i] * MassDistribution(x[i]);
609
610 if (m_ResonanceWidthIntegrationType == FullIntervalWeighted)
611 tmp *= m_brweight[i];
612 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, x[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
613
614 ret1 += tmp * dens;
615 ret2 += tmp;
616 }
617 }
618
619 // Integration from M+2*Gamma to infinity
620 if (m_ResonanceWidthIntegrationType == FullInterval || m_ResonanceWidthIntegrationType == FullIntervalWeighted) {
621 int ind2 = m_xlag32.size();
622 for (int i = 0; i < ind2; ++i) {
623 double tmass = m_Mass + 2.*m_Width + m_xlag32[i] * m_Width;
624 tmp = m_wlag32[i] * m_Width * MassDistribution(tmass);
625 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, tmass, m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
626
627 ret1 += tmp * dens;
628 ret2 += tmp;
629 }
630 }
631
632 if (m_ResonanceWidthIntegrationType == eBW || m_ResonanceWidthIntegrationType == eBWconstBR) {
633 for (size_t i = 0; i < m_xalldyn.size(); i++) {
634 tmp = m_walldyn[i];
635 double dens = IdealGasFunctions::IdealGasQuantity(type, m_QuantumStatisticsCalculationType, m_Statistics, params.T, mu, m_xalldyn[i], m_Degeneracy, m_ClusterExpansionOrder, m_IGFExtraConfig);
636 ret1 += tmp * dens;
637 ret2 += tmp;
638 }
639 }
640
641 return ret1 / ret2;
642 }
643
644 double ThermalParticle::DensityCluster(int n, const ThermalModelParameters & params, IdealGasFunctions::Quantity type, bool useWidth, double mu) const
645 {
646 double mn = 1.;
647 if ((abs(BaryonCharge()) & 1) && !(n & 1))
648 mn = -1.;
649
650 if (!(params.gammaq == 1.)) mu += log(params.gammaq) * m_AbsQuark /*GetAbsQ()*/ * params.T;
651 if (!(params.gammaS == 1. || m_AbsS == 0.)) mu += log(params.gammaS) * m_AbsS * params.T;
652 if (!(params.gammaC == 1. || m_AbsC == 0.)) mu += log(params.gammaC) * m_AbsC * params.T;
653
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:49
static bool DisclaimerPrinted
Definition Utility.h:28
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.