29 std::string ConservedChargeTag(
const std::vector<int>& conserved)
31 const char labels[4] = {
'B',
'Q',
'S',
'C'};
33 for (
int i = 0; i < 4; ++i) {
34 if (conserved[i] == 1)
35 tag.push_back(labels[i]);
42 void WarnIllDefinedSoundSpeedOnce(
const char* func,
43 const std::vector<int>& conserved,
45 const std::string& reason)
47 static std::set<std::string> warned;
48 std::ostringstream key;
49 key << func <<
"|" << ConservedChargeTag(conserved) <<
"|" << reason;
50 if (warned.insert(key.str()).second) {
51 std::cerr <<
"**WARNING** " << func <<
": ill-defined for conserved set "
52 << ConservedChargeTag(conserved)
53 <<
" at T = " << T <<
" GeV. " << reason << std::endl;
57 bool IsMatrixInvertible(
const MatrixXd& m,
double threshold = 1e-14)
59 FullPivLU<MatrixXd> lu(m);
60 lu.setThreshold(threshold);
61 return lu.isInvertible();
71 m_FeeddownCalculated(false),
72 m_TwoParticleCorrelationsCalculated(false),
73 m_FluctuationsCalculated(false),
74 m_TemperatureDerivativesCalculated(false),
75 m_GCECalculated(false),
88 m_Chem.resize(m_TPS->Particles().size());
90 m_densities.resize(m_TPS->Particles().size());
91 m_densitiestotal.resize(m_TPS->Particles().size());
94 m_wprim.resize(m_TPS->Particles().size());
95 m_wtot.resize(m_TPS->Particles().size());
96 m_skewprim.resize(m_TPS->Particles().size());
97 m_skewtot.resize(m_TPS->Particles().size());
98 m_kurtprim.resize(m_TPS->Particles().size());
99 m_kurttot.resize(m_TPS->Particles().size());
101 m_ConstrainMuB =
false;
102 m_ConstrainMuC = m_ConstrainMuQ = m_ConstrainMuS =
true;
104 m_ConstrainGammaC =
false;
108 for (
int i = 0; i < 4; ++i) m_Susc[i].resize(4);
111 m_NormBratio =
false;
113 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
115 for (
size_t j = 0; j < tpart.
Decays().size(); ++j) {
121 m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
122 m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
123 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
124 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
127 m_InteractionModel =
Ideal;
131 SetUseWidth(TPS()->ResonanceWidthIntegrationType());
133 ResetCalculatedFlags();
152 m_UseWidth = useWidth;
158 m_TPS->SetResonanceWidthIntegrationType(type);
163 if (normBratio != m_NormBratio) {
164 m_NormBratio = normBratio;
166 m_TPS->NormalizeBranchingRatios();
169 m_TPS->RestoreBranchingRatios();
175 void ThermalModelBase::ResetChemicalPotentials() {
176 m_Parameters.muS = m_Parameters.muB / 5.;
177 m_Parameters.muQ = -m_Parameters.muB / 50.;
178 m_Parameters.muC = 0.;
184 m_Volume = m_Parameters.V;
186 ResetCalculatedFlags();
192 ResetCalculatedFlags();
197 m_Parameters.muB = muB;
199 ResetCalculatedFlags();
204 m_Parameters.muQ = muQ;
206 ResetCalculatedFlags();
211 m_Parameters.muS = muS;
213 ResetCalculatedFlags();
218 m_Parameters.muC = muC;
220 ResetCalculatedFlags();
225 m_Parameters.gammaS = gammaS;
226 ResetCalculatedFlags();
231 m_Parameters.gammaC = gammaC;
232 ResetCalculatedFlags();
238 ResetCalculatedFlags();
244 ResetCalculatedFlags();
250 ResetCalculatedFlags();
256 ResetCalculatedFlags();
261 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
262 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
273 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
274 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
285 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
286 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
298 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
299 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
311 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
312 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
324 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
325 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
337 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
338 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
350 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
351 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
363 m_Parameters.gammaq = gammaq;
364 ResetCalculatedFlags();
370 m_Chem.resize(m_TPS->Particles().size());
371 m_densities.resize(m_TPS->Particles().size());
372 m_densitiestotal.resize(m_TPS->Particles().size());
374 m_wprim.resize(m_TPS->Particles().size());
375 m_wtot.resize(m_TPS->Particles().size());
376 m_skewprim.resize(m_TPS->Particles().size());
377 m_skewtot.resize(m_TPS->Particles().size());
378 m_kurtprim.resize(m_TPS->Particles().size());
379 m_kurttot.resize(m_TPS->Particles().size());
380 m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
381 m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
382 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
383 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
384 ResetCalculatedFlags();
388 m_QuantumStats = stats;
389 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
390 m_TPS->Particle(i).UseStatistics(stats);
396 std::cerr <<
"**WARNING** ThermalModelBase::SetResonanceWidthIntegrationType: Using resonance widths is switched off!" << std::endl;
400 m_TPS->SetResonanceWidthIntegrationType(type);
404 m_Chem.resize(m_TPS->Particles().size());
405 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
406 m_Chem[i] = m_TPS->Particles()[i].BaryonCharge() * m_Parameters.muB + m_TPS->Particles()[i].Strangeness() * m_Parameters.muS + m_TPS->Particles()[i].ElectricCharge() * m_Parameters.muQ + m_TPS->Particles()[i].Charm() * m_Parameters.muC;
411 if (chem.size() != m_TPS->Particles().size()) {
412 std::cerr <<
"**WARNING** " << m_TAG <<
"::SetChemicalPotentials(const std::vector<double> & chem): size of chem does not match number of hadrons in the list" << std::endl;
420 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
421 throw std::out_of_range(
"ThermalModelBase::ChemicalPotential: i is out of bounds!");
428 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
429 throw std::out_of_range(
"ThermalModelBase::SetChemicalPotential: i is out of bounds!");
436 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
437 throw std::out_of_range(
"ThermalModelBase::FullIdealChemicalPotential: i is out of bounds!");
446 if (!(m_Parameters.gammaq == 1.)) ret += log(m_Parameters.gammaq) * part.
AbsoluteQuark() * m_Parameters.T;
448 if (!(m_Parameters.gammaC == 1. || part.
AbsoluteCharm() == 0.)) ret += log(m_Parameters.gammaC) * part.
AbsoluteCharm() * m_Parameters.T;
455 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
456 m_TPS->Particle(i).CalculateThermalBranchingRatios(m_Parameters, m_UseWidth, m_Chem[i] + MuShift(i));
458 m_TPS->ProcessDecays();
466 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
467 m_densitiestotal[i] = m_densities[i];
470 for (
size_t j = 0; j < decayContributions.size(); ++j)
471 if (i != decayContributions[j].second)
472 m_densitiestotal[i] += decayContributions[j].first * m_densities[decayContributions[j].second];
475 m_densitiesbyfeeddown[feed_index] = m_densitiestotal;
479 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
480 m_densitiesbyfeeddown[feed_index][i] = m_densities[i];
483 for (
size_t j = 0; j < decayContributions.size(); ++j)
484 if (i != decayContributions[j].second)
485 m_densitiesbyfeeddown[feed_index][i] += decayContributions[j].first * m_densities[decayContributions[j].second];
489 m_FeeddownCalculated =
true;
495 if (resetInitialValues)
503 if (m_ConstrainGammaC) {
504 m_Parameters.gammaC = 1.0;
507 if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
509 m_Parameters.muS = 0.;
511 m_Parameters.muQ = 0.;
513 m_Parameters.muC = 0.;
516 ConstrainGammaCFromNccbar();
519 if (m_ConstrainMuB) {
523 if (m_Parameters.muB > 0.150) suppr = 8.;
524 if (m_Parameters.muB > 0.300) suppr = 7.;
525 if (m_Parameters.muB > 0.450) suppr = 6.;
526 if (m_Parameters.muB > 0.600) suppr = 6.;
527 if (m_Parameters.muB > 0.750) suppr = 5.;
528 if (m_Parameters.muB > 0.900) suppr = 4.;
529 if (m_Parameters.muB > 1.000) suppr = 3.;
531 m_Parameters.muS = m_Parameters.muB / suppr;
533 m_Parameters.muQ = -m_Parameters.muB / suppr / 10.;
535 m_Parameters.muC = -m_Parameters.muS;
541 if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
543 m_Parameters.muS = 0.;
545 m_Parameters.muQ = 0.;
547 m_Parameters.muC = 0.;
551 ConstrainGammaCFromNccbar();
555 m_ConstrainMuB &= m_TPS->hasBaryons();
556 m_ConstrainMuQ &= (m_TPS->hasCharged() && m_TPS->hasBaryons());
557 m_ConstrainMuS &= m_TPS->hasStrange();
558 m_ConstrainMuC &= m_TPS->hasCharmed();
560 vector<double> x22(4);
561 x22[0] = m_Parameters.muB;
562 x22[1] = m_Parameters.muQ;
563 x22[2] = m_Parameters.muS;
564 x22[3] = m_Parameters.muC;
565 vector<double> x2(4), xinit(4);
566 xinit[0] = x2[0] = m_Parameters.muB;
567 xinit[1] = x2[1] = m_Parameters.muQ;
568 xinit[2] = x2[2] = m_Parameters.muS;
569 xinit[3] = x2[3] = m_Parameters.muC;
570 int iter = 0, iterMAX = 2;
571 while (iter < iterMAX) {
572 BroydenEquationsChem eqs(
this);
573 BroydenJacobianChem jaco(
this);
574 BroydenChem broydn(
this, &eqs, &jaco);
576 broydn.Solve(x22, &crit);
581 ConstrainGammaCFromNccbar();
584 void ThermalModelBase::ConstrainGammaCFromNccbar() {
585 if (!m_ConstrainGammaC || m_NccbarGoal <= 0.)
588 if (!m_TPS->hasCharmed()) {
589 std::cerr <<
"**WARNING** ConstrainGammaCFromNccbar: "
590 <<
"No charmed particles in the list, cannot constrain gammaC" << std::endl;
594 double V = m_Parameters.V;
595 double targetNccbar = m_NccbarGoal;
598 auto computeResidual = [&](
double log_gammaC) ->
double {
599 double gc = exp(log_gammaC);
603 bool anyMuConstrained = m_ConstrainMuB || m_ConstrainMuQ || m_ConstrainMuS || m_ConstrainMuC;
604 if (anyMuConstrained) {
606 m_ConstrainGammaC =
false;
608 m_ConstrainGammaC =
true;
615 double absCharmDens = CalculateAbsoluteCharmDensity();
616 double currentNccbar = V * absCharmDens / 2.0;
618 if (!std::isfinite(currentNccbar))
619 return std::numeric_limits<double>::max();
620 return currentNccbar - targetNccbar;
624 double x0 = log(std::max(m_Parameters.gammaC, 1.e-4));
625 double x1 = x0 + 0.1;
627 double f0 = computeResidual(x0);
628 double f1 = computeResidual(x1);
630 const int maxIter = 50;
631 const double tol = 1.e-8;
634 for (iter = 0; iter < maxIter; ++iter) {
635 if (fabs(f1) < tol * std::max(1.0, targetNccbar))
638 if (fabs(f1 - f0) < 1.e-15) {
641 f1 = computeResidual(x1);
645 double x2 = x1 - f1 * (x1 - x0) / (f1 - f0);
648 x2 = std::max(x2, log(1.e-4));
649 x2 = std::min(x2, log(1000.0));
654 f1 = computeResidual(x1);
657 if (iter == maxIter) {
658 std::cerr <<
"**WARNING** ConstrainGammaCFromNccbar: "
659 <<
"Secant method did not converge after " << maxIter
660 <<
" iterations, |f| = " << fabs(f1) << std::endl;
667 double muBinit,
double muQinit,
double muSinit,
double muCinit,
668 bool ConstrMuB,
bool ConstrMuQ,
bool ConstrMuS,
bool ConstrMuC) {
671 V * rhoB, V * rhoQ, V * rhoS, V * rhoC,
672 muBinit, muQinit, muSinit, muCinit,
673 ConstrMuB, ConstrMuQ, ConstrMuS, ConstrMuC);
677 double muBinit,
double muQinit,
double muSinit,
double muCinit,
678 bool ConstrMuB,
bool ConstrMuQ,
bool ConstrMuS,
bool ConstrMuC) {
680 std::cerr <<
"**WARNING** PCE enabled, cannot assume chemical equilibrium to do optimization..." << std::endl;
695 m_Parameters.muB = muBinit;
697 m_Parameters.muS = muSinit;
699 m_Parameters.muQ = muQinit;
701 m_Parameters.muC = muCinit;
703 allzero &= (totB == 0.0 && ConstrMuB) || (muBinit == 0 && !ConstrMuB);
704 allzero &= (totQ == 0.0 && ConstrMuQ) || (muQinit == 0 && !ConstrMuQ);
705 allzero &= (totS == 0.0 && ConstrMuS) || (muSinit == 0 && !ConstrMuS);
706 allzero &= (totC == 0.0 && ConstrMuC) || (muCinit == 0 && !ConstrMuC);
710 m_Parameters.muB = 0.;
711 m_Parameters.muS = 0.;
712 m_Parameters.muQ = 0.;
713 m_Parameters.muC = 0.;
718 vector<int> vConstr(4, 1);
719 vector<int> vType(4, 0);
722 vConstr[0] = m_TPS->hasBaryons() && ConstrMuB;
723 vConstr[1] = m_TPS->hasCharged() && ConstrMuQ;
724 vConstr[2] = m_TPS->hasStrange() && ConstrMuS;
725 vConstr[3] = m_TPS->hasCharmed() && ConstrMuC;
727 vType[0] = (int)(totB == 0.0);
728 vType[1] = (int)(totQ == 0.0);
729 vType[2] = (int)(totS == 0.0);
730 vType[3] = (int)(totC == 0.0);
732 vector<double> vTotals(4);
738 vector<double> xin(4, 0.);
744 vector<double> xinactual;
745 for (
int i = 0; i < 4; ++i) {
747 xinactual.push_back(xin[i]);
751 BroydenEquationsChemTotals eqs(vConstr, vType, vTotals,
this);
752 BroydenJacobianChemTotals jaco(vConstr, vType, vTotals,
this);
755 broydn.
Solve(xinactual, &crit);
776 m_LastCalculationSuccessFlag =
true;
777 for (
size_t i = 0; i < m_densities.size(); ++i) {
778 if (m_densities[i] != m_densities[i]) {
779 m_LastCalculationSuccessFlag =
false;
781 sprintf(cc,
"Density for particle %lld (%s) is NaN!\n", m_TPS->Particle(i).PdgId(), m_TPS->Particle(i).Name().c_str());
782 std::cerr <<
"**WARNING** " << cc << std::endl;
785 m_ValidityLog.append(cc);
793 std::cerr <<
"**WARNING** " << m_TAG <<
"::CalculateChargeFluctuations(const std::vector<double>& chgs, int order) not implemented!" << std::endl;
794 return std::vector<double>();
797 std::vector<double> ThermalModelBase::CalculateGeneralizedSusceptibilities(
const std::vector<std::vector<double>> &)
799 throw std::runtime_error(
"ThermalModelBase::CalculateGeneralizedSusceptibilities: not implemented!");
802 double ThermalModelBase::CalculateHadronDensity() {
805 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
806 ret += m_densities[i];
811 double ThermalModelBase::CalculateBaryonDensity() {
814 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
815 ret += m_TPS->Particles()[i].BaryonCharge() * m_densities[i];
820 double ThermalModelBase::CalculateChargeDensity() {
823 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
824 ret += m_TPS->Particles()[i].ElectricCharge() * m_densities[i];
829 double ThermalModelBase::CalculateStrangenessDensity() {
832 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
833 ret += m_TPS->Particles()[i].Strangeness() * m_densities[i];
838 double ThermalModelBase::CalculateCharmDensity() {
841 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
842 ret += m_TPS->Particles()[i].Charm() * m_densities[i];
846 double ThermalModelBase::CalculateAbsoluteBaryonDensity() {
849 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
850 ret += fabs((
double)m_TPS->Particles()[i].BaryonCharge()) * m_densities[i];
854 double ThermalModelBase::CalculateAbsoluteChargeDensity() {
857 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
858 ret += fabs((
double)m_TPS->Particles()[i].ElectricCharge()) * m_densities[i];
862 double ThermalModelBase::CalculateAbsoluteStrangenessDensity() {
865 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
866 ret += m_TPS->Particles()[i].AbsoluteStrangeness() * m_densities[i];
870 double ThermalModelBase::CalculateAbsoluteStrangenessDensityModulo() {
873 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
874 ret += fabs((
double)m_TPS->Particles()[i].Strangeness()) * m_densities[i];
878 double ThermalModelBase::CalculateAbsoluteCharmDensity() {
881 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
882 ret += m_TPS->Particles()[i].AbsoluteCharm() * m_densities[i];
886 double ThermalModelBase::CalculateAbsoluteCharmDensityModulo() {
889 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
890 ret += fabs((
double)m_TPS->Particles()[i].Charm()) * m_densities[i];
894 double ThermalModelBase::CalculateArbitraryChargeDensity() {
897 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
898 ret += m_TPS->Particles()[i].ArbitraryCharge() * m_densities[i];
903 double ThermalModelBase::GetDensity(
long long PDGID,
const std::vector<double> *dens)
905 if (m_TPS->PdgToId(PDGID) != -1)
906 return dens->operator[](m_TPS->PdgToId(PDGID));
909 if (PDGID == 1)
return CalculateBaryonDensity();
912 if (PDGID == 310 || PDGID == 130)
913 if (m_TPS->PdgToId(311) != -1 && m_TPS->PdgToId(-311) != -1)
914 return (dens->operator[](m_TPS->PdgToId(311)) + dens->operator[](m_TPS->PdgToId(-311))) / 2.;
917 if (PDGID % 10 == 0) {
918 long long tpdgid = PDGID / 10;
919 if (m_TPS->PdgToId(tpdgid) != -1 && m_TPS->PdgToId(-tpdgid) != -1)
920 return dens->operator[](m_TPS->PdgToId(tpdgid)) + dens->operator[](m_TPS->PdgToId(-tpdgid));
924 if (PDGID == 22122112 && m_TPS->PdgToId(2212) != -1 && m_TPS->PdgToId(2112) != -1)
925 return dens->operator[](m_TPS->PdgToId(2212)) + dens->operator[](m_TPS->PdgToId(2112));
927 std::cerr <<
"**WARNING** " << m_TAG <<
": Density with PDG ID " << PDGID <<
" not found!" << std::endl;
932 double ThermalModelBase::GetDensity(
long long PDGID,
Feeddown::Type feeddown)
934 std::vector<double> *dens = NULL;
938 dens = &m_densitiestotal;
939 else if (
static_cast<size_t>(feeddown) < m_densitiesbyfeeddown.size())
940 dens = &m_densitiesbyfeeddown[
static_cast<int>(feeddown)];
942 std::cerr <<
"**WARNING** " << m_TAG <<
": GetDensity: Unknown feeddown: " <<
static_cast<int>(feeddown) << std::endl;
952 double ret = GetDensity(PDGID, dens);
958 ret += 2. * 0.308 * GetDensity(310, dens);
961 if (PDGID == 211 || PDGID == -211) {
962 ret += 0.692 * GetDensity(310, dens);
970 std::vector<double> ThermalModelBase::GetIdealGasDensities()
const {
971 std::vector<double> ret = m_densities;
972 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
978 void ThermalModelBase::ResetCalculatedFlags()
980 m_Calculated =
false;
981 m_FeeddownCalculated =
false;
982 m_TwoParticleCorrelationsCalculated =
false;
983 m_SusceptibilitiesCalculated =
false;
984 m_FluctuationsCalculated =
false;
985 m_TemperatureDerivativesCalculated =
false;
986 m_GCECalculated =
false;
992 return BaryonDensity();
994 return ElectricChargeDensity();
996 return StrangenessDensity();
998 return CharmDensity();
1005 return AbsoluteBaryonDensity();
1007 return AbsoluteElectricChargeDensity();
1009 return AbsoluteStrangenessDensity();
1011 return AbsoluteCharmDensity();
1017 if (!IsTemperatureDerivativesCalculated())
1021 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1022 ret += m_TPS->Particles()[i].ConservedCharge(chg) * m_dndT[i];
1028 double ThermalModelBase::ChargedMultiplicity(
int type)
1032 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1033 int tQ = m_TPS->Particles()[i].ElectricCharge();
1035 if (type == 0 && tQ != 0)
1037 if (type == 1 && tQ > 0)
1039 if (type == -1 && tQ < 0)
1042 ret += m_densities[i];
1047 double ThermalModelBase::ChargedScaledVariance(
int type)
1049 if (!m_FluctuationsCalculated) {
1050 std::cerr <<
"**WARNING** " << m_TAG <<
": ChargedScaledVariance(int): Fluctuations were not calculated\n";
1054 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1055 int tQ = m_TPS->Particles()[i].ElectricCharge();
1057 if (type == 0 && tQ != 0)
1059 if (type == 1 && tQ > 0)
1061 if (type == -1 && tQ < 0)
1064 for (
int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
1065 int tQ2 = m_TPS->Particles()[j].ElectricCharge();
1067 if (type == 0 && tQ2 != 0)
1069 if (type == 1 && tQ2 > 0)
1071 if (type == -1 && tQ2 < 0)
1075 ret += m_PrimCorrel[i][j];
1080 return ret * m_Parameters.T *
Volume() / ChargedMultiplicity(type);
1083 double ThermalModelBase::ChargedMultiplicityFinal(
int type)
1092 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1093 ret += m_densities[i] * m_TPS->Particles()[i].Nch()[op];
1098 double ThermalModelBase::ChargedScaledVarianceFinal(
int type)
1100 if (!m_FluctuationsCalculated) {
1101 std::cerr <<
"**WARNING** " << m_TAG <<
": ChargedScaledVarianceFinal(int): Fluctuations were not calculated" << std::endl;
1108 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1109 ret += m_densities[i] *
Volume() * m_TPS->Particles()[i].DeltaNch()[op];
1110 for (
int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
1111 ret += m_PrimCorrel[i][j] * m_Parameters.T *
Volume() * m_TPS->Particles()[i].Nch()[op] * m_TPS->Particles()[j].Nch()[op];
1114 return ret / ChargedMultiplicityFinal(type);
1118 throw std::runtime_error(
"ThermalModelBase::CalculateTwoParticleCorrelations: Calculation of two-particle correlations and fluctuations is not implemented");
1126 int NN = m_densities.size();
1129 for (
int i = 0; i < NN; ++i)
1132 m_TotalCorrel[i][i] = m_PrimCorrel[i][i];
1135 for (
size_t r = 0; r < decayContributions.size(); ++r) {
1136 int rr = decayContributions[r].second;
1138 m_TotalCorrel[i][i] += 2. * m_PrimCorrel[i][rr] * decayContributions[r].first;
1140 for (
size_t r2 = 0; r2 < decayContributions.size(); ++r2) {
1141 int rr2 = decayContributions[r2].second;
1142 m_TotalCorrel[i][i] += m_PrimCorrel[rr][rr2] * decayContributions[r].first * decayContributions[r2].first;
1146 m_TotalCorrel[i][i] += m_densities[rr] / m_Parameters.T * m_TPS->DecayCumulants()[i][r].first[1];
1164 for (
int i = 0; i < NN; ++i) {
1165 if (m_TPS->Particles()[i].IsStable()) {
1166 for (
int j = 0; j < NN; ++j) {
1167 if (j != i && m_TPS->Particles()[j].IsStable()) {
1168 m_TotalCorrel[i][j] = m_PrimCorrel[i][j];
1173 for (
size_t r = 0; r < decayContributionsJ.size(); ++r) {
1174 int rr = decayContributionsJ[r].second;
1175 m_TotalCorrel[i][j] += m_PrimCorrel[i][rr] * decayContributionsJ[r].first;
1178 for (
size_t r = 0; r < decayContributionsI.size(); ++r) {
1179 int rr = decayContributionsI[r].second;
1180 m_TotalCorrel[i][j] += m_PrimCorrel[j][rr] * decayContributionsI[r].first;
1183 for (
size_t r = 0; r < decayContributionsI.size(); ++r) {
1184 int rr = decayContributionsI[r].second;
1186 for (
size_t r2 = 0; r2 < decayContributionsJ.size(); ++r2) {
1187 int rr2 = decayContributionsJ[r2].second;
1188 m_TotalCorrel[i][j] += m_PrimCorrel[rr][rr2] * decayContributionsI[r].first * decayContributionsJ[r2].first;
1193 for (
int r = 0; r < m_TPS->ComponentsNumber(); ++r) {
1194 if (r != i && r != j) {
1195 double nij = 0., ni = 0., nj = 0., dnij = 0.;
1198 for (
size_t br = 0; br < decayDistributions.size(); ++br) {
1199 nij += decayDistributions[br].first * decayDistributions[br].second[i] * decayDistributions[br].second[j];
1200 ni += decayDistributions[br].first * decayDistributions[br].second[i];
1201 nj += decayDistributions[br].first * decayDistributions[br].second[j];
1203 dnij = nij - ni * nj;
1204 m_TotalCorrel[i][j] += m_densities[r] / m_Parameters.T * dnij;
1212 for (
int i = 0; i < NN; ++i) {
1213 m_wtot[i] = m_TotalCorrel[i][i];
1214 if (m_densitiestotal[i] > 0.) m_wtot[i] *= m_Parameters.T / m_densitiestotal[i];
1215 else m_wtot[i] = 1.;
1217 if (m_wtot[i] != m_wtot[i]) m_wtot[i] = 1.;
1223 double nB = 0., nBbar = 0.;
1225 if(TPS()->Particles()[i].BaryonCharge() == 1) nB += m_densities[i];
1226 if(TPS()->Particles()[i].BaryonCharge() == -1) nBbar += m_densities[i];
1232 double gammaB = gammaBbar * nBbar / nB + (nB - nBbar) / nB;
1233 double gammaBav = (gammaB * nB + gammaBbar * nBbar) / (nB + nBbar);
1235 double wp = 0., wm = 0.;
1246 wp += m_PrimCorrel[i][j];
1248 wm += m_PrimCorrel[i][j];
1251 wp = wp * m_Parameters.T / nB;
1252 wm = wm * m_Parameters.T / nBbar;
1254 double wp0 = wp, wm0 = wm;
1255 wp = (1. - gammaB + gammaB * wp0);
1256 wm = (1. - gammaBbar + gammaBbar * wm0);
1258 double deltachipm = wp * nB * gammaB - wp0 * nB + wm * nBbar * gammaBbar - wm0 * nBbar;
1259 deltachipm *= 1. / m_Parameters.T;
1269 double gamma = (part.
BaryonCharge() == 1) ? gammaB : gammaBbar;
1270 double chi1i = m_densities[i];
1271 double chi2i = m_PrimCorrel[i][j] * m_Parameters.T;
1272 double chi2i_new = gamma * (1. - gamma) * chi1i + gamma * gamma * chi2i;
1273 m_PrimCorrel[i][j] = chi2i_new / m_Parameters.T;
1278 double gamma = gammaB;
1279 m_PrimCorrel[i][j] = gamma * gamma * m_PrimCorrel[i][j];
1284 double gamma = gammaBbar;
1285 m_PrimCorrel[i][j] = gamma * gamma * m_PrimCorrel[i][j];
1289 m_PrimCorrel[i][j] += deltachipm * m_densities[i] * m_densities[j] / nB / nBbar;
1294 if(TPS()->Particles()[i].BaryonCharge() == 1)
1295 m_densities[i] *= gammaB;
1296 if(TPS()->Particles()[i].BaryonCharge() == -1)
1297 m_densities[i] *= gammaBbar;
1307 if (!IsFluctuationsCalculated()) {
1308 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityPrimordial: fluctuations were not computed beforehand!");
1316 int i = TPS()->PdgToId(id1);
1317 int j = TPS()->PdgToId(id2);
1320 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id1 << std::endl;
1324 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id2 << std::endl;
1332 if (!IsFluctuationsCalculated() || !IsTemperatureDerivativesCalculated()) {
1333 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityPrimordial: temperature derivatives of fluctuations were not computed beforehand!");
1336 return m_PrimChi2sdT[i][j];
1341 int i = TPS()->PdgToId(id1);
1342 int j = TPS()->PdgToId(id2);
1345 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityTemperatureDerivativePrimordialByPdg: unknown pdg code " << id1 << std::endl;
1349 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityTemperatureDerivativePrimordialByPdg: unknown pdg code " << id2 << std::endl;
1358 int i1 = TPS()->PdgToId(id1);
1359 int j1 = TPS()->PdgToId(id2);
1362 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id1 << std::endl;
1366 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id2 << std::endl;
1370 int i2 = TPS()->PdgToId(-id1);
1371 int j2 = TPS()->PdgToId(-id2);
1374 if (i2 == -1 && j2 == -1) {
1394 if (!IsFluctuationsCalculated()) {
1395 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityFinal: fluctuations were not computed beforehand!");
1398 if (!m_TPS->Particle(i).IsStable() || !m_TPS->Particle(j).IsStable()) {
1400 if (!m_TPS->Particle(j).IsStable())
1402 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityFinal: Particle " + std::to_string(tid) +
" is not stable! Final correlations not computed for unstable particles.");
1410 int i = TPS()->PdgToId(id1);
1411 int j = TPS()->PdgToId(id2);
1414 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code " << id1 << std::endl;
1418 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code " << id2 << std::endl;
1427 int i1 = TPS()->PdgToId(id1);
1428 int j1 = TPS()->PdgToId(id2);
1431 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code " << id1 << std::endl;
1435 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code " << id2 << std::endl;
1439 int i2 = TPS()->PdgToId(-id1);
1440 int j2 = TPS()->PdgToId(-id2);
1443 if (i2 == -1 && j2 == -1) {
1463 if (!IsFluctuationsCalculated()) {
1464 throw std::runtime_error(
"ThermalModelBase::PrimordialParticleChargeSusceptibility: fluctuations were not computed beforehand!");
1472 int i = TPS()->PdgToId(id1);
1474 std::cerr <<
"**WARNING** ThermalModelBase::PrimordialParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1483 int i1 = TPS()->PdgToId(id1);
1485 std::cerr <<
"**WARNING** ThermalModelBase::PrimordialNetParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1489 int i2 = TPS()->PdgToId(-id1);
1498 if (!IsFluctuationsCalculated()) {
1499 throw std::runtime_error(
"ThermalModelBase::FinalParticleChargeSusceptibility: fluctuations were not computed beforehand!");
1507 int i = TPS()->PdgToId(id1);
1509 std::cerr <<
"**WARNING** ThermalModelBase::FinalParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1518 int i1 = TPS()->PdgToId(id1);
1520 std::cerr <<
"**WARNING** ThermalModelBase::FinalNetParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1524 int i2 = TPS()->PdgToId(-id1);
1534 if (!m_TwoParticleCorrelationsCalculated)
1538 for (
int i = 0; i < 4; ++i) m_Susc[i].resize(4);
1541 for (
int i = 0; i < 4; ++i) {
1542 for (
int j = 0; j < 4; ++j) {
1544 m_dSuscdT[i][j] = 0.;
1545 for (
size_t k = 0; k < m_PrimCorrel.size(); ++k) {
1547 if (i == 0) c1 = m_TPS->Particles()[k].BaryonCharge();
1548 if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1549 if (i == 2) c1 = m_TPS->Particles()[k].Strangeness();
1550 if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1551 for (
size_t kp = 0; kp < m_PrimCorrel.size(); ++kp) {
1553 if (j == 0) c2 = m_TPS->Particles()[kp].BaryonCharge();
1554 if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1555 if (j == 2) c2 = m_TPS->Particles()[kp].Strangeness();
1556 if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1557 m_Susc[i][j] += c1 * c2 * m_PrimCorrel[k][kp];
1559 if (IsTemperatureDerivativesCalculated())
1560 m_dSuscdT[i][j] += c1 * c2 * m_PrimChi2sdT[k][kp];
1566 m_SusceptibilitiesCalculated =
true;
1571 m_ProxySusc.resize(4);
1572 for (
int i = 0; i < 4; ++i)
1573 m_ProxySusc[i].resize(4);
1576 for (
int i = 0; i < 3; ++i) {
1577 for (
int j = 0; j < 3; ++j) {
1578 m_ProxySusc[i][j] = 0.;
1579 for (
size_t k = 0; k < m_TotalCorrel.size(); ++k) {
1580 if (m_TPS->Particles()[k].IsStable()) {
1583 if (i == 0) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 2212) - 1 * (m_TPS->Particles()[k].PdgId() == -2212);
1584 if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1586 if (i == 2) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 321) - 1 * (m_TPS->Particles()[k].PdgId() == -321);
1587 if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1588 for (
size_t kp = 0; kp < m_TotalCorrel.size(); ++kp) {
1589 if (m_TPS->Particles()[kp].IsStable()) {
1592 if (j == 0) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 2212) - 1 * (m_TPS->Particles()[kp].PdgId() == -2212);
1593 if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1595 if (j == 2) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 321) - 1 * (m_TPS->Particles()[kp].PdgId() == -321);
1596 if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1597 m_ProxySusc[i][j] += c1 * c2 * m_TotalCorrel[k][kp];
1611 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1612 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1614 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1616 for (
int chg = 0; chg < 4; ++chg) {
1617 for (
size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1619 m_PrimChargesCorrel[i][chg] += c1 * c2 * m_PrimCorrel[i][j];
1624 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1625 if (m_TPS->Particles()[i].IsStable()) {
1627 for (
int chg = 0; chg < 4; ++chg) {
1628 for (
size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1629 if (m_TPS->Particles()[j].IsStable()) {
1631 m_FinalChargesCorrel[i][chg] += c1 * c2 * m_TotalCorrel[i][j];
1639 std::vector<double> ThermalModelBase::PartialPressures() {
1640 if (!IsCalculated())
1643 std::vector<double> ret(5, 0.);
1644 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1662 std::cerr <<
"**WARNING** " << m_TAG <<
": Calculation of fluctuations is not implemented" << std::endl;
1666 std::cerr <<
"**WARNING** " << m_TAG <<
": Calculation of temperature derivatives is not implemented" << std::endl;
1669 std::vector<double> ThermalModelBase::BroydenEquationsChem::Equations(
const std::vector<double>& x)
1671 std::vector<double> ret(m_N, 0.);
1674 if (m_THM->ConstrainMuB()) { m_THM->SetBaryonChemicalPotential(x[i1]); i1++; }
1675 if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1676 if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1677 if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1678 m_THM->FillChemicalPotentials();
1679 m_THM->CalculatePrimordialDensities();
1684 if (m_THM->ConstrainMuB()) {
1685 double fBd = m_THM->CalculateBaryonDensity();
1686 double fSd = m_THM->CalculateEntropyDensity();
1688 ret[i1] = (fBd / fSd - 1. / m_THM->SoverB()) * m_THM->SoverB();
1694 if (m_THM->ConstrainMuQ()) {
1695 double fBd = m_THM->CalculateBaryonDensity();
1696 double fQd = m_THM->CalculateChargeDensity();
1699 ret[i1] = (fQd / fBd - m_THM->QoverB());
1707 if (m_THM->ConstrainMuS()) {
1708 double fSd = m_THM->CalculateStrangenessDensity();
1709 double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1711 fASd = m_THM->CalculateAbsoluteStrangenessDensityModulo();
1713 ret[i1] = fSd / fASd;
1720 if (m_THM->ConstrainMuC()) {
1721 double fCd = m_THM->CalculateCharmDensity();
1722 double fACd = m_THM->CalculateAbsoluteCharmDensity();
1724 fACd = m_THM->CalculateAbsoluteCharmDensityModulo();
1726 ret[i1] = fCd / fACd;
1734 std::vector<double> ThermalModelBase::BroydenJacobianChem::Jacobian(
const std::vector<double>& x)
1738 if (m_THM->ConstrainMuB()) {
1739 throw std::runtime_error(
"ThermalModelBase::ConstrainChemicalPotentials: analytic calculation of the Jacobian not supported if muB is constrained");
1742 if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1743 if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1744 if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1745 m_THM->FillChemicalPotentials();
1746 m_THM->CalculatePrimordialDensities();
1748 double fBd = m_THM->CalculateBaryonDensity();
1749 double fQd = m_THM->CalculateChargeDensity();
1750 double fSd = m_THM->CalculateStrangenessDensity();
1751 double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1752 if (fASd < 1.e-25) {
1753 fASd = m_THM->CalculateAbsoluteStrangenessDensityModulo();
1755 double fCd = m_THM->CalculateCharmDensity();
1756 double fACd = m_THM->CalculateAbsoluteCharmDensity();
1757 if (fACd < 1.e-25) {
1758 fACd = m_THM->CalculateAbsoluteCharmDensityModulo();
1761 vector<double> chi2s;
1762 chi2s.resize(m_THM->Densities().size());
1763 for (
size_t i = 0; i < chi2s.size(); ++i) {
1764 chi2s[i] = m_THM->TPS()->Particle(i).chiDimensionfull(2, m_THM->Parameters(), m_THM->UseWidth(), m_THM->ChemicalPotential(i) + m_THM->MuShift(i))
1769 if (m_THM->ConstrainMuQ()) NNN++;
1770 if (m_THM->ConstrainMuS()) NNN++;
1771 if (m_THM->ConstrainMuC()) NNN++;
1772 MatrixXd ret(NNN, NNN);
1776 if (m_THM->ConstrainMuQ()) {
1779 double d1 = 0., d2 = 0.;
1781 if (m_THM->ConstrainMuQ()) {
1783 for (
size_t i = 0; i < chi2s.size(); ++i)
1784 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1787 for (
size_t i = 0; i < chi2s.size(); ++i)
1788 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1791 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1798 if (m_THM->ConstrainMuS()) {
1800 for (
size_t i = 0; i < chi2s.size(); ++i)
1801 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1804 for (
size_t i = 0; i < chi2s.size(); ++i)
1805 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1808 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1815 if (m_THM->ConstrainMuC()) {
1817 for (
size_t i = 0; i < chi2s.size(); ++i)
1818 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1821 for (
size_t i = 0; i < chi2s.size(); ++i)
1822 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1825 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1836 if (m_THM->ConstrainMuS()) {
1839 double d1 = 0., d2 = 0.;
1841 if (m_THM->ConstrainMuQ()) {
1843 for (
size_t i = 0; i < chi2s.size(); ++i)
1844 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1847 for (
size_t i = 0; i < chi2s.size(); ++i)
1848 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1850 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1856 if (m_THM->ConstrainMuS()) {
1858 for (
size_t i = 0; i < chi2s.size(); ++i)
1859 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1862 for (
size_t i = 0; i < chi2s.size(); ++i)
1863 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1865 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1871 if (m_THM->ConstrainMuC()) {
1873 for (
size_t i = 0; i < chi2s.size(); ++i)
1874 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1877 for (
size_t i = 0; i < chi2s.size(); ++i)
1878 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1880 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1890 if (m_THM->ConstrainMuC()) {
1893 double d1 = 0., d2 = 0.;
1895 if (m_THM->ConstrainMuQ()) {
1897 for (
size_t i = 0; i < chi2s.size(); ++i)
1898 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1901 for (
size_t i = 0; i < chi2s.size(); ++i)
1902 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).ElectricCharge() *chi2s[i];
1904 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1910 if (m_THM->ConstrainMuS()) {
1912 for (
size_t i = 0; i < chi2s.size(); ++i)
1913 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1916 for (
size_t i = 0; i < chi2s.size(); ++i)
1917 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1919 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1925 if (m_THM->ConstrainMuC()) {
1927 for (
size_t i = 0; i < chi2s.size(); ++i)
1928 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1931 for (
size_t i = 0; i < chi2s.size(); ++i)
1932 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1934 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1942 std::vector<double> retVec(NNN*NNN, 0);
1943 for (
int i = 0; i < NNN; ++i)
1944 for (
int j = 0; j < NNN; ++j)
1945 retVec[i*NNN + j] = ret(i, j);
1951 std::vector<double> ThermalModelBase::BroydenChem::Solve(
const std::vector<double>& x0, BroydenSolutionCriterium * solcrit,
int max_iterations)
1953 if (m_Equations == NULL) {
1954 throw std::runtime_error(
"Broyden::Solve: Equations to solve not specified!");
1958 std::vector<double> xcur;
1959 if (m_THM->ConstrainMuB()) { xcur.push_back(x0[0]); NNN++; }
1960 if (m_THM->ConstrainMuQ()) { xcur.push_back(x0[1]); NNN++; }
1961 if (m_THM->ConstrainMuS()) { xcur.push_back(x0[2]); NNN++; }
1962 if (m_THM->ConstrainMuC()) { xcur.push_back(x0[3]); NNN++; }
1964 m_THM->FillChemicalPotentials();
1968 m_Equations->SetDimension(NNN);
1970 m_MaxIterations = max_iterations;
1972 BroydenSolutionCriterium *SolutionCriterium = solcrit;
1973 bool UseDefaultSolutionCriterium =
false;
1974 if (SolutionCriterium == NULL) {
1975 SolutionCriterium =
new BroydenSolutionCriterium(TOL);
1976 UseDefaultSolutionCriterium =
true;
1980 bool UseDefaultJacobian =
false;
1981 if (JacobianInUse == NULL || m_THM->ConstrainMuB()) {
1983 UseDefaultJacobian =
true;
1986 double &maxdiff = m_MaxDifference;
1987 int N = m_Equations->Dimension();
1991 std::vector<double> tmpvec, xdeltavec = xcur;
1992 VectorXd xold(N), xnew(N), xdelta(N);
1993 VectorXd fold(N), fnew(N), fdelta(N);
1995 xold = VectorXd::Map(&xcur[0], xcur.size());
1997 MatrixXd Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
1999 bool constrmuB = m_THM->ConstrainMuB();
2000 bool constrmuQ = m_THM->ConstrainMuQ();
2001 bool constrmuS = m_THM->ConstrainMuS();
2002 bool constrmuC = m_THM->ConstrainMuC();
2003 bool repeat =
false;
2005 if (m_THM->ConstrainMuB()) {
2006 for (
int j = 0; j < Jac.rows(); ++j)
2007 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuB(
false); }
2008 double S = m_THM->CalculateEntropyDensity();
2009 double nB = m_THM->CalculateBaryonDensity();
2010 if (abs(S) < 1.e-25 || abs(nB) < 1.e-25) { repeat =
true; m_THM->ConstrainMuB(
false); }
2013 if (m_THM->ConstrainMuQ()) {
2014 for (
int j = 0; j < Jac.rows(); ++j)
2015 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuQ(
false); }
2016 double nQ = m_THM->CalculateChargeDensity();
2017 double nB = m_THM->CalculateBaryonDensity();
2018 if (abs(nQ) < 1.e-25 || abs(nB) < 1.e-25) { repeat =
true; m_THM->ConstrainMuQ(
false); }
2021 if (m_THM->ConstrainMuS()) {
2022 for (
int j = 0; j < Jac.rows(); ++j)
2023 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuS(
false); }
2025 double nS = m_THM->CalculateAbsoluteStrangenessDensity();
2026 if (abs(nS) < 1.e-25) { nS = m_THM->CalculateAbsoluteStrangenessDensityModulo(); }
2027 if (abs(nS) < 1.e-25) { repeat =
true; m_THM->ConstrainMuS(
false); }
2030 if (m_THM->ConstrainMuC()) {
2031 for (
int j = 0; j < Jac.rows(); ++j)
2032 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuC(
false); }
2033 double nC = m_THM->CalculateAbsoluteCharmDensity();
2034 if (abs(nC) < 1.e-25) { nC = m_THM->CalculateAbsoluteCharmDensityModulo(); }
2035 if (abs(nC) < 1.e-25) { repeat =
true; m_THM->ConstrainMuC(
false); }
2039 std::vector<double> ret = Solve(x0, solcrit, max_iterations);
2040 m_THM->ConstrainMuQ(constrmuB);
2041 m_THM->ConstrainMuQ(constrmuQ);
2042 m_THM->ConstrainMuS(constrmuS);
2043 m_THM->ConstrainMuC(constrmuC);
2047 if (Jac.determinant() == 0.0)
2049 std::cerr <<
"**WARNING** Singular Jacobian in Broyden::Solve" << std::endl;
2053 MatrixXd Jinv = Jac.inverse();
2054 tmpvec = m_Equations->Equations(xcur);
2055 fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
2057 for (m_Iterations = 1; m_Iterations < max_iterations; ++m_Iterations) {
2058 xnew = xold - Jinv * fold;
2060 VectorXd::Map(&xcur[0], xcur.size()) = xnew;
2062 tmpvec = m_Equations->Equations(xcur);
2063 fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
2067 for (
size_t i = 0; i < xcur.size(); ++i) {
2068 maxdiff = std::max(maxdiff, fabs(fnew[i]));
2071 xdelta = xnew - xold;
2072 fdelta = fnew - fold;
2074 VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
2076 if (SolutionCriterium->IsSolved(xcur, tmpvec, xdeltavec))
2083 for (
int i = 0; i < N; ++i)
2084 for (
int j = 0; j < N; ++j)
2085 norm += xdelta[i] * Jinv(i, j) * fdelta[j];
2087 p1 = (xdelta - Jinv * fdelta);
2088 for (
int i = 0; i < N; ++i) p1[i] *= 1. / norm;
2089 Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
2093 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
2094 Jinv = Jac.inverse();
2101 if (m_Iterations == max_iterations) {
2102 std::cerr <<
"**WARNING** Reached maximum number of iterations in Broyden procedure" << std::endl;
2105 if (UseDefaultSolutionCriterium) {
2106 delete SolutionCriterium;
2107 SolutionCriterium = NULL;
2109 if (UseDefaultJacobian) {
2110 delete JacobianInUse;
2111 JacobianInUse = NULL;
2117 ThermalModelBase::BroydenEquationsChemTotals::BroydenEquationsChemTotals(
const std::vector<int>& vConstr,
const std::vector<int>& vType,
const std::vector<double>& vTotals,
ThermalModelBase * model) :
2118 BroydenEquations(), m_Constr(vConstr), m_Type(vType), m_Totals(vTotals), m_THM(model)
2121 for (
size_t i = 0; i < m_Constr.size(); ++i)
2125 std::vector<double> ThermalModelBase::BroydenEquationsChemTotals::Equations(
const std::vector<double>& x)
2127 std::vector<double> ret(m_N, 0.);
2130 for (
int i = 0; i < 4; ++i) {
2132 if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
2133 if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
2134 if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
2135 if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
2139 m_THM->FillChemicalPotentials();
2140 m_THM->CalculatePrimordialDensities();
2142 vector<double> dens(4, 0.), absdens(4, 0.);
2144 dens[0] = m_THM->CalculateBaryonDensity();
2145 absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
2148 dens[1] = m_THM->CalculateChargeDensity();
2149 absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
2152 dens[2] = m_THM->CalculateStrangenessDensity();
2153 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
2154 if (absdens[2] < 1.e-25) {
2155 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensityModulo();
2159 dens[3] = m_THM->CalculateCharmDensity();
2160 absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
2161 if (absdens[3] < 1.e-25) {
2162 absdens[3] = m_THM->CalculateAbsoluteCharmDensityModulo();
2168 for (
int i = 0; i < 4; ++i) {
2171 ret[i1] = (dens[i] * m_THM->Parameters().V - m_Totals[i]) / m_Totals[i];
2173 ret[i1] = dens[i] / absdens[i];
2181 std::vector<double> ThermalModelBase::BroydenJacobianChemTotals::Jacobian(
const std::vector<double>& x)
2184 for (
int i = 0; i < 4; ++i) NNN += m_Constr[i];
2188 for (
int i = 0; i < 4; ++i) {
2190 if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
2191 if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
2192 if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
2193 if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
2198 m_THM->FillChemicalPotentials();
2199 m_THM->CalculatePrimordialDensities();
2201 vector<double> dens(4, 0.), absdens(4, 0.);
2203 dens[0] = m_THM->CalculateBaryonDensity();
2204 absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
2207 dens[1] = m_THM->CalculateChargeDensity();
2208 absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
2211 dens[2] = m_THM->CalculateStrangenessDensity();
2212 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
2213 if (absdens[2] < 1.e-25) {
2214 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensityModulo();
2218 dens[3] = m_THM->CalculateCharmDensity();
2219 absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
2220 if (absdens[3] < 1.e-25) {
2221 absdens[3] = m_THM->CalculateAbsoluteCharmDensityModulo();
2225 vector<double> chi2s;
2226 chi2s.resize(m_THM->Densities().size());
2227 for (
size_t i = 0; i < chi2s.size(); ++i) {
2228 chi2s[i] = m_THM->TPS()->Particle(i).chiDimensionfull(2, m_THM->Parameters(), m_THM->UseWidth(), m_THM->ChemicalPotential(i) + m_THM->MuShift(i))
2232 vector< vector<double> > deriv(4, vector<double>(4)), derivabs(4, vector<double>(4));
2233 for (
int i = 0; i < 4; ++i)
2234 for (
int j = 0; j < 4; ++j) {
2236 for (
size_t part = 0; part < chi2s.size(); ++part)
2237 deriv[i][j] += m_THM->TPS()->Particles()[part].GetCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * chi2s[part];
2239 derivabs[i][j] = 0.;
2240 for (
size_t part = 0; part < chi2s.size(); ++part)
2241 derivabs[i][j] += m_THM->TPS()->Particles()[part].GetAbsCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * chi2s[part];
2245 MatrixXd ret(NNN, NNN);
2249 for (
int i = 0; i < 4; ++i) {
2252 for (
int j = 0; j < 4; ++j)
2256 ret(i1, i2) = deriv[i][j] * m_THM->Parameters().V / m_Totals[i];
2258 ret(i1, i2) = deriv[i][j] / absdens[i] - dens[i] / absdens[i] / absdens[i] * derivabs[i][j];
2265 std::vector<double> retVec(NNN*NNN, 0);
2266 for (
int i = 0; i < NNN; ++i)
2267 for (
int j = 0; j < NNN; ++j)
2268 retVec[i*NNN + j] = ret(i, j);
2274 void ThermalModelBase::SetDensityModelForParticleSpecies(
int i,
GeneralizedDensity *density_model)
2277 TPS()->Particle(i).SetGeneralizedDensity(density_model);
2279 std::cerr <<
"**WARNING** ThermalModelBase::SetDensityModelForParticleSpecies(): Particle id " << i <<
" is outside the range!" << std::endl;
2283 void ThermalModelBase::SetDensityModelForParticleSpeciesByPdg(
long long PDGID,
GeneralizedDensity *density_model)
2285 int id = TPS()->PdgToId(PDGID);
2287 TPS()->Particle(
id).SetGeneralizedDensity(density_model);
2289 std::cerr <<
"**WARNING** ThermalModelBase::SetDensityModelForParticleSpeciesByPdg(): Pdg code " << PDGID <<
" is outside the range!" << std::endl;
2293 void ThermalModelBase::ClearDensityModels() {
2294 for (
auto& particle : TPS()->Particles())
2295 particle.ClearGeneralizedDensity();
2298 void ThermalModelBase::SetMagneticField(
double B,
int lmax) {
2299 m_IGFExtraConfig.MagneticField.B = B;
2301 m_IGFExtraConfig.MagneticField.lmax = lmax;
2302 for (
auto& particle : TPS()->Particles())
2303 particle.SetMagneticField(B, m_IGFExtraConfig.MagneticField.lmax);
2304 RecomputeThresholdsDueToMagneticField();
2305 ResetCalculatedFlags();
2308 void ThermalModelBase::RecomputeThresholdsDueToMagneticField() {
2309 const double &B = m_IGFExtraConfig.MagneticField.B;
2310 for (
int ipart = 0; ipart < TPS()->ComponentsNumber(); ++ipart) {
2311 ThermalParticle &part = TPS()->Particle(ipart);
2312 if (!part.ZeroWidthEnforced() || part.ElectricCharge()==0) {
2314 part.CalculateAndSetDynamicalThreshold();
2315 part.FillCoefficientsDynamical();
2316 }
else if (!part.ZeroWidthEnforced()) {
2317 double szmax = (part.Degeneracy() - 1.) / 2.;
2319 double mmin = sqrt(2. * abs(part.ElectricCharge()) * B * (szmax - 0.5));
2320 part.CalculateAndSetDynamicalThreshold();
2321 if (mmin > part.DecayThresholdMassDynamical()) {
2322 part.SetDecayThresholdMassDynamical(mmin);
2324 part.FillCoefficientsDynamical();
2331 void ThermalModelBase::ClearMagneticField() {
2332 m_IGFExtraConfig.MagneticField.B = 0.;
2333 for (
auto& particle : TPS()->Particles())
2334 particle.ClearMagneticField();
2335 ResetCalculatedFlags();
2339 assert(IsSusceptibilitiesCalculated());
2340 return m_Susc[i][j];
2344 assert(IsSusceptibilitiesCalculated() && IsTemperatureDerivativesCalculated());
2345 return m_dSuscdT[i][j];
2349 assert(IsFluctuationsCalculated());
2350 return m_ProxySusc[i][j];
2353 double ThermalModelBase::GetdndT(
int i)
const {
2354 if (IsTemperatureDerivativesCalculated() && i >= 0 && i <
ComponentsNumber())
2357 std::cerr <<
"**WARNING** ThermalModelBase::GetdndT(): Temperature derivatives are not calculated or particle id " << i <<
" is outside the range!" << std::endl;
2365 for (
size_t k = 0; k < m_PrimCorrel.size(); ++k) {
2366 int c1 = m_TPS->Particles()[k].ConservedCharge(i);
2367 for (
size_t kp = 0; kp < m_PrimCorrel.size(); ++kp) {
2368 int c2 = m_TPS->Particles()[kp].ConservedCharge(j);
2369 ret += c1 * c2 * m_PrimCorrel[k][kp];
2375 double ThermalModelBase::CalculateHeatCapacityMu()
2377 double dedT = CalculateEnergyDensityDerivativeT();
2381 for(
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
2382 ret -= m_Chem[i] * m_dndT[i];
2390 for (
int i = 0; i < 4; ++i)
2391 if (ConservedDensities[i] == 1)
2401 for(
int i = 0; i < 4; ++i) {
2402 if (ConservedDensities[i] == 0)
2405 for(
int j = 0; j < 4; ++j) {
2406 if (ConservedDensities[j] == 0)
2421 for (
int i = 0; i < 4; ++i)
2422 if (ConservedDensities[i] == 1)
2429 ret(0, 0) = model->CalculateEntropyDensityDerivativeT();
2434 for(
int i = 0; i < 4; ++i) {
2435 if (ConservedDensities[i] == 0)
2445 for(
int i = 0; i < 4; ++i) {
2446 if (ConservedDensities[i] == 0)
2449 for(
int j = 0; j < 4; ++j) {
2450 if (ConservedDensities[j] == 0)
2462 vector<vector<double>> ThermalModelBase::PressureHessian()
2465 if (!m_FluctuationsCalculated)
2467 if (!m_TemperatureDerivativesCalculated)
2471 vector<int> allCharges = {1, 1, 1, 1};
2475 int N = H_eigen.rows();
2476 vector<vector<double>> H(N, vector<double>(N, 0.0));
2477 for (
int i = 0; i < N; ++i) {
2478 for (
int j = 0; j < N; ++j) {
2479 H[i][j] = H_eigen(i, j);
2486 bool ThermalModelBase::IsThermodynamicallyStable()
2489 if (!m_FluctuationsCalculated)
2491 if (!m_TemperatureDerivativesCalculated)
2495 vector<int> allCharges = {1, 1, 1, 1};
2499 Eigen::SelfAdjointEigenSolver<MatrixXd> solver(H);
2500 if (solver.info() != Eigen::Success) {
2505 const auto& eigenvalues = solver.eigenvalues();
2506 for (
int i = 0; i < eigenvalues.size(); ++i) {
2507 if (eigenvalues(i) < 0.0) {
2515 double ThermalModelBase::CalculateAdiabaticSpeedOfSoundSquared(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2517 const double nanv = std::numeric_limits<double>::quiet_NaN();
2518 const double eps = 1e-14;
2523 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2525 if (!TPS()->hasBaryons())
2526 ConservedCharges[0] = 0;
2527 if (!TPS()->hasCharged())
2528 ConservedCharges[1] = 0;
2529 if (!TPS()->hasStrange())
2530 ConservedCharges[2] = 0;
2531 if (!TPS()->hasCharmed())
2532 ConservedCharges[3] = 0;
2538 for (
int i = 0; i < 4; ++i) {
2539 if (ConservedCharges[i] == 1
2541 ConservedCharges[i] = 0;
2546 bool AllMuZero =
true;
2547 for(
int i = 0; i < ConservedCharges.size(); ++i)
2548 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2551 WarnIllDefinedSoundSpeedOnce(
2552 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2553 "all relevant chemical potentials are zero (0/0 limit at T=0).");
2558 if (!IsTemperatureDerivativesCalculated())
2566 for(
int i = 0; i < 4; ++i)
2567 if (ConservedCharges[i] == 1)
2570 WarnIllDefinedSoundSpeedOnce(
2571 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2572 "no conserved densities selected.");
2577 if (!IsFluctuationsCalculated())
2584 if (!IsMatrixInvertible(chi2matr)) {
2585 WarnIllDefinedSoundSpeedOnce(
2586 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2587 "susceptibility matrix is singular at T=0.");
2590 MatrixXd chi2inv = chi2matr.inverse();
2593 for(
int i = 0; i < 4; ++i) {
2594 if (ConservedCharges[i] == 0)
2597 for(
int j = 0; j < 4; ++j) {
2598 if (ConservedCharges[j] == 0)
2603 ret += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2610 if (std::abs(ep) < eps) {
2611 WarnIllDefinedSoundSpeedOnce(
2612 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2613 "EnergyDensity + Pressure is zero.");
2623 if (!IsTemperatureDerivativesCalculated())
2631 if (!IsMatrixInvertible(PiMatr)) {
2632 WarnIllDefinedSoundSpeedOnce(
2633 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2634 "pressure Hessian matrix is singular.");
2637 MatrixXd PiMatrInv = PiMatr.inverse();
2640 vector<double> x = {s};
2641 for(
int i = 0; i < ConservedCharges.size(); ++i)
2642 if (ConservedCharges[i] == 1)
2646 for(
int i = 0; i < x.size(); ++i)
2647 for(
int j = 0; j < x.size(); ++j)
2648 ret += x[i] * x[j] * PiMatrInv(i,j);
2650 if (std::abs(ep) < eps) {
2651 WarnIllDefinedSoundSpeedOnce(
2652 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2653 "EnergyDensity + Pressure is zero.");
2661 double ThermalModelBase::CalculateIsothermalSpeedOfSoundSquared(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2663 const double nanv = std::numeric_limits<double>::quiet_NaN();
2664 const double eps = 1e-14;
2669 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2671 if (!TPS()->hasBaryons())
2672 ConservedCharges[0] = 0;
2673 if (!TPS()->hasCharged())
2674 ConservedCharges[1] = 0;
2675 if (!TPS()->hasStrange())
2676 ConservedCharges[2] = 0;
2677 if (!TPS()->hasCharmed())
2678 ConservedCharges[3] = 0;
2684 for (
int i = 0; i < 4; ++i) {
2685 if (ConservedCharges[i] == 1
2687 ConservedCharges[i] = 0;
2691 for (
int i = 0; i < 4; ++i)
2692 if (ConservedCharges[i] == 1)
2695 WarnIllDefinedSoundSpeedOnce(
2696 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2697 "no conserved densities selected.");
2703 bool AllMuZero =
true;
2704 for(
int i = 0; i < ConservedCharges.size(); ++i)
2705 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2712 if (!IsMatrixInvertible(chi2Matr)) {
2713 WarnIllDefinedSoundSpeedOnce(
2714 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2715 "susceptibility matrix is singular.");
2719 MatrixXd chi2inv= chi2Matr.inverse();
2721 double numerator = 0.;
2722 double denominator = 0.;
2724 for(
int i = 0; i < 4; ++i) {
2725 if (ConservedCharges[i] == 0)
2729 for(
int j = 0; j < 4; ++j) {
2730 if (ConservedCharges[j] == 0)
2736 numerator += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2737 denominator += T * ConservedChargeDensitydT(chg1) * chi2inv(i1, i2) * ConservedChargeDensity(chg2);
2739 ret += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2745 if (std::abs(denominator) < eps) {
2746 WarnIllDefinedSoundSpeedOnce(
2747 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2748 "denominator is zero.");
2751 return numerator / denominator;
2754 double ThermalModelBase::CalculateHeatCapacity(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2762 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2764 if (!TPS()->hasBaryons())
2765 ConservedCharges[0] = 0;
2766 if (!TPS()->hasCharged())
2767 ConservedCharges[1] = 0;
2768 if (!TPS()->hasStrange())
2769 ConservedCharges[2] = 0;
2770 if (!TPS()->hasCharmed())
2771 ConservedCharges[3] = 0;
2778 const double eps = 1e-14;
2779 for (
int i = 0; i < 4; ++i) {
2780 if (ConservedCharges[i] == 1
2782 ConservedCharges[i] = 0;
2787 double TdsdT = HeatCapacityMu();
2791 bool AllMuZero =
true;
2792 for(
int i = 0; i < ConservedCharges.size(); ++i)
2793 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2799 if (!IsFluctuationsCalculated())
2803 double denominator = 1.;
2805 auto PiMatrInv = PiMatr.inverse();
2806 int N = PiMatr.rows();
2807 for(
int i = 1; i < N; ++i) {
2808 denominator -= PiMatr(0, i) * PiMatrInv(i, 0);
2811 double heatCapacity = TdsdT / denominator;
2812 return heatCapacity;
map< string, double > params
Contains some helper functions.
Sub-class where it is determined whether the required accuracy is achieved in the Broyden's method.
Abstract class which defines the system of non-linear equations to be solved by the Broyden's method.
Class implementing the Broyden method to solve a system of non-linear equations.
virtual std::vector< double > Solve(const std::vector< double > &x0, BroydenSolutionCriterium *solcrit=NULL, int max_iterations=MAX_ITERS)
int MaxIterations() const
Class which implements calculation of the Jacobian needed for the Broyden's method.
static bool PrintDisclaimer()
static bool DisclaimerPrinted
Implements the possibility of a generalized calculation of the densities. For example,...
Abstract base class for an HRG model implementation.
virtual void CalculateSusceptibilityMatrix()
Calculates the conserved charges susceptibility matrix.
virtual double FullIdealChemicalPotential(int i) const
Chemical potential entering the ideal gas expressions of particle species i.
virtual void FixParametersNoReset()
Method which actually implements ConstrainChemicalPotentialsNoReset() (for backward compatibility).
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
virtual void SetGammaC(double gammaC)
Set the charm quark fugacity factor.
virtual void CalculateParticleChargeCorrelationMatrix()
Calculates the matrix of correlators between primordial (and also final) particle numbers and conserv...
virtual void SetTemperature(double T)
Set the temperature.
virtual void CalculateFluctuations()
Computes the fluctuation observables.
bool UsePartialChemicalEquilibrium()
Whether partial chemical equilibrium with additional chemical potentials is used.
virtual bool SolveChemicalPotentials(double totB=0., double totQ=0., double totS=0., double totC=0., double muBinit=0., double muQinit=0., double muSinit=0., double muCinit=0., bool ConstrMuB=true, bool ConstrMuQ=true, bool ConstrMuS=true, bool ConstrMuC=true)
The procedure which calculates the chemical potentials which reproduce the specified total baryon,...
virtual double TwoParticleSusceptibilityPrimordialByPdg(long long id1, long long id2)
Returns the computed primordial particle number (cross-)susceptibility for particles with pdg codes ...
virtual void DisableMesonMesonVirial()
virtual std::vector< double > CalculateChargeFluctuations(const std::vector< double > &chgs, int order=4, bool dimensionfull=false)
Calculates fluctuations (diagonal susceptibilities) of an arbitrary "conserved" charge.
virtual void SetVirial(int, int, double)
Set the excluded volume coefficient .
virtual void FillChemicalPotentials()
Sets the chemical potentials of all particles.
virtual void CalculateTemperatureDerivatives()
Computes the temperature derivatives of densities, shifted chemical potentials, and primordial hadron...
virtual void DisableMesonBaryonAttraction()
void ConstrainChemicalPotentials(bool resetInitialValues=true)
Constrains the chemical potentials by the conservation laws imposed.
virtual void FixParameters()
Method which actually implements ConstrainChemicalPotentials() (for backward compatibility).
virtual void DisableMesonBaryonVirial()
virtual double TwoParticleSusceptibilityFinalByPdg(long long id1, long long id2)
Returns the computed final particle number (cross-)susceptibility for particles with pdg codes id1 a...
virtual double TwoParticleSusceptibilityFinal(int i, int j) const
Returns the computed final particle number (cross-)susceptibility for particles with ids i and j....
virtual void SetGammaS(double gammaS)
Set the strange quark fugacity factor.
virtual void SetCharm(int C)
Set the total charm (for canonical ensemble only)
virtual double FinalNetParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed final (after decays) net particle vs conserved charge (cross-)susceptibility fo...
void SetResonanceWidthIntegrationType(ThermalParticle::ResonanceWidthIntegration type)
Set the ThermalParticle::ResonanceWidthIntegration scheme for all particles. Calls the corresponding ...
virtual void CalculateFeeddown()
Calculates the total densities which include feeddown contributions.
virtual double TwoParticleSusceptibilityTemperatureDerivativePrimordial(int i, int j) const
Returns the computed temperature derivative of the primordial particle number (cross-)susceptibility ...
void SetUseWidth(bool useWidth)
Sets whether finite resonance widths are used. Deprecated.
virtual double FinalParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed final (after decays) particle vs conserved charge (cross-)susceptibility for pa...
virtual void DisableBaryonAntiBaryonAttraction()
virtual double FinalParticleChargeSusceptibility(int i, ConservedCharge::Name chg) const
Returns the computed final (after decays) particle vs conserved charge (cross-)susceptibility for pa...
virtual void SetChemicalPotentials(const std::vector< double > &chem=std::vector< double >(0))
Sets the chemical potentials of all particles.
double ChemicalPotential(int i) const
Chemical potential of particle species i.
virtual void SetElectricCharge(int Q)
Set the total electric charge (for canonical ensemble only)
virtual void SetBaryonChemicalPotential(double muB)
Set the baryon chemical potential.
virtual void CalculateTwoParticleCorrelations()
Computes the fluctuations and correlations of the primordial particle numbers.
virtual double SusceptibilityDimensionfull(ConservedCharge::Name i, ConservedCharge::Name j) const
A 2nd order susceptibility of conserved charges.
void SetNormBratio(bool normBratio)
Whether branching ratios are renormalized to 100%.
virtual void SetParameters(const ThermalModelParameters ¶ms)
The thermal parameters.
virtual void DisableMesonMesonAttraction()
virtual void SetElectricChemicalPotential(double muQ)
Set the electric chemical potential.
virtual double PrimordialNetParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed primordial net particle vs conserved charge (cross-)susceptibility for particle...
virtual double TwoParticleSusceptibilityTemperatureDerivativePrimordialByPdg(long long id1, long long id2)
Returns the computed temperature derivative of the primordial particle number (cross-)susceptibility ...
virtual double NetParticleSusceptibilityFinalByPdg(long long id1, long long id2)
Returns the computed (cross-)susceptibility between final net-particle numbers for pdg codes id1 and...
virtual void SetChemicalPotential(int i, double chem)
Sets the chemical potential of particle species i.
virtual bool FixChemicalPotentialsThroughDensities(double rhoB=0., double rhoQ=0., double rhoS=0., double rhoC=0., double muBinit=0., double muQinit=0., double muSinit=0., double muCinit=0., bool ConstrMuB=true, bool ConstrMuQ=true, bool ConstrMuS=true, bool ConstrMuC=true)
The procedure which calculates the chemical potentials which reproduce the specified baryon,...
virtual void ValidateCalculation()
Checks whether issues have occured during the calculation of particle densities in the CalculateDensi...
int ComponentsNumber() const
Number of different particle species in the list.
virtual void SetBaryonCharge(int B)
Set the total baryon number (for canonical ensemble only)
virtual void DisableBaryonBaryonVirial()
virtual void CalculateProxySusceptibilityMatrix()
Calculates the susceptibility matrix of conserved charges proxies.
virtual void DisableBaryonAntiBaryonVirial()
ThermalModelBase(ThermalParticleSystem *TPS, const ThermalModelParameters ¶ms=ThermalModelParameters())
Construct a new ThermalModelBase object.
virtual void DisableBaryonBaryonAttraction()
virtual double PrimordialParticleChargeSusceptibility(int i, ConservedCharge::Name chg) const
Returns the computed primordial particle vs conserved charge (cross-)susceptibility for particle wit...
virtual void CalculatePrimordialDensities()=0
Calculates the primordial densities of all species.
virtual void SetStrangenessChemicalPotential(double muS)
Set the strangeness chemical potential.
virtual double TwoParticleSusceptibilityPrimordial(int i, int j) const
Returns the computed primordial particle number (cross-)susceptibility for particles with ids i and ...
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
virtual void FillVirial(const std::vector< double > &ri=std::vector< double >(0))
Fills the excluded volume coefficients based on the provided radii parameters for all species.
virtual void SetGammaq(double gammaq)
Set the light quark fugacity factor.
virtual void SetStrangeness(int S)
Set the total strangeness (for canonical ensemble only)
virtual void SetAttraction(int, int, double)
Set the vdW mean field attraction coefficient .
virtual double PrimordialParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed primordial particle vs conserved charge (cross-)susceptibility for particle wit...
const ThermalModelParameters & Parameters() const
virtual double NetParticleSusceptibilityPrimordialByPdg(long long id1, long long id2)
Returns the computed (cross-)susceptibility between primordial net-particle numbers for pdg codes id...
virtual void SetCharmChemicalPotential(double muC)
Set the charm chemical potential.
virtual void ApplyBaryonAnnihilation(double gammaBbar)
[EXPERIMENTAL] Applies a baryon annihilation toy model to baryon yields and susceptibilities with the...
virtual void SetStatistics(bool stats)
double Volume() const
System volume (fm )
@ GCE
Grand canonical ensemble.
virtual void CalculateTwoParticleFluctuationsDecays()
Computes particle number correlations and fluctuations for all final-state particles which are marked...
Class containing all information about a particle specie.
double AbsoluteCharm() const
Absolute charm quark content |s|.
int BaryonCharge() const
Particle's baryon number.
double Density(const ThermalModelParameters ¶ms, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
Computes a specified ideal gas thermodynamic function.
const ParticleDecaysVector & Decays() const
A vector of particle's decays.
ResonanceWidthIntegration
Treatment of finite resonance widths.
@ eBW
Energy-dependent Breit-Wigner scheme (eBW)
@ BWTwoGamma
Energy-independent Breit-Wigner in +-2\Gamma interval.
@ ZeroWidth
Zero-width approximation.
double AbsoluteStrangeness() const
Absolute strange quark content |s|.
double AbsoluteQuark() const
Absolute light quark content |u,d|.
const ParticleDecaysVector & DecaysOriginal() const
A backup copy of particle's decays.
Class containing the particle list.
std::vector< std::pair< double, std::vector< int > > > ResonanceFinalStatesDistribution
std::vector< SingleDecayContribution > DecayContributionsToParticle
A vector of SingleDecayContribution where each element corresponds to a certain resonance species.
constexpr double GeVtoifm()
A constant to transform GeV into fm .
constexpr double GeVtoifm3()
A constant to transform GeV into fm .
constexpr double mnucleon()
Nucleon's mass. Value as in UrQMD.
The main namespace where all classes and functions of the Thermal-FIST library reside.
MatrixXd GetSusceptibilityMatrix(ThermalModelBase *model, const vector< int > &ConservedDensities)
MatrixXd GetPressureHessianMatrix(ThermalModelBase *model, const vector< int > &ConservedDensities)
Name
Set of all conserved charges considered.
@ BaryonCharge
Baryon number.
@ StrangenessCharge
Strangeness.
@ ElectricCharge
Electric charge.
@ Strong
Feeddown from strong decays.
@ Weak
Feeddown from strong, electromagnetic, and weak decays.
@ StabilityFlag
Feeddown from all particles marked as unstable.
static const int NumberOfDecayTypes
Structure containing all thermal parameters of the model.