Thermal-FIST 1.6
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
EventGeneratorBase.cpp
Go to the documentation of this file.
1/*
2 * Thermal-FIST package
3 *
4 * Copyright (c) 2015-2019 Volodymyr Vovchenko
5 *
6 * GNU General Public License (GPLv3 or later)
7 */
9
10#include <functional>
11#include <algorithm>
12#include <stdexcept>
13
14#include "HRGBase/xMath.h"
26
27namespace thermalfist {
28
30 double EventGeneratorBase::m_LastWeight = 1., EventGeneratorBase::m_LastLogWeight = 0., EventGeneratorBase::m_LastNormWeight = 1.;
31
32 std::vector<double> LorentzBoost(const std::vector<double>& fourvector, double vx, double vy, double vz)
33 {
34 std::vector<double> ret(4, 0);
35 double v2 = vx * vx + vy * vy + vz * vz;
36 if (v2 == 0.0)
37 return fourvector;
38 double gamma = 1. / sqrt(1. - v2);
39
40 const double& r0 = fourvector[0];
41 const double& rx = fourvector[1];
42 const double& ry = fourvector[2];
43 const double& rz = fourvector[3];
44
45 ret[0] = gamma * r0 - gamma * (vx * rx + vy * ry + vz * rz);
46 ret[1] = -gamma * vx * r0 + (1. + (gamma - 1.) * vx * vx / v2) * rx +
47 (gamma - 1.) * vx * vy / v2 * ry + (gamma - 1.) * vx * vz / v2 * rz;
48 ret[2] = -gamma * vy * r0 + (1. + (gamma - 1.) * vy * vy / v2) * ry +
49 (gamma - 1.) * vy * vx / v2 * rx + (gamma - 1.) * vy * vz / v2 * rz;
50 ret[3] = -gamma * vz * r0 + (1. + (gamma - 1.) * vz * vz / v2) * rz +
51 (gamma - 1.) * vz * vx / v2 * rx + (gamma - 1.) * vz * vy / v2 * ry;
52
53 return ret;
54 }
55
57 m_THM(NULL), m_ParametersSet(false),
58 m_MeanB(0.), m_MeanAB(0.),
59 m_MeanSM(0.), m_MeanASM(0.),
60 m_MeanCM(0.), m_MeanACM(0.),
61 m_MeanCHRM(0.), m_MeanACHRM(0.),
62 m_MeanCHRMM(0.), m_MeanACHRMM(0.)
63 {
64 fCEAccepted = fCETotal = 0;
65 }
66
71
73 {
74 for (size_t i = 0; i < m_MomentumGens.size(); ++i) {
75 if (m_MomentumGens[i] != NULL)
76 delete m_MomentumGens[i];
77 }
78 m_MomentumGens.resize(0);
79
80 for (size_t i = 0; i < m_BWGens.size(); ++i) {
81 if (m_BWGens[i] != NULL)
82 delete m_BWGens[i];
83 }
84 m_BWGens.resize(0);
85 }
86
87 //void EventGeneratorBase::SetConfiguration(const ThermalModelParameters& params, EventGeneratorConfiguration::Ensemble ensemble, EventGeneratorConfiguration::ModelType modeltype, ThermalParticleSystem *TPS, ThermalModelBase *THMEVVDW)
89 const EventGeneratorConfiguration& config)
90 {
91 m_Config = config;
93
94 if (TPS == NULL)
95 return;
96
98 m_Config.CFOParameters.muC = 0.;
99 }
100 else if (m_Config.fEnsemble == EventGeneratorConfiguration::SCE) {
101 m_Config.CFOParameters.muS = 0.;
102 m_Config.CFOParameters.muC = 0.;
103 }
104 else if (0 && m_Config.fEnsemble == EventGeneratorConfiguration::CE) {
105 if (m_Config.CanonicalB)
106 m_Config.CFOParameters.muB = 0.;
107 if (m_Config.CanonicalS)
108 m_Config.CFOParameters.muS = 0.;
109 if (m_Config.CanonicalQ)
110 m_Config.CFOParameters.muQ = 0.;
111 if (m_Config.CanonicalC)
112 m_Config.CFOParameters.muC = 0.;
113 }
114
116 m_THM = new ThermalModelIdeal(TPS, m_Config.CFOParameters);
117 }
118 else if (m_Config.fModelType == EventGeneratorConfiguration::DiagonalEV) {
119 m_THM = new ThermalModelEVDiagonal(TPS, m_Config.CFOParameters);
120 }
122 m_THM = new ThermalModelEVCrossterms(TPS, m_Config.CFOParameters);
123 }
124 else if (m_Config.fModelType == EventGeneratorConfiguration::QvdW) {
125 m_THM = new ThermalModelVDWFull(TPS, m_Config.CFOParameters);
126 }
127 else if (m_Config.fModelType == EventGeneratorConfiguration::RealGas) {
128 m_THM = new ThermalModelRealGas(TPS, m_Config.CFOParameters);
129 }
130
131 if (m_Config.fEnsemble == EventGeneratorConfiguration::CE && m_Config.fUseGCEConservedCharges) {
132 if (!m_Config.fUsePCE)
133 m_THM->FillChemicalPotentials();
134 else
135 m_THM->SetChemicalPotentials(m_Config.fPCEChems);
136
137 m_THM->CalculatePrimordialDensities();
138
139 // Round to nearest integer
140 m_Config.B = lround(m_THM->BaryonDensity() * m_THM->Volume());
141 m_Config.Q = lround(m_THM->ElectricChargeDensity() * m_THM->Volume());
142 m_Config.S = lround(m_THM->StrangenessDensity() * m_THM->Volume());
143 m_Config.C = lround(m_THM->CharmDensity() * m_THM->Volume());
144 }
145
146 m_THM->SetUseWidth(TPS->ResonanceWidthIntegrationType());
147
148 m_THM->ConstrainMuB(false);
149 m_THM->ConstrainMuQ(false);
150 m_THM->ConstrainMuS(false);
151 m_THM->ConstrainMuC(false);
152
153 if (!m_Config.fUsePCE)
154 m_THM->FillChemicalPotentials();
155 else
156 m_THM->SetChemicalPotentials(m_Config.fPCEChems);
157
161 for (size_t i = 0; i < m_THM->Densities().size(); ++i) {
162 for (size_t j = 0; j < m_THM->Densities().size(); ++j) {
163 if (m_Config.bij.size() == m_THM->Densities().size()
164 && m_Config.bij[i].size() == m_THM->Densities().size())
165 m_THM->SetVirial(i, j, m_Config.bij[i][j]);
166
167 if (m_Config.aij.size() == m_THM->Densities().size()
168 && m_Config.aij[i].size() == m_THM->Densities().size())
169 m_THM->SetAttraction(i, j, m_Config.aij[i][j]);
170 }
171 }
172 }
173
176 if (config.RealGasExcludedVolumePrescription == 0) {
177 evmod = new ExcludedVolumeModelVDW();
178 }
179 else if (config.RealGasExcludedVolumePrescription == 1) {
180 evmod = new ExcludedVolumeModelCS();
181 }
182 else if (config.RealGasExcludedVolumePrescription == 2) {
183 evmod = new ExcludedVolumeModelVirial();
184 }
185 else if (config.RealGasExcludedVolumePrescription == 3) {
186 evmod = new ExcludedVolumeModelTVM();
187 }
188 else {
189 evmod = new ExcludedVolumeModelVDW();
190 }
191 static_cast<ThermalModelRealGas*>(m_THM)->SetExcludedVolumeModel(new ExcludedVolumeModelCrosstermsGeneralized(evmod, m_Config.bij));
192 static_cast<ThermalModelRealGas*>(m_THM)->SetMeanFieldModel(new MeanFieldModelMultiVDW(m_Config.aij));
193 }
194
195 if (m_Config.fEnsemble == EventGeneratorConfiguration::CE) {
196 // The following procedure currently not used,
197 // but can be considered if SolveChemicalPotentials routine fails
198 // Note to take into account PCE possiblity if this option is considered
199 // TODO: Properly for mixed-canonical ensembles and charm
200 if (0 && !(m_Config.B == 0 && m_Config.Q == 0 && m_Config.S == 0) && !m_Config.fUsePCE) {
201 if (m_Config.S == 0 && !(m_Config.Q == 0 || m_Config.B == 0)) {
202 double QBrat = (double)(m_Config.Q) / m_Config.B;
203
204 double left = 0.000, right = 0.900, center;
205
206 m_THM->SetBaryonChemicalPotential(left);
207 m_THM->SetQoverB(QBrat);
208 m_THM->FixParameters();
209 m_THM->CalculatePrimordialDensities();
210 double valleft = m_THM->CalculateBaryonDensity() * m_THM->Volume() - m_Config.B;
211
212 m_THM->SetBaryonChemicalPotential(right);
213 m_THM->SetQoverB(QBrat);
214 m_THM->FixParameters();
215 m_THM->CalculatePrimordialDensities();
216 double valright = m_THM->CalculateBaryonDensity() * m_THM->Volume() - m_Config.B;
217
218 double valcenter;
219
220 while ((right - left) > 0.00001) {
221 center = (left + right) / 2.;
222 m_THM->SetBaryonChemicalPotential(center);
223 m_THM->SetQoverB(QBrat);
224 m_THM->FixParameters();
225 m_THM->CalculatePrimordialDensities();
226 valcenter = m_THM->CalculateBaryonDensity() * m_THM->Volume() - m_Config.B;
227
228 if (valleft*valcenter > 0.) {
229 left = center;
230 valleft = valcenter;
231 }
232 else {
233 right = center;
234 valright = valcenter;
235 }
236 }
237
238 m_THM->SetBaryonChemicalPotential(center);
239 m_THM->SetQoverB(QBrat);
240 m_THM->FixParameters();
241
242 m_Config.CFOParameters.muB = m_THM->Parameters().muB;
243 m_Config.CFOParameters.muS = m_THM->Parameters().muS;
244 m_Config.CFOParameters.muQ = m_THM->Parameters().muQ;
245
246 m_THM->FillChemicalPotentials();
247 }
248 }
249
250 if (!m_Config.fUsePCE)
251 {
252 bool solve_chems = m_THM->SolveChemicalPotentials(m_Config.B, m_Config.Q, m_Config.S, m_Config.C,
253 m_THM->Parameters().muB, m_THM->Parameters().muQ, m_THM->Parameters().muS, m_THM->Parameters().muC,
254 m_Config.CanonicalB, m_Config.CanonicalQ, m_Config.CanonicalS, m_Config.CanonicalC);
255 if (m_THM->Parameters().muB != m_THM->Parameters().muB ||
256 m_THM->Parameters().muQ != m_THM->Parameters().muQ ||
257 m_THM->Parameters().muS != m_THM->Parameters().muS ||
258 m_THM->Parameters().muC != m_THM->Parameters().muC ||
259 !solve_chems)
260 {
261 printf("**WARNING** Could not constrain chemical potentials. Setting all for exactly conserved charges to zero...\n");
262 if (m_Config.CanonicalB)
263 m_THM->SetBaryonChemicalPotential(0.);
264 else
265 m_THM->SetBaryonChemicalPotential(m_Config.CFOParameters.muB);
266
267 if (m_Config.CanonicalQ)
268 m_THM->SetElectricChemicalPotential(0.);
269 else
270 m_THM->SetElectricChemicalPotential(m_Config.CFOParameters.muQ);
271
272 if (m_Config.CanonicalS)
273 m_THM->SetStrangenessChemicalPotential(0.);
274 else
275 m_THM->SetStrangenessChemicalPotential(m_Config.CFOParameters.muS);
276
277 if (m_Config.CanonicalC)
278 m_THM->SetCharmChemicalPotential(0.);
279 else
280 m_THM->SetCharmChemicalPotential(m_Config.CFOParameters.muC);
281
282 m_THM->FillChemicalPotentials();
283 }
284 m_Config.CFOParameters.muB = m_THM->Parameters().muB;
285 m_Config.CFOParameters.muS = m_THM->Parameters().muS;
286 m_Config.CFOParameters.muQ = m_THM->Parameters().muQ;
287 m_Config.CFOParameters.muC = m_THM->Parameters().muC;
288
289 //std::cout << "Chemical potentials constrained!\n"
290 // << "muB = " << m_Config.CFOParameters.muB
291 // << " muQ = " << m_Config.CFOParameters.muQ
292 // << " muS = " << m_Config.CFOParameters.muS
293 // << " muC = " << m_Config.CFOParameters.muC << "\n";
294
295 //std::cout << "B = " << m_THM->CalculateBaryonDensity() * m_THM->Parameters().V
296 // << " Q = " << m_THM->CalculateChargeDensity() * m_THM->Parameters().V
297 // << " S = " << m_THM->CalculateStrangenessDensity() * m_THM->Parameters().V
298 // << " C = " << m_THM->CalculateCharmDensity() * m_THM->Parameters().V
299 // << "\n";
300 }
301 }
302
303 if (m_Config.fEnsemble == EventGeneratorConfiguration::SCE && !m_Config.fUsePCE) {
304 m_THM->ConstrainMuS(true);
305 m_THM->ConstrainMuC(true);
306 m_THM->ConstrainChemicalPotentials();
307 m_THM->FillChemicalPotentials();
308 m_Config.CFOParameters.muS = m_THM->Parameters().muS;
309 m_Config.CFOParameters.muC = m_THM->Parameters().muC;
310 }
311
312 if (m_Config.fEnsemble == EventGeneratorConfiguration::CCE && !m_Config.fUsePCE) {
313 m_THM->ConstrainMuC(true);
314 m_THM->ConstrainChemicalPotentials();
315 m_THM->FillChemicalPotentials();
316 m_Config.CFOParameters.muC = m_THM->Parameters().muC;
317 }
318
319 //m_THM->CalculateDensitiesGCE();
320 m_THM->CalculatePrimordialDensities();
321 m_DensitiesIdeal = m_THM->GetIdealGasDensities();
322
325
326 m_Radii = ComputeEVRadii();
327 }
328
329
331 if (!m_THM->IsCalculated()) {
332 m_THM->CalculatePrimordialDensities();
333 }
334
335 m_Baryons.resize(0);
336 m_AntiBaryons.resize(0);
337 m_StrangeMesons.resize(0);
338 m_AntiStrangeMesons.resize(0);
339 m_ChargeMesons.resize(0);
340 m_AntiChargeMesons.resize(0);
341 m_CharmMesons.resize(0);
342 m_AntiCharmMesons.resize(0);
343 m_CharmAll.resize(0);
344 m_AntiCharmAll.resize(0);
345 m_MeanB = 0.;
346 m_MeanAB = 0.;
347 m_MeanSM = 0.;
348 m_MeanASM = 0.;
349 m_MeanCM = 0.;
350 m_MeanACM = 0.;
351 m_MeanCHRMM = 0.;
352 m_MeanACHRMM = 0.;
353 m_MeanCHRM = 0.;
354 m_MeanACHRM = 0.;
355
356 std::vector<double> yields = m_THM->Densities();
357 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i)
358 yields[i] *= m_THM->Volume();
359
360 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
361 if (m_THM->TPS()->Particles()[i].BaryonCharge() == 1) {
362 m_Baryons.push_back(std::make_pair(yields[i], i));
363 m_MeanB += yields[i];
364 }
365 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == -1) {
366 m_AntiBaryons.push_back(std::make_pair(yields[i], i));
367 m_MeanAB += yields[i];
368 }
369 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == 1) {
370 m_StrangeMesons.push_back(std::make_pair(yields[i], i));
371 m_MeanSM += yields[i];
372 }
373 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == -1) {
374 m_AntiStrangeMesons.push_back(std::make_pair(yields[i], i));
375 m_MeanASM += yields[i];
376 }
377 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == 0 && m_THM->TPS()->Particles()[i].ElectricCharge() == 1) {
378 m_ChargeMesons.push_back(std::make_pair(yields[i], i));
379 m_MeanCM += yields[i];
380 }
381 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == 0 && m_THM->TPS()->Particles()[i].ElectricCharge() == -1) {
382 m_AntiChargeMesons.push_back(std::make_pair(yields[i], i));
383 m_MeanACM += yields[i];
384 }
385 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == 0 && m_THM->TPS()->Particles()[i].ElectricCharge() == 0 && m_THM->TPS()->Particles()[i].Charm() == 1) {
386 m_CharmMesons.push_back(std::make_pair(yields[i], i));
387 m_MeanCHRMM += yields[i];
388 }
389 else if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0 && m_THM->TPS()->Particles()[i].Strangeness() == 0 && m_THM->TPS()->Particles()[i].ElectricCharge() == 0 && m_THM->TPS()->Particles()[i].Charm() == -1) {
390 m_AntiCharmMesons.push_back(std::make_pair(yields[i], i));
391 m_MeanACHRMM += yields[i];
392 }
393
394 if (m_THM->TPS()->Particles()[i].Charm() == 1) {
395 m_CharmAll.push_back(std::make_pair(yields[i], i));
396 m_MeanCHRM += yields[i];
397 }
398 else if (m_THM->TPS()->Particles()[i].Charm() == -1) {
399 m_AntiCharmAll.push_back(std::make_pair(yields[i], i));
400 m_MeanACHRM += yields[i];
401 }
402 }
403
404 // sort in descending order and convert to prefix sums
405 std::sort(m_Baryons.begin(), m_Baryons.end(), std::greater< std::pair<double, int> >());
406 std::sort(m_AntiBaryons.begin(), m_AntiBaryons.end(), std::greater< std::pair<double, int> >());
407 std::sort(m_StrangeMesons.begin(), m_StrangeMesons.end(), std::greater< std::pair<double, int> >());
408 std::sort(m_AntiStrangeMesons.begin(), m_AntiStrangeMesons.end(), std::greater< std::pair<double, int> >());
409 std::sort(m_ChargeMesons.begin(), m_ChargeMesons.end(), std::greater< std::pair<double, int> >());
410 std::sort(m_AntiChargeMesons.begin(), m_AntiChargeMesons.end(), std::greater< std::pair<double, int> >());
411 std::sort(m_CharmMesons.begin(), m_CharmMesons.end(), std::greater< std::pair<double, int> >());
412 std::sort(m_AntiCharmMesons.begin(), m_AntiCharmMesons.end(), std::greater< std::pair<double, int> >());
413 std::sort(m_CharmAll.begin(), m_CharmAll.end(), std::greater< std::pair<double, int> >());
414 std::sort(m_AntiCharmAll.begin(), m_AntiCharmAll.end(), std::greater< std::pair<double, int> >());
415
416 for (int i = 1; i < static_cast<int>(m_Baryons.size()); ++i) m_Baryons[i].first += m_Baryons[i - 1].first;
417 for (int i = 1; i < static_cast<int>(m_AntiBaryons.size()); ++i) m_AntiBaryons[i].first += m_AntiBaryons[i - 1].first;
418 for (int i = 1; i < static_cast<int>(m_StrangeMesons.size()); ++i) m_StrangeMesons[i].first += m_StrangeMesons[i - 1].first;
419 for (int i = 1; i < static_cast<int>(m_AntiStrangeMesons.size()); ++i) m_AntiStrangeMesons[i].first += m_AntiStrangeMesons[i - 1].first;
420 for (int i = 1; i < static_cast<int>(m_ChargeMesons.size()); ++i) m_ChargeMesons[i].first += m_ChargeMesons[i - 1].first;
421 for (int i = 1; i < static_cast<int>(m_AntiChargeMesons.size()); ++i) m_AntiChargeMesons[i].first += m_AntiChargeMesons[i - 1].first;
422 for (int i = 1; i < static_cast<int>(m_CharmMesons.size()); ++i) m_CharmMesons[i].first += m_CharmMesons[i - 1].first;
423 for (int i = 1; i < static_cast<int>(m_AntiCharmMesons.size()); ++i) m_AntiCharmMesons[i].first += m_AntiCharmMesons[i - 1].first;
424 for (int i = 1; i < static_cast<int>(m_CharmAll.size()); ++i) m_CharmAll[i].first += m_CharmAll[i - 1].first;
425 for (int i = 1; i < static_cast<int>(m_AntiCharmAll.size()); ++i) m_AntiCharmAll[i].first += m_AntiCharmAll[i - 1].first;
426 }
427
428 std::vector<int> EventGeneratorBase::GenerateTotals() const {
429 const_cast<EventGeneratorBase*>(this)->CheckSetParameters();
430
431 if (!m_THM->IsCalculated())
432 m_THM->CalculatePrimordialDensities();
433
434 std::vector<int> totals(m_THM->TPS()->Particles().size());
435
436 m_LastWeight = 1.;
437 m_LastNormWeight = 1.;
438
439 while (true) {
440 // First generate a configuration which satisfies conservation laws
442 totals = GenerateTotalsCCE();
443 else if (m_Config.fEnsemble == EventGeneratorConfiguration::SCE)
444 totals = GenerateTotalsSCE();
445 else if (m_Config.fEnsemble == EventGeneratorConfiguration::CE)
446 totals = GenerateTotalsCE();
447 else
448 totals = GenerateTotalsGCE();
449
450 double weight = ComputeWeightNew(totals);
451 //std::cout << ComputeWeight(totals) << " " << ComputeWeightNew(totals) << "\n";
452 if (weight < 0.)
453 continue;
454
455 break;
456 }
457
458 fCEAccepted++;
459
460 return totals;
461 }
462
464 {
465 fCETotal++;
466
467 //if (!m_THM->IsGCECalculated())
468 // m_THM->CalculateDensitiesGCE();
469 if (!m_THM->IsCalculated())
470 m_THM->CalculatePrimordialDensities();
471 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
472
473 const std::vector<double>& densities = m_THM->Densities();
474 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
475 double mean = densities[i] * m_THM->Volume();
476 int total = RandomGenerators::RandomPoisson(mean);
477 totals[i] = total;
478 }
479
480 return totals;
481 }
482
484 {
485 if (!m_THM->IsCalculated())
486 m_THM->CalculatePrimordialDensities();
487
488 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
489
490 // Generate SCE configuration depending on whether Vc > V, Vc = V, or Vc < V
491 while (true) {
492 const std::vector<double>& densities = m_THM->Densities();
493
494 // If Vc = V then just generate yields from a single ensemble
495 if (m_THM->Volume() == m_THM->CanonicalVolume()) {
496 totals = GenerateTotalsSCESubVolume(m_THM->Volume());
497 }
498 // If Vc > V then generate yields from a single ensemble with volume Vc
499 // particle from this ensemble is within a smaller volume V
500 // with probability V/Vc
501 else if (m_THM->Volume() < m_THM->CanonicalVolume()) {
502 std::vector<int> totalsaux = GenerateTotalsSCESubVolume(m_THM->CanonicalVolume());
503 double prob = m_THM->Volume() / m_THM->CanonicalVolume();
504 for (size_t i = 0; i < totalsaux.size(); ++i) {
505 for (int j = 0; j < totalsaux[i]; ++j) {
506 if (RandomGenerators::randgenMT.rand() < prob)
507 totals[i]++;
508 }
509 }
510 }
511 // If V > Vc then generate yields from (int)(V/Vc) SCE ensembles
512 // plus special treatment of one more ensemble if (V mod Vc) != 0
513 else {
514 // Number of normal SCE sub-ensembles
515 int multiples = static_cast<int>(m_THM->Volume() / m_THM->CanonicalVolume());
516
517 for (int iter = 0; iter < multiples; ++iter) {
518 std::vector<int> totalsaux = GenerateTotalsSCESubVolume(m_THM->CanonicalVolume());
519 for (size_t i = 0; i < totalsaux.size(); ++i)
520 totals[i] += totalsaux[i];
521 }
522
523 // For (V mod Vc) != 0 there is one more subvolume Vsub < Vc
524 double fraction = (m_THM->Volume() - multiples * m_THM->CanonicalVolume()) / m_THM->CanonicalVolume();
525
526 if (fraction > 0.0) {
527
528 bool successflag = false;
529
530 while (!successflag) {
531
532 std::vector<int> totalsaux = GenerateTotalsSCESubVolume(m_THM->CanonicalVolume());
533 std::vector<int> totalsaux2(m_THM->TPS()->Particles().size(), 0);
534 int netS = 0;
535 for (size_t i = 0; i < totalsaux.size(); ++i) {
536 if (m_THM->TPS()->Particles()[i].Strangeness() > 0) {
537 for (int j = 0; j < totalsaux[i]; ++j) {
538 if (RandomGenerators::randgenMT.rand() < fraction) {
539 totalsaux2[i]++;
540 netS += m_THM->TPS()->Particles()[i].Strangeness();
541 }
542 }
543 }
544 }
545
546 // Check if possible to match S+ with S-
547 // If S = 1 then must be at least one S = -1 hadron
548 if (netS == 1) {
549 bool fl = false;
550 for (size_t i = 0; i < totalsaux.size(); ++i) {
551 if (m_THM->TPS()->Particles()[i].Strangeness() < 0 && totalsaux[i] > 0) {
552 fl = true;
553 break;
554 }
555 }
556 if (!fl) {
557 printf("**WARNING** SCE Event generator: Cannot match S- with S+ = 1, discarding subconfiguration...\n");
558 continue;
559 }
560 }
561
562 int repeatmax = 10000;
563 int repeat = 0;
564 while (true) {
565 int netS2 = netS;
566 for (size_t i = 0; i < totalsaux.size(); ++i) {
567 if (m_THM->TPS()->Particles()[i].Strangeness() < 0) {
568 totalsaux2[i] = 0;
569 for (int j = 0; j < totalsaux[i]; ++j) {
570 if (RandomGenerators::randgenMT.rand() < fraction) {
571 totalsaux2[i]++;
572 netS2 += m_THM->TPS()->Particles()[i].Strangeness();
573 }
574 }
575 }
576 }
577 if (netS2 == 0) {
578 for (size_t i = 0; i < totalsaux2.size(); ++i)
579 totals[i] += totalsaux2[i];
580 successflag = true;
581 break;
582 }
583 repeat++;
584 if (repeat >= repeatmax) {
585 printf("**WARNING** SCE event generator: Cannot match S- with S+, too many tries, discarding configuration...\n");
586 break;
587 }
588 }
589 }
590 }
591 }
592
593 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
594 if (m_THM->TPS()->Particles()[i].Strangeness() == 0) {
595 double mean = densities[i] * m_THM->Volume();
596 int total = RandomGenerators::RandomPoisson(mean);
597 totals[i] = total;
598 }
599 }
600
601 return totals;
602 }
603
604 return totals;
605 }
606
607 std::vector<int> EventGeneratorBase::GenerateTotalsSCESubVolume(double VolumeSC) const
608 {
609 if (!m_THM->IsCalculated())
610 m_THM->CalculatePrimordialDensities();
611 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
612
613 std::vector< std::pair<double, int> > fStrangeMesonsc = m_StrangeMesons;
614 std::vector< std::pair<double, int> > fAntiStrangeMesonsc = m_AntiStrangeMesons;
615
616 for (size_t i = 0; i < fStrangeMesonsc.size(); ++i)
617 fStrangeMesonsc[i].first *= VolumeSC / m_THM->Volume();
618
619 for (size_t i = 0; i < fAntiStrangeMesonsc.size(); ++i)
620 fAntiStrangeMesonsc[i].first *= VolumeSC / m_THM->Volume();
621
622 double fMeanSMc = m_MeanSM * VolumeSC / m_THM->Volume();
623 double fMeanASMc = m_MeanASM * VolumeSC / m_THM->Volume();
624
625 while (1) {
626 fCETotal++;
627 const std::vector<double>& densities = m_THM->Densities();
628
629 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) totals[i] = 0;
630 int netS = 0;
631 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
632 if (m_THM->TPS()->Particles()[i].BaryonCharge() != 0 && m_THM->TPS()->Particles()[i].Strangeness() != 0) {
633 double mean = densities[i] * VolumeSC;
634 int total = RandomGenerators::RandomPoisson(mean);
635 totals[i] = total;
636 netS += totals[i] * m_THM->TPS()->Particles()[i].Strangeness();
637 }
638 }
639 int tSM = RandomGenerators::RandomPoisson(fMeanSMc);
640 int tASM = RandomGenerators::RandomPoisson(fMeanASMc);
641
642 if (netS != tASM - tSM) continue;
643
644 for (int i = 0; i < tSM; ++i) {
645 std::vector< std::pair<double, int> >::iterator it = lower_bound(fStrangeMesonsc.begin(), fStrangeMesonsc.end(), std::make_pair(fMeanSMc*RandomGenerators::randgenMT.rand(), 0));
646 int tind = std::distance(fStrangeMesonsc.begin(), it);
647 if (tind < 0) tind = 0;
648 if (tind >= static_cast<int>(fStrangeMesonsc.size())) tind = fStrangeMesonsc.size() - 1;
649 totals[fStrangeMesonsc[tind].second]++;
650 }
651 for (int i = 0; i < tASM; ++i) {
652 std::vector< std::pair<double, int> >::iterator it = lower_bound(fAntiStrangeMesonsc.begin(), fAntiStrangeMesonsc.end(), std::make_pair(fMeanASMc*RandomGenerators::randgenMT.rand(), 0));
653 int tind = std::distance(fAntiStrangeMesonsc.begin(), it);
654 if (tind < 0) tind = 0;
655 if (tind >= static_cast<int>(fAntiStrangeMesonsc.size())) tind = fAntiStrangeMesonsc.size() - 1;
656 totals[fAntiStrangeMesonsc[tind].second]++;
657 }
658
659 // Cross-check that all resulting strangeness is zero
660 int finS = 0;
661 for (size_t i = 0; i < totals.size(); ++i) {
662 finS += totals[i] * m_THM->TPS()->Particles()[i].Strangeness();
663 }
664
665 if (finS != 0) {
666 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsSCESubVolume(): Generated strangeness is non-zero!");
667 }
668
669 return totals;
670 }
671 return totals;
672 }
673
675 {
676 if (!m_THM->IsCalculated())
677 m_THM->CalculatePrimordialDensities();
678
679 // Check there are no multi-charmed particles, otherwise error
680 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
681 if (abs(m_THM->TPS()->Particles()[i].Charm()) > 1) {
682 throw std::runtime_error("CCE Event generator does not support lists with multi-charmed particles");
683 }
684 }
685
686 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
687
688 // Generate CCE configuration depending on whether Vc > V, Vc = V, or Vc < V
689 const std::vector<double>& densities = m_THM->Densities();
690
691 // If Vc = V then just generate yields from a single ensemble
692 if (m_THM->Volume() == m_THM->CanonicalVolume()) {
693 totals = GenerateTotalsCCESubVolume(m_THM->Volume());
694 }
695 // If Vc > V then generate yields from a single ensemble with volume Vc
696 // particle from this ensemble is within a smaller volume V
697 // with probability V/Vc
698 else if (m_THM->Volume() < m_THM->CanonicalVolume()) {
699 std::vector<int> totalsaux = GenerateTotalsCCESubVolume(m_THM->CanonicalVolume());
700 double prob = m_THM->Volume() / m_THM->CanonicalVolume();
701 for (size_t i = 0; i < totalsaux.size(); ++i) {
702 for (int j = 0; j < totalsaux[i]; ++j) {
703 if (RandomGenerators::randgenMT.rand() < prob)
704 totals[i]++;
705 }
706 }
707 }
708 // If V > Vc then generate yields from (int)(V/Vc) SCE ensembles
709 // plus special treatment of one more ensemble if (V mod Vc) != 0
710 else {
711 // Number of normal CCE sub-ensembles
712 int multiples = static_cast<int>(m_THM->Volume() / m_THM->CanonicalVolume());
713
714 for (int iter = 0; iter < multiples; ++iter) {
715 std::vector<int> totalsaux = GenerateTotalsCCESubVolume(m_THM->CanonicalVolume());
716 for (size_t i = 0; i < totalsaux.size(); ++i)
717 totals[i] += totalsaux[i];
718 }
719
720 // For (V mod Vc) != 0 there is one more subvolume Vsub < Vc
721 double fraction = (m_THM->Volume() - multiples * m_THM->CanonicalVolume()) / m_THM->CanonicalVolume();
722
723 if (fraction > 0.0) {
724
725 bool successflag = false;
726
727 while (!successflag) {
728
729 std::vector<int> totalsaux = GenerateTotalsCCESubVolume(m_THM->CanonicalVolume());
730 std::vector<int> totalsaux2(m_THM->TPS()->Particles().size(), 0);
731 int netC = 0;
732 for (size_t i = 0; i < totalsaux.size(); ++i) {
733 if (m_THM->TPS()->Particles()[i].Charm() > 0) {
734 for (int j = 0; j < totalsaux[i]; ++j) {
735 if (RandomGenerators::randgenMT.rand() < fraction) {
736 totalsaux2[i]++;
737 netC += m_THM->TPS()->Particles()[i].Charm();
738 }
739 }
740 }
741 }
742
743 // Check if possible to match C+ with C-
744 // If C = 1 then must be at least one C = -1 hadron
745 if (netC == 1) {
746 bool fl = false;
747 for (size_t i = 0; i < totalsaux.size(); ++i) {
748 if (m_THM->TPS()->Particles()[i].Charm() < 0 && totalsaux[i] > 0) {
749 fl = true;
750 break;
751 }
752 }
753 if (!fl) {
754 printf("**WARNING** CCE Event generator: Cannot match C- with C+ = 1, discarding...\n");
755 continue;
756 }
757 }
758
759 int repeatmax = 10000;
760 int repeat = 0;
761 while (true) {
762 int netC2 = netC;
763 for (size_t i = 0; i < totalsaux.size(); ++i) {
764 if (m_THM->TPS()->Particles()[i].Charm() < 0) {
765 totalsaux2[i] = 0;
766 for (int j = 0; j < totalsaux[i]; ++j) {
767 if (RandomGenerators::randgenMT.rand() < fraction) {
768 totalsaux2[i]++;
769 netC2 += m_THM->TPS()->Particles()[i].Charm();
770 }
771 }
772 }
773 }
774 if (netC2 == 0) {
775 for (size_t i = 0; i < totalsaux2.size(); ++i)
776 totals[i] += totalsaux2[i];
777 successflag = true;
778 break;
779 }
780 repeat++;
781 if (repeat >= repeatmax) {
782 printf("**WARNING** CCE event generator: Cannot match S- with S+, too many tries, discarding...\n");
783 break;
784 }
785 }
786 }
787 }
788 }
789
790 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
791 if (m_THM->TPS()->Particles()[i].Charm() == 0) {
792 double mean = densities[i] * m_THM->Volume();
793 int total = RandomGenerators::RandomPoisson(mean);
794 totals[i] = total;
795 }
796 }
797
798 return totals;
799 }
800
801 std::vector<int> EventGeneratorBase::GenerateTotalsCCESubVolume(double VolumeSC) const
802 {
803 if (!m_THM->IsCalculated())
804 m_THM->CalculatePrimordialDensities();
805
806 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
807
808 std::vector< std::pair<double, int> > fCharmAllc = m_CharmAll;
809 std::vector< std::pair<double, int> > fAntiCharmAllc = m_AntiCharmAll;
810
811 for (size_t i = 0; i < fCharmAllc.size(); ++i)
812 fCharmAllc[i].first *= VolumeSC / m_THM->Volume();
813
814 for (size_t i = 0; i < fAntiCharmAllc.size(); ++i)
815 fAntiCharmAllc[i].first *= VolumeSC / m_THM->Volume();
816
817 // Assuming no multi-charmed particles
818 double fMeanCharmc = m_MeanCHRM * VolumeSC / m_THM->Volume();
819 double fMeanAntiCharmc = m_MeanACHRM * VolumeSC / m_THM->Volume();
820
821 fCETotal++;
822
823 int netC = 0;
824 int tC = RandomGenerators::RandomPoisson(fMeanCharmc);
825 int tAC = RandomGenerators::RandomPoisson(fMeanAntiCharmc);
826 while (tC - tAC != m_Config.C - netC) {
827 fCETotal++;
828 tC = RandomGenerators::RandomPoisson(fMeanCharmc);
829 tAC = RandomGenerators::RandomPoisson(fMeanAntiCharmc);
830 }
831
832 for (int i = 0; i < tC; ++i) {
833 std::vector< std::pair<double, int> >::iterator it = lower_bound(fCharmAllc.begin(), fCharmAllc.end(), std::make_pair(fMeanCharmc*RandomGenerators::randgenMT.rand(), 0));
834 int tind = std::distance(fCharmAllc.begin(), it);
835 if (tind < 0) tind = 0;
836 if (tind >= static_cast<int>(fCharmAllc.size())) tind = fCharmAllc.size() - 1;
837 totals[fCharmAllc[tind].second]++;
838 }
839 for (int i = 0; i < tAC; ++i) {
840 std::vector< std::pair<double, int> >::iterator it = lower_bound(fAntiCharmAllc.begin(), fAntiCharmAllc.end(), std::make_pair(fMeanAntiCharmc*RandomGenerators::randgenMT.rand(), 0));
841 int tind = std::distance(fAntiCharmAllc.begin(), it);
842 if (tind < 0) tind = 0;
843 if (tind >= static_cast<int>(fAntiCharmAllc.size())) tind = fAntiCharmAllc.size() - 1;
844 totals[fAntiCharmAllc[tind].second]++;
845 }
846
847 // Cross-check that total resulting net charm is zero
848 int finC = 0;
849 for (size_t i = 0; i < totals.size(); ++i) {
850 finC += totals[i] * m_THM->TPS()->Particles()[i].Charm();
851 }
852
853 if (finC != m_Config.C) {
854 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsCCESubVolume(): Generated charm is non-zero!");
855 }
856
857 return totals;
858 }
859
865
866 std::vector<std::vector<double>> EventGeneratorBase::ComputeEVRadii() const
867 {
868 int Nspecies = m_THM->TPS()->ComponentsNumber();
869 std::vector<std::vector<double>> radii = std::vector<std::vector<double>>(Nspecies,
870 std::vector<double>(Nspecies, 0.0));
871
872 for (int i = 0; i < Nspecies; ++i) {
873 for (int j = 0; j < Nspecies; ++j) {
874 double b = 0.0;
875 if (i < m_Config.bij.size() && j < m_Config.bij[i].size())
876 b = 0.5 * (m_Config.bij[i][j] + m_Config.bij[j][i]);
877 radii[i][j] = CuteHRGHelper::rv(b);
878 }
879 }
880
881 return radii;
882 }
883
885 const std::vector<SimpleParticle>& particles,
886 const SimpleParticle& cand,
887 const std::vector<int>& ids,
888 const std::vector<std::vector<double>>& radii)
889 const
890 {
894 return false;
895 int idcand = m_THM->TPS()->PdgToId(cand.PDGID);
896 for (int ipart = 0; ipart < particles.size(); ++ipart) {
897 const SimpleParticle& part = particles[ipart];
898 int idpart = 0;
899 if (ids.size())
900 idpart = ids[ipart];
901 else
902 idpart = m_THM->TPS()->PdgToId(part.PDGID);
903
904 double r = 0.0;
905 if (radii.size()) {
906 r = radii[idpart][idcand];
907 }
908 else {
909 double b = 0.5 * (m_Config.bij[idpart][idcand] + m_Config.bij[idcand][idpart]);
910 r = CuteHRGHelper::rv(b);
911 }
912
913 if (r == 0.0)
914 continue;
915
916 double dist2 = ParticleDecaysMC::ParticleDistanceSquared(part, cand);
917 if (dist2 <= 4. * r * r)
918 return true;
919 }
920 return false;
921 }
922
923
924 std::vector<int> EventGeneratorBase::GenerateTotalsCE() const {
925 if (!m_THM->IsCalculated())
926 m_THM->CalculatePrimordialDensities();
927 std::vector<int> totals(m_THM->TPS()->Particles().size(), 0);
928
929 const std::vector< std::pair<double, int> >& fBaryonsc = m_Baryons;
930 const std::vector< std::pair<double, int> >& fAntiBaryonsc = m_AntiBaryons;
931 const std::vector< std::pair<double, int> >& fStrangeMesonsc = m_StrangeMesons;
932 const std::vector< std::pair<double, int> >& fAntiStrangeMesonsc = m_AntiStrangeMesons;
933 const std::vector< std::pair<double, int> >& fChargeMesonsc = m_ChargeMesons;
934 const std::vector< std::pair<double, int> >& fAntiChargeMesonsc = m_AntiChargeMesons;
935 const std::vector< std::pair<double, int> >& fCharmMesonsc = m_CharmMesons;
936 const std::vector< std::pair<double, int> >& fAntiCharmMesonsc = m_AntiCharmMesons;
937
938 // Primitive rejection sampling (not used, but can be explored for comparisons)
939 while (0) {
940 fCETotal++;
941 int netB = 0, netS = 0, netQ = 0, netC = 0;
942 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
943 double mean = m_THM->Densities()[i] * m_THM->Volume();
944 int total = RandomGenerators::RandomPoisson(mean);
945 totals[i] = total;
946 netB += totals[i] * m_THM->TPS()->Particles()[i].BaryonCharge();
947 netS += totals[i] * m_THM->TPS()->Particles()[i].Strangeness();
948 netQ += totals[i] * m_THM->TPS()->Particles()[i].ElectricCharge();
949 netC += totals[i] * m_THM->TPS()->Particles()[i].Charm();
950 }
951 //if ((!m_Config.CanonicalB || netB == m_THM->Parameters().B)
952 // && (!m_Config.CanonicalS || netS == m_THM->Parameters().S)
953 // && (!m_Config.CanonicalQ || netQ == m_THM->Parameters().Q)
954 // && (!m_Config.CanonicalC || netC == m_THM->Parameters().C)) {
955 // fCEAccepted++;
956 // return totals;
957 //}
958 if ((!m_Config.CanonicalB || netB == m_Config.B)
959 && (!m_Config.CanonicalS || netS == m_Config.S)
960 && (!m_Config.CanonicalQ || netQ == m_Config.Q)
961 && (!m_Config.CanonicalC || netC == m_Config.C)) {
962 fCEAccepted++;
963 return totals;
964 }
965 }
966
967 // Multi-step procedure as described in F. Becattini, L. Ferroni, hep-ph/0307061
968 while (1) {
969 fCETotal++;
970
971 const std::vector<double>& densities = m_THM->Densities();
972
973 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) totals[i] = 0;
974 int netB = 0, netS = 0, netQ = 0, netC = 0;
975
976
977 // Light nuclei first
978 bool flNuclei = false; // Whether light nuclei appear at all
979
980 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
981 if (abs(m_THM->TPS()->Particles()[i].BaryonCharge()) > 1) {
982 flNuclei = true;
983 double mean = densities[i] * m_THM->Volume();
984 int total = RandomGenerators::RandomPoisson(mean);
985 totals[i] = total;
986 netB += totals[i] * m_THM->TPS()->Particles()[i].BaryonCharge();
987 netS += totals[i] * m_THM->TPS()->Particles()[i].Strangeness();
988 netQ += totals[i] * m_THM->TPS()->Particles()[i].ElectricCharge();
989 netC += totals[i] * m_THM->TPS()->Particles()[i].Charm();
990 }
991 }
992
993 // Then all hadrons
994
995 int tB = 0, tAB = 0;
996 // First total baryons and antibaryons from the Poisson distribution
997 if (flNuclei || !m_Config.CanonicalB) {
999 tAB = RandomGenerators::RandomPoisson(m_MeanAB);
1000 if (m_Config.CanonicalB && tB - tAB != m_Config.B - netB) continue;
1001 //if (RandomGenerators::randgenMT.rand() > RandomGenerators::SkellamProbability(m_THM->Parameters().B - netB, m_MeanB, m_MeanAB))
1002 // continue;
1003 }
1004 else
1005 // Generate from the Bessel distribution, using Devroye's method, if no light nuclei
1006 {
1007 int nu = m_Config.B - netB;
1008 if (nu < 0) nu = -nu;
1009 double a = 2. * sqrt(m_MeanB * m_MeanAB);
1010 //int BessN = RandomGenerators::BesselDistributionGenerator::RandomBesselDevroye3(a, nu);
1011 //int BessN = RandomGenerators::BesselDistributionGenerator::RandomBesselPoisson(a, nu);
1012 //int BessN = RandomGenerators::BesselDistributionGenerator::RandomBesselCombined(a, nu);
1014 if (m_Config.B - netB < 0) {
1015 tB = BessN;
1016 tAB = nu + tB;
1017 }
1018 else {
1019 tAB = BessN;
1020 tB = nu + tAB;
1021 }
1022 }
1023
1024 // Then individual baryons and antibaryons from the multinomial distribution
1025 for (int i = 0; i < tB; ++i) {
1026 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fBaryonsc.begin(), fBaryonsc.end(), std::make_pair(m_MeanB*RandomGenerators::randgenMT.rand(), 0));
1027 int tind = std::distance(fBaryonsc.begin(), it);
1028 if (tind < 0) tind = 0;
1029 if (tind >= static_cast<int>(fBaryonsc.size())) tind = fBaryonsc.size() - 1;
1030 totals[fBaryonsc[tind].second]++;
1031 netS += m_THM->TPS()->Particles()[fBaryonsc[tind].second].Strangeness();
1032 netQ += m_THM->TPS()->Particles()[fBaryonsc[tind].second].ElectricCharge();
1033 netC += m_THM->TPS()->Particles()[fBaryonsc[tind].second].Charm();
1034 }
1035 for (int i = 0; i < tAB; ++i) {
1036 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fAntiBaryonsc.begin(), fAntiBaryonsc.end(), std::make_pair(m_MeanAB*RandomGenerators::randgenMT.rand(), 0));
1037 int tind = std::distance(fAntiBaryonsc.begin(), it);
1038 if (tind < 0) tind = 0;
1039 if (tind >= static_cast<int>(fAntiBaryonsc.size())) tind = fAntiBaryonsc.size() - 1;
1040 totals[fAntiBaryonsc[tind].second]++;
1041 netS += m_THM->TPS()->Particles()[fAntiBaryonsc[tind].second].Strangeness();
1042 netQ += m_THM->TPS()->Particles()[fAntiBaryonsc[tind].second].ElectricCharge();
1043 netC += m_THM->TPS()->Particles()[fAntiBaryonsc[tind].second].Charm();
1044 }
1045
1046 // Total numbers of (anti)strange mesons
1047
1048 int tSM = RandomGenerators::RandomPoisson(m_MeanSM);
1049 int tASM = RandomGenerators::RandomPoisson(m_MeanASM);
1050 if (m_Config.CanonicalS && netS != tASM - tSM + m_Config.S) continue;
1051
1052
1053 // Multinomial distribution for individual numbers of (anti)strange mesons
1054 for (int i = 0; i < tSM; ++i) {
1055 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fStrangeMesonsc.begin(), fStrangeMesonsc.end(), std::make_pair(m_MeanSM*RandomGenerators::randgenMT.rand(), 0));
1056 int tind = std::distance(fStrangeMesonsc.begin(), it);
1057 if (tind < 0) tind = 0;
1058 if (tind >= static_cast<int>(fStrangeMesonsc.size())) tind = fStrangeMesonsc.size() - 1;
1059 totals[fStrangeMesonsc[tind].second]++;
1060 netQ += m_THM->TPS()->Particles()[fStrangeMesonsc[tind].second].ElectricCharge();
1061 netC += m_THM->TPS()->Particles()[fStrangeMesonsc[tind].second].Charm();
1062 }
1063 for (int i = 0; i < tASM; ++i) {
1064 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fAntiStrangeMesonsc.begin(), fAntiStrangeMesonsc.end(), std::make_pair(m_MeanASM*RandomGenerators::randgenMT.rand(), 0));
1065 int tind = std::distance(fAntiStrangeMesonsc.begin(), it);
1066 if (tind < 0) tind = 0;
1067 if (tind >= static_cast<int>(fAntiStrangeMesonsc.size())) tind = fAntiStrangeMesonsc.size() - 1;
1068 totals[fAntiStrangeMesonsc[tind].second]++;
1069 netQ += m_THM->TPS()->Particles()[fAntiStrangeMesonsc[tind].second].ElectricCharge();
1070 netC += m_THM->TPS()->Particles()[fAntiStrangeMesonsc[tind].second].Charm();
1071 }
1072
1073 // Total numbers of remaining electrically charged mesons
1074 int tCM = RandomGenerators::RandomPoisson(m_MeanCM);
1075 int tACM = RandomGenerators::RandomPoisson(m_MeanACM);
1076 if (m_Config.CanonicalQ && netQ != tACM - tCM + m_Config.Q) continue;
1077
1078 // Multinomial distribution for individual numbers of remaining electrically charged mesons
1079 for (int i = 0; i < tCM; ++i) {
1080 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fChargeMesonsc.begin(), fChargeMesonsc.end(), std::make_pair(m_MeanCM*RandomGenerators::randgenMT.rand(), 0));
1081 int tind = std::distance(fChargeMesonsc.begin(), it);
1082 if (tind < 0) tind = 0;
1083 if (tind >= static_cast<int>(fChargeMesonsc.size())) tind = fChargeMesonsc.size() - 1;
1084 totals[fChargeMesonsc[tind].second]++;
1085 netC += m_THM->TPS()->Particles()[fChargeMesonsc[tind].second].Charm();
1086 }
1087 for (int i = 0; i < tACM; ++i) {
1088 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fAntiChargeMesonsc.begin(), fAntiChargeMesonsc.end(), std::make_pair(m_MeanACM*RandomGenerators::randgenMT.rand(), 0));
1089 int tind = std::distance(fAntiChargeMesonsc.begin(), it);
1090 if (tind < 0) tind = 0;
1091 if (tind >= static_cast<int>(fAntiChargeMesonsc.size())) tind = fAntiChargeMesonsc.size() - 1;
1092 totals[fAntiChargeMesonsc[tind].second]++;
1093 netC += m_THM->TPS()->Particles()[fAntiChargeMesonsc[tind].second].Charm();
1094 }
1095
1096 // Total numbers of remaining charmed mesons
1097 int tCHRMM = RandomGenerators::RandomPoisson(m_MeanCHRMM);
1098 int tACHRNMM = RandomGenerators::RandomPoisson(m_MeanACHRMM);
1099
1100 if (m_Config.CanonicalC && netC != tACHRNMM - tCHRMM + m_Config.C) continue;
1101
1102 // Multinomial distribution for individual numbers of the remaining charmed mesons
1103 for (int i = 0; i < tCHRMM; ++i) {
1104 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fCharmMesonsc.begin(), fCharmMesonsc.end(), std::make_pair(m_MeanCHRMM*RandomGenerators::randgenMT.rand(), 0));
1105 int tind = std::distance(fCharmMesonsc.begin(), it);
1106 if (tind < 0) tind = 0;
1107 if (tind >= static_cast<int>(fCharmMesonsc.size())) tind = fCharmMesonsc.size() - 1;
1108 totals[fCharmMesonsc[tind].second]++;
1109 }
1110 for (int i = 0; i < tACHRNMM; ++i) {
1111 std::vector< std::pair<double, int> >::const_iterator it = lower_bound(fAntiCharmMesonsc.begin(), fAntiCharmMesonsc.end(), std::make_pair(m_MeanACHRMM*RandomGenerators::randgenMT.rand(), 0));
1112 int tind = std::distance(fAntiCharmMesonsc.begin(), it);
1113 if (tind < 0) tind = 0;
1114 if (tind >= static_cast<int>(fAntiCharmMesonsc.size())) tind = fAntiCharmMesonsc.size() - 1;
1115 totals[fAntiCharmMesonsc[tind].second]++;
1116 }
1117
1118 // Poisson distribution for all neutral particles
1119 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
1120 if (m_THM->TPS()->Particles()[i].BaryonCharge() == 0
1121 && m_THM->TPS()->Particles()[i].Strangeness() == 0
1122 && m_THM->TPS()->Particles()[i].ElectricCharge() == 0
1123 && m_THM->TPS()->Particles()[i].Charm() == 0) {
1124 double mean = densities[i] * m_THM->Volume();
1125 int total = RandomGenerators::RandomPoisson(mean);
1126 totals[i] = total;
1127 }
1128 }
1129
1130 // Cross-check that all resulting charges are OK
1131 int finB = 0, finQ = 0, finS = 0, finC = 0;
1132 for (size_t i = 0; i < totals.size(); ++i) {
1133 finB += totals[i] * m_THM->TPS()->Particles()[i].BaryonCharge();
1134 finQ += totals[i] * m_THM->TPS()->Particles()[i].ElectricCharge();
1135 finS += totals[i] * m_THM->TPS()->Particles()[i].Strangeness();
1136 finC += totals[i] * m_THM->TPS()->Particles()[i].Charm();
1137 }
1138
1139 if (m_Config.CanonicalB && finB != m_Config.B) {
1140 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsCE(): Generated baryon number does not match the input!");
1141 }
1142
1143 if (m_Config.CanonicalQ && finQ != m_Config.Q) {
1144 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsCE(): Generated electric charge does not match the input!");
1145 }
1146
1147 if (m_Config.CanonicalS && finS != m_Config.S) {
1148 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsCE(): Generated strangeness does not match the input!");
1149 }
1150
1151 if (m_Config.CanonicalC && finC != m_Config.C) {
1152 throw std::runtime_error("**ERROR** EventGeneratorBase::GenerateTotalsCE(): Generated charm does not match the input!");
1153 }
1154
1155 return totals;
1156 }
1157 return totals;
1158 }
1159
1160 std::pair<std::vector<int>, double> EventGeneratorBase::SampleYields() const
1161 {
1162 std::vector<int> totals = GenerateTotals();
1163 return make_pair(totals, m_LastNormWeight);
1164 //std::vector<int> totals = GenerateTotalsGCE();
1165 //return make_pair(totals, 1.);
1166 }
1167
1169 {
1170 const_cast<EventGeneratorBase*>(this)->CheckSetParameters();
1171 const ThermalParticle& species = m_THM->TPS()->Particles()[id];
1172 double tmass = species.Mass();
1173 if (m_THM->UseWidth() && !species.ZeroWidthEnforced() && !(species.GetResonanceWidthIntegrationType() == ThermalParticle::ZeroWidth))
1174 tmass = m_BWGens[id]->GetRandom();
1175
1176 // Check for Bose-Einstein condensation
1177 // Force m = mu if the sampled mass is too small
1178 double tmu = m_THM->FullIdealChemicalPotential(id);
1179 if (species.Statistics() == -1 && tmu > tmass) {
1180 tmass = tmu;
1181 }
1182
1183 std::vector<double> momentum = m_MomentumGens[id]->GetMomentum(tmass);
1184
1185 return SimpleParticle(momentum[0], momentum[1], momentum[2], tmass, species.PdgId(), 0,
1186 momentum[3], momentum[4], momentum[5], momentum[6]);
1187 }
1188
1190 {
1191 int id = m_THM->TPS()->PdgToId(pdgid);
1192 if (id == -1) {
1193 throw std::invalid_argument("EventGeneratorBase::SampleParticleByPdg(): The input pdg code does not exist in the particle list!");
1194 }
1195 return SampleParticle(id);
1196 }
1197
1198 SimpleEvent EventGeneratorBase::SampleMomenta(const std::vector<int>& yields) const
1199 {
1200 return SampleMomentaWithShuffle(yields);
1201 //const_cast<EventGeneratorBase*>(this)->CheckSetParameters();
1202
1203 //SimpleEvent ret;
1204
1205 //std::vector<int> ids;
1206
1207 //for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
1208 // const ThermalParticle& species = m_THM->TPS()->Particles()[i];
1209 // //primParticles[i].resize(0);
1210 // int total = yields[i];
1211 // for (int part = 0; part < total; ++part) {
1212 // SimpleParticle cand = SampleParticle(i);
1213 // if (!CheckEVOverlap(ret.Particles, cand, ids, m_Radii)) {
1214 // ret.Particles.push_back(cand);
1215 // ids.push_back(i);
1216 // }
1217 // else {
1218 // part--;
1219 // }
1220 // }
1221 //}
1222
1223 //ret.AllParticles = ret.Particles;
1224
1225 //ret.DecayMap.resize(ret.Particles.size());
1226 //fill(ret.DecayMap.begin(), ret.DecayMap.end(), -1);
1227
1228 //ret.DecayMapFinal.resize(ret.Particles.size());
1229 //for (int i = 0; i < ret.DecayMapFinal.size(); ++i)
1230 // ret.DecayMapFinal[i] = i;
1231
1232 //return ret;
1233 }
1234
1235 SimpleEvent EventGeneratorBase::SampleMomentaWithShuffle(const std::vector<int>& yields) const
1236 {
1237 const_cast<EventGeneratorBase*>(this)->CheckSetParameters();
1238
1239 SimpleEvent ret;
1240
1241 std::vector<int> ids;
1242 for (int i = 0; i < m_THM->TPS()->Particles().size(); ++i)
1243 for (int part = 0; part < yields[i]; ++part)
1244 ids.push_back(i);
1245 //std::random_shuffle(ids.begin(), ids.end()); // Removed in C++17
1246 std::shuffle(ids.begin(), ids.end(), RandomGenerators::rng_std);
1247
1248 ret.Particles.resize(ids.size());
1249
1250
1251 bool flOverlap = true;
1252 while (flOverlap) {
1253 int sampled = 0;
1254
1255 // Check if the event has no particles at all
1256 if(ids.size() == 0)
1257 break;
1258
1259 while (sampled < ids.size()) {
1260 flOverlap = false;
1261 int i = ids[sampled];
1262 const ThermalParticle& species = m_THM->TPS()->Particles()[i];
1264
1265 if (m_Config.fUseEVRejectionCoordinates &&
1268 || m_Config.fModelType == EventGeneratorConfiguration::QvdW)) {
1269 for (int i = 0; i < sampled; ++i) {
1270 double r = m_Radii[ids[i]][ids[sampled]];
1271 if (r != 0.0) {
1272 flOverlap |= (ParticleDecaysMC::ParticleDistanceSquared(ret.Particles[i], cand) <= 4. * r * r);
1273 }
1274 }
1275
1276 if (flOverlap) {
1277 if (EVUseSPR()) {
1278 continue;
1279 }
1280 else {
1281 break;
1282 }
1283 }
1284 }
1285
1286 ret.Particles[sampled] = cand;
1287 sampled++;
1288 }
1289 }
1290
1291 ret.AllParticles = ret.Particles;
1292
1293 ret.DecayMap.resize(ret.Particles.size());
1294 fill(ret.DecayMap.begin(), ret.DecayMap.end(), -1);
1295
1296 ret.DecayMapFinal.resize(ret.Particles.size());
1297 for (int i = 0; i < ret.DecayMapFinal.size(); ++i)
1298 ret.DecayMapFinal[i] = i;
1299
1300 return ret;
1301 }
1302
1304 {
1305 const_cast<EventGeneratorBase*>(this)->CheckSetParameters();
1306
1307 if (!m_THM->IsCalculated())
1308 m_THM->CalculatePrimordialDensities();
1309
1310 std::vector<int> totals = GenerateTotals();
1313 && m_Config.fUseEVRejectionMultiplicity) {
1314 while (RandomGenerators::randgenMT.rand() > m_LastNormWeight) {
1315 if (m_LastNormWeight > 1.) {
1316 printf("**WARNING** Event weight %lf > 1 in Monte Carlo rejection sampling!", m_LastNormWeight);
1317 }
1318 totals = GenerateTotals();
1319 }
1320 m_LastWeight = 1.0;
1321 m_LastLogWeight = 0.;
1322 m_LastNormWeight = 1.0;
1323 }
1324
1325 SimpleEvent ret = SampleMomenta(totals);
1326 ret.weight = m_LastWeight;
1327 ret.logweight = m_LastLogWeight;
1328 ret.weight = m_LastNormWeight;
1329
1330 if (DoDecays)
1331 return PerformDecays(ret, m_THM->TPS());
1332 else
1333 return ret;
1334 }
1335
1336 // SimpleEvent EventGeneratorBase::PerformDecaysAlternativeWay(const SimpleEvent& evtin, ThermalParticleSystem* TPS)
1337 // {
1338 // SimpleEvent ret;
1339 // ret.weight = evtin.weight;
1340 // ret.logweight = evtin.logweight;
1341 // ret.AllParticles = evtin.Particles;
1342 // reverse(ret.AllParticles.begin(), ret.AllParticles.end());
1343
1344 // for (auto&& part : ret.AllParticles)
1345 // part.processed = false;
1346
1347
1348 // bool flag_repeat = true;
1349 // while (flag_repeat) {
1350 // flag_repeat = false;
1351
1352 // bool current_stable_flag = false;
1353 // long long current_pdgcode = 0;
1354 // long long current_tid = -1;
1355 // for (int i = ret.AllParticles.size() - 1; i >= 0; --i) {
1356 // SimpleParticle& particle = ret.AllParticles[i];
1357
1358 // if (particle.processed)
1359 // continue;
1360
1361 // long long tpdgcode = particle.PDGID;
1362 // if (!(tpdgcode == current_pdgcode))
1363 // {
1364 // current_tid = TPS->PdgToId(tpdgcode);
1365 // if (current_tid != -1)
1366 // current_stable_flag = TPS->Particle(current_tid).IsStable();
1367 // else
1368 // current_stable_flag = true;
1369 // current_pdgcode = tpdgcode;
1370 // }
1371
1372
1373 // if (current_stable_flag) {
1374 // //SimpleParticle prt = primParticles[i][j];
1375 // //double tpt = prt.GetPt();
1376 // //double ty = prt.GetY();
1377 // //if (static_cast<int>(m_acc.size()) < i || !m_acc[i].init || m_acc[i].getAcceptance(ty + m_ycm, tpt) > RandomGenerators::randgenMT.rand())
1378 // // ret.Particles.push_back(prt);
1379 // //primParticles[i][j].processed = true;
1380 // ret.Particles.push_back(particle);
1381 // particle.processed = true;
1382 // }
1383 // else {
1384 // flag_repeat = true;
1385 // double DecParam = RandomGenerators::randgenMT.rand(), tsum = 0.;
1386
1387 // std::vector<double> Bratios;
1388 // if (particle.MotherPDGID != 0 ||
1389 // TPS->ResonanceWidthIntegrationType() != ThermalParticle::eBW) {
1390 // Bratios = TPS->Particles()[current_tid].BranchingRatiosM(particle.m, false);
1391 // }
1392 // else {
1393 // Bratios = TPS->Particles()[current_tid].BranchingRatiosM(particle.m, true);
1394 // }
1395
1396 // int DecayIndex = 0;
1397 // for (DecayIndex = 0; DecayIndex < static_cast<int>(Bratios.size()); ++DecayIndex) {
1398 // tsum += Bratios[DecayIndex];
1399 // if (tsum > DecParam) break;
1400 // }
1401 // if (DecayIndex < static_cast<int>(TPS->Particles()[current_tid].Decays().size())) {
1402 // std::vector<double> masses(0);
1403 // std::vector<long long> pdgids(0);
1404 // for (size_t di = 0; di < TPS->Particles()[current_tid].Decays()[DecayIndex].mDaughters.size(); di++) {
1405 // long long dpdg = TPS->Particles()[current_tid].Decays()[DecayIndex].mDaughters[di];
1406 // if (TPS->PdgToId(dpdg) == -1) {
1407 // continue;
1408 // }
1409 // masses.push_back(TPS->ParticleByPDG(dpdg).Mass());
1410 // pdgids.push_back(dpdg);
1411 // }
1412 // std::vector<SimpleParticle> decres = ParticleDecaysMC::ManyBodyDecay(particle, masses, pdgids);
1413 // for (size_t ind = 0; ind < decres.size(); ind++) {
1414 // decres[ind].processed = false;
1415 // if (TPS->PdgToId(decres[ind].PDGID) != -1)
1416 // ret.AllParticles.push_back(decres[ind]);
1417 // }
1418 // ret.AllParticles[i].processed = true;
1419 // }
1420 // else {
1421 // // Decay through unknown branching ratio, presumably radiative, no hadrons, just ignore the decay products
1422 // ret.AllParticles[i].processed = true;
1423 // }
1424 // }
1425 // }
1426 // }
1427
1428 // return ret;
1429 // }
1430
1432 {
1433 SimpleEvent ret;
1434 ret.weight = evtin.weight;
1435 ret.logweight = evtin.logweight;
1436
1437 ret.AllParticles = evtin.AllParticles;
1438 ret.DecayMap = evtin.DecayMap;
1439
1440 std::vector< std::vector<SimpleParticle> > primParticles(TPS->Particles().size(), std::vector<SimpleParticle>(0));
1441 std::vector< std::vector<int> > AllParticlesMap(TPS->Particles().size(), std::vector<int>(0));
1442 for(int i = 0; i < evtin.Particles.size(); ++i) {
1443 const SimpleParticle& particle = evtin.Particles[i];
1444 long long tid = TPS->PdgToId(particle.PDGID);
1445 if (tid != -1) {
1446 primParticles[tid].push_back(particle);
1447 AllParticlesMap[tid].push_back(i);
1448 }
1449 }
1450
1451 bool flag_repeat = true;
1452 while (flag_repeat) {
1453 flag_repeat = false;
1454 for (int i = static_cast<int>(primParticles.size()) - 1; i >= 0; --i) {
1455 if (TPS->Particles()[i].IsStable()) {
1456 for (size_t j = 0; j < primParticles[i].size(); ++j) {
1457 if (!primParticles[i][j].processed) {
1458 SimpleParticle prt = primParticles[i][j];
1459 ret.Particles.push_back(prt);
1460 primParticles[i][j].processed = true;
1461 int tid = AllParticlesMap[i][j];
1462 while (tid >= 0 && tid < ret.DecayMap.size() && ret.DecayMap[tid] != -1)
1463 tid = ret.DecayMap[tid];
1464 ret.DecayMapFinal.push_back(tid);
1465 }
1466 }
1467 }
1468 else {
1469 for (size_t j = 0; j < primParticles[i].size(); ++j) {
1470 if (!primParticles[i][j].processed) {
1471 flag_repeat = true;
1472 double DecParam = RandomGenerators::randgenMT.rand(), tsum = 0.;
1473
1474 std::vector<double> Bratios;
1475 double Width = 0.;
1476 if (primParticles[i][j].MotherPDGID != 0 ||
1478 Bratios = TPS->Particles()[i].BranchingRatiosM(primParticles[i][j].m, false);
1479 Width = TPS->Particles()[i].ResonanceWidth();
1480 }
1481 else {
1482 Bratios = TPS->Particles()[i].BranchingRatiosM(primParticles[i][j].m, true);
1483 Width = TPS->Particles()[i].TotalWidtheBW(primParticles[i][j].m);
1484 }
1485
1486 int DecayIndex = 0;
1487 for (DecayIndex = 0; DecayIndex < static_cast<int>(Bratios.size()); ++DecayIndex) {
1488 tsum += Bratios[DecayIndex];
1489 if (tsum > DecParam) break;
1490 }
1491 if (DecayIndex < static_cast<int>(TPS->Particles()[i].Decays().size())) {
1492 std::vector<double> masses(0);
1493 std::vector<long long> pdgids(0);
1494 for (size_t di = 0; di < TPS->Particles()[i].Decays()[DecayIndex].mDaughters.size(); di++) {
1495 long long dpdg = TPS->Particles()[i].Decays()[DecayIndex].mDaughters[di];
1496 if (TPS->PdgToId(dpdg) == -1) {
1497 // Try to see if the daughter particle is a photon/lepton
1498 if (ExtraParticles::PdgToId(dpdg) == -1)
1499 continue;
1500 else
1501 masses.push_back(ExtraParticles::ParticleByPdg(dpdg).Mass());
1502 }
1503 else {
1504 masses.push_back(TPS->ParticleByPDG(dpdg).Mass());
1505 }
1506 pdgids.push_back(dpdg);
1507 }
1508
1509 // Propagate along straight line before decay
1510 double prop_dx = 0., prop_dy = 0., prop_dz = 0., prop_dt = 0.;
1511 if (decayerFlags.propagateParticles) {
1512 double ct = 0.;
1513 if (Width != 0.)
1514 ct = 1. / Width / xMath::GeVtoifm();
1515 else
1516 ct = DecayLifetimes::GetLifetime(primParticles[i][j].PDGID);
1517
1518 if (ct == 0.) {
1519 if (abs(primParticles[i][j].PDGID) != 311) {
1520 // K0s "decaying" into K0S and K0L is an exception
1521 printf("**WARNING** Could not find the lifetime for decaying particle %lld. Setting to zero...\n", primParticles[i][j].PDGID);
1522 }
1523 }
1524
1525 // Sample the lifetime in the rest frame
1526 ct = -ct * log(1. - RandomGenerators::randgenMT.randDblExc());
1527
1528 // Lorentz time delay
1529 double vx = primParticles[i][j].px / primParticles[i][j].p0;
1530 double vy = primParticles[i][j].py / primParticles[i][j].p0;
1531 double vz = primParticles[i][j].pz / primParticles[i][j].p0;
1532 double gamma = 1. / sqrt(1. - vx*vx - vy*vy - vz*vz);
1533 ct *= gamma;
1534
1535 // Propagate
1536 prop_dx += vx * ct;
1537 prop_dy += vy * ct;
1538 prop_dz += vz * ct;
1539 prop_dt += ct;
1540 }
1541
1542 std::vector<SimpleParticle> decres = ParticleDecaysMC::ManyBodyDecay(primParticles[i][j], masses, pdgids);
1543 for (size_t ind = 0; ind < decres.size(); ind++) {
1544 decres[ind].processed = false;
1545
1546 // Propagate before decay
1547 if (decayerFlags.propagateParticles && prop_dt != 0.0) {
1548 decres[ind].r0 += prop_dt;
1549 decres[ind].rx += prop_dx;
1550 decres[ind].ry += prop_dy;
1551 decres[ind].rz += prop_dz;
1552 }
1553
1554 if (TPS->PdgToId(decres[ind].PDGID) != -1) {
1555 int tid = TPS->PdgToId(decres[ind].PDGID);
1556 SimpleParticle& dprt = decres[ind];
1557 primParticles[tid].push_back(dprt);
1558 ret.AllParticles.push_back(dprt);
1559 AllParticlesMap[tid].push_back(static_cast<int>(ret.AllParticles.size()) - 1);
1560 ret.DecayMap.push_back(AllParticlesMap[i][j]);
1561 }
1562 else if (ExtraParticles::PdgToId(decres[ind].PDGID) != -1) {
1563 SimpleParticle& dprt = decres[ind];
1564 ret.AllParticles.push_back(dprt);
1565 ret.DecayMap.push_back(AllParticlesMap[i][j]);
1566 ret.PhotonsLeptons.push_back(dprt);
1567 }
1568 }
1569 primParticles[i][j].processed = true;
1570 }
1571 else {
1572 // Decay through unknown branching ratio, presumably radiative, no hadrons, just ignore the decay products
1573 primParticles[i][j].processed = true;
1574 }
1575 }
1576 }
1577 }
1578 }
1579 }
1580
1581 return ret;
1582 }
1583
1584 std::vector<double> EventGeneratorBase::GCEMeanYields() const
1585 {
1586 std::vector<double> ret = m_THM->Densities();
1587 for(size_t i = 0; i < ret.size(); ++i) {
1588 ret[i] *= m_THM->Volume();
1589 }
1590 return ret;
1591 }
1592
1594 {
1596 RescaleCEMeans(V / m_THM->Volume());
1597 m_THM->SetVolume(V);
1598 m_Config.CFOParameters.V = V;
1599 m_THM->SetCanonicalVolume(V);
1600 m_Config.CFOParameters.SVc = V;
1601 }
1602
1604 {
1605 m_MeanB *= Vmod;
1606 m_MeanAB *= Vmod;
1607 m_MeanSM *= Vmod;
1608 m_MeanASM *= Vmod;
1609 m_MeanCM *= Vmod;
1610 m_MeanACM *= Vmod;
1611 m_MeanCHRMM *= Vmod;
1612 m_MeanACHRMM *= Vmod;
1613 m_MeanCHRM *= Vmod;
1614 m_MeanACHRM *= Vmod;
1615
1616 for (int i = 0; i < static_cast<int>(m_Baryons.size()); ++i) m_Baryons[i].first *= Vmod;
1617 for (int i = 0; i < static_cast<int>(m_AntiBaryons.size()); ++i) m_AntiBaryons[i].first *= Vmod;
1618 for (int i = 0; i < static_cast<int>(m_StrangeMesons.size()); ++i) m_StrangeMesons[i].first *= Vmod;
1619 for (int i = 0; i < static_cast<int>(m_AntiStrangeMesons.size()); ++i) m_AntiStrangeMesons[i].first *= Vmod;
1620 for (int i = 0; i < static_cast<int>(m_ChargeMesons.size()); ++i) m_ChargeMesons[i].first *= Vmod;
1621 for (int i = 0; i < static_cast<int>(m_AntiChargeMesons.size()); ++i) m_AntiChargeMesons[i].first *= Vmod;
1622 for (int i = 0; i < static_cast<int>(m_CharmMesons.size()); ++i) m_CharmMesons[i].first *= Vmod;
1623 for (int i = 0; i < static_cast<int>(m_AntiCharmMesons.size()); ++i) m_AntiCharmMesons[i].first *= Vmod;
1624 for (int i = 0; i < static_cast<int>(m_CharmAll.size()); ++i) m_CharmAll[i].first *= Vmod;
1625 for (int i = 0; i < static_cast<int>(m_AntiCharmAll.size()); ++i) m_AntiCharmAll[i].first *= Vmod;
1626 }
1627
1628 double EventGeneratorBase::ComputeWeight(const std::vector<int>& totals) const
1629 {
1630 // Compute the normalized weight factor due to EV/vdW interactions
1631 // If V - bN < 0, returns -1.
1632 std::vector<double>* densitiesid = NULL;
1633 std::vector<double> tmpdens;
1634 const std::vector<double>& densities = m_THM->Densities();
1635 if (m_THM->InteractionModel() != ThermalModelBase::Ideal) {
1636 tmpdens = m_DensitiesIdeal;
1637 densitiesid = &tmpdens;
1638 }
1639
1640 double ret = 1.;
1641
1642 if (m_THM->InteractionModel() == ThermalModelBase::DiagonalEV) {
1643 ThermalModelEVDiagonal* model = static_cast<ThermalModelEVDiagonal*>(m_THM);
1644 double V = m_THM->Volume();
1645 double VVN = m_THM->Volume();
1646
1647 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i)
1648 VVN -= model->ExcludedVolume(i) * totals[i];
1649
1650 if (VVN < 0.)
1651 return -1.;
1652
1653 double weight = 1.;
1654 double logweight = 0.;
1655
1656 double normweight = 1.;
1657 double weightev = 1.;
1658 double VVNev = m_THM->Volume();
1659 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i)
1660 VVNev -= model->ExcludedVolume(i) * densities[i] * m_THM->Volume();
1661
1662 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
1663 weight *= pow(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i], totals[i]);
1664 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1665 logweight += totals[i] * log(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i]);
1666
1667 weightev *= pow(VVNev / V * densitiesid->operator[](i) / densities[i], densities[i] * V);
1668
1669 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1670 //normweight *= pow(VVN / V, totals[i]) / pow(VVNev / V, densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1671 normweight *= pow(VVN / VVNev, totals[i]) * pow(VVNev / V, totals[i] - densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1672 }
1673
1674 m_LastWeight = weight;
1675 m_LastLogWeight = logweight;
1676 m_LastNormWeight = normweight;
1677
1678 ret = normweight;
1679 }
1680
1681
1682 if (m_THM->InteractionModel() == ThermalModelBase::CrosstermsEV) {
1684 double V = m_THM->Volume();
1685
1686 double weight = 1.;
1687 double logweight = 0.;
1688 double normweight = 1.;
1689 double weightev = 1.;
1690 bool fl = 1;
1691 int Nspecies = m_THM->TPS()->Particles().size();
1692 for (size_t i = 0; i < Nspecies; ++i) {
1693 double VVN = m_THM->Volume();
1694
1695 for (size_t j = 0; j < Nspecies; ++j)
1696 VVN -= model->VirialCoefficient(j, i) * totals[j];
1697
1698 if (VVN < 0.) { fl = false; break; }
1699
1700 double VVNev = m_THM->Volume();
1701 for (size_t j = 0; j < Nspecies; ++j)
1702 VVNev -= model->VirialCoefficient(j, i) * densities[j] * V;
1703
1704 weight *= pow(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i], totals[i]);
1705 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1706 logweight += totals[i] * log(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i]);
1707
1708 weightev *= pow(VVNev / m_THM->Volume() * densitiesid->operator[](i) / densities[i], densities[i] * V);
1709 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1710 normweight *= pow(VVN / VVNev, totals[i]) * pow(VVNev / V, totals[i] - densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1711 }
1712
1713 if (!fl)
1714 return -1.;
1715
1716 m_LastWeight = weight;
1717 m_LastLogWeight = logweight;
1718 m_LastNormWeight = normweight;
1719
1720 ret = normweight;
1721 }
1722
1723 if (m_THM->InteractionModel() == ThermalModelBase::QvdW) {
1724 ThermalModelVDW* model = static_cast<ThermalModelVDW*>(m_THM);
1725 double V = m_THM->Volume();
1726
1727 double weight = 1.;
1728 double logweight = 0.;
1729 double normweight = 1.;
1730 double weightvdw = 1.;
1731 bool fl = 1;
1732 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
1733 double VVN = m_THM->Volume();
1734
1735 for (size_t j = 0; j < m_THM->TPS()->Particles().size(); ++j)
1736 VVN -= model->VirialCoefficient(j, i) * totals[j];
1737
1738 if (VVN < 0.) { fl = false; break; }
1739
1740 double VVNev = m_THM->Volume();
1741 for (size_t j = 0; j < m_THM->TPS()->Particles().size(); ++j)
1742 VVNev -= model->VirialCoefficient(j, i) * densities[j] * V;
1743
1744 weight *= pow(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i], totals[i]);
1745 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1746 logweight += totals[i] * log(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i]);
1747
1748 for (size_t j = 0; j < m_THM->TPS()->Particles().size(); ++j) {
1749 double aij = model->AttractionCoefficient(i, j);
1750 weight *= exp(aij * totals[j] / m_THM->Parameters().T / m_THM->Volume() * totals[i]);
1751 logweight += totals[i] * aij * totals[j] / m_THM->Parameters().T / m_THM->Volume();
1752 }
1753
1754 weightvdw *= pow(VVNev / m_THM->Volume() * densitiesid->operator[](i) / densities[i], densities[i] * V);
1755 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1756 normweight *= pow(VVN / VVNev, totals[i]) * pow(VVNev / V, totals[i] - densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1757
1758 for (size_t j = 0; j < m_THM->TPS()->Particles().size(); ++j) {
1759 double aij = model->AttractionCoefficient(i, j);
1760 weightvdw *= exp(aij * densities[j] / m_THM->Parameters().T * densities[i] * V);
1761 normweight *= exp(aij * totals[j] / m_THM->Parameters().T / m_THM->Volume() * totals[i] - aij * densities[j] / m_THM->Parameters().T * densities[i] * V);
1762 }
1763
1764 }
1765 if (!fl)
1766 return -1.;
1767
1768 m_LastWeight = weight;
1769 m_LastLogWeight = logweight;
1770 m_LastNormWeight = normweight;
1771
1772 ret = normweight;
1773 }
1774
1775 return ret;
1776 }
1777
1778 double EventGeneratorBase::ComputeWeightNew(const std::vector<int>& totals) const
1779 {
1780 // Compute the normlaized weight factor due to EV/vdW interactions
1781 // If V - bN < 0, returns -1.
1782 std::vector<double>* densitiesid = NULL;
1783 std::vector<double> tmpdens;
1784 const std::vector<double>& densities = m_THM->Densities();
1785 if (m_THM->InteractionModel() != ThermalModelBase::Ideal) {
1786 tmpdens = m_DensitiesIdeal;
1787 densitiesid = &tmpdens;
1788 }
1789
1790 double ret = 1.;
1791
1792 if (m_THM->InteractionModel() == ThermalModelBase::DiagonalEV) {
1793 ThermalModelEVDiagonal* model = static_cast<ThermalModelEVDiagonal*>(m_THM);
1794 double V = m_THM->Volume();
1795 double VVN = m_THM->Volume();
1796
1797 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i)
1798 VVN -= model->ExcludedVolume(i) * totals[i];
1799
1800 if (VVN < 0.)
1801 return -1.;
1802
1803 double weight = 1.;
1804 double logweight = 0.;
1805
1806 double normweight = 1.;
1807 double weightev = 1.;
1808 double VVNev = m_THM->Volume();
1809 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i)
1810 VVNev -= model->ExcludedVolume(i) * densities[i] * m_THM->Volume();
1811
1812 for (size_t i = 0; i < m_THM->TPS()->Particles().size(); ++i) {
1813 weight *= pow(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i], totals[i]);
1814 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1815 logweight += totals[i] * log(VVN / m_THM->Volume() * densitiesid->operator[](i) / densities[i]);
1816
1817 weightev *= pow(VVNev / V * densitiesid->operator[](i) / densities[i], densities[i] * V);
1818
1819 if (densitiesid->operator[](i) > 0. && densities[i] > 0.)
1820 //normweight *= pow(VVN / V, totals[i]) / pow(VVNev / V, densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1821 normweight *= pow(VVN / VVNev, totals[i]) * pow(VVNev / V, totals[i] - densities[i] * V) * pow(densitiesid->operator[](i) / densities[i], totals[i] - (densities[i] * V));
1822 }
1823
1824 m_LastWeight = weight;
1825 m_LastLogWeight = logweight;
1826 m_LastNormWeight = normweight;
1827
1828 ret = normweight;
1829 }
1830
1831
1832 if (m_THM->InteractionModel() == ThermalModelBase::CrosstermsEV) {
1834 double V = m_THM->Volume();
1835
1836 double weight = 1.;
1837 double logweight = 0.;
1838 double normweight = 1.;
1839 double weightev = 1.;
1840 bool fl = true;
1841 int Nspecies = m_THM->TPS()->Particles().size();
1842
1843 int NEVcomp = model->EVComponentIndices().size();
1844 std::vector<int> Nscomp(NEVcomp, 0);
1845 std::vector<double> Nevscomp(NEVcomp, 0.);
1846 std::vector<double> bns(NEVcomp, 0.), bnevs(NEVcomp, 0.), dmuTs(NEVcomp, 0.);
1847 const std::vector< std::vector<double> >& virial = model->VirialMatrix();
1848
1849 for (size_t icomp = 0; icomp < NEVcomp; ++icomp) {
1850 const std::vector<int>& indis = model->EVComponentIndices()[icomp];
1851 int Nlocal = indis.size();
1852 for (size_t ilocal = 0; ilocal < Nlocal; ++ilocal) {
1853 int ip = indis[ilocal];
1854 Nscomp[icomp] += totals[ip];
1855 Nevscomp[icomp] += densities[ip] * V;
1856 }
1857
1858 if (indis.size()) {
1859 int i1 = indis[0];
1860
1861 for (size_t j = 0; j < Nspecies; ++j) {
1862 //bns[icomp] += model->VirialCoefficient(j, i1) * totals[j] / V;
1863 //bnevs[icomp] += model->VirialCoefficient(j, i1) * densities[j];
1864 bns[icomp] += virial[j][i1] * totals[j];// / V;
1865 bnevs[icomp] += virial[j][i1] * densities[j];
1866 }
1867 bns[icomp] /= V;
1868
1869 if (bns[icomp] > 1.)
1870 fl = false;
1871
1872 //dmuTs[icomp] = model->DeltaMu(i1) / model->Parameters().T;
1873 dmuTs[icomp] = log(densities[i1] / densitiesid->operator[](i1) / (1. - bnevs[icomp]));
1874 }
1875
1876 normweight *= pow((1. - bns[icomp]) / (1. - bnevs[icomp]), Nscomp[icomp]) * exp(-dmuTs[icomp] * (Nscomp[icomp] - Nevscomp[icomp]));
1877
1878 }
1879
1880 if (!fl)
1881 return -1.;
1882
1883 m_LastWeight = normweight;
1884 m_LastLogWeight = log(normweight);
1885 m_LastNormWeight = normweight;
1886
1887 ret = normweight;
1888 }
1889
1890 if (m_THM->InteractionModel() == ThermalModelBase::QvdW) {
1891 ThermalModelVDW* model = static_cast<ThermalModelVDW*>(m_THM);
1892 double V = m_THM->Volume();
1893
1894 double weight = 1.;
1895 double logweight = 0.;
1896 double normweight = 1.;
1897 double weightvdw = 1.;
1898 bool fl = true;
1899
1900 int Nspecies = m_THM->TPS()->Particles().size();
1901
1902 int NVDWcomp = model->VDWComponentIndices().size();
1903 std::vector<int> Nscomp(NVDWcomp, 0);
1904 std::vector<double> Nvdwscomp(NVDWcomp, 0.);
1905 std::vector<double> bns(NVDWcomp, 0.), bnvdws(NVDWcomp, 0.), dmuTs(NVDWcomp, 0.), aijs(NVDWcomp, 0.), aijvdws(NVDWcomp, 0.);
1906 const std::vector< std::vector<double> >& virial = model->VirialMatrix();
1907 const std::vector< std::vector<double> >& attr = model->AttractionMatrix();
1908
1909 for (size_t icomp = 0; icomp < NVDWcomp; ++icomp) {
1910 const std::vector<int>& indis = model->VDWComponentIndices()[icomp];
1911 int Nlocal = indis.size();
1912 for (size_t ilocal = 0; ilocal < Nlocal; ++ilocal) {
1913 int ip = indis[ilocal];
1914 Nscomp[icomp] += totals[ip];
1915 Nvdwscomp[icomp] += densities[ip] * V;
1916 }
1917
1918 if (indis.size()) {
1919 int i1 = indis[0];
1920
1921 for (size_t j = 0; j < Nspecies; ++j) {
1922 //bns[icomp] += model->VirialCoefficient(j, i1) * totals[j] / V;
1923 //bnevs[icomp] += model->VirialCoefficient(j, i1) * densities[j];
1924 bns[icomp] += virial[j][i1] * totals[j];// / V;
1925 bnvdws[icomp] += virial[j][i1] * densities[j];
1926
1927 aijs[icomp] += attr[i1][j] * totals[j];
1928 aijvdws[icomp] += attr[i1][j] * densities[j];
1929 }
1930 bns[icomp] /= V;
1931 aijs[icomp] /= V * model->Parameters().T;
1932 aijvdws[icomp] /= model->Parameters().T;
1933
1934
1935 if (bns[icomp] > 1.)
1936 fl = false;
1937
1938 //dmuTs[icomp] = model->DeltaMu(i1) / model->Parameters().T;
1939 dmuTs[icomp] = log(densities[i1] / densitiesid->operator[](i1) / (1. - bnvdws[icomp]));
1940 }
1941
1942 normweight *= pow((1. - bns[icomp]) / (1. - bnvdws[icomp]), Nscomp[icomp])
1943 * exp(-dmuTs[icomp] * (Nscomp[icomp] - Nvdwscomp[icomp]))
1944 * exp(aijs[icomp] * Nscomp[icomp] - aijvdws[icomp] * Nvdwscomp[icomp]);
1945 }
1946
1947 if (!fl)
1948 return -1.;
1949
1950 m_LastWeight = normweight;
1951 m_LastLogWeight = log(normweight);
1952 m_LastNormWeight = normweight;
1953
1954 ret = normweight;
1955 }
1956
1957 if (m_THM->InteractionModel() == ThermalModelBase::RealGas) {
1958 ThermalModelRealGas* model = static_cast<ThermalModelRealGas*>(m_THM);
1959 double V = m_THM->Volume();
1960
1961 double weight = 1.;
1962 double logweight = 0.;
1963 double normweight = 1.;
1964 double weightvdw = 1.;
1965 bool fl = true;
1966
1967 int Nspecies = m_THM->TPS()->Particles().size();
1968
1970 int Nevcomp = evmod->ComponentsNumber();
1971 const std::vector<int>& evinds = evmod->ComponentIndices();
1972 const std::vector<int>& evindsfrom = evmod->ComponentIndicesFrom();
1973 std::vector<int> Nscomp(Nevcomp, 0);
1974 std::vector<double> Nvdwscomp(Nevcomp, 0.);
1975 //std::vector<double> dmuTs(Nspecies, 0.);
1976
1977 std::vector<double> ev_favs(Nevcomp, 0.);
1978 for (size_t icomp = 0; icomp < Nevcomp; ++icomp) {
1979 ev_favs[icomp] = evmod->f(evindsfrom[icomp]);
1980 }
1981 std::vector<double> densities_sampled(Nspecies);
1982 for (size_t j = 0; j < Nspecies; ++j) {
1983 densities_sampled[j] = totals[j] / V;
1984 }
1985 evmod->SetDensities(densities_sampled);
1986 std::vector<double> ev_fsampled(Nevcomp, 0.);
1987 for (size_t icomp = 0; icomp < Nevcomp; ++icomp) {
1988 ev_fsampled[icomp] = evmod->f(evindsfrom[icomp]);
1989 }
1990 evmod->SetDensities(m_THM->Densities());
1991
1992 MeanFieldModelMultiBase* mfmod = model->MeanFieldModel();
1993 double mf_vav = mfmod->v();
1994 mfmod->SetDensities(densities_sampled);
1995 double mf_vsampled = mfmod->v();
1996 mfmod->SetDensities(m_THM->Densities());
1997
1998 for (size_t j = 0; j < Nspecies; ++j) {
1999 int jcomp = evinds[j];
2000 normweight *= pow(ev_fsampled[jcomp] / ev_favs[jcomp], totals[j]);
2001
2002 double dmuT = 0.;
2003 if (densitiesid->operator[](j))
2004 dmuT = log(densities[j] / densitiesid->operator[](j) / ev_favs[jcomp]);
2005 normweight *= exp(-dmuT * (totals[j] - densities[j] * V));
2006 }
2007
2008 normweight *= exp(-V * (mf_vsampled - mf_vav) / m_THM->Parameters().T);
2009
2010 if (!fl)
2011 return -1.;
2012
2013 m_LastWeight = normweight;
2014 m_LastLogWeight = log(normweight);
2015 m_LastNormWeight = normweight;
2016
2017 ret = normweight;
2018 }
2019
2020 //printf("Weight: %lf\n", ret);
2021
2022 return ret;
2023 }
2024
2039
2040} // namespace thermalfist
Contains some functions to deal with excluded volumes.
std::vector< std::vector< double > > ComputeEVRadii() const
virtual std::vector< double > GCEMeanYields() const
The grand-canonical mean yields.
virtual SimpleParticle SampleParticleByPdg(long long pdgid) const
Samples the position and momentum of a particle species with given pdg code.
std::vector< RandomGenerators::ThermalBreitWignerGenerator * > m_BWGens
std::vector< int > GenerateTotalsSCESubVolume(double VolumeSC) const
static SimpleEvent PerformDecays(const SimpleEvent &evtin, const ThermalParticleSystem *TPS, const DecayerFlags &decayerFlags=DecayerFlags())
Performs decays of all unstable particles until only stable ones left.
virtual std::pair< std::vector< int >, double > SampleYields() const
Samples the primordial yields for each particle species.
virtual SimpleEvent GetEvent(bool PerformDecays=true) const
Generates a single event.
std::vector< RandomGenerators::ParticleMomentumGenerator * > m_MomentumGens
Vector of momentum generators for each particle species.
bool CheckEVOverlap(const std::vector< SimpleParticle > &evt, const SimpleParticle &cand, const std::vector< int > &ids=std::vector< int >(), const std::vector< std::vector< double > > &radii=std::vector< std::vector< double > >()) const
virtual SimpleParticle SampleParticle(int id) const
Samples the position and momentum of a particle species i.
void ClearMomentumGenerators()
Clears the momentum generators for all particles.
EventGeneratorConfiguration m_Config
virtual void SetMomentumGenerators()
Sets the momentum generators for all particles. Overloaded.
std::vector< int > GenerateTotalsCCESubVolume(double VolumeSC) const
virtual void CheckSetParameters()
Sets the hypersurface parameters.
double ComputeWeight(const std::vector< int > &totals) const
std::vector< double > m_DensitiesIdeal
Ideal gas densities used for sampling an interacting HRG.
virtual SimpleEvent SampleMomenta(const std::vector< int > &yields) const
Samples the momenta of the particles and returns the sampled list of particles as an event.
std::vector< int > GenerateTotalsGCE() const
std::vector< int > GenerateTotalsSCE() const
std::vector< int > GenerateTotalsCE() const
void SetConfiguration(ThermalParticleSystem *TPS, const EventGeneratorConfiguration &config)
Sets the event generator configuration.
double ComputeWeightNew(const std::vector< int > &totals) const
std::vector< int > GenerateTotals() const
std::vector< int > GenerateTotalsCCE() const
virtual SimpleEvent SampleMomentaWithShuffle(const std::vector< int > &yields) const
Samples the momenta of the particles and returns the sampled list of particles as an event.
void SetVolume(double V)
Set system volume.
void RescaleCEMeans(double Vmod)
Rescale the precalculated GCE means.
virtual void SetParameters()
Sets up the event generator ready for production.
Base class implementing the ideal gas.
Class implementing auxiliary functions for the Carnahan-Starling excluded volume model.
Implementation of a crossterms generalized excluded volume model.
Base class for multi-component excluded volume models.
virtual double f(int i) const
Calculates the suppression factor for species i.
virtual const int ComponentsNumber() const
Gets the number of components.
virtual const std::vector< int > & ComponentIndices() const
Gets the component indices.
virtual const std::vector< int > & ComponentIndicesFrom() const
Gets the component indices from.
virtual void SetDensities(const std::vector< double > &n)
Sets the densities of particle species.
Class implementing auxiliary functions for the VDW excluded volume model truncated at n^3....
Class implementing auxiliary functions for the van der Waals excluded volume model.
Class implementing auxiliary functions for the VDW excluded volume model truncated at n^2.
Base class for multi-component mean field models.
virtual void SetDensities(const std::vector< double > &n)
Sets the densities of particle species.
virtual double v() const
Calculates the mean field value.
Implementation of the van der Waals mean field model for multiple components.
@ QvdW
Quantum van der Waals model.
@ DiagonalEV
Diagonal excluded volume model.
@ CrosstermsEV
Crossterms excluded volume model.
const ThermalModelParameters & Parameters() const
Class implementing the crossterms excluded-volume model.
const std::vector< std::vector< int > > & EVComponentIndices() const
Class implementing the diagonal excluded-volume model.
double ExcludedVolume(int i) const
The excluded volume parameter of particle species i.
Class implementing the Ideal HRG model.
Class implementing the quantum real gas HRG model.
ExcludedVolumeModelMultiBase * ExcludedVolumeModel() const
Get the excluded volume model used in the real gas HRG model.
MeanFieldModelMultiBase * MeanFieldModel() const
Get the mean field model used in the real gas HRG model.
Class implementing the quantum van der Waals HRG model.
double AttractionCoefficient(int i, int j) const
QvdW mean field attraction coefficient .
const std::vector< std::vector< int > > & VDWComponentIndices() const
const std::vector< std::vector< double > > & VirialMatrix() const
const std::vector< std::vector< double > > & AttractionMatrix() const
double VirialCoefficient(int i, int j) const
Excluded volume coefficient .
Class containing all information about a particle specie.
long long PdgId() const
Particle's Particle Data Group (PDG) ID number.
int Statistics() const
Particle's statistics.
double Mass() const
Particle's mass [GeV].
ResonanceWidthIntegration GetResonanceWidthIntegrationType() const
Resonance width integration scheme used to treat finite resonance widths.
@ eBW
Energy-dependent Breit-Wigner scheme (eBW)
@ ZeroWidth
Zero-width approximation.
bool ZeroWidthEnforced() const
Whether zero-width approximation is enforced for this particle species.
Class containing the particle list.
ThermalParticle::ResonanceWidthIntegration ResonanceWidthIntegrationType() const
int PdgToId(long long pdgid) const
Transforms PDG ID to a 0-based particle id number.
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
const ThermalParticle & ParticleByPDG(long long pdgid) const
ThermalParticle object corresponding to particle species with a provided PDG ID.
double rv(double v)
Computes the radius parameter from a given excluded volume parameter value.
const ThermalParticle & ParticleByPdg(long long pdg)
double ParticleDistanceSquared(const SimpleParticle &part1, const SimpleParticle &part2)
Return the square of the distance between particles at equal time.
std::vector< SimpleParticle > ManyBodyDecay(const SimpleParticle &Mother, std::vector< double > masses, std::vector< long long > pdgs)
Samples the decay products of a many-body decay.
int RandomPoisson(double mean)
Generates random integer distributed by Poisson with specified mean Uses randgenMT.
MTRand randgenMT
The Mersenne Twister random number generator.
std::mt19937 rng_std
The Mersenne Twister random number generator from STD library.
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
ThermalModelVDW ThermalModelVDWFull
For backward compatibility.
std::vector< double > LorentzBoost(const std::vector< double > &fourvector, double vx, double vy, double vz)
Performs a Lorentz boost on a four-vector.
Structure containing the thermal event generator configuration.
Ensemble fEnsemble
The statistical ensemble used.
int B
The total values of conserved charges in the CE.
bool fUseEVRejectionMultiplicity
Whether to use rejection sampling instead of importance sampling for the EV multiplicity sampling.
int RealGasExcludedVolumePrescription
The type of generalized excluded volume model prescription.
bool fUseEVUseSPRApproximation
Whether to use the SPR (single-particle rejection) approximation for the EV effects in coordinate spa...
ThermalModelParameters CFOParameters
The chemical freeze-out parameters.
bool CanonicalB
Mixed-canonical configuration (full canonical by default)
ModelType fModelType
The type of interaction model.
bool fUsePCE
Whether partial chemical equilibrium (PCE) is used.
bool fUseEVRejectionCoordinates
Whether to use rejection sampling in the coordinate space to model EV effects.
@ CrosstermsEV
Crossterms excluded-volume.
bool fUseGCEConservedCharges
Whether to calculate total conserved charge values from GCE.
static int RandomBesselDevroye1(double a, int nu, MTRand &rangen)
Structure holding information about a single event in the event generator.
Definition SimpleEvent.h:20
double weight
Event weight factor.
Definition SimpleEvent.h:22
std::vector< SimpleParticle > Particles
Vector of all final particles in the event.
Definition SimpleEvent.h:28
double logweight
Log of the event weight factor.
Definition SimpleEvent.h:25
std::vector< SimpleParticle > AllParticles
Vector of all particles which ever appeared in the event (including those that decay and photons/lept...
Definition SimpleEvent.h:31
std::vector< int > DecayMap
Definition SimpleEvent.h:38
std::vector< SimpleParticle > PhotonsLeptons
Vector of all decay photons/leptons.
Definition SimpleEvent.h:34
std::vector< int > DecayMapFinal
Vector for each Particles element pointing to the index of the primordial resonance from which this p...
Definition SimpleEvent.h:41
Structure holding information about a single particle in the event generator.
Structure containing all thermal parameters of the model.
Contains some extra mathematical functions used in the code.