Thermal-FIST 1.5
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 for (size_t i = 0; i < tpart.Decays().size(); ++i) {
383 double tbr = tpart.Decays()[i].mBratio;
384 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && firstdecay)
385 tbr = m_Particles[ind].Decays()[i].mBratioAverage;
386
387 std::vector< std::pair<double, std::vector<int> > > tret = retorig;
388
389 for (size_t j = 0; j < tpart.Decays()[i].mDaughters.size(); ++j) {
390 if (m_PDGtoID.count(tpart.Decays()[i].mDaughters[j]) != 0) {
391
392 std::vector< std::pair<double, std::vector<int> > > tmp = GoResonanceDecayDistributions(m_PDGtoID[tpart.Decays()[i].mDaughters[j]]);
393 std::vector< std::pair<double, std::vector<int> > > tmp2(tret.size() * tmp.size());
394 for (int i1 = 0; i1 < static_cast<int>(tret.size()); ++i1) {
395 for (int i2 = 0; i2 < static_cast<int>(tmp.size()); ++i2) {
396 tmp2[i1*tmp.size() + i2].first = tret[i1].first * tmp[i2].first;
397 tmp2[i1*tmp.size() + i2].second.resize(m_Particles.size());
398 for (size_t jj = 0; jj < tmp2[i1*tmp.size() + i2].second.size(); ++jj)
399 tmp2[i1*tmp.size() + i2].second[jj] = tret[i1].second[jj] + tmp[i2].second[jj];
400 }
401 }
402 tret = tmp2;
403
404 // Restrict maximum number of channels to 1500, otherwise memory is an issue, relevant for the THERMUS-3.0 table
405 if (tret.size() > 1500) {
406 printf("**WARNING** %s (%lld) Decay Distributions: Too large array, cutting the number of channels to 1500!\n",
407 m_Particles[ind].Name().c_str(),
408 m_Particles[ind].PdgId());
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 1500, otherwise memory is an issue, relevant for the THERMUS-3.0 table
421 if (ret.size() > 1500) {
422 printf("**WARNING** %s (%lld) Decay Distributions: Too large array, cutting the number of channels to 1500!\n",
423 m_Particles[ind].Name().c_str(),
424 m_Particles[ind].PdgId());
426 }
427
428 double totprob = 0.;
429 for (size_t i = 0; i < ret.size(); ++i)
430 totprob += ret[i].first;
431 if (totprob > 1.) {
432 for (size_t i = 0; i < ret.size(); ++i)
433 ret[i].first *= 1. / totprob;
434 }
435 else if (totprob < 1.) {
436 double emptyprob = 1. - totprob;
437 ret.push_back(std::make_pair(emptyprob, retorig[0].second));
438 }
439
440 if (!firstdecay)
441 m_DecayDistributionsMap[ind] = ret;
442
443 // Debugging
444
445 //if (tpart.BaryonCharge() == 1) {
446 // printf("Checking baryon number conservation in decays for %d\n", tpart.PdgId());
447 // double tBav = 0.;
448 // for (int i = 0; i < ret.size(); ++i) {
449 // double tbr = ret[i].first;
450 // for (int j = 0; j < ret[i].second.size(); ++j)
451 // if (m_Particles[j].IsStable())
452 // tBav += tbr * ret[i].second[j] * m_Particles[j].BaryonCharge();
453 // }
454 // printf("<B> = %lf\n", tBav);
455 // //printf("Decay distributions for %d\n", tpart.PdgId());
456 // //for (int i = 0; i < ret.size(); ++i) {
457 // // printf("%lf\n", ret[i].first);
458 // // for (int j = 0; j < ret[i].second.size(); ++j)
459 // // if (ret[i].second[j] > 0)
460 // // printf("%d: %d\n", m_Particles[j].PdgId(), ret[i].second[j]);
461 // //}
462 //}
463
464 return ret;
465 }
466
467 bool ThermalParticleSystem::AcceptParticle(const ThermalParticle& part, const std::set<std::string>& flags, double mcut) const
468 {
469 if (mcut >= 0. && part.Mass() > mcut)
470 return false;
471 if (flags.count(ThermalParticleSystem::flag_nostrangeness) > 0 && part.AbsoluteStrangeness() != 0)
472 return false;
473 if (flags.count(ThermalParticleSystem::flag_nocharm) > 0 && part.AbsoluteCharm() != 0)
474 return false;
475 if (flags.count(ThermalParticleSystem::flag_nonuclei) > 0 && abs(part.BaryonCharge()) > 1)
476 return false;
477 if (flags.count(ThermalParticleSystem::flag_noexcitednuclei) > 0 && abs(part.BaryonCharge()) > 1 && !part.IsStable())
478 return false;
479 return true;
480 }
481
482 void ThermalParticleSystem::LoadList(const std::vector<std::string>& ListFiles, const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags, double mcut)
483 {
484 m_NumberOfParticles = 0;
485 m_Particles.resize(0);
486 m_PDGtoID.clear();
487
488 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
489 m_MaxAbsBaryonNumber = 0;
490
491 if (ListFiles.size() == 1 && CheckListIsiSS(ListFiles[0])) {
492 LoadListiSS(ListFiles[0], flags, mcut);
493 return;
494 }
495
496 for(int i = 0; i < ListFiles.size(); ++i)
497 AddParticlesToListFromFile(ListFiles[i], flags, mcut);
498
499 FinalizeList();
500
501 std::vector<std::string> tDecayFiles = DecayFiles;
502 if (tDecayFiles.size() == 1 && tDecayFiles[0] == "")
503 tDecayFiles.clear();
504
505 if (tDecayFiles.size() == 0 && ListFiles.size() > 0) {
506 for (size_t ilist = 0; ilist < ListFiles.size(); ++ilist) {
507 string decayprefix = "";
508 string decayprefixfile = "";
509
510 for (int i = ListFiles[ilist].size() - 1; i >= 0; --i) {
511 if (ListFiles[ilist][i] == '\\' || ListFiles[ilist][i] == '/')
512 {
513 decayprefix = ListFiles[ilist].substr(0, i + 1);
514 break;
515 }
516 decayprefixfile += ListFiles[ilist][i];
517 }
518
519 reverse(decayprefixfile.begin(), decayprefixfile.end());
520
521
522 string DecayFile = "";
523 if (decayprefixfile.substr(0, 4) == "list") {
524 DecayFile = decayprefix + "decays" + decayprefixfile.substr(4);
525 }
526 else {
527 DecayFile = decayprefix + "decays.dat";
528 }
529
530 if (ilist == 0)
531 tDecayFiles.push_back(decayprefix + "decays.dat");
532
533 tDecayFiles.push_back(DecayFile);
534 }
535 }
536
537 LoadDecays(tDecayFiles, flags);
538
539 FinalizeListLoad();
540 }
541
542 void ThermalParticleSystem::LoadList(const std::string& InputFile, const std::string& DecayFile, bool GenAntiP, double mcut) {
543
544 std::set<std::string> flags;
545 if (!GenAntiP)
547
548 std::vector<std::string> DecayFiles(0);
549 if (DecayFile != "")
550 DecayFiles.push_back(DecayFile);
551
552 LoadList(std::vector<std::string>(1, InputFile), DecayFiles, flags, mcut);
553 }
554
555 void ThermalParticleSystem::AddParticlesToListFromFile(const std::string& InputFile, const std::set<std::string>& flags, double mcut)
556 {
557 ifstream fin;
558 fin.open(InputFile.c_str());
559 if (fin.is_open()) {
560
561 char tmpc[2000];
562 fin.getline(tmpc, 2000);
563 string tmp = string(tmpc);
564 vector<string> elems = CuteHRGHelper::split(tmp, '#');
565
566 int flnew = 0;
567 if (elems.size() < 1 || CuteHRGHelper::split(elems[0], ';').size() < 4)
568 flnew = 1;
569 else
570 flnew = 0;
571
572 fin.clear();
573 fin.seekg(0, ios::beg);
574
575 if (flnew == 1)
576 LoadTable_NewFormat(fin, flags, mcut);
577 else
578 LoadTable_OldFormat(fin, flags, mcut);
579
580 fin.close();
581
582 }
583 }
584
585 void ThermalParticleSystem::LoadTable_OldFormat(std::ifstream & fin, const std::set<std::string>& flags, double mcut)
586 {
587 bool GenerateAntiParticles = (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0);
588 if (fin.is_open()) {
589 string tmp;
590 char tmpc[500];
591 fin.getline(tmpc, 500);
592 tmp = string(tmpc);
593 while (1) {
594 vector<string> fields = CuteHRGHelper::split(tmp, ';');
595 if (fields.size() < 14) break;
596 int stable, spin, stat, str, bary, chg, charm;
597 long long pdgid;
598 double mass, width, threshold, abss, absc, radius = 0.5;
599 string name, decayname = "";
600 stable = atoi(fields[0].c_str());
601 name = fields[1];
602 //pdgid = atoi(fields[2].c_str());
603 pdgid = stringToLongLong(fields[2]);
604 spin = atoi(fields[3].c_str());
605 stat = atoi(fields[4].c_str());
606 mass = atof(fields[5].c_str());
607 str = atoi(fields[6].c_str());
608 bary = atoi(fields[7].c_str());
609 chg = atoi(fields[8].c_str());
610 charm = atoi(fields[9].c_str());
611 abss = atof(fields[10].c_str());
612 absc = atof(fields[11].c_str());
613 width = atof(fields[12].c_str());
614 threshold = atof(fields[13].c_str());
615 if (fields.size() >= 15) radius = atof(fields[14].c_str());
616 if (fields.size() == 16) decayname = fields[15];
617
618 ThermalParticle part_candidate = ThermalParticle(static_cast<bool>(stable), name, pdgid, static_cast<double>(spin), stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
619
620 //if (mcut >= 0. && mass > mcut) {
621 if (m_PDGtoID.count(pdgid) != 0) {
622 throw std::invalid_argument("ThermalParticleSystem::LoadTable_NewFormat: Duplicate pdg code " + std::to_string(pdgid));
623 }
624 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0) {
625 fin.getline(tmpc, 500);
626 tmp = string(tmpc);
627 continue;
628 }
629
630 if (bary != 0) m_NumBaryons++;
631 if (chg != 0) m_NumCharged++;
632 if (str != 0) m_NumStrange++;
633 if (charm != 0) m_NumCharmed++;
634 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
635
636 m_Particles.push_back(part_candidate);
637 m_PDGtoID[pdgid] = m_Particles.size() - 1;
638 m_NumberOfParticles++;
639
640 if (GenerateAntiParticles && !(bary == 0 && chg == 0 && str == 0 && charm == 0) && (m_PDGtoID.count(-pdgid) == 0)) {
641
642 if (bary != 0) m_NumBaryons++;
643 if (chg != 0) m_NumCharged++;
644 if (str != 0) m_NumStrange++;
645 if (charm != 0) m_NumCharmed++;
646
647 if (bary == 0 && name[name.size() - 1] == '+')
648 name[name.size() - 1] = '-';
649 else if (bary == 0 && name[name.size() - 1] == '-')
650 name[name.size() - 1] = '+';
651 else
652 name = "anti-" + name;
653 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));
654 m_Particles[m_Particles.size() - 1].SetAntiParticle(true);
655 m_PDGtoID[-pdgid] = m_Particles.size() - 1;
656 }
657
658 fin.getline(tmpc, 500);
659 tmp = string(tmpc);
660 }
661 }
662 }
663
664 void ThermalParticleSystem::LoadTable_NewFormat(std::ifstream & fin, const std::set<std::string>& flags, double mcut)
665 {
666 bool GenerateAntiParticles = (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0);
667 if (fin.is_open()) {
668 char cc[2000];
669 while (!fin.eof()) {
670 fin.getline(cc, 2000);
671 string tmp = string(cc);
672 vector<string> elems = CuteHRGHelper::split(tmp, '#');
673 if (elems.size() < 1 || elems[0].size() == 0)
674 continue;
675
676 istringstream iss(elems[0]);
677
678 int stable, stat, str, bary, chg, charm;
679 long long pdgid;
680 double mass, degeneracy, width, threshold, abss, absc;
681 string name;
682
683 if (iss >> pdgid
684 >> name
685 >> stable
686 >> mass
687 >> degeneracy
688 >> stat
689 >> bary
690 >> chg
691 >> str
692 >> charm
693 >> abss
694 >> absc
695 >> width
696 >> threshold) {
697
698 ThermalParticle part_candidate = ThermalParticle((bool)stable, name, pdgid, degeneracy, stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
699
700 //if (mcut >= 0. && mass > mcut)
701 if (m_PDGtoID.count(pdgid) != 0) {
702 throw std::invalid_argument("ThermalParticleSystem::LoadTable_NewFormat: Duplicate pdg code " + std::to_string(pdgid));
703 }
704
705 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0)
706 continue;
707
708 if (bary != 0) m_NumBaryons++;
709 if (chg != 0) m_NumCharged++;
710 if (str != 0) m_NumStrange++;
711 if (charm != 0) m_NumCharmed++;
712 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
713
714 m_Particles.push_back(part_candidate);
715 m_PDGtoID[pdgid] = m_Particles.size() - 1;
716 m_NumberOfParticles++;
717
718 if (GenerateAntiParticles && !(bary == 0 && chg == 0 && str == 0 && charm == 0) && (m_PDGtoID.count(-pdgid) == 0)) {
719
720 if (bary != 0) m_NumBaryons++;
721 if (chg != 0) m_NumCharged++;
722 if (str != 0) m_NumStrange++;
723 if (charm != 0) m_NumCharmed++;
724
725 if (bary == 0 && name[name.size() - 1] == '+')
726 name[name.size() - 1] = '-';
727 else if (bary == 0 && name[name.size() - 1] == '-')
728 name[name.size() - 1] = '+';
729 else
730 name = "anti-" + name;
731 m_Particles.push_back(ThermalParticle((bool)stable, name, -pdgid, degeneracy, stat, mass, -str, -bary, -chg, abss, width, threshold, -charm, absc));
732 m_Particles[m_Particles.size() - 1].SetAntiParticle(true);
733 m_PDGtoID[pdgid] = m_Particles.size() - 1;
734 }
735 }
736 }
737 }
738 }
739
740 void ThermalParticleSystem::SetTableFromVector(const std::vector<ThermalParticle>& part_in, bool GenerateAntiParticles)
741 {
742 m_Particles.resize(0);
743
744 for (size_t i = 0; i < part_in.size(); ++i) {
745 const ThermalParticle &part = part_in[i];
746 if (!GenerateAntiParticles) {
747 m_Particles.push_back(part);
748 }
749 else if (part.PdgId() > 0) {
750 m_Particles.push_back(part);
751
752 if (!part.IsNeutral()) {
753 m_Particles.push_back(part.GenerateAntiParticle());
754 }
755 }
756 }
757
758 FinalizeList();
759
760 if (GenerateAntiParticles) {
761 for (size_t i = 0; i < m_Particles.size(); ++i) {
762 if (m_Particles[i].IsAntiParticle() && PdgToId(-m_Particles[i].PdgId()) != -1) {
763 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[PdgToId(-m_Particles[i].PdgId())].Decays()));
764 }
765 }
766 }
767
768 FinalizeDecaysLoad();
769
773 }
774
775 void ThermalParticleSystem::WriteTableToFile(const std::string& OutputFile, bool WriteAntiParticles)
776 {
777 std::ofstream fout(OutputFile.c_str());
778 if (fout.is_open()) {
779 fout << "#"
780 << std::setw(14) << "pdgid"
781 << std::setw(20) << "name"
782 << std::setw(15) << "stable"
783 << std::setw(15) << "mass[GeV]"
784 << std::setw(15) << "degeneracy"
785 << std::setw(15) << "statistics"
786 << std::setw(15) << "B"
787 << std::setw(15) << "Q"
788 << std::setw(15) << "S"
789 << std::setw(15) << "C"
790 << std::setw(15) << "|S|"
791 << std::setw(15) << "|C|"
792 << std::setw(15) << "width[GeV]"
793 << std::setw(15) << "threshold[GeV]"
794 << std::endl;
795
796 for (size_t i = 0; i < m_Particles.size(); ++i) {
797 const ThermalParticle& part = m_Particles[i];
798 if (part.PdgId() < 0 && !WriteAntiParticles)
799 continue;
800
801 fout << std::setw(15) << part.PdgId()
802 << std::setw(20) << part.Name()
803 << std::setw(15) << static_cast<int>(part.IsStable())
804 << std::setw(15) << part.Mass()
805 << std::setw(15) << part.Degeneracy()
806 << std::setw(15) << part.Statistics()
807 << std::setw(15) << part.BaryonCharge()
808 << std::setw(15) << part.ElectricCharge()
809 << std::setw(15) << part.Strangeness()
810 << std::setw(15) << part.Charm()
811 << std::setw(15) << part.AbsoluteStrangeness()
812 << std::setw(15) << part.AbsoluteCharm()
813 << std::setw(15) << part.ResonanceWidth()
814 << std::setw(15) << part.DecayThresholdMass()
815 << std::endl;
816 }
817 fout.close();
818 }
819 }
820
821 void ThermalParticleSystem::LoadDecays(const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags)
822 {
823 for (size_t i = 0; i < m_Particles.size(); ++i)
824 m_Particles[i].ClearDecays();
825
826 for (size_t i = 0; i < DecayFiles.size(); ++i) {
827 ifstream fin(DecayFiles[i].c_str());
828
829 if (fin.is_open()) {
830
831 char tmpc[2000];
832 fin.getline(tmpc, 2000);
833 string tmp = string(tmpc);
834 vector<string> elems = CuteHRGHelper::split(tmp, '#');
835
836 int flnew = 0;
837 if (tmp.size() == 0 || elems.size() >= 2)
838 flnew = 1;
839 else
840 flnew = 0;
841
842 fin.clear();
843 fin.seekg(0, ios::beg);
844
845 if (flnew == 1)
846 ReadDecays_NewFormat(fin);
847 else
848 ReadDecays_OldFormat(fin);
849
850 fin.close();
851
852 }
853
854 }
855
856 if (flags.count(ThermalParticleSystem::flag_no_antiparticles) == 0) {
857 for (size_t i = 0; i < m_Particles.size(); ++i) {
858 if (m_Particles[i].PdgId() < 0)
859 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[m_PDGtoID[-m_Particles[i].PdgId()]].Decays()));
860 }
861 }
862
863 FinalizeDecaysLoad();
864 }
865
866 void ThermalParticleSystem::LoadDecays(const std::string& DecaysFile, bool GenerateAntiParticles)
867 {
868 std::set<std::string> flags;
869 if (!GenerateAntiParticles)
871
872 LoadDecays(vector<string>(1, DecaysFile), flags);
873 }
874
875 void ThermalParticleSystem::ReadDecays_NewFormat(std::ifstream & fin)
876 {
877 vector< ThermalParticle::ParticleDecaysVector > decays(0);
878 map<long long, int> decaymap;
879 decaymap.clear();
880
881
882 if (fin.is_open()) {
883 char cc[2000];
884 int index = 0;
885 while (!fin.eof()) {
886 fin.getline(cc, 2000);
887 string tmp = string(cc);
888 vector<string> elems = CuteHRGHelper::split(tmp, '#');
889 if (elems.size() < 1 || elems[0].size() == 0)
890 continue;
891
892 int tdecaysnumber = 0;
893 long long tpdgid = 0;
895
896 istringstream iss(elems[0]);
897 if (!(iss >> tpdgid)) continue;
898
899 {
900 bool fl = false;
901 while (!fl) {
902 if (fin.eof()) break;
903 fin.getline(cc, 500);
904 tmp = string(cc);
905 elems = CuteHRGHelper::split(tmp, '#');
906 if (elems.size() < 1 || elems[0].size() == 0)
907 continue;
908
909 istringstream isstnum(elems[0]);
910 if (!(isstnum >> tdecaysnumber)) {
911 tdecaysnumber = 0;
912 continue;
913 }
914 fl = true;
915 }
916 }
917
918 for (int i = 0; i < tdecaysnumber; ++i) {
919 bool fl = false;
920 while (!fl) {
921 if (fin.eof()) break;
922 fin.getline(cc, 500);
923 tmp = string(cc);
924 elems = CuteHRGHelper::split(tmp, '#');
925 if (elems.size() < 1 || elems[0].size() == 0)
926 continue;
927
928 ParticleDecayChannel tdecay;
929 istringstream issdec(elems[0]);
930 if (!(issdec >> tdecay.mBratio)) continue;
931 long long tmpid;
932 while (issdec >> tmpid) {
933 tdecay.mDaughters.push_back(tmpid);
934 }
935 tdecays.push_back(tdecay);
936 fl = true;
937 }
938 }
939
940 if (static_cast<int>(tdecays.size()) == tdecaysnumber && static_cast<int>(tdecays.size()) != 0) {
941 decays.push_back(tdecays);
942 decaymap[tpdgid] = index;
943 index++;
944 }
945 }
946
947 for (size_t i = 0; i < m_Particles.size(); ++i) {
948 if (decaymap.count(m_Particles[i].PdgId()) != 0)
949 m_Particles[i].SetDecays(decays[decaymap[m_Particles[i].PdgId()]]);
950 }
951 }
952 }
953
954 void ThermalParticleSystem::Initialize(const std::vector<std::string>& ListFiles, const std::vector<std::string>& DecayFiles, const std::set<std::string>& flags, double mcut)
955 {
958
959 m_NumberOfParticles = 0;
960 m_Particles.resize(0);
961 m_PDGtoID.clear();
962 m_ResonanceWidthShape = ThermalParticle::RelativisticBreitWigner;
963 m_ResonanceWidthIntegrationType = ThermalParticle::ZeroWidth;
964
966
967 m_DecayContributionsByFeeddown.resize(Feeddown::NumberOfTypes);
968
972
973 LoadList(ListFiles, DecayFiles, flags, mcut);
974 }
975
976 void ThermalParticleSystem::Initialize(const std::string& InputFile, const std::string& DecayFile, bool GenAntiP, double mcut)
977 {
978 std::set<std::string> flags;
979 if (!GenAntiP)
981 Initialize(vector<string>(1, InputFile), vector<string>(1, DecayFile), flags, mcut);
982 }
983
984 void ThermalParticleSystem::FinalizeListLoad()
985 {
986 SetResonanceWidthShape(m_ResonanceWidthShape);
987 SetResonanceWidthIntegrationType(m_ResonanceWidthIntegrationType);
988 SetCalculationType(m_QStatsCalculationType);
989
992 }
993
994 void ThermalParticleSystem::FinalizeDecaysLoad()
995 {
996 for (size_t i = 0; i < m_Particles.size(); ++i)
997 m_Particles[i].SetDecaysOriginal(m_Particles[i].Decays());
998
1001 ProcessDecays();
1002 }
1003
1004 bool ThermalParticleSystem::CheckListIsiSS(const std::string& filename)
1005 {
1006 ifstream fin(filename.c_str());
1007 if (fin.is_open()) {
1008 string tmp;
1009 fin >> tmp;
1010 return (tmp == "iSS");
1011 }
1012 return false;
1013 }
1014
1015 void ThermalParticleSystem::LoadListiSS(const std::string& filename, const std::set<std::string>& flags, double mcut)
1016 {
1017 m_NumberOfParticles = 0;
1018 m_Particles.resize(0);
1019 m_PDGtoID.clear();
1020
1021 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
1022 m_MaxAbsBaryonNumber = 0;
1023
1024 ifstream fin(filename.c_str());
1025
1026 if (fin.is_open()) {
1027 char cc[2000];
1028 // Skip the header line
1029 fin.getline(cc, 2000);
1030 // Read all the particles
1031 while (!fin.eof()) {
1032 fin.getline(cc, 2000);
1033 string tmp = string(cc);
1034 vector<string> elems = CuteHRGHelper::split(tmp, '#');
1035 if (elems.size() < 1 || elems[0].size() == 0)
1036 continue;
1037
1038 istringstream iss(elems[0]);
1039
1040 int stable, stat, str, bary, chg, charm, itmp, tdecaynumber;
1041 long long pdgid, ltmp;
1042 double mass, degeneracy, width, threshold, abss, absc;
1043 string name;
1044
1045 if (iss >> pdgid
1046 >> name
1047 >> mass
1048 >> width
1049 >> degeneracy
1050 >> bary
1051 >> str
1052 >> charm
1053 >> itmp
1054 >> itmp
1055 >> chg
1056 >> tdecaynumber
1057 ) {
1058
1059 stable = 0;
1060 abss = std::abs(str);
1061 if (pdgid == 333)
1062 abss = 2.;
1063 absc = std::abs(charm);
1064 threshold = 0.;
1065 stat = (std::abs(bary) % 2 == 0 ? -1 : 1);
1066
1067 ThermalParticle part_candidate = ThermalParticle(
1068 (bool)stable, name, pdgid, degeneracy, stat, mass, str, bary, chg, abss, width, threshold, charm, absc);
1069
1070 if (pdgid < 0)
1071 part_candidate.SetAntiParticle(true);
1072
1073 if (!AcceptParticle(part_candidate, flags, mcut) || m_PDGtoID.count(pdgid) != 0)
1074 continue;
1075
1076 if (bary != 0) m_NumBaryons++;
1077 if (chg != 0) m_NumCharged++;
1078 if (str != 0) m_NumStrange++;
1079 if (charm != 0) m_NumCharmed++;
1080 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(bary));
1081
1082 m_Particles.push_back(part_candidate);
1083 m_PDGtoID[pdgid] = m_Particles.size() - 1;
1084 m_NumberOfParticles++;
1085
1086 // now read the decays
1088 for (size_t idec = 0; idec < tdecaynumber; ++idec) {
1089 fin.getline(cc, 2000);
1090 string tmp = string(cc);
1091 elems = CuteHRGHelper::split(tmp, '#');
1092 istringstream issdec(elems[0]);
1093
1094 ParticleDecayChannel tdecay;
1095 issdec >> ltmp;
1096 int ndecayparticles;
1097 double BR;
1098 issdec >> ndecayparticles >> tdecay.mBratio;
1099 for (size_t idaughter = 0; idaughter < 5; ++idaughter) {
1100 issdec >> ltmp;
1101 if (idaughter < ndecayparticles)
1102 tdecay.mDaughters.push_back(ltmp);
1103 }
1104 tdecays.push_back(tdecay);
1105 }
1106
1107 if (static_cast<int>(tdecays.size()) == tdecaynumber
1108 && static_cast<int>(tdecays.size()) != 0
1109 && tdecays[0].mDaughters.size() != 1) {
1110 m_Particles.back().SetDecays(tdecays);
1111 }
1112 else {
1113 stable = 1;
1114 m_Particles.back().SetStable(true);
1115 }
1116
1117 // Add antibaryon
1118 if (bary > 0 && (m_PDGtoID.count(-pdgid) == 0)) {
1119
1120 if (bary != 0) m_NumBaryons++;
1121 if (chg != 0) m_NumCharged++;
1122 if (str != 0) m_NumStrange++;
1123 if (charm != 0) m_NumCharmed++;
1124
1125 if (bary == 0 && name[name.size() - 1] == '+')
1126 name[name.size() - 1] = '-';
1127 else if (bary == 0 && name[name.size() - 1] == '-')
1128 name[name.size() - 1] = '+';
1129 else
1130 name = "anti-" + name;
1131 m_Particles.push_back(ThermalParticle((bool)stable, name, -pdgid, degeneracy, stat, mass, -str, -bary, -chg, abss, width, threshold, -charm, absc));
1132 m_Particles.back().SetAntiParticle(true);
1133 m_PDGtoID[pdgid] = m_Particles.size() - 1;
1134 }
1135
1136 }
1137 }
1138
1139 FinalizeList();
1140
1141 for (size_t i = 0; i < m_Particles.size(); ++i) {
1142 if (m_Particles[i].BaryonCharge() < 0)
1143 m_Particles[i].SetDecays(GetDecaysFromAntiParticle(m_Particles[m_PDGtoID[-m_Particles[i].PdgId()]].Decays()));
1144 }
1145
1146 FinalizeDecaysLoad();
1147
1148 FinalizeListLoad();
1149 }
1150 }
1151
1152 void ThermalParticleSystem::WriteDecaysToFile(const std::string& OutputFile, bool WriteAntiParticles)
1153 {
1154 std::ofstream fout(OutputFile.c_str());
1155 if (fout.is_open()) {
1156 fout << "# the list of decays" << std::endl;
1157 fout << "# each entry consists of the following:" << std::endl;
1158 fout << "# a line with the pdgid of decaying particle" << std::endl;
1159 fout << "# a line with the number of decay channels" << std::endl;
1160 fout << "# for each channel a line containing whitespace-separated values of the channel branching ratio and pdg ids of the daughter products" << std::endl;
1161 fout << "# everything after the # symbol is treated as a comment and ignored" << std::endl;
1162 fout << "# decays of antiparticles are not listed but generated from the listed decays of particles" << std::endl;
1163 fout << std::endl;
1164
1165 for (unsigned int i = 0; i < m_Particles.size(); ++i) {
1166 if ((m_Particles[i].PdgId()>0 || WriteAntiParticles) && m_Particles[i].Decays().size()>0) {
1167 fout << std::left << std::setw(36) << m_Particles[i].PdgId();
1168 fout << " # " << m_Particles[i].Name() << std::endl;
1169
1170 fout << std::left << std::setw(36) << m_Particles[i].Decays().size();
1171 fout << " # " << m_Particles[i].Decays().size() << " decay channel";
1172 if (m_Particles[i].Decays().size() % 10 != 1 || m_Particles[i].Decays().size() % 100 == 11) fout << "s";
1173 fout << std::endl;
1174
1175 for (unsigned int j = 0; j < m_Particles[i].Decays().size(); ++j) {
1176 fout << std::left << std::setw(15) << m_Particles[i].Decays()[j].mBratio << " ";
1177 std::ostringstream oss;
1178 for (unsigned int k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
1179 oss << m_Particles[i].Decays()[j].mDaughters[k];
1180 if (k != m_Particles[i].Decays()[j].mDaughters.size() - 1)
1181 oss << " ";
1182 }
1183 fout << std::left << std::setw(20) << oss.str();
1184 fout << " # " << m_Particles[i].Name() << " -> ";
1185 for (unsigned int k = 0; k < m_Particles[i].Decays()[j].mDaughters.size(); ++k) {
1186 if (m_PDGtoID.count(m_Particles[i].Decays()[j].mDaughters[k]) == 0) {
1187 //if (m_Particles[i].Decays()[j].mDaughters[k] == 22) fout << "?gamma?";
1188 long long tpdg = m_Particles[i].Decays()[j].mDaughters[k];
1189 if (ExtraParticles::PdgToId(tpdg) != -1)
1190 fout << ExtraParticles::ParticleByPdg(tpdg).Name();
1191 else fout << "???";
1192 }
1193 else
1194 fout << m_Particles[m_PDGtoID[m_Particles[i].Decays()[j].mDaughters[k]]].Name();
1195 if (k != m_Particles[i].Decays()[j].mDaughters.size() - 1)
1196 fout << " + ";
1197 }
1198 fout << std::endl;
1199 }
1200 fout << std::endl;
1201 }
1202 }
1203
1204 fout.close();
1205 }
1206 }
1207
1208 void ThermalParticleSystem::ReadDecays_OldFormat(std::ifstream & fin)
1209 {
1210 vector< ThermalParticle::ParticleDecaysVector > decays(0);
1211 vector<long long> pdgids(0);
1212 map<long long, int> decaymap;
1213 decaymap.clear();
1214
1215 if (fin.is_open()) {
1216 int decaypartnumber = 0;
1217 fin >> decaypartnumber;
1218 decays.reserve(decaypartnumber);
1219
1220 for (int i = 0; i < decaypartnumber; ++i) {
1221 int decaysnumber, daughters;
1222 long long pdgid, tmpid;
1223 double bratio;
1224 fin >> pdgid >> decaysnumber;
1225 decaymap[pdgid] = i;
1226 decays.push_back(ThermalParticle::ParticleDecaysVector(0));
1227 pdgids.push_back(pdgid);
1228 for (int j = 0; j < decaysnumber; ++j) {
1230 fin >> bratio;
1231 decay.mBratio = bratio / 100.;
1232 fin >> daughters;
1233 decay.mDaughters.reserve(daughters);
1234 for (int k = 0; k < daughters; ++k) {
1235 fin >> tmpid;
1236 decay.mDaughters.push_back(tmpid);
1237 }
1238 decays[i].push_back(decay);
1239 }
1240 }
1241 }
1242
1243 for (size_t i = 0; i < m_Particles.size(); ++i) {
1244 if (decaymap.count(m_Particles[i].PdgId()) != 0)
1245 m_Particles[i].SetDecays(decays[decaymap[m_Particles[i].PdgId()]]);
1246 }
1247
1248 }
1249
1250 std::string ThermalParticleSystem::GetNameFromPDG(long long pdgid) {
1251 if (m_PDGtoID.count(pdgid) != 0)
1252 return m_Particles[m_PDGtoID[pdgid]].Name();
1253 if (pdgid == 1) return string("Npart");
1254 if (pdgid == 310) return string("K0S");
1255 if (pdgid == 130) return string("K0L");
1256 if (pdgid % 10 == 0) {
1257 long long tpdgid = pdgid / 10;
1258 if (PdgToId(tpdgid) != -1 && PdgToId(-tpdgid) != -1)
1259 return m_Particles[PdgToId(tpdgid)].Name() + "+" + m_Particles[PdgToId(-tpdgid)].Name();
1260 }
1261 if (pdgid == 22122112) return string("p+n");
1262
1263 return ExtraParticles::NameByPdg(pdgid);
1264
1265 //return string("???");
1266 }
1267
1269 for (size_t i = 0; i < m_Particles.size(); ++i) m_Particles[i].NormalizeBranchingRatios();
1270 ProcessDecays();
1271 }
1272
1273
1275 for (size_t i = 0; i < m_Particles.size(); ++i) m_Particles[i].RestoreBranchingRatios();
1276 ProcessDecays();
1277 }
1278
1280 {
1281 m_QStatsCalculationType = type;
1282 for (size_t i = 0; i < m_Particles.size(); ++i)
1283 m_Particles[i].SetCalculationType(type);
1284 }
1285
1287 {
1288 for (size_t i = 0; i < m_Particles.size(); ++i)
1289 m_Particles[i].SetClusterExpansionOrder(order);
1290 }
1291
1293 {
1294 m_ResonanceWidthShape = shape;
1295 for (size_t i = 0; i < m_Particles.size(); ++i)
1296 m_Particles[i].SetResonanceWidthShape(shape);
1297 }
1298
1300 {
1301 bool dodecays = (type != m_ResonanceWidthIntegrationType);
1302
1303 m_ResonanceWidthIntegrationType = type;
1304
1305 for (size_t i = 0; i < m_Particles.size(); ++i) {
1306 if (!m_Particles[i].ZeroWidthEnforced())
1307 m_Particles[i].SetResonanceWidthIntegrationType(type);
1308 }
1309
1310 if (dodecays)
1311 ProcessDecays();
1312 }
1313
1315 {
1316 if (id < 0 || id >= static_cast<int>(m_Particles.size())) {
1317 throw std::out_of_range("ThermalParticleSystem::Particle(int id): id is out of bounds!");
1318 }
1319 return m_Particles[id];
1320 }
1321
1323 {
1324 if (id < 0 || id >= static_cast<int>(m_Particles.size())) {
1325 throw std::out_of_range("ThermalParticleSystem::Particle(int id): id is out of bounds!");
1326 }
1327 return m_Particles[id];
1328 }
1329
1331 {
1332 int id = PdgToId(pdgid);
1333 if (id == -1) {
1334 throw std::invalid_argument("ThermalParticleSystem::ParticleByPDG(long long pdgid): pdgid " + std::to_string(pdgid) + " is unknown");
1335 }
1336 return m_Particles[id];
1337 }
1338
1340 {
1341 int id = PdgToId(pdgid);
1342 if (id == -1) {
1343 throw std::invalid_argument("ThermalParticleSystem::ParticleByPDG(long long pdgid): pdgid " + std::to_string(pdgid) + " is unknown");
1344 }
1345 return m_Particles[id];
1346 }
1347
1348 int ThermalParticleSystem::PdgToId(long long pdgid) const
1349 {
1350 map<long long, int>::const_iterator it = m_PDGtoID.find(pdgid);
1351
1352 if (it != m_PDGtoID.end()) {
1353 return it->second;
1354 }
1355 else {
1356 return -1;
1357 }
1358 }
1359
1361 {
1362 m_NumBaryons = m_NumCharged = m_NumStrange = m_NumCharmed = 0;
1363 m_MaxAbsBaryonNumber = 0;
1364 m_NumberOfParticles = 0;
1365 m_PDGtoID.clear();
1366 for (size_t i = 0; i < m_Particles.size(); ++i) {
1367 m_PDGtoID[m_Particles[i].PdgId()] = i;
1368 if (m_Particles[i].BaryonCharge() != 0) m_NumBaryons++;
1369 if (m_Particles[i].ElectricCharge() != 0) m_NumCharged++;
1370 if (m_Particles[i].Strangeness() != 0) m_NumStrange++;
1371 if (m_Particles[i].Charm() != 0) m_NumCharmed++;
1372 if (m_Particles[i].PdgId() > 0) m_NumberOfParticles++;
1373 m_MaxAbsBaryonNumber = max(m_MaxAbsBaryonNumber, abs(m_Particles[i].BaryonCharge()));
1374 }
1375
1376 for (size_t i = 0; i < m_DecayContributionsByFeeddown.size(); ++i)
1377 m_DecayContributionsByFeeddown[i].resize(m_Particles.size());
1378 }
1379
1381 {
1383 sort(m_Particles.begin(), m_Particles.end(), cmpParticleMass);
1385 sort(m_Particles.begin(), m_Particles.end(), cmpParticleMassAndPdg);
1386 else
1387 sort(m_Particles.begin(), m_Particles.end(), cmpParticlePDG);
1388 FillPdgMap();
1389 for (size_t i = 0; i < m_Particles.size(); ++i) {
1390 if (m_Particles[i].DecayType() == ParticleDecayType::Default)
1391 m_Particles[i].SetDecayType( DecayTypeByParticleType(m_Particles[i]) );
1392 }
1393 }
1394
1396 {
1397 m_Particles.push_back(part);
1398 FillPdgMap();
1399 }
1400
1402 {
1403 if (ind >= 0 && ind < static_cast<int>(m_Particles.size())) {
1404 m_Particles.erase(m_Particles.begin() + ind);
1405 FillPdgMap();
1406 }
1407 }
1408
1410 {
1411 std::vector<int> check = CheckDecayChargesConservationVector(ind);
1412 for (int i = 0; i < check.size(); ++i)
1413 if (check[i] != 1)
1414 return false;
1415 return true;
1416 }
1417
1419 {
1420 bool ret = true;
1421 int cnt = 0;
1422 for (int i = 0; i < Particles().size(); ++i) {
1423 const ThermalParticle& part = Particles()[i];
1424 if (!part.IsStable() && part.Decays().size() == 0 && cnt < 10) {
1425 printf("**WARNING** %s (%lld): Particle marked unstable but no decay channels found!\n",
1426 part.Name().c_str(),
1427 part.PdgId());
1428 ret = false;
1429 cnt++;
1430 if (cnt == 10) {
1431 throw std::runtime_error("**WARNING** Further warnings are discarded...");
1432 }
1433 }
1434 }
1435 return ret;
1436 }
1437
1439 {
1440 bool ret = true;
1441 for (int i = 0; i < Particles().size(); ++i) {
1442 const ThermalParticle& part = Particles()[i];
1443 if (part.AbsoluteStrangeness() == 0 && part.Strangeness() != 0) {
1444 std::cerr << "**WARNING** " << part.Name() << " (" << part.PdgId() << "): Particle with non-zero strangeness has zero strange quark content |s|!" << std::endl;
1445 ret = false;
1446 }
1447
1448 if (part.AbsoluteCharm() == 0 && part.Charm() != 0) {
1449 std::cerr << "**WARNING** " << part.Name() << " (" << part.PdgId() << "): Particle with non-zero charm has zero charm quark content |s|!" << std::endl;
1450 ret = false;
1451 }
1452 }
1453 return ret;
1454 }
1455
1457 {
1458 const ThermalParticle& part = Particles()[ind];
1459 int goalB = part.BaryonCharge();
1460 int goalQ = part.ElectricCharge();
1461 int goalS = part.Strangeness();
1462 int goalC = part.Charm();
1463
1464 std::map<long long, int> tPDGtoID = m_PDGtoID;
1465
1466 std::vector<int> ret(4, 1);
1467
1468 for (size_t i = 0; i < part.Decays().size(); ++i) {
1469 int decB = 0, decQ = 0, decS = 0, decC = 0;
1470 for (size_t j = 0; j < part.Decays()[i].mDaughters.size(); ++j) {
1471 long long tpdg = part.Decays()[i].mDaughters[j];
1472 if (tPDGtoID.count(tpdg) != 0) {
1473 int tid = tPDGtoID[tpdg];
1474 decB += Particles()[tid].BaryonCharge();
1475 decQ += Particles()[tid].ElectricCharge();
1476 decS += Particles()[tid].Strangeness();
1477 decC += Particles()[tid].Charm();
1478 }
1479 else if (ExtraParticles::PdgToId(tpdg) != -1) {
1480 int tid = ExtraParticles::PdgToId(tpdg);
1484 decC += ExtraParticles::Particle(tid).Charm();
1485 }
1486 }
1487
1488 if (goalB != decB)
1489 ret[0] = 0;
1490 if (goalQ != decQ)
1491 ret[1] = 0;
1492 if (goalS != decS)
1493 ret[2] = 0;
1494 if (goalC != decC)
1495 ret[3] = 0;
1496 }
1497
1498 return ret;
1499 }
1500
1502 {
1503 bool ret = true;
1504 ret &= m_PDGtoID == rhs.m_PDGtoID;
1505 ret &= m_NumBaryons == rhs.m_NumBaryons;
1506 ret &= m_NumCharged == rhs.m_NumCharged;
1507 ret &= m_NumStrange == rhs.m_NumStrange;
1508 ret &= m_NumCharmed == rhs.m_NumCharmed;
1509 ret &= m_MaxAbsBaryonNumber == rhs.m_MaxAbsBaryonNumber;
1510 ret &= m_NumberOfParticles == rhs.m_NumberOfParticles;
1511 ret &= m_ResonanceWidthIntegrationType == rhs.m_ResonanceWidthIntegrationType;
1512 ret &= m_DecayDistributionsMap == rhs.m_DecayDistributionsMap;
1513
1514 ret &= m_Particles == rhs.m_Particles;
1515
1516 return ret;
1517 }
1518
1520 {
1521 // Check if it's a known stable (wrt to any time scale of relevance) particle
1522 set<long long> stablePDG;
1523 stablePDG.insert(2212); stablePDG.insert(-2212); // proton
1524 stablePDG.insert(2112); stablePDG.insert(-2112); // neutron
1525 stablePDG.insert(1000010020); stablePDG.insert(-1000010020); // deuteron
1526 stablePDG.insert(1000020030); stablePDG.insert(-1000020030); // He3
1527 stablePDG.insert(1000010030); stablePDG.insert(-1000010030); // triton
1528 stablePDG.insert(1000020040); stablePDG.insert(-1000020040); // He4
1529
1530 if (stablePDG.count(part.PdgId()) > 0) {
1532 }
1533
1534 // Check if it's a known weakly decaying particle
1535 set<long long> weakPDG;
1536 weakPDG.insert(310); // K0S
1537 weakPDG.insert(130); // K0L
1538 weakPDG.insert(211); weakPDG.insert(-211); // pi+-
1539 weakPDG.insert(321); weakPDG.insert(-321); // K+-
1540 weakPDG.insert(3122); weakPDG.insert(-3122); // Lambda
1541 weakPDG.insert(3222); weakPDG.insert(-3222); // Sigma+
1542 weakPDG.insert(3112); weakPDG.insert(-3112); // Sigma-
1543 weakPDG.insert(3322); weakPDG.insert(-3322); // Ksi0
1544 weakPDG.insert(3312); weakPDG.insert(-3312); // Ksi-
1545 weakPDG.insert(3334); weakPDG.insert(-3334); // Omega
1546 weakPDG.insert(411); weakPDG.insert(-411); // D+-
1547 weakPDG.insert(421); weakPDG.insert(-421); // D0
1548 weakPDG.insert(431); weakPDG.insert(-431); // Ds
1549 weakPDG.insert(4232); weakPDG.insert(-4232); // Ksic+
1550 weakPDG.insert(4132); weakPDG.insert(-4132); // Ksic0
1551 weakPDG.insert(4422); weakPDG.insert(-4422); // Ksicc++
1552 weakPDG.insert(4412); weakPDG.insert(-4412); // Ksicc+
1553 weakPDG.insert(4332); weakPDG.insert(-4332); // Omegac
1554
1555 if (weakPDG.count(part.PdgId()) > 0) {
1557 }
1558
1559 // Check if it's a known electromagnetically decaying particle
1560 // Note: we treat eta decay as "electromagnetic" although some of them are in fact isospin-invariance breaking strong decays
1561 set<long long> emPDG;
1562 emPDG.insert(111); // pi0
1563 emPDG.insert(221); // eta
1564 emPDG.insert(331); // eta'
1565 emPDG.insert(3212); emPDG.insert(-3212); // Sigma0
1566
1567 if (emPDG.count(part.PdgId()) > 0) {
1569 }
1570
1571 if (!part.IsStable()) // if particle not marked as stable assume it at least decays strongly
1572 {
1574 }
1575 else {
1576 // if contains strangeness (or charm), it is not stable under weak decays
1577 if (part.AbsoluteStrangeness() != 0 || part.AbsoluteCharm() != 0)
1579
1581 }
1582
1583
1585 }
1586
1588 m_DecayContributionsByFeeddown[Feeddown::Weak].resize(m_Particles.size());
1589 m_DecayContributionsByFeeddown[Feeddown::Electromagnetic].resize(m_Particles.size());
1590 m_DecayContributionsByFeeddown[Feeddown::Strong].resize(m_Particles.size());
1591 for (size_t i = 0; i < m_Particles.size(); ++i) {
1592 m_DecayContributionsByFeeddown[Feeddown::Weak][i].resize(0);
1593 m_DecayContributionsByFeeddown[Feeddown::Electromagnetic][i].resize(0);
1594 m_DecayContributionsByFeeddown[Feeddown::Strong][i].resize(0);
1595 }
1596 for (int i = static_cast<int>(m_Particles.size()) - 1; i >= 0; i--)
1597 if (m_Particles[i].DecayType() != ParticleDecayType::Stable && m_Particles[i].DecayType() != ParticleDecayType::Default) {
1598 GoResonanceByFeeddown(i, i, 1., Feeddown::Type(static_cast<int>(m_Particles[i].DecayType())));
1599 }
1600 }
1601
1602 void ThermalParticleSystem::GoResonanceByFeeddown(int ind, int startind, double BR, Feeddown::Type feeddown) {
1603 for (int feed_index = static_cast<int>(Feeddown::Weak); feed_index <= static_cast<int>(Feeddown::Strong); ++feed_index) {
1604 if (static_cast<int>(feeddown) < feed_index) continue;
1605 //std::vector< std::pair<double, int> >& decayContributions = m_Particles[ind].DecayContributionsByFeeddown()[feed_index];
1606 DecayContributionsToParticle& decayContributions = m_DecayContributionsByFeeddown[feed_index][ind];
1607 if (ind != startind && decayContributions.size() > 0 && decayContributions[decayContributions.size() - 1].second == startind)
1608 {
1609 decayContributions[decayContributions.size() - 1].first += BR;
1610 }
1611 else if (ind != startind) {
1612 decayContributions.push_back(make_pair(BR, startind));
1613 }
1614 }
1615
1616
1617 if (m_Particles[ind].DecayType() != ParticleDecayType::Stable && m_Particles[ind].DecayType() != ParticleDecayType::Default) {
1618 for (size_t i = 0; i < m_Particles[ind].Decays().size(); ++i) {
1619 const ParticleDecayChannel& decaychannel = m_Particles[ind].Decays()[i];
1620 double tbr = decaychannel.mBratio;
1621
1622 if (m_ResonanceWidthIntegrationType == ThermalParticle::eBW && ind == startind)
1623 tbr = decaychannel.mBratioAverage;
1624
1625 for (size_t j = 0; j < decaychannel.mDaughters.size(); ++j) {
1626 if (m_PDGtoID.count(decaychannel.mDaughters[j]) != 0)
1627 GoResonanceByFeeddown(m_PDGtoID[decaychannel.mDaughters[j]], startind, BR*tbr, Feeddown::Type(static_cast<int>(m_Particles[ind].DecayType())));
1628 }
1629 }
1630 }
1631 }
1632
1634 std::vector<double> ret(ComponentsNumber(), 0.);
1635 for (size_t i = 0; i < m_Particles.size(); ++i) {
1636 ret[i] = static_cast<double>(m_Particles[i].ConservedCharge(charge));
1637 }
1638 return ret;
1639 }
1640
1641
1642 namespace CuteHRGHelper {
1643 std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems) {
1644 std::stringstream ss(s);
1645 std::string item;
1646 while (std::getline(ss, item, delim)) {
1647 elems.push_back(item);
1648 }
1649 return elems;
1650 }
1651
1652 std::vector<std::string> split(const std::string& s, char delim) {
1653 std::vector<std::string> elems;
1654 split(s, delim, elems);
1655 return elems;
1656 }
1657
1658 void cutDecayDistributionsVector(std::vector< std::pair<double, std::vector<int> > >& vect, int maxsize)
1659 {
1660 if (static_cast<int>(vect.size()) > maxsize) {
1661 std::sort(vect.begin(), vect.end());
1662 std::reverse(vect.begin(), vect.end());
1663 vect.resize(1500);
1664 }
1665 }
1666 }
1667
1668 namespace DecayLifetimes {
1669 // lifetimes from pdg in seconds
1670 map<long long, double> lifetimes = {
1671 {211, 2.6033e-8}, // pi+-
1672 {111, 8.43e-17}, // pi0
1673 {321, 1.238e-8}, // K+-
1674 {310, 8.954e-11}, // K0S
1675 {130, 5.116e-8}, // K0L
1676 {411, 1.033e-12}, // D+-
1677 {421, 4.103e-13}, // D0
1678 {431, 5.012e-13}, // Ds+-
1679 {2112, 878.4}, // n
1680 {3122, 2.617e-10}, // Lambda
1681 {3222, 8.018e-11}, // Sigma+
1682 {3212, 74.e-21}, // Sigma0
1683 {3112, 1.479e-10}, // Sigma-
1684 {3322, 2.9e-10}, // Xi0
1685 {3312, 1.639e-10}, // Xi-
1686 {3334, 8.21e-11} // Omega-
1687 // TODO: Charmed baryons and hypernuclei
1688 };
1689
1690 // resonance widths in GeV
1691 map<long long, double> widths = {
1692 {221, 1.31e-6} // eta
1693 };
1694
1695 double GetLifetime(long long pdg) {
1696 if (lifetimes.count(abs(pdg)))
1697 return lifetimes[abs(pdg)] * 1.e15;
1698
1699 if (widths.count(abs(pdg))) {
1700 double width = widths[abs(pdg)];
1701 double ctau = 1. / (width * xMath::GeVtoifm());
1702 return ctau;
1703 }
1704
1705 // No entry found, return zero
1706 return 0.;
1707 }
1708 }
1709} // namespace thermalfist
Contains some helper functions.
static bool PrintDisclaimer()
Definition Utility.cpp:47
static bool DisclaimerPrinted
Definition Utility.h:27
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=1000)
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.