Thermal-FIST 1.6
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
ThermalParticleSystem.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 <algorithm>
12#include <queue>
13#include <iostream>
14#include <iomanip>
15#include <sstream>
16#include <set>
17#include <cmath>
18#include <cstdlib>
19
20#include "HRGBase/Utility.h"
22
23using namespace std;
24
25namespace thermalfist {
26
27 namespace {
29 bool cmpParticleMass(const ThermalParticle &a, const ThermalParticle &b) {
30 return (a.Mass() < b.Mass());
31 }
32
35 bool cmpParticleMassAndPdg(const ThermalParticle& a, const ThermalParticle& b) {
36 if (a.Mass() == b.Mass()) {
37 if (abs(a.PdgId()) != abs(b.PdgId()))
38 return abs(a.PdgId()) < abs(b.PdgId());
39 return (a.PdgId() > b.PdgId());
40 }
41 return (a.Mass() < b.Mass());
42 }
43
45 bool cmpParticlePDG(const ThermalParticle &a, const ThermalParticle &b) {
46 if (abs(a.Charm()) != abs(b.Charm())) return (abs(a.Charm()) < abs(b.Charm()));
47 if (abs(a.AbsoluteCharm()) != abs(b.AbsoluteCharm())) return (abs(a.AbsoluteCharm()) < abs(b.AbsoluteCharm()));
48 if (abs(a.BaryonCharge()) != abs(b.BaryonCharge())) return (abs(a.BaryonCharge()) < abs(b.BaryonCharge()));
49 if (abs(a.Strangeness()) != abs(b.Strangeness())) return (abs(a.Strangeness()) < abs(b.Strangeness()));
50 if (a.Mass() == b.Mass()) {
51 if (abs(a.PdgId()) != abs(b.PdgId()))
52 return abs(a.PdgId()) < abs(b.PdgId());
53 return (a.PdgId() > b.PdgId());
54 }
55 return (a.Mass() < b.Mass());
56 }
57 }
58
59 const std::string ThermalParticleSystem::flag_no_antiparticles = "no_antiparticles";
60 const std::string ThermalParticleSystem::flag_nostrangeness = "no_strangeness";
61 const std::string ThermalParticleSystem::flag_nocharm = "no_charm";
62 const std::string ThermalParticleSystem::flag_nonuclei = "no_nuclei";
63 const std::string ThermalParticleSystem::flag_noexcitednuclei = "no_excitednuclei";
64
65
66 ThermalParticleSystem::ThermalParticleSystem(const std::vector<std::string>& ListFiles, const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags, double mcut)
67 {
68 Initialize(ListFiles, DecayFiles, flags, mcut);
69 }
70
74
77 for (unsigned int i = 0; i < ret.size(); ++i) {
78 for (unsigned int j = 0; j < ret[i].mDaughters.size(); ++j) {
79 if (m_PDGtoID.count(-ret[i].mDaughters[j]) > 0) ret[i].mDaughters[j] = -ret[i].mDaughters[j];
80 }
81 }
82 return ret;
83 }
84
90
92 {
93 for (size_t i = 0; i < m_Particles.size(); ++i) {
94 if (m_Particles[i].Decays().size() != 0) {
95 double tsumb = 0.;
96
97 for (size_t j = 0; j < m_Particles[i].Decays().size(); ++j) {
98
99 m_Particles[i].Decays()[j].mPole = m_Particles[i].Mass();
100
101 std::string tname = "";
102
103 double M0 = 0.;
104 double tS = 0.;
105 for (size_t k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
106 int tid = PdgToId(m_Particles[i].Decays()[j].mDaughters[k]);
107 if (tid != -1) {
108 M0 += m_Particles[tid].Mass();
109 tS += max(0., (m_Particles[tid].Degeneracy() - 1.) / 2.);
110 if (k != 0)
111 tname += " - ";
112 tname += m_Particles[tid].Name();
113 }
114 }
115 m_Particles[i].Decays()[j].mM0 = M0;
116 m_Particles[i].Decays()[j].mL = abs(max(0., (m_Particles[i].Degeneracy() - 1.) / 2.) - tS);
117
118 tsumb += m_Particles[i].Decays()[j].mBratio;
119 m_Particles[i].Decays()[j].mBratioAverage = m_Particles[i].Decays()[j].mBratio;
120
121 if (tname.size() > 0)
122 m_Particles[i].Decays()[j].mChannelName = tname;
123 }
124 }
125 m_Particles[i].CalculateAndSetDynamicalThreshold();
126 m_Particles[i].FillCoefficientsDynamical();
127 }
128 }
129
131 {
132 for (size_t i = 0; i < m_Particles.size(); ++i) {
133 if (m_Particles[i].Decays().size() != 0) {
134 for (size_t j = 0; j < m_Particles[i].Decays().size(); ++j) {
135 double M0 = 0.;
136 for (size_t k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
137 if (PdgToId(m_Particles[i].Decays()[j].mDaughters[k]) != -1)
138 M0 += m_Particles[PdgToId(m_Particles[i].Decays()[j].mDaughters[k])].Mass();
139 }
140 m_Particles[i].Decays()[j].mM0 = M0;
141 }
142 m_Particles[i].FillCoefficients();
143 }
144 }
145 }
146
148 m_DecayContributionsByFeeddown[Feeddown::StabilityFlag].resize(m_Particles.size());
149 m_DecayCumulants.resize(m_Particles.size());
150 m_DecayProbabilities.resize(m_Particles.size());
151 for (size_t i = 0; i < m_Particles.size(); ++i) {
152 m_DecayContributionsByFeeddown[Feeddown::StabilityFlag][i].resize(0);
153 m_DecayProbabilities[i].resize(0);
154 m_DecayCumulants[i].resize(0);
155 }
156 for (int i = static_cast<int>(m_Particles.size()) - 1; i >= 0; i--)
157 if (!m_Particles[i].IsStable()) {
158 GoResonance(i, i, 1.);
159 }
160
161 for (size_t i = 0; i < m_Particles.size(); ++i) {
162 for (size_t j = 0; j < m_DecayContributionsByFeeddown[Feeddown::StabilityFlag][i].size(); ++j) {
163 SingleDecayContribution &DecayContrib = m_DecayContributionsByFeeddown[Feeddown::StabilityFlag][i][j];
164 vector<double> tmp = GoResonanceDecayProbs(DecayContrib.second, i, true);
165 if (tmp.size() > 1) m_DecayProbabilities[i].push_back(make_pair(tmp, DecayContrib.second));
166 }
167 for (size_t j = 0; j < m_DecayProbabilities[i].size(); ++j) {
168 double tmp = 0., tmp2 = 0., tmp3 = 0., tmp4 = 0.;
169 for (int jj = 0; jj < static_cast<int>(m_DecayProbabilities[i][j].first.size()); ++jj) {
170 tmp += m_DecayProbabilities[i][j].first[jj] * jj;
171 tmp2 += m_DecayProbabilities[i][j].first[jj] * jj * jj;
172 tmp3 += m_DecayProbabilities[i][j].first[jj] * jj * jj * jj;
173 tmp4 += m_DecayProbabilities[i][j].first[jj] * jj * jj * jj * jj;
174 }
175 double n2 = 0., n3 = 0., n4 = 0.;
176 n2 = tmp2 - tmp * tmp;
177 n3 = tmp3 - 3. * tmp2 * tmp + 2. * tmp * tmp * tmp;
178 n4 = tmp4 - 4. * tmp3 * tmp + 6. * tmp2 * tmp * tmp - 3. * tmp * tmp * tmp * tmp - 3. * n2 * n2;
179 vector<double> moments(0);
180 moments.push_back(tmp);
181 moments.push_back(n2);
182 moments.push_back(n3);
183 moments.push_back(n4);
184 m_DecayCumulants[i].push_back(make_pair(moments, m_DecayProbabilities[i][j].second));
185 }
186 }
187
188 m_DecayDistributionsMap.resize(m_Particles.size());
189 m_ResonanceFinalStatesDistributions.resize(m_Particles.size());
190 for (size_t i = 0; i < m_Particles.size(); ++i) {
191 m_ResonanceFinalStatesDistributions[i].resize(0);
192 m_DecayDistributionsMap[i].resize(0);
193 }
194 for (size_t i = 0; i < m_Particles.size(); ++i) {
195 m_ResonanceFinalStatesDistributions[i] = GoResonanceDecayDistributions(i, true);
196 }
197 // Clear m_DecayDistributionsMap and memory it occupies
198 std::vector< std::vector< std::pair<double, std::vector<int> > > >().swap(m_DecayDistributionsMap);
199
200 for (size_t i = 0; i < m_Particles.size(); ++i) {
201 vector<int> nchtyp(0);
202 nchtyp.push_back(0);
203 nchtyp.push_back(1);
204 nchtyp.push_back(-1);
205
206 m_Particles[i].Nch().resize(0);
207 m_Particles[i].DeltaNch().resize(0);
208
209 for (int nti = 0; nti < 3; nti++) {
210 vector<double> prob = GoResonanceDecayProbsCharge(i, nchtyp[nti], true);
211 double tmp = 0., tmp2 = 0., tmp3 = 0., tmp4 = 0.;
212 for (int jj = 0; jj < static_cast<int>(prob.size()); ++jj) {
213 tmp += prob[jj] * jj;
214 tmp2 += prob[jj] * jj * jj;
215 tmp3 += prob[jj] * jj * jj * jj;
216 tmp4 += prob[jj] * jj * jj * jj * jj;
217 }
218 double n2 = 0., n3 = 0., n4 = 0.;
219 n2 = tmp2 - tmp * tmp;
220 n3 = tmp3 - 3. * tmp2 * tmp + 2. * tmp * tmp * tmp;
221 n4 = tmp4 - 4. * tmp3 * tmp + 6. * tmp2 * tmp * tmp - 3. * tmp * tmp * tmp * tmp - 3. * n2 * n2;
222 m_Particles[i].Nch().push_back(tmp);
223 m_Particles[i].DeltaNch().push_back(n2);
224 }
225
226 }
227 }
228
229
230 void ThermalParticleSystem::GoResonance(int ind, int startind, double BR) {
231 DecayContributionsToParticle& DecayContrib = m_DecayContributionsByFeeddown[Feeddown::StabilityFlag][ind];
232 if (ind != startind && DecayContrib.size() > 0 && DecayContrib[DecayContrib.size() - 1].second == startind)
233 {
234 DecayContrib[DecayContrib.size() - 1].first += BR;
235 }
236 else if (ind != startind)
237 DecayContrib.push_back(make_pair(BR, startind));
238
239 if (!m_Particles[ind].IsStable()) {
240 for (size_t i = 0; i < m_Particles[ind].Decays().size(); ++i) {
241 const ParticleDecayChannel& decaychannel = m_Particles[ind].Decays()[i];
242 double tbr = decaychannel.mBratio;
243
244 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && ind == startind)
245 tbr = decaychannel.mBratioAverage;
246
247 for (size_t j = 0; j < decaychannel.mDaughters.size(); ++j) {
248 if (m_PDGtoID.count(decaychannel.mDaughters[j]) != 0)
249 GoResonance(m_PDGtoID[decaychannel.mDaughters[j]], startind, BR*tbr);
250 }
251 }
252 }
253 }
254
255 std::vector<double> ThermalParticleSystem::GoResonanceDecayProbs(int ind, int goalind, bool firstdecay) {
256 std::vector<double> ret(1, 0.);
257 if (m_Particles[ind].IsStable()) {
258 if (ind == goalind) ret.push_back(1.);
259 else ret[0] = 1.;
260 return ret;
261 }
262 else if (ind == goalind) {
263 ret.push_back(1.);
264 return ret;
265 }
266 else {
267 ret[0] = 0.;
268 vector<double> tret;
269 for (size_t i = 0; i < m_Particles[ind].Decays().size(); ++i) {
270 double tbr = m_Particles[ind].Decays()[i].mBratio;
271 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && firstdecay)
272 tbr = m_Particles[ind].Decays()[i].mBratioAverage;
273
274 tret.resize(1);
275 tret[0] = 1.;
276 for (size_t j = 0; j < m_Particles[ind].Decays()[i].mDaughters.size(); ++j) {
277 if (m_PDGtoID.count(m_Particles[ind].Decays()[i].mDaughters[j]) != 0) {
278 vector<double> tmp = GoResonanceDecayProbs(m_PDGtoID[m_Particles[ind].Decays()[i].mDaughters[j]], goalind);
279 vector<double> tmp2(tret.size() + tmp.size() - 1, 0.);
280 for (size_t i1 = 0; i1 < tret.size(); ++i1)
281 for (size_t i2 = 0; i2 < tmp.size(); ++i2)
282 tmp2[i1 + i2] += tret[i1] * tmp[i2];
283 tret = tmp2;
284 }
285 }
286 if (ret.size() < tret.size()) ret.resize(tret.size(), 0.);
287 for (size_t j = 0; j < tret.size(); ++j)
288 ret[j] += tbr * tret[j];
289 }
290 double totprob = 0.;
291 for (size_t i = 0; i < ret.size(); ++i)
292 totprob += ret[i];
293 if (totprob > 1.) {
294 for (size_t i = 0; i < ret.size(); ++i)
295 ret[i] *= 1. / totprob;
296 }
297 else {
298 ret[0] += 1. - totprob;
299 }
300 return ret;
301 }
302 //return ret;
303 }
304
305 std::vector<double> ThermalParticleSystem::GoResonanceDecayProbsCharge(int ind, int nch, bool firstdecay)
306 {
307 bool fl = false;
308 int tQ = m_Particles[ind].ElectricCharge();
309 if (nch == 0 && tQ != 0)
310 fl = true;
311 if (nch == 1 && tQ > 0)
312 fl = true;
313 if (nch == -1 && tQ < 0)
314 fl = true;
315
316 std::vector<double> ret(1, 0.);
317 if (m_Particles[ind].IsStable()) {
318 if (fl) ret.push_back(1.);
319 else ret[0] = 1.;
320 return ret;
321 }
322 else {
323 ret[0] = 0.;
324 vector<double> tret;
325 for (size_t i = 0; i < m_Particles[ind].Decays().size(); ++i) {
326 double tbr = m_Particles[ind].Decays()[i].mBratio;
327 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && firstdecay)
328 tbr = m_Particles[ind].Decays()[i].mBratioAverage;
329
330 tret.resize(1);
331 tret[0] = 1.;
332 for (size_t j = 0; j < m_Particles[ind].Decays()[i].mDaughters.size(); ++j) {
333 if (m_PDGtoID.count(m_Particles[ind].Decays()[i].mDaughters[j]) != 0) {
334 vector<double> tmp = GoResonanceDecayProbsCharge(m_PDGtoID[m_Particles[ind].Decays()[i].mDaughters[j]], nch);
335 vector<double> tmp2(tret.size() + tmp.size() - 1, 0.);
336 for (size_t i1 = 0; i1 < tret.size(); ++i1)
337 for (size_t i2 = 0; i2 < tmp.size(); ++i2)
338 tmp2[i1 + i2] += tret[i1] * tmp[i2];
339 tret = tmp2;
340 }
341 }
342 if (ret.size() < tret.size())
343 ret.resize(tret.size(), 0.);
344 for (size_t j = 0; j < tret.size(); ++j)
345 ret[j] += tbr * tret[j];
346 }
347 double totprob = 0.;
348 for (size_t i = 0; i < ret.size(); ++i)
349 totprob += ret[i];
350 if (totprob > 1.) {
351 for (size_t i = 0; i < ret.size(); ++i)
352 ret[i] *= 1. / totprob;
353 }
354 else {
355 ret[0] += 1. - totprob;
356 }
357 return ret;
358 }
359 //return ret;
360 }
361
362 ThermalParticleSystem::ResonanceFinalStatesDistribution ThermalParticleSystem::GoResonanceDecayDistributions(int ind, bool firstdecay)
363 {
364 if (!firstdecay && m_DecayDistributionsMap[ind].size() != 0)
365 return m_DecayDistributionsMap[ind];
366
367
368 std::vector< std::pair<double, std::vector<int> > > retorig(1);
369 retorig[0].first = 1.;
370 retorig[0].second = std::vector<int>(m_Particles.size(), 0);
371 retorig[0].second[ind] = 1;
372
373 std::vector< std::pair<double, std::vector<int> > > ret(0);
374
375 ThermalParticle &tpart = m_Particles[ind];
376
377 if (tpart.IsStable()) {
378 m_ResonanceFinalStatesDistributions[ind] = retorig;
379 return retorig;
380 }
381
382 bool wasCut = false;
383
384 for (size_t i = 0; i < tpart.Decays().size(); ++i) {
385 double tbr = tpart.Decays()[i].mBratio;
386 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && firstdecay)
387 tbr = m_Particles[ind].Decays()[i].mBratioAverage;
388
389 std::vector< std::pair<double, std::vector<int> > > tret = retorig;
390
391 for (size_t j = 0; j < tpart.Decays()[i].mDaughters.size(); ++j) {
392 if (m_PDGtoID.count(tpart.Decays()[i].mDaughters[j]) != 0) {
393
394 std::vector< std::pair<double, std::vector<int> > > tmp = GoResonanceDecayDistributions(m_PDGtoID[tpart.Decays()[i].mDaughters[j]]);
395 std::vector< std::pair<double, std::vector<int> > > tmp2(tret.size() * tmp.size());
396 for (int i1 = 0; i1 < static_cast<int>(tret.size()); ++i1) {
397 for (int i2 = 0; i2 < static_cast<int>(tmp.size()); ++i2) {
398 tmp2[i1*tmp.size() + i2].first = tret[i1].first * tmp[i2].first;
399 tmp2[i1*tmp.size() + i2].second.resize(m_Particles.size());
400 for (size_t jj = 0; jj < tmp2[i1*tmp.size() + i2].second.size(); ++jj)
401 tmp2[i1*tmp.size() + i2].second[jj] = tret[i1].second[jj] + tmp[i2].second[jj];
402 }
403 }
404 tret = tmp2;
405
406 // Restrict maximum number of channels to avoid memory issues
407 if (static_cast<int>(tret.size()) > m_MaxDecayDistributionsSize) {
408 wasCut = true;
409 CuteHRGHelper::cutDecayDistributionsVector(tret, m_MaxDecayDistributionsSize);
410 }
411 }
412 }
413
414 for (size_t j = 0; j < tret.size(); ++j) {
415 tret[j].first *= tbr;
416 ret.push_back(tret[j]);
417 }
418 }
419
420 // Restrict maximum number of channels to avoid memory issues
421 if (static_cast<int>(ret.size()) > m_MaxDecayDistributionsSize) {
422 wasCut = true;
423 CuteHRGHelper::cutDecayDistributionsVector(ret, m_MaxDecayDistributionsSize);
424 }
425
426 if (wasCut && firstdecay) {
427 printf("**WARNING** %s (%lld) Decay Distributions: Too large array, cutting the number of channels to %d\n",
428 m_Particles[ind].Name().c_str(),
429 m_Particles[ind].PdgId(),
430 m_MaxDecayDistributionsSize);
431 }
432
433 double totprob = 0.;
434 for (size_t i = 0; i < ret.size(); ++i)
435 totprob += ret[i].first;
436 if (totprob > 1.) {
437 for (size_t i = 0; i < ret.size(); ++i)
438 ret[i].first *= 1. / totprob;
439 }
440 else if (totprob < 1.) {
441 double emptyprob = 1. - totprob;
442 ret.push_back(std::make_pair(emptyprob, retorig[0].second));
443 }
444
445 if (!firstdecay)
446 m_DecayDistributionsMap[ind] = ret;
447
448 // Debugging
449
450 //if (tpart.BaryonCharge() == 1) {
451 // printf("Checking baryon number conservation in decays for %d\n", tpart.PdgId());
452 // double tBav = 0.;
453 // for (int i = 0; i < ret.size(); ++i) {
454 // double tbr = ret[i].first;
455 // for (int j = 0; j < ret[i].second.size(); ++j)
456 // if (m_Particles[j].IsStable())
457 // tBav += tbr * ret[i].second[j] * m_Particles[j].BaryonCharge();
458 // }
459 // printf("<B> = %lf\n", tBav);
460 // //printf("Decay distributions for %d\n", tpart.PdgId());
461 // //for (int i = 0; i < ret.size(); ++i) {
462 // // printf("%lf\n", ret[i].first);
463 // // for (int j = 0; j < ret[i].second.size(); ++j)
464 // // if (ret[i].second[j] > 0)
465 // // printf("%d: %d\n", m_Particles[j].PdgId(), ret[i].second[j]);
466 // //}
467 //}
468
469 return ret;
470 }
471
472 bool ThermalParticleSystem::AcceptParticle(const ThermalParticle& part, const std::set<std::string>& flags, double mcut) const
473 {
474 if (mcut >= 0. && part.Mass() > mcut)
475 return false;
476 if (flags.count(ThermalParticleSystem::flag_nostrangeness) > 0 && part.AbsoluteStrangeness() != 0)
477 return false;
478 if (flags.count(ThermalParticleSystem::flag_nocharm) > 0 && part.AbsoluteCharm() != 0)
479 return false;
480 if (flags.count(ThermalParticleSystem::flag_nonuclei) > 0 && abs(part.BaryonCharge()) > 1)
481 return false;
482 if (flags.count(ThermalParticleSystem::flag_noexcitednuclei) > 0 && abs(part.BaryonCharge()) > 1 && !part.IsStable())
483 return false;
484 return true;
485 }
486
487 void ThermalParticleSystem::LoadList(const std::vector<std::string>& ListFiles, const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags, double mcut)
488 {
489 m_NumberOfParticles = 0;
490 m_Particles.resize(0);
491 m_PDGtoID.clear();
492
493 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
494 m_MaxAbsBaryonNumber = 0;
495
496 if (ListFiles.size() == 1 && CheckListIsiSS(ListFiles[0])) {
497 LoadListiSS(ListFiles[0], flags, mcut);
498 return;
499 }
500
501 for(int i = 0; i < ListFiles.size(); ++i)
502 AddParticlesToListFromFile(ListFiles[i], flags, mcut);
503
504 FinalizeList();
505
506 std::vector<std::string> tDecayFiles = DecayFiles;
507 if (tDecayFiles.size() == 1 && tDecayFiles[0] == "")
508 tDecayFiles.clear();
509
510 if (tDecayFiles.size() == 0 && ListFiles.size() > 0) {
511 for (size_t ilist = 0; ilist < ListFiles.size(); ++ilist) {
512 string decayprefix = "";
513 string decayprefixfile = "";
514
515 for (int i = ListFiles[ilist].size() - 1; i >= 0; --i) {
516 if (ListFiles[ilist][i] == '\\' || ListFiles[ilist][i] == '/')
517 {
518 decayprefix = ListFiles[ilist].substr(0, i + 1);
519 break;
520 }
521 decayprefixfile += ListFiles[ilist][i];
522 }
523
524 reverse(decayprefixfile.begin(), decayprefixfile.end());
525
526
527 string DecayFile = "";
528 if (decayprefixfile.substr(0, 4) == "list") {
529 DecayFile = decayprefix + "decays" + decayprefixfile.substr(4);
530 }
531 else {
532 DecayFile = decayprefix + "decays.dat";
533 }
534
535 if (ilist == 0)
536 tDecayFiles.push_back(decayprefix + "decays.dat");
537
538 tDecayFiles.push_back(DecayFile);
539 }
540 }
541
542 LoadDecays(tDecayFiles, flags);
543
544 FinalizeListLoad();
545 }
546
547 void ThermalParticleSystem::LoadList(const std::string& InputFile, const std::string& DecayFile, bool GenAntiP, double mcut) {
548
549 std::set<std::string> flags;
550 if (!GenAntiP)
552
553 std::vector<std::string> DecayFiles(0);
554 if (DecayFile != "")
555 DecayFiles.push_back(DecayFile);
556
557 LoadList(std::vector<std::string>(1, InputFile), DecayFiles, flags, mcut);
558 }
559
560 void ThermalParticleSystem::AddParticlesToListFromFile(const std::string& InputFile, const std::set<std::string>& flags, double mcut)
561 {
562 ifstream fin;
563 fin.open(InputFile.c_str());
564 if (fin.is_open()) {
565
566 char tmpc[2000];
567 fin.getline(tmpc, 2000);
568 string tmp = string(tmpc);
569 vector<string> elems = CuteHRGHelper::split(tmp, '#');
570
571 int flnew = 0;
572 if (elems.size() < 1 || CuteHRGHelper::split(elems[0], ';').size() < 4)
573 flnew = 1;
574 else
575 flnew = 0;
576
577 fin.clear();
578 fin.seekg(0, ios::beg);
579
580 if (flnew == 1)
581 LoadTable_NewFormat(fin, flags, mcut);
582 else
583 LoadTable_OldFormat(fin, flags, mcut);
584
585 fin.close();
586
587 }
588 }
589
590 void ThermalParticleSystem::LoadTable_OldFormat(std::ifstream & fin, const std::set<std::string>& flags, double mcut)
591 {
592 bool GenerateAntiParticles = (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0);
593 if (fin.is_open()) {
594 string tmp;
595 char tmpc[500];
596 fin.getline(tmpc, 500);
597 tmp = string(tmpc);
598 while (1) {
599 vector<string> fields = CuteHRGHelper::split(tmp, ';');
600 if (fields.size() < 14) break;
601 int stable, spin, stat, str, bary, chg, charm;
602 long long pdgid;
603 double mass, width, threshold, abss, absc, radius = 0.5;
604 string name, decayname = "";
605 stable = atoi(fields[0].c_str());
606 name = fields[1];
607 //pdgid = atoi(fields[2].c_str());
608 pdgid = stringToLongLong(fields[2]);
609 spin = atoi(fields[3].c_str());
610 stat = atoi(fields[4].c_str());
611 mass = atof(fields[5].c_str());
612 str = atoi(fields[6].c_str());
613 bary = atoi(fields[7].c_str());
614 chg = atoi(fields[8].c_str());
615 charm = atoi(fields[9].c_str());
616 abss = atof(fields[10].c_str());
617 absc = atof(fields[11].c_str());
618 width = atof(fields[12].c_str());
619 threshold = atof(fields[13].c_str());
620 if (fields.size() >= 15) radius = atof(fields[14].c_str());
621 if (fields.size() == 16) decayname = fields[15];
622
623 ThermalParticle part_candidate = ThermalParticle(static_cast<bool>(stable), name, pdgid, static_cast<double>(spin), stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
624
625 //if (mcut >= 0. && mass > mcut) {
626 if (m_PDGtoID.count(pdgid) != 0) {
627 throw std::invalid_argument("ThermalParticleSystem::LoadTable_NewFormat: Duplicate pdg code " + std::to_string(pdgid));
628 }
629 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0) {
630 fin.getline(tmpc, 500);
631 tmp = string(tmpc);
632 continue;
633 }
634
635 if (bary != 0) m_NumBaryons++;
636 if (chg != 0) m_NumCharged++;
637 if (str != 0) m_NumStrange++;
638 if (charm != 0) m_NumCharmed++;
639 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
640
641 m_Particles.push_back(part_candidate);
642 m_PDGtoID[pdgid] = m_Particles.size() - 1;
643 m_NumberOfParticles++;
644
645 if (GenerateAntiParticles && !(bary == 0 && chg == 0 && str == 0 && charm == 0) && (m_PDGtoID.count(-pdgid) == 0)) {
646
647 if (bary != 0) m_NumBaryons++;
648 if (chg != 0) m_NumCharged++;
649 if (str != 0) m_NumStrange++;
650 if (charm != 0) m_NumCharmed++;
651
652 if (bary == 0 && name[name.size() - 1] == '+')
653 name[name.size() - 1] = '-';
654 else if (bary == 0 && name[name.size() - 1] == '-')
655 name[name.size() - 1] = '+';
656 else
657 name = "anti-" + name;
658 m_Particles.push_back(ThermalParticle(static_cast<bool>(stable), name, -pdgid, static_cast<double>(spin), stat, mass, -str, -bary, -chg, abss, width, threshold, -charm, absc));
659 m_Particles[m_Particles.size() - 1].SetAntiParticle(true);
660 m_PDGtoID[-pdgid] = m_Particles.size() - 1;
661 }
662
663 fin.getline(tmpc, 500);
664 tmp = string(tmpc);
665 }
666 }
667 }
668
669 void ThermalParticleSystem::LoadTable_NewFormat(std::ifstream & fin, const std::set<std::string>& flags, double mcut)
670 {
671 bool GenerateAntiParticles = (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0);
672 if (fin.is_open()) {
673 char cc[2000];
674 while (!fin.eof()) {
675 fin.getline(cc, 2000);
676 string tmp = string(cc);
677 vector<string> elems = CuteHRGHelper::split(tmp, '#');
678 if (elems.size() < 1 || elems[0].size() == 0)
679 continue;
680
681 istringstream iss(elems[0]);
682
683 int stable, stat, str, bary, chg, charm;
684 long long pdgid;
685 double mass, degeneracy, width, threshold, abss, absc;
686 string name;
687
688 if (iss >> pdgid
689 >> name
690 >> stable
691 >> mass
692 >> degeneracy
693 >> stat
694 >> bary
695 >> chg
696 >> str
697 >> charm
698 >> abss
699 >> absc
700 >> width
701 >> threshold) {
702
703 ThermalParticle part_candidate = ThermalParticle((bool)stable, name, pdgid, degeneracy, stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
704
705 //if (mcut >= 0. && mass > mcut)
706 if (m_PDGtoID.count(pdgid) != 0) {
707 throw std::invalid_argument("ThermalParticleSystem::LoadTable_NewFormat: Duplicate pdg code " + std::to_string(pdgid));
708 }
709
710 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0)
711 continue;
712
713 if (bary != 0) m_NumBaryons++;
714 if (chg != 0) m_NumCharged++;
715 if (str != 0) m_NumStrange++;
716 if (charm != 0) m_NumCharmed++;
717 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
718
719 m_Particles.push_back(part_candidate);
720 m_PDGtoID[pdgid] = m_Particles.size() - 1;
721 m_NumberOfParticles++;
722
723 if (GenerateAntiParticles && !(bary == 0 && chg == 0 && str == 0 && charm == 0) && (m_PDGtoID.count(-pdgid) == 0)) {
724
725 if (bary != 0) m_NumBaryons++;
726 if (chg != 0) m_NumCharged++;
727 if (str != 0) m_NumStrange++;
728 if (charm != 0) m_NumCharmed++;
729
730 if (bary == 0 && name[name.size() - 1] == '+')
731 name[name.size() - 1] = '-';
732 else if (bary == 0 && name[name.size() - 1] == '-')
733 name[name.size() - 1] = '+';
734 else
735 name = "anti-" + name;
736 m_Particles.push_back(ThermalParticle((bool)stable, name, -pdgid, degeneracy, stat, mass, -str, -bary, -chg, abss, width, threshold, -charm, absc));
737 m_Particles[m_Particles.size() - 1].SetAntiParticle(true);
738 m_PDGtoID[pdgid] = m_Particles.size() - 1;
739 }
740 }
741 }
742 }
743 }
744
745 void ThermalParticleSystem::SetTableFromVector(const std::vector<ThermalParticle>& part_in, bool GenerateAntiParticles)
746 {
747 m_Particles.resize(0);
748
749 for (size_t i = 0; i < part_in.size(); ++i) {
750 const ThermalParticle &part = part_in[i];
751 if (!GenerateAntiParticles) {
752 m_Particles.push_back(part);
753 }
754 else if (part.PdgId() > 0) {
755 m_Particles.push_back(part);
756
757 if (!part.IsNeutral()) {
758 m_Particles.push_back(part.GenerateAntiParticle());
759 }
760 }
761 }
762
763 FinalizeList();
764
765 if (GenerateAntiParticles) {
766 for (size_t i = 0; i < m_Particles.size(); ++i) {
767 if (m_Particles[i].IsAntiParticle() && PdgToId(-m_Particles[i].PdgId()) != -1) {
768 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[PdgToId(-m_Particles[i].PdgId())].Decays()));
769 }
770 }
771 }
772
773 FinalizeDecaysLoad();
774
778 }
779
780 void ThermalParticleSystem::WriteTableToFile(const std::string& OutputFile, bool WriteAntiParticles)
781 {
782 std::ofstream fout(OutputFile.c_str());
783 if (fout.is_open()) {
784 fout << "#"
785 << std::setw(14) << "pdgid"
786 << std::setw(20) << "name"
787 << std::setw(15) << "stable"
788 << std::setw(15) << "mass[GeV]"
789 << std::setw(15) << "degeneracy"
790 << std::setw(15) << "statistics"
791 << std::setw(15) << "B"
792 << std::setw(15) << "Q"
793 << std::setw(15) << "S"
794 << std::setw(15) << "C"
795 << std::setw(15) << "|S|"
796 << std::setw(15) << "|C|"
797 << std::setw(15) << "width[GeV]"
798 << std::setw(15) << "threshold[GeV]"
799 << std::endl;
800
801 for (size_t i = 0; i < m_Particles.size(); ++i) {
802 const ThermalParticle& part = m_Particles[i];
803 if (part.PdgId() < 0 && !WriteAntiParticles)
804 continue;
805
806 fout << std::setw(15) << part.PdgId()
807 << std::setw(20) << part.Name()
808 << std::setw(15) << static_cast<int>(part.IsStable())
809 << std::setw(15) << part.Mass()
810 << std::setw(15) << part.Degeneracy()
811 << std::setw(15) << part.Statistics()
812 << std::setw(15) << part.BaryonCharge()
813 << std::setw(15) << part.ElectricCharge()
814 << std::setw(15) << part.Strangeness()
815 << std::setw(15) << part.Charm()
816 << std::setw(15) << part.AbsoluteStrangeness()
817 << std::setw(15) << part.AbsoluteCharm()
818 << std::setw(15) << part.ResonanceWidth()
819 << std::setw(15) << part.DecayThresholdMass()
820 << std::endl;
821 }
822 fout.close();
823 }
824 }
825
826 void ThermalParticleSystem::LoadDecays(const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags)
827 {
828 for (size_t i = 0; i < m_Particles.size(); ++i)
829 m_Particles[i].ClearDecays();
830
831 for (size_t i = 0; i < DecayFiles.size(); ++i) {
832 ifstream fin(DecayFiles[i].c_str());
833
834 if (fin.is_open()) {
835
836 char tmpc[2000];
837 fin.getline(tmpc, 2000);
838 string tmp = string(tmpc);
839 vector<string> elems = CuteHRGHelper::split(tmp, '#');
840
841 int flnew = 0;
842 if (tmp.size() == 0 || elems.size() >= 2)
843 flnew = 1;
844 else
845 flnew = 0;
846
847 fin.clear();
848 fin.seekg(0, ios::beg);
849
850 if (flnew == 1)
851 ReadDecays_NewFormat(fin);
852 else
853 ReadDecays_OldFormat(fin);
854
855 fin.close();
856
857 }
858
859 }
860
861 if (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0) {
862 for (size_t i = 0; i < m_Particles.size(); ++i) {
863 if (m_Particles[i].PdgId() < 0)
864 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[m_PDGtoID[-m_Particles[i].PdgId()]].Decays()));
865 }
866 }
867
868 FinalizeDecaysLoad();
869 }
870
871 void ThermalParticleSystem::LoadDecays(const std::string& DecaysFile, bool GenerateAntiParticles)
872 {
873 std::set<std::string> flags;
874 if (!GenerateAntiParticles)
876
877 LoadDecays(vector<string>(1, DecaysFile), flags);
878 }
879
880 void ThermalParticleSystem::ReadDecays_NewFormat(std::ifstream & fin)
881 {
882 vector< ThermalParticle::ParticleDecaysVector > decays(0);
883 map<long long, int> decaymap;
884 decaymap.clear();
885
886
887 if (fin.is_open()) {
888 char cc[2000];
889 int index = 0;
890 while (!fin.eof()) {
891 fin.getline(cc, 2000);
892 string tmp = string(cc);
893 vector<string> elems = CuteHRGHelper::split(tmp, '#');
894 if (elems.size() < 1 || elems[0].size() == 0)
895 continue;
896
897 int tdecaysnumber = 0;
898 long long tpdgid = 0;
900
901 istringstream iss(elems[0]);
902 if (!(iss >> tpdgid)) continue;
903
904 {
905 bool fl = false;
906 while (!fl) {
907 if (fin.eof()) break;
908 fin.getline(cc, 500);
909 tmp = string(cc);
910 elems = CuteHRGHelper::split(tmp, '#');
911 if (elems.size() < 1 || elems[0].size() == 0)
912 continue;
913
914 istringstream isstnum(elems[0]);
915 if (!(isstnum >> tdecaysnumber)) {
916 tdecaysnumber = 0;
917 continue;
918 }
919 fl = true;
920 }
921 }
922
923 for (int i = 0; i < tdecaysnumber; ++i) {
924 bool fl = false;
925 while (!fl) {
926 if (fin.eof()) break;
927 fin.getline(cc, 500);
928 tmp = string(cc);
929 elems = CuteHRGHelper::split(tmp, '#');
930 if (elems.size() < 1 || elems[0].size() == 0)
931 continue;
932
933 ParticleDecayChannel tdecay;
934 istringstream issdec(elems[0]);
935 if (!(issdec >> tdecay.mBratio)) continue;
936 long long tmpid;
937 while (issdec >> tmpid) {
938 tdecay.mDaughters.push_back(tmpid);
939 }
940 tdecays.push_back(tdecay);
941 fl = true;
942 }
943 }
944
945 if (static_cast<int>(tdecays.size()) == tdecaysnumber && static_cast<int>(tdecays.size()) != 0) {
946 decays.push_back(tdecays);
947 decaymap[tpdgid] = index;
948 index++;
949 }
950 }
951
952 for (size_t i = 0; i < m_Particles.size(); ++i) {
953 if (decaymap.count(m_Particles[i].PdgId()) != 0)
954 m_Particles[i].SetDecays(decays[decaymap[m_Particles[i].PdgId()]]);
955 }
956 }
957 }
958
959 void ThermalParticleSystem::Initialize(const std::vector<std::string>& ListFiles, const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags, double mcut)
960 {
963
964 m_NumberOfParticles = 0;
965 m_Particles.resize(0);
966 m_PDGtoID.clear();
967 m_ResonanceWidthShape = ThermalParticle::RelativisticBreitWigner;
968 m_ResonanceWidthIntegrationType = ThermalParticle::ZeroWidth;
969
971
972 m_MaxDecayDistributionsSize = 8000;
973
974 m_DecayContributionsByFeeddown.resize(Feeddown::NumberOfTypes);
975
979
980 LoadList(ListFiles, DecayFiles, flags, mcut);
981 }
982
983 void ThermalParticleSystem::Initialize(const std::string& InputFile, const std::string& DecayFile, bool GenAntiP, double mcut)
984 {
985 std::set<std::string> flags;
986 if (!GenAntiP)
988 Initialize(vector<string>(1, InputFile), vector<string>(1, DecayFile), flags, mcut);
989 }
990
991 void ThermalParticleSystem::FinalizeListLoad()
992 {
993 SetResonanceWidthShape(m_ResonanceWidthShape);
994 SetResonanceWidthIntegrationType(m_ResonanceWidthIntegrationType);
995 SetCalculationType(m_QStatsCalculationType);
996
999 }
1000
1001 void ThermalParticleSystem::FinalizeDecaysLoad()
1002 {
1003 for (size_t i = 0; i < m_Particles.size(); ++i)
1004 m_Particles[i].SetDecaysOriginal(m_Particles[i].Decays());
1005
1008 ProcessDecays();
1009 }
1010
1011 bool ThermalParticleSystem::CheckListIsiSS(const std::string& filename)
1012 {
1013 ifstream fin(filename.c_str());
1014 if (fin.is_open()) {
1015 string tmp;
1016 fin >> tmp;
1017 return (tmp == "iSS");
1018 }
1019 return false;
1020 }
1021
1022 void ThermalParticleSystem::LoadListiSS(const std::string& filename, const std::set<std::string>& flags, double mcut)
1023 {
1024 m_NumberOfParticles = 0;
1025 m_Particles.resize(0);
1026 m_PDGtoID.clear();
1027
1028 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
1029 m_MaxAbsBaryonNumber = 0;
1030
1031 ifstream fin(filename.c_str());
1032
1033 if (fin.is_open()) {
1034 char cc[2000];
1035 // Skip the header line
1036 fin.getline(cc, 2000);
1037 // Read all the particles
1038 while (!fin.eof()) {
1039 fin.getline(cc, 2000);
1040 string tmp = string(cc);
1041 vector<string> elems = CuteHRGHelper::split(tmp, '#');
1042 if (elems.size() < 1 || elems[0].size() == 0)
1043 continue;
1044
1045 istringstream iss(elems[0]);
1046
1047 int stable, stat, str, bary, chg, charm, itmp, tdecaynumber;
1048 long long pdgid, ltmp;
1049 double mass, degeneracy, width, threshold, abss, absc;
1050 string name;
1051
1052 if (iss >> pdgid
1053 >> name
1054 >> mass
1055 >> width
1056 >> degeneracy
1057 >> bary
1058 >> str
1059 >> charm
1060 >> itmp
1061 >> itmp
1062 >> chg
1063 >> tdecaynumber
1064 ) {
1065
1066 stable = 0;
1067 abss = std::abs(str);
1068 if (pdgid == 333)
1069 abss = 2.;
1070 absc = std::abs(charm);
1071 threshold = 0.;
1072 stat = (std::abs(bary) % 2 == 0 ? -1 : 1);
1073
1074 ThermalParticle part_candidate = ThermalParticle(
1075 (bool)stable, name, pdgid, degeneracy, stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
1076
1077 if (pdgid < 0)
1078 part_candidate.SetAntiParticle(true);
1079
1080 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0)
1081 continue;
1082
1083 if (bary != 0) m_NumBaryons++;
1084 if (chg != 0) m_NumCharged++;
1085 if (str != 0) m_NumStrange++;
1086 if (charm != 0) m_NumCharmed++;
1087 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
1088
1089 m_Particles.push_back(part_candidate);
1090 m_PDGtoID[pdgid] = m_Particles.size() - 1;
1091 m_NumberOfParticles++;
1092
1093 // now read the decays
1095 for (size_t idec = 0; idec < tdecaynumber; ++idec) {
1096 fin.getline(cc, 2000);
1097 string tmp = string(cc);
1098 elems = CuteHRGHelper::split(tmp, '#');
1099 istringstream issdec(elems[0]);
1100
1101 ParticleDecayChannel tdecay;
1102 issdec >> ltmp;
1103 int ndecayparticles;
1104 double BR;
1105 issdec >> ndecayparticles >> tdecay.mBratio;
1106 for (size_t idaughter = 0; idaughter < 5; ++idaughter) {
1107 issdec >> ltmp;
1108 if (idaughter < ndecayparticles)
1109 tdecay.mDaughters.push_back(ltmp);
1110 }
1111 tdecays.push_back(tdecay);
1112 }
1113
1114 if (static_cast<int>(tdecays.size()) == tdecaynumber
1115 && static_cast<int>(tdecays.size()) != 0
1116 && tdecays[0].mDaughters.size() != 1) {
1117 m_Particles.back().SetDecays(tdecays);
1118 }
1119 else {
1120 stable = 1;
1121 m_Particles.back().SetStable(true);
1122 }
1123
1124 // Add antibaryon
1125 if (bary > 0 && (m_PDGtoID.count(-pdgid) == 0)) {
1126
1127 if (bary != 0) m_NumBaryons++;
1128 if (chg != 0) m_NumCharged++;
1129 if (str != 0) m_NumStrange++;
1130 if (charm != 0) m_NumCharmed++;
1131
1132 if (bary == 0 && name[name.size() - 1] == '+')
1133 name[name.size() - 1] = '-';
1134 else if (bary == 0 && name[name.size() - 1] == '-')
1135 name[name.size() - 1] = '+';
1136 else
1137 name = "anti-" + name;
1138 m_Particles.push_back(ThermalParticle((bool)stable, name, -pdgid, degeneracy, stat, mass, -str, -bary, -chg, abss, width, threshold, -charm, absc));
1139 m_Particles.back().SetAntiParticle(true);
1140 m_PDGtoID[pdgid] = m_Particles.size() - 1;
1141 }
1142
1143 }
1144 }
1145
1146 FinalizeList();
1147
1148 for (size_t i = 0; i < m_Particles.size(); ++i) {
1149 if (m_Particles[i].BaryonCharge() < 0)
1150 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[m_PDGtoID[-m_Particles[i].PdgId()]].Decays()));
1151 }
1152
1153 FinalizeDecaysLoad();
1154
1155 FinalizeListLoad();
1156 }
1157 }
1158
1159 void ThermalParticleSystem::WriteDecaysToFile(const std::string& OutputFile, bool WriteAntiParticles)
1160 {
1161 std::ofstream fout(OutputFile.c_str());
1162 if (fout.is_open()) {
1163 fout << "# the list of decays" << std::endl;
1164 fout << "# each entry consists of the following:" << std::endl;
1165 fout << "# a line with the pdgid of decaying particle" << std::endl;
1166 fout << "# a line with the number of decay channels" << std::endl;
1167 fout << "# for each channel a line containing whitespace-separated values of the channel branching ratio and pdg ids of the daughter products" << std::endl;
1168 fout << "# everything after the # symbol is treated as a comment and ignored" << std::endl;
1169 fout << "# decays of antiparticles are not listed but generated from the listed decays of particles" << std::endl;
1170 fout << std::endl;
1171
1172 for (unsigned int i = 0; i < m_Particles.size(); ++i) {
1173 if ((m_Particles[i].PdgId()>0 || WriteAntiParticles) && m_Particles[i].Decays().size()>0) {
1174 fout << std::left << std::setw(36) << m_Particles[i].PdgId();
1175 fout << " # " << m_Particles[i].Name() << std::endl;
1176
1177 fout << std::left << std::setw(36) << m_Particles[i].Decays().size();
1178 fout << " # " << m_Particles[i].Decays().size() << " decay channel";
1179 if (m_Particles[i].Decays().size() % 10 != 1 || m_Particles[i].Decays().size() % 100 == 11) fout << "s";
1180 fout << std::endl;
1181
1182 for (unsigned int j = 0; j < m_Particles[i].Decays().size(); ++j) {
1183 fout << std::left << std::setw(15) << m_Particles[i].Decays()[j].mBratio << " ";
1184 std::ostringstream oss;
1185 for (unsigned int k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
1186 oss << m_Particles[i].Decays()[j].mDaughters[k];
1187 if (k != m_Particles[i].Decays()[j].mDaughters.size() - 1)
1188 oss << " ";
1189 }
1190 fout << std::left << std::setw(20) << oss.str();
1191 fout << " # " << m_Particles[i].Name() << " -> ";
1192 for (unsigned int k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
1193 if (m_PDGtoID.count(m_Particles[i].Decays()[j].mDaughters[k]) == 0) {
1194 //if (m_Particles[i].Decays()[j].mDaughters[k] == 22) fout << "?gamma?";
1195 long long tpdg = m_Particles[i].Decays()[j].mDaughters[k];
1196 if (ExtraParticles::PdgToId(tpdg) != -1)
1197 fout << ExtraParticles::ParticleByPdg(tpdg).Name();
1198 else fout << "???";
1199 }
1200 else
1201 fout << m_Particles[m_PDGtoID[m_Particles[i].Decays()[j].mDaughters[k]]].Name();
1202 if (k != m_Particles[i].Decays()[j].mDaughters.size() - 1)
1203 fout << " + ";
1204 }
1205 fout << std::endl;
1206 }
1207 fout << std::endl;
1208 }
1209 }
1210
1211 fout.close();
1212 }
1213 }
1214
1215 void ThermalParticleSystem::ReadDecays_OldFormat(std::ifstream & fin)
1216 {
1217 vector< ThermalParticle::ParticleDecaysVector > decays(0);
1218 vector<long long> pdgids(0);
1219 map<long long, int> decaymap;
1220 decaymap.clear();
1221
1222 if (fin.is_open()) {
1223 int decaypartnumber = 0;
1224 fin >> decaypartnumber;
1225 decays.reserve(decaypartnumber);
1226
1227 for (int i = 0; i < decaypartnumber; ++i) {
1228 int decaysnumber, daughters;
1229 long long pdgid, tmpid;
1230 double bratio;
1231 fin >> pdgid >> decaysnumber;
1232 decaymap[pdgid] = i;
1233 decays.push_back(ThermalParticle::ParticleDecaysVector(0));
1234 pdgids.push_back(pdgid);
1235 for (int j = 0; j < decaysnumber; ++j) {
1237 fin >> bratio;
1238 decay.mBratio = bratio / 100.;
1239 fin >> daughters;
1240 decay.mDaughters.reserve(daughters);
1241 for (int k = 0; k < daughters; ++k) {
1242 fin >> tmpid;
1243 decay.mDaughters.push_back(tmpid);
1244 }
1245 decays[i].push_back(decay);
1246 }
1247 }
1248 }
1249
1250 for (size_t i = 0; i < m_Particles.size(); ++i) {
1251 if (decaymap.count(m_Particles[i].PdgId()) != 0)
1252 m_Particles[i].SetDecays(decays[decaymap[m_Particles[i].PdgId()]]);
1253 }
1254
1255 }
1256
1257 std::string ThermalParticleSystem::GetNameFromPDG(long long pdgid) {
1258 if (m_PDGtoID.count(pdgid) != 0)
1259 return m_Particles[m_PDGtoID[pdgid]].Name();
1260 if (pdgid == 1) return string("Npart");
1261 if (pdgid == 310) return string("K0S");
1262 if (pdgid == 130) return string("K0L");
1263 if (pdgid % 10 == 0) {
1264 long long tpdgid = pdgid / 10;
1265 if (PdgToId(tpdgid) != -1 && PdgToId(-tpdgid) != -1)
1266 return m_Particles[PdgToId(tpdgid)].Name() + "+" + m_Particles[PdgToId(-tpdgid)].Name();
1267 }
1268 if (pdgid == 22122112) return string("p+n");
1269
1270 return ExtraParticles::NameByPdg(pdgid);
1271
1272 //return string("???");
1273 }
1274
1276 for (size_t i = 0; i < m_Particles.size(); ++i) m_Particles[i].NormalizeBranchingRatios();
1277 ProcessDecays();
1278 }
1279
1280
1282 for (size_t i = 0; i < m_Particles.size(); ++i) m_Particles[i].RestoreBranchingRatios();
1283 ProcessDecays();
1284 }
1285
1287 {
1288 m_QStatsCalculationType = type;
1289 for (size_t i = 0; i < m_Particles.size(); ++i)
1290 m_Particles[i].SetCalculationType(type);
1291 }
1292
1294 {
1295 for (size_t i = 0; i < m_Particles.size(); ++i)
1296 m_Particles[i].SetClusterExpansionOrder(order);
1297 }
1298
1300 {
1301 m_ResonanceWidthShape = shape;
1302 for (size_t i = 0; i < m_Particles.size(); ++i)
1303 m_Particles[i].SetResonanceWidthShape(shape);
1304 }
1305
1307 {
1308 bool dodecays = (type != m_ResonanceWidthIntegrationType);
1309
1310 m_ResonanceWidthIntegrationType = type;
1311
1312 for (size_t i = 0; i < m_Particles.size(); ++i) {
1313 if (!m_Particles[i].ZeroWidthEnforced())
1314 m_Particles[i].SetResonanceWidthIntegrationType(type);
1315 }
1316
1317 if (dodecays)
1318 ProcessDecays();
1319 }
1320
1322 {
1323 if (id < 0 || id >= static_cast<int>(m_Particles.size())) {
1324 throw std::out_of_range("ThermalParticleSystem::Particle(int id): id is out of bounds!");
1325 }
1326 return m_Particles[id];
1327 }
1328
1330 {
1331 if (id < 0 || id >= static_cast<int>(m_Particles.size())) {
1332 throw std::out_of_range("ThermalParticleSystem::Particle(int id): id is out of bounds!");
1333 }
1334 return m_Particles[id];
1335 }
1336
1338 {
1339 int id = PdgToId(pdgid);
1340 if (id == -1) {
1341 throw std::invalid_argument("ThermalParticleSystem::ParticleByPDG(long long pdgid): pdgid " + std::to_string(pdgid) + " is unknown");
1342 }
1343 return m_Particles[id];
1344 }
1345
1347 {
1348 int id = PdgToId(pdgid);
1349 if (id == -1) {
1350 throw std::invalid_argument("ThermalParticleSystem::ParticleByPDG(long long pdgid): pdgid " + std::to_string(pdgid) + " is unknown");
1351 }
1352 return m_Particles[id];
1353 }
1354
1355 int ThermalParticleSystem::PdgToId(long long pdgid) const
1356 {
1357 map<long long, int>::const_iterator it = m_PDGtoID.find(pdgid);
1358
1359 if (it != m_PDGtoID.end()) {
1360 return it->second;
1361 }
1362 else {
1363 return -1;
1364 }
1365 }
1366
1368 {
1369 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
1370 m_MaxAbsBaryonNumber = 0;
1371 m_NumberOfParticles = 0;
1372 m_PDGtoID.clear();
1373 for (size_t i = 0; i < m_Particles.size(); ++i) {
1374 m_PDGtoID[m_Particles[i].PdgId()] = i;
1375 if (m_Particles[i].BaryonCharge() != 0) m_NumBaryons++;
1376 if (m_Particles[i].ElectricCharge() != 0) m_NumCharged++;
1377 if (m_Particles[i].Strangeness() != 0) m_NumStrange++;
1378 if (m_Particles[i].Charm() != 0) m_NumCharmed++;
1379 if (m_Particles[i].PdgId() > 0) m_NumberOfParticles++;
1380 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(m_Particles[i].BaryonCharge()));
1381 }
1382
1383 for (size_t i = 0; i < m_DecayContributionsByFeeddown.size(); ++i)
1384 m_DecayContributionsByFeeddown[i].resize(m_Particles.size());
1385 }
1386
1388 {
1390 sort(m_Particles.begin(), m_Particles.end(), cmpParticleMass);
1392 sort(m_Particles.begin(), m_Particles.end(), cmpParticleMassAndPdg);
1393 else
1394 sort(m_Particles.begin(), m_Particles.end(), cmpParticlePDG);
1395 FillPdgMap();
1396 for (size_t i = 0; i < m_Particles.size(); ++i) {
1397 if (m_Particles[i].DecayType() == ParticleDecayType::Default)
1398 m_Particles[i].SetDecayType( DecayTypeByParticleType(m_Particles[i]) );
1399 }
1400 }
1401
1403 {
1404 m_Particles.push_back(part);
1405 FillPdgMap();
1406 }
1407
1409 {
1410 if (ind >= 0 && ind < static_cast<int>(m_Particles.size())) {
1411 m_Particles.erase(m_Particles.begin() + ind);
1412 FillPdgMap();
1413 }
1414 }
1415
1417 {
1418 std::vector<int> check = CheckDecayChargesConservationVector(ind);
1419 for (int i = 0; i < check.size(); ++i)
1420 if (check[i] != 1)
1421 return false;
1422 return true;
1423 }
1424
1426 {
1427 bool ret = true;
1428 int cnt = 0;
1429 for (int i = 0; i < Particles().size(); ++i) {
1430 const ThermalParticle& part = Particles()[i];
1431 if (!part.IsStable() && part.Decays().size() == 0 && cnt < 10) {
1432 printf("**WARNING** %s (%lld): Particle marked unstable but no decay channels found!\n",
1433 part.Name().c_str(),
1434 part.PdgId());
1435 ret = false;
1436 cnt++;
1437 if (cnt == 10) {
1438 // throw std::runtime_error("**WARNING** Further warnings are discarded...");
1439 printf("**WARNING** Further warnings are discarded...\n");
1440 }
1441 }
1442 }
1443 return ret;
1444 }
1445
1447 {
1448 bool ret = true;
1449 for (int i = 0; i < Particles().size(); ++i) {
1450 const ThermalParticle& part = Particles()[i];
1451 if (part.AbsoluteStrangeness() == 0 && part.Strangeness() != 0) {
1452 std::cerr << "**WARNING** " << part.Name() << " (" << part.PdgId() << "): Particle with non-zero strangeness has zero strange quark content |s|!" << std::endl;
1453 ret = false;
1454 }
1455
1456 if (part.AbsoluteCharm() == 0 && part.Charm() != 0) {
1457 std::cerr << "**WARNING** " << part.Name() << " (" << part.PdgId() << "): Particle with non-zero charm has zero charm quark content |s|!" << std::endl;
1458 ret = false;
1459 }
1460 }
1461 return ret;
1462 }
1463
1465 {
1466 const ThermalParticle& part = Particles()[ind];
1467 int goalB = part.BaryonCharge();
1468 int goalQ = part.ElectricCharge();
1469 int goalS = part.Strangeness();
1470 int goalC = part.Charm();
1471
1472 std::map<long long, int> tPDGtoID = m_PDGtoID;
1473
1474 std::vector<int> ret(4, 1);
1475
1476 for (size_t i = 0; i < part.Decays().size(); ++i) {
1477 int decB = 0, decQ = 0, decS = 0, decC = 0;
1478 for (size_t j = 0; j < part.Decays()[i].mDaughters.size(); ++j) {
1479 long long tpdg = part.Decays()[i].mDaughters[j];
1480 if (tPDGtoID.count(tpdg) != 0) {
1481 int tid = tPDGtoID[tpdg];
1482 decB += Particles()[tid].BaryonCharge();
1483 decQ += Particles()[tid].ElectricCharge();
1484 decS += Particles()[tid].Strangeness();
1485 decC += Particles()[tid].Charm();
1486 }
1487 else if (ExtraParticles::PdgToId(tpdg) != -1) {
1488 int tid = ExtraParticles::PdgToId(tpdg);
1492 decC += ExtraParticles::Particle(tid).Charm();
1493 }
1494 }
1495
1496 if (goalB != decB)
1497 ret[0] = 0;
1498 if (goalQ != decQ)
1499 ret[1] = 0;
1500 if (goalS != decS)
1501 ret[2] = 0;
1502 if (goalC != decC)
1503 ret[3] = 0;
1504 }
1505
1506 return ret;
1507 }
1508
1510 {
1511 bool ret = true;
1512 ret &= m_PDGtoID == rhs.m_PDGtoID;
1513 ret &= m_NumBaryons == rhs.m_NumBaryons;
1514 ret &= m_NumCharged == rhs.m_NumCharged;
1515 ret &= m_NumStrange == rhs.m_NumStrange;
1516 ret &= m_NumCharmed == rhs.m_NumCharmed;
1517 ret &= m_MaxAbsBaryonNumber == rhs.m_MaxAbsBaryonNumber;
1518 ret &= m_NumberOfParticles == rhs.m_NumberOfParticles;
1519 ret &= m_ResonanceWidthIntegrationType == rhs.m_ResonanceWidthIntegrationType;
1520 ret &= m_DecayDistributionsMap == rhs.m_DecayDistributionsMap;
1521
1522 ret &= m_Particles == rhs.m_Particles;
1523
1524 return ret;
1525 }
1526
1528 {
1529 // Check if it's a known stable (wrt to any time scale of relevance) particle
1530 set<long long> stablePDG;
1531 stablePDG.insert(2212); stablePDG.insert(-2212); // proton
1532 stablePDG.insert(2112); stablePDG.insert(-2112); // neutron
1533 stablePDG.insert(1000010020); stablePDG.insert(-1000010020); // deuteron
1534 stablePDG.insert(1000020030); stablePDG.insert(-1000020030); // He3
1535 stablePDG.insert(1000010030); stablePDG.insert(-1000010030); // triton
1536 stablePDG.insert(1000020040); stablePDG.insert(-1000020040); // He4
1537
1538 if (stablePDG.count(part.PdgId()) > 0) {
1540 }
1541
1542 // Check if it's a known weakly decaying particle
1543 set<long long> weakPDG;
1544 weakPDG.insert(310); // K0S
1545 weakPDG.insert(130); // K0L
1546 weakPDG.insert(211); weakPDG.insert(-211); // pi+-
1547 weakPDG.insert(321); weakPDG.insert(-321); // K+-
1548 weakPDG.insert(3122); weakPDG.insert(-3122); // Lambda
1549 weakPDG.insert(3222); weakPDG.insert(-3222); // Sigma+
1550 weakPDG.insert(3112); weakPDG.insert(-3112); // Sigma-
1551 weakPDG.insert(3322); weakPDG.insert(-3322); // Ksi0
1552 weakPDG.insert(3312); weakPDG.insert(-3312); // Ksi-
1553 weakPDG.insert(3334); weakPDG.insert(-3334); // Omega
1554 weakPDG.insert(411); weakPDG.insert(-411); // D+-
1555 weakPDG.insert(421); weakPDG.insert(-421); // D0
1556 weakPDG.insert(431); weakPDG.insert(-431); // Ds
1557 weakPDG.insert(4232); weakPDG.insert(-4232); // Ksic+
1558 weakPDG.insert(4132); weakPDG.insert(-4132); // Ksic0
1559 weakPDG.insert(4422); weakPDG.insert(-4422); // Ksicc++
1560 weakPDG.insert(4412); weakPDG.insert(-4412); // Ksicc+
1561 weakPDG.insert(4332); weakPDG.insert(-4332); // Omegac
1562
1563 if (weakPDG.count(part.PdgId()) > 0) {
1565 }
1566
1567 // Check if it's a known electromagnetically decaying particle
1568 // Note: we treat eta decay as "electromagnetic" although some of them are in fact isospin-invariance breaking strong decays
1569 set<long long> emPDG;
1570 emPDG.insert(111); // pi0
1571 emPDG.insert(221); // eta
1572 emPDG.insert(331); // eta'
1573 emPDG.insert(3212); emPDG.insert(-3212); // Sigma0
1574
1575 if (emPDG.count(part.PdgId()) > 0) {
1577 }
1578
1579 if (!part.IsStable()) // if particle not marked as stable assume it at least decays strongly
1580 {
1582 }
1583 else {
1584 // if contains strangeness (or charm), it is not stable under weak decays
1585 if (part.AbsoluteStrangeness() != 0 || part.AbsoluteCharm() != 0)
1587
1589 }
1590
1591
1593 }
1594
1596 m_DecayContributionsByFeeddown[Feeddown::Weak].resize(m_Particles.size());
1597 m_DecayContributionsByFeeddown[Feeddown::Electromagnetic].resize(m_Particles.size());
1598 m_DecayContributionsByFeeddown[Feeddown::Strong].resize(m_Particles.size());
1599 for (size_t i = 0; i < m_Particles.size(); ++i) {
1600 m_DecayContributionsByFeeddown[Feeddown::Weak][i].resize(0);
1601 m_DecayContributionsByFeeddown[Feeddown::Electromagnetic][i].resize(0);
1602 m_DecayContributionsByFeeddown[Feeddown::Strong][i].resize(0);
1603 }
1604 for (int i = static_cast<int>(m_Particles.size()) - 1; i >= 0; i--)
1605 if (m_Particles[i].DecayType() != ParticleDecayType::Stable && m_Particles[i].DecayType() != ParticleDecayType::Default) {
1606 GoResonanceByFeeddown(i, i, 1., Feeddown::Type(static_cast<int>(m_Particles[i].DecayType())));
1607 }
1608 }
1609
1610 void ThermalParticleSystem::GoResonanceByFeeddown(int ind, int startind, double BR, Feeddown::Type feeddown) {
1611 for (int feed_index = static_cast<int>(Feeddown::Weak); feed_index <= static_cast<int>(Feeddown::Strong); ++feed_index) {
1612 if (static_cast<int>(feeddown) < feed_index) continue;
1613 //std::vector< std::pair<double, int> >& decayContributions = m_Particles[ind].DecayContributionsByFeeddown()[feed_index];
1614 DecayContributionsToParticle& decayContributions = m_DecayContributionsByFeeddown[feed_index][ind];
1615 if (ind != startind && decayContributions.size() > 0 && decayContributions[decayContributions.size() - 1].second == startind)
1616 {
1617 decayContributions[decayContributions.size() - 1].first += BR;
1618 }
1619 else if (ind != startind) {
1620 decayContributions.push_back(make_pair(BR, startind));
1621 }
1622 }
1623
1624
1625 if (m_Particles[ind].DecayType() != ParticleDecayType::Stable && m_Particles[ind].DecayType() != ParticleDecayType::Default) {
1626 for (size_t i = 0; i < m_Particles[ind].Decays().size(); ++i) {
1627 const ParticleDecayChannel& decaychannel = m_Particles[ind].Decays()[i];
1628 double tbr = decaychannel.mBratio;
1629
1630 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && ind == startind)
1631 tbr = decaychannel.mBratioAverage;
1632
1633 for (size_t j = 0; j < decaychannel.mDaughters.size(); ++j) {
1634 if (m_PDGtoID.count(decaychannel.mDaughters[j]) != 0)
1635 GoResonanceByFeeddown(m_PDGtoID[decaychannel.mDaughters[j]], startind, BR*tbr, Feeddown::Type(static_cast<int>(m_Particles[ind].DecayType())));
1636 }
1637 }
1638 }
1639 }
1640
1642 std::vector<double> ret(ComponentsNumber(), 0.);
1643 for (size_t i = 0; i < m_Particles.size(); ++i) {
1644 ret[i] = static_cast<double>(m_Particles[i].ConservedCharge(charge));
1645 }
1646 return ret;
1647 }
1648
1649
1650 namespace CuteHRGHelper {
1651 std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems) {
1652 std::stringstream ss(s);
1653 std::string item;
1654 while (std::getline(ss, item, delim)) {
1655 elems.push_back(item);
1656 }
1657 return elems;
1658 }
1659
1660 std::vector<std::string> split(const std::string& s, char delim) {
1661 std::vector<std::string> elems;
1662 split(s, delim, elems);
1663 return elems;
1664 }
1665
1666 void cutDecayDistributionsVector(std::vector< std::pair<double, std::vector<int> > >& vect, int maxsize)
1667 {
1668 if (static_cast<int>(vect.size()) > maxsize) {
1669 std::sort(vect.begin(), vect.end());
1670 std::reverse(vect.begin(), vect.end());
1671 vect.resize(maxsize);
1672 }
1673 }
1674 }
1675
1676 namespace DecayLifetimes {
1677 // lifetimes from pdg in seconds
1678 map<long long, double> lifetimes = {
1679 {211, 2.6033e-8}, // pi+-
1680 {111, 8.43e-17}, // pi0
1681 {321, 1.238e-8}, // K+-
1682 {310, 8.954e-11}, // K0S
1683 {130, 5.116e-8}, // K0L
1684 {411, 1.033e-12}, // D+-
1685 {421, 4.103e-13}, // D0
1686 {431, 5.012e-13}, // Ds+-
1687 {2112, 878.4}, // n
1688 {3122, 2.617e-10}, // Lambda
1689 {3222, 8.018e-11}, // Sigma+
1690 {3212, 74.e-21}, // Sigma0
1691 {3112, 1.479e-10}, // Sigma-
1692 {3322, 2.9e-10}, // Xi0
1693 {3312, 1.639e-10}, // Xi-
1694 {3334, 8.21e-11} // Omega-
1695 // TODO: Charmed baryons and hypernuclei
1696 };
1697
1698 // resonance widths in GeV
1699 map<long long, double> widths = {
1700 {221, 1.31e-6} // eta
1701 };
1702
1703 double GetLifetime(long long pdg) {
1704 if (lifetimes.count(abs(pdg)))
1705 return lifetimes[abs(pdg)] * 1.e15;
1706
1707 if (widths.count(abs(pdg))) {
1708 double width = widths[abs(pdg)];
1709 double ctau = 1. / (width * xMath::GeVtoifm());
1710 return ctau;
1711 }
1712
1713 // No entry found, return zero
1714 return 0.;
1715 }
1716 }
1717} // namespace thermalfist
Contains some helper functions.
static bool PrintDisclaimer()
Definition Utility.cpp:49
static bool DisclaimerPrinted
Definition Utility.h:28
Class containing all information about a particle specie.
long long PdgId() const
Particle's Particle Data Group (PDG) ID number.
double AbsoluteCharm() const
Absolute charm quark content |s|.
int BaryonCharge() const
Particle's baryon number.
int Statistics() const
Particle's statistics.
double Mass() const
Particle's mass [GeV].
std::vector< ParticleDecayChannel > ParticleDecaysVector
Vector of all decay channels of a particle.
int Strangeness() const
Particle's strangeness.
const ParticleDecaysVector & Decays() const
A vector of particle's decays.
ResonanceWidthIntegration
Treatment of finite resonance widths.
@ eBW
Energy-dependent Breit-Wigner scheme (eBW)
@ ZeroWidth
Zero-width approximation.
double AbsoluteStrangeness() const
Absolute strange quark content |s|.
double DecayThresholdMass() const
The decays threshold mass.
int ElectricCharge() const
Particle's electric charge.
ResonanceWidthShape
Relativistic vs non-relativistic Breit-Wigner shape.
bool IsNeutral() const
Whether particle is neutral one.
int Charm() const
Particle's charm.
const std::string & Name() const
Particle's name.
double ResonanceWidth() const
Particle's width at the pole mass (GeV)
bool IsStable() const
Return particle stability flag.
ThermalParticle GenerateAntiParticle() const
Generates the anti-particle to the current particle specie.
double Degeneracy() const
Particle's internal degeneracy factor.
void SetResonanceWidthIntegrationType(ThermalParticle::ResonanceWidthIntegration type)
Set (or get) the ThermalParticle::ResonanceWidthIntegration scheme for all particles.
void SetTableFromVector(const std::vector< ThermalParticle > &part_in, bool GenerateAntiParticles=true)
Sets the particle list from a provided vector of ThermalParticle objects.
std::vector< std::pair< double, std::vector< int > > > ResonanceFinalStatesDistribution
ThermalParticleSystem(const std::string &InputFile="", bool GenAntiP=true, double mcut=-1.)
Construct a new ThermalParticleSystem object.
static const std::string flag_noexcitednuclei
int PdgToId(long long pdgid) const
Transforms PDG ID to a 0-based particle id number.
SortModeType SortMode() const
Current mode to sort particle species.
void WriteTableToFile(const std::string &OutputFile="", bool WriteAntiParticles=false)
Writes the particle list to file.
void ProcessDecays()
Computes the decay contributions of decaying resonances to all particle yields.
std::string GetNameFromPDG(long long pdgid)
Get the name of particle species with the specified PDG ID.
ThermalParticle::ParticleDecaysVector GetDecaysFromAntiParticle(const ThermalParticle::ParticleDecaysVector &Decays)
Generates the decay channels for an antiparticle based on the provided decay channels of a particle.
void SetCalculationType(IdealGasFunctions::QStatsCalculationType type)
Sets the CalculationType() method to evaluate quantum statistics.
void NormalizeBranchingRatios()
Normalize branching ratios for all particles such that they add up to 100%.
bool operator==(const ThermalParticleSystem &rhs) const
void SetClusterExpansionOrder(int order)
Set the number of terms in the cluster expansion method.
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
std::vector< SingleDecayContribution > DecayContributionsToParticle
A vector of SingleDecayContribution where each element corresponds to a certain resonance species.
void RestoreBranchingRatios()
Restore the original values of all the branching ratios.
void FillDecayProperties()
Computes and fills decay channels of all particles with extra information.
void LoadList(const std::vector< std::string > &ListFiles, const std::vector< std::string > &DecayFiles=std::vector< std::string >(0), const std::set< std::string > &flags=std::set< std::string >(), double mcut=1.e9)
Loads the particle list from file.
static const std::string flag_no_antiparticles
std::pair< double, int > SingleDecayContribution
void FillResonanceDecaysByFeeddown()
Same as FillResonanceDecays() but separately for weak, electromagnetic, and strong decay feeddowns.
void FillDecayThresholds()
Computes mass thresholds of all decay channels of all particles. Obsolete.
void AddParticlesToListFromFile(const std::string &InputFile="", const std::set< std::string > &flags=std::set< std::string >(), double mcut=-1.)
static const std::string flag_nostrangeness
std::vector< int > CheckDecayChargesConservationVector(int ind) const
static ParticleDecayType::DecayType DecayTypeByParticleType(const ThermalParticle &part)
Determines the decay type of a given particle specie.
const ThermalParticle & Particle(int id) const
ThermalParticle object corresponding to particle species with a provided 0-based index.
void RemoveParticleAt(int ind)
Removes particle specie with specified 0-based particle id number from the list.
void AddParticle(const ThermalParticle &part)
Adds a new particle specie to the list.
void SetResonanceWidthShape(ThermalParticle::ResonanceWidthShape shape)
Set (or get) the ThermalParticle::ResonanceWidthShape for all particles.
void LoadDecays(const std::vector< std::string > &DecayFiles, const std::set< std::string > &flags=std::set< std::string >())
Load the decay channels for all particles from a file.
const ThermalParticle & ParticleByPDG(long long pdgid) const
ThermalParticle object corresponding to particle species with a provided PDG ID.
void FillResonanceDecays()
Computes the decay contributions of decaying resonances to all particle yields.
std::vector< double > GetConservedChargesVector(ConservedCharge::Name charge)
Calculates vector of conserved charges for all particle species.
int ComponentsNumber() const
Number of different particle species in the list.
void WriteDecaysToFile(const std::string &OutputFile="", bool WriteAntiParticles=false)
Writes the decay channels to a file.
~ThermalParticleSystem(void)
Destroy the ThermalParticleSystem object.
Contains several helper routines.
void cutDecayDistributionsVector(std::vector< std::pair< double, std::vector< int > > > &vect, int maxsize=2000)
std::vector< std::string > split(const std::string &s, char delim)
const ThermalParticle & Particle(int id)
const ThermalParticle & ParticleByPdg(long long pdg)
std::string NameByPdg(long long pdg)
QStatsCalculationType
Identifies whether quantum statistics are to be computed using the cluster expansion or numerical int...
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
long long stringToLongLong(const std::string &str)
Name
Set of all conserved charges considered.
static const int NumberOfTypes
@ Strong
Feeddown from strong decays.
@ Weak
Feeddown from strong, electromagnetic, and weak decays.
@ Electromagnetic
Feeddown from strong and electromagnetic decays.
@ StabilityFlag
Feeddown from all particles marked as unstable.
Structure containing information about a single decay channel of a particle.
std::vector< long long > mDaughters
DecayType
Type of particle's decay.
@ Electromagnetic
Electromagnetically decaying.