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;
105 for (
int i = 0; i < 4; ++i) m_Susc[i].resize(4);
108 m_NormBratio =
false;
110 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
112 for (
size_t j = 0; j < tpart.
Decays().size(); ++j) {
118 m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
119 m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
120 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
121 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
124 m_InteractionModel =
Ideal;
128 SetUseWidth(TPS()->ResonanceWidthIntegrationType());
130 ResetCalculatedFlags();
149 m_UseWidth = useWidth;
155 m_TPS->SetResonanceWidthIntegrationType(type);
160 if (normBratio != m_NormBratio) {
161 m_NormBratio = normBratio;
163 m_TPS->NormalizeBranchingRatios();
166 m_TPS->RestoreBranchingRatios();
172 void ThermalModelBase::ResetChemicalPotentials() {
173 m_Parameters.muS = m_Parameters.muB / 5.;
174 m_Parameters.muQ = -m_Parameters.muB / 50.;
175 m_Parameters.muC = 0.;
181 m_Volume = m_Parameters.V;
183 ResetCalculatedFlags();
189 ResetCalculatedFlags();
194 m_Parameters.muB = muB;
196 ResetCalculatedFlags();
201 m_Parameters.muQ = muQ;
203 ResetCalculatedFlags();
208 m_Parameters.muS = muS;
210 ResetCalculatedFlags();
215 m_Parameters.muC = muC;
217 ResetCalculatedFlags();
222 m_Parameters.gammaS = gammaS;
223 ResetCalculatedFlags();
228 m_Parameters.gammaC = gammaC;
229 ResetCalculatedFlags();
235 ResetCalculatedFlags();
241 ResetCalculatedFlags();
247 ResetCalculatedFlags();
253 ResetCalculatedFlags();
258 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
259 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
270 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
271 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
282 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
283 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
295 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
296 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
308 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
309 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
321 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
322 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
334 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
335 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
347 for (
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
348 for (
int j = 0; j < TPS()->ComponentsNumber(); ++j) {
360 m_Parameters.gammaq = gammaq;
361 ResetCalculatedFlags();
367 m_Chem.resize(m_TPS->Particles().size());
368 m_densities.resize(m_TPS->Particles().size());
369 m_densitiestotal.resize(m_TPS->Particles().size());
371 m_wprim.resize(m_TPS->Particles().size());
372 m_wtot.resize(m_TPS->Particles().size());
373 m_skewprim.resize(m_TPS->Particles().size());
374 m_skewtot.resize(m_TPS->Particles().size());
375 m_kurtprim.resize(m_TPS->Particles().size());
376 m_kurttot.resize(m_TPS->Particles().size());
377 m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
378 m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->
ComponentsNumber(), 0.));
379 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
380 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
381 ResetCalculatedFlags();
385 m_QuantumStats = stats;
386 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
387 m_TPS->Particle(i).UseStatistics(stats);
393 std::cerr <<
"**WARNING** ThermalModelBase::SetResonanceWidthIntegrationType: Using resonance widths is switched off!" << std::endl;
397 m_TPS->SetResonanceWidthIntegrationType(type);
401 m_Chem.resize(m_TPS->Particles().size());
402 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
403 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;
408 if (chem.size() != m_TPS->Particles().size()) {
409 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;
417 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
418 throw std::out_of_range(
"ThermalModelBase::ChemicalPotential: i is out of bounds!");
425 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
426 throw std::out_of_range(
"ThermalModelBase::SetChemicalPotential: i is out of bounds!");
433 if (i < 0 || i >=
static_cast<int>(m_Chem.size())) {
434 throw std::out_of_range(
"ThermalModelBase::FullIdealChemicalPotential: i is out of bounds!");
443 if (!(m_Parameters.gammaq == 1.)) ret += log(m_Parameters.gammaq) * part.
AbsoluteQuark() * m_Parameters.T;
445 if (!(m_Parameters.gammaC == 1. || part.
AbsoluteCharm() == 0.)) ret += log(m_Parameters.gammaC) * part.
AbsoluteCharm() * m_Parameters.T;
452 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
453 m_TPS->Particle(i).CalculateThermalBranchingRatios(m_Parameters, m_UseWidth, m_Chem[i] + MuShift(i));
455 m_TPS->ProcessDecays();
463 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
464 m_densitiestotal[i] = m_densities[i];
467 for (
size_t j = 0; j < decayContributions.size(); ++j)
468 if (i != decayContributions[j].second)
469 m_densitiestotal[i] += decayContributions[j].first * m_densities[decayContributions[j].second];
472 m_densitiesbyfeeddown[feed_index] = m_densitiestotal;
476 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
477 m_densitiesbyfeeddown[feed_index][i] = m_densities[i];
480 for (
size_t j = 0; j < decayContributions.size(); ++j)
481 if (i != decayContributions[j].second)
482 m_densitiesbyfeeddown[feed_index][i] += decayContributions[j].first * m_densities[decayContributions[j].second];
486 m_FeeddownCalculated =
true;
492 if (resetInitialValues)
499 if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
501 m_Parameters.muS = 0.;
503 m_Parameters.muQ = 0.;
505 m_Parameters.muC = 0.;
510 if (m_ConstrainMuB) {
514 if (m_Parameters.muB > 0.150) suppr = 8.;
515 if (m_Parameters.muB > 0.300) suppr = 7.;
516 if (m_Parameters.muB > 0.450) suppr = 6.;
517 if (m_Parameters.muB > 0.600) suppr = 6.;
518 if (m_Parameters.muB > 0.750) suppr = 5.;
519 if (m_Parameters.muB > 0.900) suppr = 4.;
520 if (m_Parameters.muB > 1.000) suppr = 3.;
522 m_Parameters.muS = m_Parameters.muB / suppr;
524 m_Parameters.muQ = -m_Parameters.muB / suppr / 10.;
526 m_Parameters.muC = -m_Parameters.muS;
532 if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
534 m_Parameters.muS = 0.;
536 m_Parameters.muQ = 0.;
538 m_Parameters.muC = 0.;
545 m_ConstrainMuB &= m_TPS->hasBaryons();
546 m_ConstrainMuQ &= (m_TPS->hasCharged() && m_TPS->hasBaryons());
547 m_ConstrainMuS &= m_TPS->hasStrange();
548 m_ConstrainMuC &= m_TPS->hasCharmed();
550 vector<double> x22(4);
551 x22[0] = m_Parameters.muB;
552 x22[1] = m_Parameters.muQ;
553 x22[2] = m_Parameters.muS;
554 x22[3] = m_Parameters.muC;
555 vector<double> x2(4), xinit(4);
556 xinit[0] = x2[0] = m_Parameters.muB;
557 xinit[1] = x2[1] = m_Parameters.muQ;
558 xinit[2] = x2[2] = m_Parameters.muS;
559 xinit[3] = x2[3] = m_Parameters.muC;
560 int iter = 0, iterMAX = 2;
561 while (iter < iterMAX) {
562 BroydenEquationsChem eqs(
this);
563 BroydenJacobianChem jaco(
this);
564 BroydenChem broydn(
this, &eqs, &jaco);
566 broydn.Solve(x22, &crit);
573 double muBinit,
double muQinit,
double muSinit,
double muCinit,
574 bool ConstrMuB,
bool ConstrMuQ,
bool ConstrMuS,
bool ConstrMuC) {
577 V * rhoB, V * rhoQ, V * rhoS, V * rhoC,
578 muBinit, muQinit, muSinit, muCinit,
579 ConstrMuB, ConstrMuQ, ConstrMuS, ConstrMuC);
583 double muBinit,
double muQinit,
double muSinit,
double muCinit,
584 bool ConstrMuB,
bool ConstrMuQ,
bool ConstrMuS,
bool ConstrMuC) {
586 std::cerr <<
"**WARNING** PCE enabled, cannot assume chemical equilibrium to do optimization..." << std::endl;
601 m_Parameters.muB = muBinit;
603 m_Parameters.muS = muSinit;
605 m_Parameters.muQ = muQinit;
607 m_Parameters.muC = muCinit;
609 allzero &= (totB == 0.0 && ConstrMuB) || (muBinit == 0 && !ConstrMuB);
610 allzero &= (totQ == 0.0 && ConstrMuQ) || (muQinit == 0 && !ConstrMuQ);
611 allzero &= (totS == 0.0 && ConstrMuS) || (muSinit == 0 && !ConstrMuS);
612 allzero &= (totC == 0.0 && ConstrMuC) || (muCinit == 0 && !ConstrMuC);
616 m_Parameters.muB = 0.;
617 m_Parameters.muS = 0.;
618 m_Parameters.muQ = 0.;
619 m_Parameters.muC = 0.;
624 vector<int> vConstr(4, 1);
625 vector<int> vType(4, 0);
628 vConstr[0] = m_TPS->hasBaryons() && ConstrMuB;
629 vConstr[1] = m_TPS->hasCharged() && ConstrMuQ;
630 vConstr[2] = m_TPS->hasStrange() && ConstrMuS;
631 vConstr[3] = m_TPS->hasCharmed() && ConstrMuC;
633 vType[0] = (int)(totB == 0.0);
634 vType[1] = (int)(totQ == 0.0);
635 vType[2] = (int)(totS == 0.0);
636 vType[3] = (int)(totC == 0.0);
638 vector<double> vTotals(4);
644 vector<double> xin(4, 0.);
650 vector<double> xinactual;
651 for (
int i = 0; i < 4; ++i) {
653 xinactual.push_back(xin[i]);
657 BroydenEquationsChemTotals eqs(vConstr, vType, vTotals,
this);
658 BroydenJacobianChemTotals jaco(vConstr, vType, vTotals,
this);
661 broydn.
Solve(xinactual, &crit);
682 m_LastCalculationSuccessFlag =
true;
683 for (
size_t i = 0; i < m_densities.size(); ++i) {
684 if (m_densities[i] != m_densities[i]) {
685 m_LastCalculationSuccessFlag =
false;
687 sprintf(cc,
"Density for particle %d (%s) is NaN!\n", m_TPS->Particle(i).PdgId(), m_TPS->Particle(i).Name().c_str());
688 std::cerr <<
"**WARNING** " << cc << std::endl;
691 m_ValidityLog.append(cc);
699 std::cerr <<
"**WARNING** " << m_TAG <<
"::CalculateChargeFluctuations(const std::vector<double>& chgs, int order) not implemented!" << std::endl;
700 return std::vector<double>();
703 std::vector<double> ThermalModelBase::CalculateGeneralizedSusceptibilities(
const std::vector<std::vector<double>> &)
705 throw std::runtime_error(
"ThermalModelBase::CalculateGeneralizedSusceptibilities: not implemented!");
708 double ThermalModelBase::CalculateHadronDensity() {
711 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
712 ret += m_densities[i];
717 double ThermalModelBase::CalculateBaryonDensity() {
720 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
721 ret += m_TPS->Particles()[i].BaryonCharge() * m_densities[i];
726 double ThermalModelBase::CalculateChargeDensity() {
729 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
730 ret += m_TPS->Particles()[i].ElectricCharge() * m_densities[i];
735 double ThermalModelBase::CalculateStrangenessDensity() {
738 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
739 ret += m_TPS->Particles()[i].Strangeness() * m_densities[i];
744 double ThermalModelBase::CalculateCharmDensity() {
747 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
748 ret += m_TPS->Particles()[i].Charm() * m_densities[i];
752 double ThermalModelBase::CalculateAbsoluteBaryonDensity() {
755 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
756 ret += fabs((
double)m_TPS->Particles()[i].BaryonCharge()) * m_densities[i];
760 double ThermalModelBase::CalculateAbsoluteChargeDensity() {
763 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
764 ret += fabs((
double)m_TPS->Particles()[i].ElectricCharge()) * m_densities[i];
768 double ThermalModelBase::CalculateAbsoluteStrangenessDensity() {
771 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
772 ret += m_TPS->Particles()[i].AbsoluteStrangeness() * m_densities[i];
776 double ThermalModelBase::CalculateAbsoluteStrangenessDensityModulo() {
779 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
780 ret += fabs((
double)m_TPS->Particles()[i].Strangeness()) * m_densities[i];
784 double ThermalModelBase::CalculateAbsoluteCharmDensity() {
787 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
788 ret += m_TPS->Particles()[i].AbsoluteCharm() * m_densities[i];
792 double ThermalModelBase::CalculateAbsoluteCharmDensityModulo() {
795 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
796 ret += fabs((
double)m_TPS->Particles()[i].Charm()) * m_densities[i];
800 double ThermalModelBase::CalculateArbitraryChargeDensity() {
803 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i)
804 ret += m_TPS->Particles()[i].ArbitraryCharge() * m_densities[i];
809 double ThermalModelBase::GetDensity(
long long PDGID,
const std::vector<double> *dens)
811 if (m_TPS->PdgToId(PDGID) != -1)
812 return dens->operator[](m_TPS->PdgToId(PDGID));
815 if (PDGID == 1)
return CalculateBaryonDensity();
818 if (PDGID == 310 || PDGID == 130)
819 if (m_TPS->PdgToId(311) != -1 && m_TPS->PdgToId(-311) != -1)
820 return (dens->operator[](m_TPS->PdgToId(311)) + dens->operator[](m_TPS->PdgToId(-311))) / 2.;
823 if (PDGID % 10 == 0) {
824 long long tpdgid = PDGID / 10;
825 if (m_TPS->PdgToId(tpdgid) != -1 && m_TPS->PdgToId(-tpdgid) != -1)
826 return dens->operator[](m_TPS->PdgToId(tpdgid)) + dens->operator[](m_TPS->PdgToId(-tpdgid));
830 if (PDGID == 22122112 && m_TPS->PdgToId(2212) != -1 && m_TPS->PdgToId(2112) != -1)
831 return dens->operator[](m_TPS->PdgToId(2212)) + dens->operator[](m_TPS->PdgToId(2112));
833 std::cerr <<
"**WARNING** " << m_TAG <<
": Density with PDG ID " << PDGID <<
" not found!" << std::endl;
838 double ThermalModelBase::GetDensity(
long long PDGID,
Feeddown::Type feeddown)
840 std::vector<double> *dens = NULL;
844 dens = &m_densitiestotal;
845 else if (
static_cast<size_t>(feeddown) < m_densitiesbyfeeddown.size())
846 dens = &m_densitiesbyfeeddown[
static_cast<int>(feeddown)];
848 std::cerr <<
"**WARNING** " << m_TAG <<
": GetDensity: Unknown feeddown: " <<
static_cast<int>(feeddown) << std::endl;
858 double ret = GetDensity(PDGID, dens);
864 ret += 2. * 0.308 * GetDensity(310, dens);
867 if (PDGID == 211 || PDGID == -211) {
868 ret += 0.692 * GetDensity(310, dens);
876 std::vector<double> ThermalModelBase::GetIdealGasDensities()
const {
877 std::vector<double> ret = m_densities;
878 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
884 void ThermalModelBase::ResetCalculatedFlags()
886 m_Calculated =
false;
887 m_FeeddownCalculated =
false;
888 m_TwoParticleCorrelationsCalculated =
false;
889 m_SusceptibilitiesCalculated =
false;
890 m_FluctuationsCalculated =
false;
891 m_TemperatureDerivativesCalculated =
false;
892 m_GCECalculated =
false;
898 return BaryonDensity();
900 return ElectricChargeDensity();
902 return StrangenessDensity();
904 return CharmDensity();
911 return AbsoluteBaryonDensity();
913 return AbsoluteElectricChargeDensity();
915 return AbsoluteStrangenessDensity();
917 return AbsoluteCharmDensity();
923 if (!IsTemperatureDerivativesCalculated())
927 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
928 ret += m_TPS->Particles()[i].ConservedCharge(chg) * m_dndT[i];
934 double ThermalModelBase::ChargedMultiplicity(
int type)
938 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
939 int tQ = m_TPS->Particles()[i].ElectricCharge();
941 if (type == 0 && tQ != 0)
943 if (type == 1 && tQ > 0)
945 if (type == -1 && tQ < 0)
948 ret += m_densities[i];
953 double ThermalModelBase::ChargedScaledVariance(
int type)
955 if (!m_FluctuationsCalculated) {
956 std::cerr <<
"**WARNING** " << m_TAG <<
": ChargedScaledVariance(int): Fluctuations were not calculated\n";
960 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
961 int tQ = m_TPS->Particles()[i].ElectricCharge();
963 if (type == 0 && tQ != 0)
965 if (type == 1 && tQ > 0)
967 if (type == -1 && tQ < 0)
970 for (
int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
971 int tQ2 = m_TPS->Particles()[j].ElectricCharge();
973 if (type == 0 && tQ2 != 0)
975 if (type == 1 && tQ2 > 0)
977 if (type == -1 && tQ2 < 0)
981 ret += m_PrimCorrel[i][j];
986 return ret * m_Parameters.T *
Volume() / ChargedMultiplicity(type);
989 double ThermalModelBase::ChargedMultiplicityFinal(
int type)
998 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
999 ret += m_densities[i] * m_TPS->Particles()[i].Nch()[op];
1004 double ThermalModelBase::ChargedScaledVarianceFinal(
int type)
1006 if (!m_FluctuationsCalculated) {
1007 std::cerr <<
"**WARNING** " << m_TAG <<
": ChargedScaledVarianceFinal(int): Fluctuations were not calculated" << std::endl;
1014 for (
int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
1015 ret += m_densities[i] *
Volume() * m_TPS->Particles()[i].DeltaNch()[op];
1016 for (
int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
1017 ret += m_PrimCorrel[i][j] * m_Parameters.T *
Volume() * m_TPS->Particles()[i].Nch()[op] * m_TPS->Particles()[j].Nch()[op];
1020 return ret / ChargedMultiplicityFinal(type);
1024 throw std::runtime_error(
"ThermalModelBase::CalculateTwoParticleCorrelations: Calculation of two-particle correlations and fluctuations is not implemented");
1032 int NN = m_densities.size();
1035 for (
int i = 0; i < NN; ++i)
1038 m_TotalCorrel[i][i] = m_PrimCorrel[i][i];
1041 for (
size_t r = 0; r < decayContributions.size(); ++r) {
1042 int rr = decayContributions[r].second;
1044 m_TotalCorrel[i][i] += 2. * m_PrimCorrel[i][rr] * decayContributions[r].first;
1046 for (
size_t r2 = 0; r2 < decayContributions.size(); ++r2) {
1047 int rr2 = decayContributions[r2].second;
1048 m_TotalCorrel[i][i] += m_PrimCorrel[rr][rr2] * decayContributions[r].first * decayContributions[r2].first;
1052 m_TotalCorrel[i][i] += m_densities[rr] / m_Parameters.T * m_TPS->DecayCumulants()[i][r].first[1];
1070 for (
int i = 0; i < NN; ++i) {
1071 if (m_TPS->Particles()[i].IsStable()) {
1072 for (
int j = 0; j < NN; ++j) {
1073 if (j != i && m_TPS->Particles()[j].IsStable()) {
1074 m_TotalCorrel[i][j] = m_PrimCorrel[i][j];
1079 for (
size_t r = 0; r < decayContributionsJ.size(); ++r) {
1080 int rr = decayContributionsJ[r].second;
1081 m_TotalCorrel[i][j] += m_PrimCorrel[i][rr] * decayContributionsJ[r].first;
1084 for (
size_t r = 0; r < decayContributionsI.size(); ++r) {
1085 int rr = decayContributionsI[r].second;
1086 m_TotalCorrel[i][j] += m_PrimCorrel[j][rr] * decayContributionsI[r].first;
1089 for (
size_t r = 0; r < decayContributionsI.size(); ++r) {
1090 int rr = decayContributionsI[r].second;
1092 for (
size_t r2 = 0; r2 < decayContributionsJ.size(); ++r2) {
1093 int rr2 = decayContributionsJ[r2].second;
1094 m_TotalCorrel[i][j] += m_PrimCorrel[rr][rr2] * decayContributionsI[r].first * decayContributionsJ[r2].first;
1099 for (
int r = 0; r < m_TPS->ComponentsNumber(); ++r) {
1100 if (r != i && r != j) {
1101 double nij = 0., ni = 0., nj = 0., dnij = 0.;
1104 for (
size_t br = 0; br < decayDistributions.size(); ++br) {
1105 nij += decayDistributions[br].first * decayDistributions[br].second[i] * decayDistributions[br].second[j];
1106 ni += decayDistributions[br].first * decayDistributions[br].second[i];
1107 nj += decayDistributions[br].first * decayDistributions[br].second[j];
1109 dnij = nij - ni * nj;
1110 m_TotalCorrel[i][j] += m_densities[r] / m_Parameters.T * dnij;
1118 for (
int i = 0; i < NN; ++i) {
1119 m_wtot[i] = m_TotalCorrel[i][i];
1120 if (m_densitiestotal[i] > 0.) m_wtot[i] *= m_Parameters.T / m_densitiestotal[i];
1121 else m_wtot[i] = 1.;
1123 if (m_wtot[i] != m_wtot[i]) m_wtot[i] = 1.;
1129 if (!IsFluctuationsCalculated()) {
1130 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityPrimordial: fluctuations were not computed beforehand!");
1138 int i = TPS()->PdgToId(id1);
1139 int j = TPS()->PdgToId(id2);
1142 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id1 << std::endl;
1146 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id2 << std::endl;
1154 if (!IsFluctuationsCalculated() || !IsTemperatureDerivativesCalculated()) {
1155 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityPrimordial: temperature derivatives of fluctuations were not computed beforehand!");
1158 return m_PrimChi2sdT[i][j];
1163 int i = TPS()->PdgToId(id1);
1164 int j = TPS()->PdgToId(id2);
1167 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityTemperatureDerivativePrimordialByPdg: unknown pdg code " << id1 << std::endl;
1171 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityTemperatureDerivativePrimordialByPdg: unknown pdg code " << id2 << std::endl;
1180 int i1 = TPS()->PdgToId(id1);
1181 int j1 = TPS()->PdgToId(id2);
1184 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id1 << std::endl;
1188 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code " << id2 << std::endl;
1192 int i2 = TPS()->PdgToId(-id1);
1193 int j2 = TPS()->PdgToId(-id2);
1196 if (i2 == -1 && j2 == -1) {
1216 if (!IsFluctuationsCalculated()) {
1217 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityFinal: fluctuations were not computed beforehand!");
1220 if (!m_TPS->Particle(i).IsStable() || !m_TPS->Particle(j).IsStable()) {
1222 if (!m_TPS->Particle(j).IsStable())
1224 throw std::runtime_error(
"ThermalModelBase::TwoParticleSusceptibilityFinal: Particle " + std::to_string(tid) +
" is not stable! Final correlations not computed for unstable particles.");
1232 int i = TPS()->PdgToId(id1);
1233 int j = TPS()->PdgToId(id2);
1236 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code " << id1 << std::endl;
1240 std::cerr <<
"**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code " << id2 << std::endl;
1249 int i1 = TPS()->PdgToId(id1);
1250 int j1 = TPS()->PdgToId(id2);
1253 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code " << id1 << std::endl;
1257 std::cerr <<
"**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code " << id2 << std::endl;
1261 int i2 = TPS()->PdgToId(-id1);
1262 int j2 = TPS()->PdgToId(-id2);
1265 if (i2 == -1 && j2 == -1) {
1285 if (!IsFluctuationsCalculated()) {
1286 throw std::runtime_error(
"ThermalModelBase::PrimordialParticleChargeSusceptibility: fluctuations were not computed beforehand!");
1294 int i = TPS()->PdgToId(id1);
1296 std::cerr <<
"**WARNING** ThermalModelBase::PrimordialParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1305 int i1 = TPS()->PdgToId(id1);
1307 std::cerr <<
"**WARNING** ThermalModelBase::PrimordialNetParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1311 int i2 = TPS()->PdgToId(-id1);
1320 if (!IsFluctuationsCalculated()) {
1321 throw std::runtime_error(
"ThermalModelBase::FinalParticleChargeSusceptibility: fluctuations were not computed beforehand!");
1329 int i = TPS()->PdgToId(id1);
1331 std::cerr <<
"**WARNING** ThermalModelBase::FinalParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1340 int i1 = TPS()->PdgToId(id1);
1342 std::cerr <<
"**WARNING** ThermalModelBase::FinalNetParticleChargeSusceptibilityByPdg: unknown pdg code " << id1 << std::endl;
1346 int i2 = TPS()->PdgToId(-id1);
1356 if (!m_TwoParticleCorrelationsCalculated)
1360 for (
int i = 0; i < 4; ++i) m_Susc[i].resize(4);
1363 for (
int i = 0; i < 4; ++i) {
1364 for (
int j = 0; j < 4; ++j) {
1366 m_dSuscdT[i][j] = 0.;
1367 for (
size_t k = 0; k < m_PrimCorrel.size(); ++k) {
1369 if (i == 0) c1 = m_TPS->Particles()[k].BaryonCharge();
1370 if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1371 if (i == 2) c1 = m_TPS->Particles()[k].Strangeness();
1372 if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1373 for (
size_t kp = 0; kp < m_PrimCorrel.size(); ++kp) {
1375 if (j == 0) c2 = m_TPS->Particles()[kp].BaryonCharge();
1376 if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1377 if (j == 2) c2 = m_TPS->Particles()[kp].Strangeness();
1378 if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1379 m_Susc[i][j] += c1 * c2 * m_PrimCorrel[k][kp];
1381 if (IsTemperatureDerivativesCalculated())
1382 m_dSuscdT[i][j] += c1 * c2 * m_PrimChi2sdT[k][kp];
1388 m_SusceptibilitiesCalculated =
true;
1393 m_ProxySusc.resize(4);
1394 for (
int i = 0; i < 4; ++i)
1395 m_ProxySusc[i].resize(4);
1398 for (
int i = 0; i < 3; ++i) {
1399 for (
int j = 0; j < 3; ++j) {
1400 m_ProxySusc[i][j] = 0.;
1401 for (
size_t k = 0; k < m_TotalCorrel.size(); ++k) {
1402 if (m_TPS->Particles()[k].IsStable()) {
1405 if (i == 0) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 2212) - 1 * (m_TPS->Particles()[k].PdgId() == -2212);
1406 if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1408 if (i == 2) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 321) - 1 * (m_TPS->Particles()[k].PdgId() == -321);
1409 if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1410 for (
size_t kp = 0; kp < m_TotalCorrel.size(); ++kp) {
1411 if (m_TPS->Particles()[kp].IsStable()) {
1414 if (j == 0) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 2212) - 1 * (m_TPS->Particles()[kp].PdgId() == -2212);
1415 if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1417 if (j == 2) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 321) - 1 * (m_TPS->Particles()[kp].PdgId() == -321);
1418 if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1419 m_ProxySusc[i][j] += c1 * c2 * m_TotalCorrel[k][kp];
1433 m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1434 m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1436 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1438 for (
int chg = 0; chg < 4; ++chg) {
1439 for (
size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1441 m_PrimChargesCorrel[i][chg] += c1 * c2 * m_PrimCorrel[i][j];
1446 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1447 if (m_TPS->Particles()[i].IsStable()) {
1449 for (
int chg = 0; chg < 4; ++chg) {
1450 for (
size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1451 if (m_TPS->Particles()[j].IsStable()) {
1453 m_FinalChargesCorrel[i][chg] += c1 * c2 * m_TotalCorrel[i][j];
1461 std::vector<double> ThermalModelBase::PartialPressures() {
1462 if (!IsCalculated())
1465 std::vector<double> ret(5, 0.);
1466 for (
size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1484 std::cerr <<
"**WARNING** " << m_TAG <<
": Calculation of fluctuations is not implemented" << std::endl;
1488 std::cerr <<
"**WARNING** " << m_TAG <<
": Calculation of temperature derivatives is not implemented" << std::endl;
1491 std::vector<double> ThermalModelBase::BroydenEquationsChem::Equations(
const std::vector<double>& x)
1493 std::vector<double> ret(m_N, 0.);
1496 if (m_THM->ConstrainMuB()) { m_THM->SetBaryonChemicalPotential(x[i1]); i1++; }
1497 if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1498 if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1499 if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1500 m_THM->FillChemicalPotentials();
1501 m_THM->CalculatePrimordialDensities();
1506 if (m_THM->ConstrainMuB()) {
1507 double fBd = m_THM->CalculateBaryonDensity();
1508 double fSd = m_THM->CalculateEntropyDensity();
1510 ret[i1] = (fBd / fSd - 1. / m_THM->SoverB()) * m_THM->SoverB();
1516 if (m_THM->ConstrainMuQ()) {
1517 double fBd = m_THM->CalculateBaryonDensity();
1518 double fQd = m_THM->CalculateChargeDensity();
1521 ret[i1] = (fQd / fBd - m_THM->QoverB());
1529 if (m_THM->ConstrainMuS()) {
1530 double fSd = m_THM->CalculateStrangenessDensity();
1531 double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1533 fASd = m_THM->CalculateAbsoluteStrangenessDensityModulo();
1535 ret[i1] = fSd / fASd;
1542 if (m_THM->ConstrainMuC()) {
1543 double fCd = m_THM->CalculateCharmDensity();
1544 double fACd = m_THM->CalculateAbsoluteCharmDensity();
1546 fACd = m_THM->CalculateAbsoluteCharmDensityModulo();
1548 ret[i1] = fCd / fACd;
1556 std::vector<double> ThermalModelBase::BroydenJacobianChem::Jacobian(
const std::vector<double>& x)
1560 if (m_THM->ConstrainMuB()) {
1561 throw std::runtime_error(
"ThermalModelBase::ConstrainChemicalPotentials: analytic calculation of the Jacobian not supported if muB is constrained");
1564 if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1565 if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1566 if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1567 m_THM->FillChemicalPotentials();
1568 m_THM->CalculatePrimordialDensities();
1570 double fBd = m_THM->CalculateBaryonDensity();
1571 double fQd = m_THM->CalculateChargeDensity();
1572 double fSd = m_THM->CalculateStrangenessDensity();
1573 double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1574 if (fASd < 1.e-25) {
1575 fASd = m_THM->CalculateAbsoluteStrangenessDensityModulo();
1577 double fCd = m_THM->CalculateCharmDensity();
1578 double fACd = m_THM->CalculateAbsoluteCharmDensity();
1579 if (fACd < 1.e-25) {
1580 fACd = m_THM->CalculateAbsoluteCharmDensityModulo();
1583 vector<double> chi2s;
1584 chi2s.resize(m_THM->Densities().size());
1585 for (
size_t i = 0; i < chi2s.size(); ++i) {
1586 chi2s[i] = m_THM->TPS()->Particle(i).chiDimensionfull(2, m_THM->Parameters(), m_THM->UseWidth(), m_THM->ChemicalPotential(i) + m_THM->MuShift(i))
1591 if (m_THM->ConstrainMuQ()) NNN++;
1592 if (m_THM->ConstrainMuS()) NNN++;
1593 if (m_THM->ConstrainMuC()) NNN++;
1594 MatrixXd ret(NNN, NNN);
1598 if (m_THM->ConstrainMuQ()) {
1601 double d1 = 0., d2 = 0.;
1603 if (m_THM->ConstrainMuQ()) {
1605 for (
size_t i = 0; i < chi2s.size(); ++i)
1606 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1609 for (
size_t i = 0; i < chi2s.size(); ++i)
1610 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1613 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1620 if (m_THM->ConstrainMuS()) {
1622 for (
size_t i = 0; i < chi2s.size(); ++i)
1623 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1626 for (
size_t i = 0; i < chi2s.size(); ++i)
1627 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1630 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1637 if (m_THM->ConstrainMuC()) {
1639 for (
size_t i = 0; i < chi2s.size(); ++i)
1640 d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1643 for (
size_t i = 0; i < chi2s.size(); ++i)
1644 d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1647 ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1658 if (m_THM->ConstrainMuS()) {
1661 double d1 = 0., d2 = 0.;
1663 if (m_THM->ConstrainMuQ()) {
1665 for (
size_t i = 0; i < chi2s.size(); ++i)
1666 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1669 for (
size_t i = 0; i < chi2s.size(); ++i)
1670 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1672 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1678 if (m_THM->ConstrainMuS()) {
1680 for (
size_t i = 0; i < chi2s.size(); ++i)
1681 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1684 for (
size_t i = 0; i < chi2s.size(); ++i)
1685 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1687 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1693 if (m_THM->ConstrainMuC()) {
1695 for (
size_t i = 0; i < chi2s.size(); ++i)
1696 d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1699 for (
size_t i = 0; i < chi2s.size(); ++i)
1700 d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1702 ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1712 if (m_THM->ConstrainMuC()) {
1715 double d1 = 0., d2 = 0.;
1717 if (m_THM->ConstrainMuQ()) {
1719 for (
size_t i = 0; i < chi2s.size(); ++i)
1720 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).ElectricCharge() * chi2s[i];
1723 for (
size_t i = 0; i < chi2s.size(); ++i)
1724 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).ElectricCharge() *chi2s[i];
1726 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1732 if (m_THM->ConstrainMuS()) {
1734 for (
size_t i = 0; i < chi2s.size(); ++i)
1735 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1738 for (
size_t i = 0; i < chi2s.size(); ++i)
1739 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Strangeness() * chi2s[i];
1741 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1747 if (m_THM->ConstrainMuC()) {
1749 for (
size_t i = 0; i < chi2s.size(); ++i)
1750 d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1753 for (
size_t i = 0; i < chi2s.size(); ++i)
1754 d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Charm() * chi2s[i];
1756 ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1764 std::vector<double> retVec(NNN*NNN, 0);
1765 for (
int i = 0; i < NNN; ++i)
1766 for (
int j = 0; j < NNN; ++j)
1767 retVec[i*NNN + j] = ret(i, j);
1773 std::vector<double> ThermalModelBase::BroydenChem::Solve(
const std::vector<double>& x0, BroydenSolutionCriterium * solcrit,
int max_iterations)
1775 if (m_Equations == NULL) {
1776 throw std::runtime_error(
"Broyden::Solve: Equations to solve not specified!");
1780 std::vector<double> xcur;
1781 if (m_THM->ConstrainMuB()) { xcur.push_back(x0[0]); NNN++; }
1782 if (m_THM->ConstrainMuQ()) { xcur.push_back(x0[1]); NNN++; }
1783 if (m_THM->ConstrainMuS()) { xcur.push_back(x0[2]); NNN++; }
1784 if (m_THM->ConstrainMuC()) { xcur.push_back(x0[3]); NNN++; }
1786 m_THM->FillChemicalPotentials();
1790 m_Equations->SetDimension(NNN);
1792 m_MaxIterations = max_iterations;
1794 BroydenSolutionCriterium *SolutionCriterium = solcrit;
1795 bool UseDefaultSolutionCriterium =
false;
1796 if (SolutionCriterium == NULL) {
1797 SolutionCriterium =
new BroydenSolutionCriterium(TOL);
1798 UseDefaultSolutionCriterium =
true;
1802 bool UseDefaultJacobian =
false;
1803 if (JacobianInUse == NULL || m_THM->ConstrainMuB()) {
1805 UseDefaultJacobian =
true;
1808 double &maxdiff = m_MaxDifference;
1809 int N = m_Equations->Dimension();
1813 std::vector<double> tmpvec, xdeltavec = xcur;
1814 VectorXd xold(N), xnew(N), xdelta(N);
1815 VectorXd fold(N), fnew(N), fdelta(N);
1817 xold = VectorXd::Map(&xcur[0], xcur.size());
1819 MatrixXd Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
1821 bool constrmuB = m_THM->ConstrainMuB();
1822 bool constrmuQ = m_THM->ConstrainMuQ();
1823 bool constrmuS = m_THM->ConstrainMuS();
1824 bool constrmuC = m_THM->ConstrainMuC();
1825 bool repeat =
false;
1827 if (m_THM->ConstrainMuB()) {
1828 for (
int j = 0; j < Jac.rows(); ++j)
1829 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuB(
false); }
1830 double S = m_THM->CalculateEntropyDensity();
1831 double nB = m_THM->CalculateBaryonDensity();
1832 if (abs(S) < 1.e-25 || abs(nB) < 1.e-25) { repeat =
true; m_THM->ConstrainMuB(
false); }
1835 if (m_THM->ConstrainMuQ()) {
1836 for (
int j = 0; j < Jac.rows(); ++j)
1837 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuQ(
false); }
1838 double nQ = m_THM->CalculateChargeDensity();
1839 double nB = m_THM->CalculateBaryonDensity();
1840 if (abs(nQ) < 1.e-25 || abs(nB) < 1.e-25) { repeat =
true; m_THM->ConstrainMuQ(
false); }
1843 if (m_THM->ConstrainMuS()) {
1844 for (
int j = 0; j < Jac.rows(); ++j)
1845 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuS(
false); }
1847 double nS = m_THM->CalculateAbsoluteStrangenessDensity();
1848 if (abs(nS) < 1.e-25) { nS = m_THM->CalculateAbsoluteStrangenessDensityModulo(); }
1849 if (abs(nS) < 1.e-25) { repeat =
true; m_THM->ConstrainMuS(
false); }
1852 if (m_THM->ConstrainMuC()) {
1853 for (
int j = 0; j < Jac.rows(); ++j)
1854 if (Jac(NNN, j) > 1.e8) { repeat =
true; m_THM->ConstrainMuC(
false); }
1855 double nC = m_THM->CalculateAbsoluteCharmDensity();
1856 if (abs(nC) < 1.e-25) { nC = m_THM->CalculateAbsoluteCharmDensityModulo(); }
1857 if (abs(nC) < 1.e-25) { repeat =
true; m_THM->ConstrainMuC(
false); }
1861 std::vector<double> ret = Solve(x0, solcrit, max_iterations);
1862 m_THM->ConstrainMuQ(constrmuB);
1863 m_THM->ConstrainMuQ(constrmuQ);
1864 m_THM->ConstrainMuS(constrmuS);
1865 m_THM->ConstrainMuC(constrmuC);
1869 if (Jac.determinant() == 0.0)
1871 std::cerr <<
"**WARNING** Singular Jacobian in Broyden::Solve" << std::endl;
1875 MatrixXd Jinv = Jac.inverse();
1876 tmpvec = m_Equations->Equations(xcur);
1877 fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
1879 for (m_Iterations = 1; m_Iterations < max_iterations; ++m_Iterations) {
1880 xnew = xold - Jinv * fold;
1882 VectorXd::Map(&xcur[0], xcur.size()) = xnew;
1884 tmpvec = m_Equations->Equations(xcur);
1885 fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
1889 for (
size_t i = 0; i < xcur.size(); ++i) {
1890 maxdiff = std::max(maxdiff, fabs(fnew[i]));
1893 xdelta = xnew - xold;
1894 fdelta = fnew - fold;
1896 VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
1898 if (SolutionCriterium->IsSolved(xcur, tmpvec, xdeltavec))
1905 for (
int i = 0; i < N; ++i)
1906 for (
int j = 0; j < N; ++j)
1907 norm += xdelta[i] * Jinv(i, j) * fdelta[j];
1909 p1 = (xdelta - Jinv * fdelta);
1910 for (
int i = 0; i < N; ++i) p1[i] *= 1. / norm;
1911 Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
1915 Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
1916 Jinv = Jac.inverse();
1923 if (m_Iterations == max_iterations) {
1924 std::cerr <<
"**WARNING** Reached maximum number of iterations in Broyden procedure" << std::endl;
1927 if (UseDefaultSolutionCriterium) {
1928 delete SolutionCriterium;
1929 SolutionCriterium = NULL;
1931 if (UseDefaultJacobian) {
1932 delete JacobianInUse;
1933 JacobianInUse = NULL;
1939 ThermalModelBase::BroydenEquationsChemTotals::BroydenEquationsChemTotals(
const std::vector<int>& vConstr,
const std::vector<int>& vType,
const std::vector<double>& vTotals,
ThermalModelBase * model) :
1940 BroydenEquations(), m_Constr(vConstr), m_Type(vType), m_Totals(vTotals), m_THM(model)
1943 for (
size_t i = 0; i < m_Constr.size(); ++i)
1947 std::vector<double> ThermalModelBase::BroydenEquationsChemTotals::Equations(
const std::vector<double>& x)
1949 std::vector<double> ret(m_N, 0.);
1952 for (
int i = 0; i < 4; ++i) {
1954 if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
1955 if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
1956 if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
1957 if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
1961 m_THM->FillChemicalPotentials();
1962 m_THM->CalculatePrimordialDensities();
1964 vector<double> dens(4, 0.), absdens(4, 0.);
1966 dens[0] = m_THM->CalculateBaryonDensity();
1967 absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
1970 dens[1] = m_THM->CalculateChargeDensity();
1971 absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
1974 dens[2] = m_THM->CalculateStrangenessDensity();
1975 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
1976 if (absdens[2] < 1.e-25) {
1977 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensityModulo();
1981 dens[3] = m_THM->CalculateCharmDensity();
1982 absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
1983 if (absdens[3] < 1.e-25) {
1984 absdens[3] = m_THM->CalculateAbsoluteCharmDensityModulo();
1990 for (
int i = 0; i < 4; ++i) {
1993 ret[i1] = (dens[i] * m_THM->Parameters().V - m_Totals[i]) / m_Totals[i];
1995 ret[i1] = dens[i] / absdens[i];
2003 std::vector<double> ThermalModelBase::BroydenJacobianChemTotals::Jacobian(
const std::vector<double>& x)
2006 for (
int i = 0; i < 4; ++i) NNN += m_Constr[i];
2010 for (
int i = 0; i < 4; ++i) {
2012 if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
2013 if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
2014 if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
2015 if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
2020 m_THM->FillChemicalPotentials();
2021 m_THM->CalculatePrimordialDensities();
2023 vector<double> dens(4, 0.), absdens(4, 0.);
2025 dens[0] = m_THM->CalculateBaryonDensity();
2026 absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
2029 dens[1] = m_THM->CalculateChargeDensity();
2030 absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
2033 dens[2] = m_THM->CalculateStrangenessDensity();
2034 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
2035 if (absdens[2] < 1.e-25) {
2036 absdens[2] = m_THM->CalculateAbsoluteStrangenessDensityModulo();
2040 dens[3] = m_THM->CalculateCharmDensity();
2041 absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
2042 if (absdens[3] < 1.e-25) {
2043 absdens[3] = m_THM->CalculateAbsoluteCharmDensityModulo();
2047 vector<double> chi2s;
2048 chi2s.resize(m_THM->Densities().size());
2049 for (
size_t i = 0; i < chi2s.size(); ++i) {
2050 chi2s[i] = m_THM->TPS()->Particle(i).chiDimensionfull(2, m_THM->Parameters(), m_THM->UseWidth(), m_THM->ChemicalPotential(i) + m_THM->MuShift(i))
2054 vector< vector<double> > deriv(4, vector<double>(4)), derivabs(4, vector<double>(4));
2055 for (
int i = 0; i < 4; ++i)
2056 for (
int j = 0; j < 4; ++j) {
2058 for (
size_t part = 0; part < chi2s.size(); ++part)
2059 deriv[i][j] += m_THM->TPS()->Particles()[part].GetCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * chi2s[part];
2061 derivabs[i][j] = 0.;
2062 for (
size_t part = 0; part < chi2s.size(); ++part)
2063 derivabs[i][j] += m_THM->TPS()->Particles()[part].GetAbsCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * chi2s[part];
2067 MatrixXd ret(NNN, NNN);
2071 for (
int i = 0; i < 4; ++i) {
2074 for (
int j = 0; j < 4; ++j)
2078 ret(i1, i2) = deriv[i][j] * m_THM->Parameters().V / m_Totals[i];
2080 ret(i1, i2) = deriv[i][j] / absdens[i] - dens[i] / absdens[i] / absdens[i] * derivabs[i][j];
2087 std::vector<double> retVec(NNN*NNN, 0);
2088 for (
int i = 0; i < NNN; ++i)
2089 for (
int j = 0; j < NNN; ++j)
2090 retVec[i*NNN + j] = ret(i, j);
2096 void ThermalModelBase::SetDensityModelForParticleSpecies(
int i,
GeneralizedDensity *density_model)
2099 TPS()->Particle(i).SetGeneralizedDensity(density_model);
2101 std::cerr <<
"**WARNING** ThermalModelBase::SetDensityModelForParticleSpecies(): Particle id " << i <<
" is outside the range!" << std::endl;
2105 void ThermalModelBase::SetDensityModelForParticleSpeciesByPdg(
long long PDGID,
GeneralizedDensity *density_model)
2107 int id = TPS()->PdgToId(PDGID);
2109 TPS()->Particle(
id).SetGeneralizedDensity(density_model);
2111 std::cerr <<
"**WARNING** ThermalModelBase::SetDensityModelForParticleSpeciesByPdg(): Pdg code " << PDGID <<
" is outside the range!" << std::endl;
2115 void ThermalModelBase::ClearDensityModels() {
2116 for (
auto& particle : TPS()->Particles())
2117 particle.ClearGeneralizedDensity();
2120 void ThermalModelBase::SetMagneticField(
double B,
int lmax) {
2121 m_IGFExtraConfig.MagneticField.B = B;
2123 m_IGFExtraConfig.MagneticField.lmax = lmax;
2124 for (
auto& particle : TPS()->Particles())
2125 particle.SetMagneticField(B, m_IGFExtraConfig.MagneticField.lmax);
2126 RecomputeThresholdsDueToMagneticField();
2127 ResetCalculatedFlags();
2130 void ThermalModelBase::RecomputeThresholdsDueToMagneticField() {
2131 const double &B = m_IGFExtraConfig.MagneticField.B;
2132 for (
int ipart = 0; ipart < TPS()->ComponentsNumber(); ++ipart) {
2133 ThermalParticle &part = TPS()->Particle(ipart);
2134 if (!part.ZeroWidthEnforced() || part.ElectricCharge()==0) {
2136 part.CalculateAndSetDynamicalThreshold();
2137 part.FillCoefficientsDynamical();
2138 }
else if (!part.ZeroWidthEnforced()) {
2139 double szmax = (part.Degeneracy() - 1.) / 2.;
2141 double mmin = sqrt(2. * abs(part.ElectricCharge()) * B * (szmax - 0.5));
2142 part.CalculateAndSetDynamicalThreshold();
2143 if (mmin > part.DecayThresholdMassDynamical()) {
2144 part.SetDecayThresholdMassDynamical(mmin);
2146 part.FillCoefficientsDynamical();
2153 void ThermalModelBase::ClearMagneticField() {
2154 m_IGFExtraConfig.MagneticField.B = 0.;
2155 for (
auto& particle : TPS()->Particles())
2156 particle.ClearMagneticField();
2157 ResetCalculatedFlags();
2161 assert(IsSusceptibilitiesCalculated());
2162 return m_Susc[i][j];
2166 assert(IsSusceptibilitiesCalculated() && IsTemperatureDerivativesCalculated());
2167 return m_dSuscdT[i][j];
2171 assert(IsFluctuationsCalculated());
2172 return m_ProxySusc[i][j];
2175 double ThermalModelBase::GetdndT(
int i)
const {
2176 if (IsTemperatureDerivativesCalculated() && i >= 0 && i <
ComponentsNumber())
2179 std::cerr <<
"**WARNING** ThermalModelBase::GetdndT(): Temperature derivatives are not calculated or particle id " << i <<
" is outside the range!" << std::endl;
2187 for (
size_t k = 0; k < m_PrimCorrel.size(); ++k) {
2188 int c1 = m_TPS->Particles()[k].ConservedCharge(i);
2189 for (
size_t kp = 0; kp < m_PrimCorrel.size(); ++kp) {
2190 int c2 = m_TPS->Particles()[kp].ConservedCharge(j);
2191 ret += c1 * c2 * m_PrimCorrel[k][kp];
2197 double ThermalModelBase::CalculateHeatCapacityMu()
2199 double dedT = CalculateEnergyDensityDerivativeT();
2203 for(
int i = 0; i < TPS()->ComponentsNumber(); ++i) {
2204 ret -= m_Chem[i] * m_dndT[i];
2212 for (
int i = 0; i < 4; ++i)
2213 if (ConservedDensities[i] == 1)
2223 for(
int i = 0; i < 4; ++i) {
2224 if (ConservedDensities[i] == 0)
2227 for(
int j = 0; j < 4; ++j) {
2228 if (ConservedDensities[j] == 0)
2243 for (
int i = 0; i < 4; ++i)
2244 if (ConservedDensities[i] == 1)
2251 ret(0, 0) = model->CalculateEntropyDensityDerivativeT();
2256 for(
int i = 0; i < 4; ++i) {
2257 if (ConservedDensities[i] == 0)
2267 for(
int i = 0; i < 4; ++i) {
2268 if (ConservedDensities[i] == 0)
2271 for(
int j = 0; j < 4; ++j) {
2272 if (ConservedDensities[j] == 0)
2284 vector<vector<double>> ThermalModelBase::PressureHessian()
2287 if (!m_FluctuationsCalculated)
2289 if (!m_TemperatureDerivativesCalculated)
2293 vector<int> allCharges = {1, 1, 1, 1};
2297 int N = H_eigen.rows();
2298 vector<vector<double>> H(N, vector<double>(N, 0.0));
2299 for (
int i = 0; i < N; ++i) {
2300 for (
int j = 0; j < N; ++j) {
2301 H[i][j] = H_eigen(i, j);
2308 bool ThermalModelBase::IsThermodynamicallyStable()
2311 if (!m_FluctuationsCalculated)
2313 if (!m_TemperatureDerivativesCalculated)
2317 vector<int> allCharges = {1, 1, 1, 1};
2321 Eigen::SelfAdjointEigenSolver<MatrixXd> solver(H);
2322 if (solver.info() != Eigen::Success) {
2327 const auto& eigenvalues = solver.eigenvalues();
2328 for (
int i = 0; i < eigenvalues.size(); ++i) {
2329 if (eigenvalues(i) < 0.0) {
2337 double ThermalModelBase::CalculateAdiabaticSpeedOfSoundSquared(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2339 const double nanv = std::numeric_limits<double>::quiet_NaN();
2340 const double eps = 1e-14;
2345 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2347 if (!TPS()->hasBaryons())
2348 ConservedCharges[0] = 0;
2349 if (!TPS()->hasCharged())
2350 ConservedCharges[1] = 0;
2351 if (!TPS()->hasStrange())
2352 ConservedCharges[2] = 0;
2353 if (!TPS()->hasCharmed())
2354 ConservedCharges[3] = 0;
2360 for (
int i = 0; i < 4; ++i) {
2361 if (ConservedCharges[i] == 1
2363 ConservedCharges[i] = 0;
2368 bool AllMuZero =
true;
2369 for(
int i = 0; i < ConservedCharges.size(); ++i)
2370 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2373 WarnIllDefinedSoundSpeedOnce(
2374 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2375 "all relevant chemical potentials are zero (0/0 limit at T=0).");
2380 if (!IsTemperatureDerivativesCalculated())
2388 for(
int i = 0; i < 4; ++i)
2389 if (ConservedCharges[i] == 1)
2392 WarnIllDefinedSoundSpeedOnce(
2393 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2394 "no conserved densities selected.");
2399 if (!IsFluctuationsCalculated())
2406 if (!IsMatrixInvertible(chi2matr)) {
2407 WarnIllDefinedSoundSpeedOnce(
2408 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2409 "susceptibility matrix is singular at T=0.");
2412 MatrixXd chi2inv = chi2matr.inverse();
2415 for(
int i = 0; i < 4; ++i) {
2416 if (ConservedCharges[i] == 0)
2419 for(
int j = 0; j < 4; ++j) {
2420 if (ConservedCharges[j] == 0)
2425 ret += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2432 if (std::abs(ep) < eps) {
2433 WarnIllDefinedSoundSpeedOnce(
2434 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2435 "EnergyDensity + Pressure is zero.");
2445 if (!IsTemperatureDerivativesCalculated())
2453 if (!IsMatrixInvertible(PiMatr)) {
2454 WarnIllDefinedSoundSpeedOnce(
2455 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2456 "pressure Hessian matrix is singular.");
2459 MatrixXd PiMatrInv = PiMatr.inverse();
2462 vector<double> x = {s};
2463 for(
int i = 0; i < ConservedCharges.size(); ++i)
2464 if (ConservedCharges[i] == 1)
2468 for(
int i = 0; i < x.size(); ++i)
2469 for(
int j = 0; j < x.size(); ++j)
2470 ret += x[i] * x[j] * PiMatrInv(i,j);
2472 if (std::abs(ep) < eps) {
2473 WarnIllDefinedSoundSpeedOnce(
2474 "CalculateAdiabaticSpeedOfSoundSquared", ConservedCharges, T,
2475 "EnergyDensity + Pressure is zero.");
2483 double ThermalModelBase::CalculateIsothermalSpeedOfSoundSquared(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2485 const double nanv = std::numeric_limits<double>::quiet_NaN();
2486 const double eps = 1e-14;
2491 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2493 if (!TPS()->hasBaryons())
2494 ConservedCharges[0] = 0;
2495 if (!TPS()->hasCharged())
2496 ConservedCharges[1] = 0;
2497 if (!TPS()->hasStrange())
2498 ConservedCharges[2] = 0;
2499 if (!TPS()->hasCharmed())
2500 ConservedCharges[3] = 0;
2506 for (
int i = 0; i < 4; ++i) {
2507 if (ConservedCharges[i] == 1
2509 ConservedCharges[i] = 0;
2513 for (
int i = 0; i < 4; ++i)
2514 if (ConservedCharges[i] == 1)
2517 WarnIllDefinedSoundSpeedOnce(
2518 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2519 "no conserved densities selected.");
2525 bool AllMuZero =
true;
2526 for(
int i = 0; i < ConservedCharges.size(); ++i)
2527 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2534 if (!IsMatrixInvertible(chi2Matr)) {
2535 WarnIllDefinedSoundSpeedOnce(
2536 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2537 "susceptibility matrix is singular.");
2541 MatrixXd chi2inv= chi2Matr.inverse();
2543 double numerator = 0.;
2544 double denominator = 0.;
2546 for(
int i = 0; i < 4; ++i) {
2547 if (ConservedCharges[i] == 0)
2551 for(
int j = 0; j < 4; ++j) {
2552 if (ConservedCharges[j] == 0)
2558 numerator += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2559 denominator += T * ConservedChargeDensitydT(chg1) * chi2inv(i1, i2) * ConservedChargeDensity(chg2);
2561 ret += ConservedChargeDensity(chg1) * ConservedChargeDensity(chg2) * chi2inv(i1, i2);
2567 if (std::abs(denominator) < eps) {
2568 WarnIllDefinedSoundSpeedOnce(
2569 "CalculateIsothermalSpeedOfSoundSquared", ConservedCharges, T,
2570 "denominator is zero.");
2573 return numerator / denominator;
2576 double ThermalModelBase::CalculateHeatCapacity(
bool rhoBconst,
bool rhoQconst,
bool rhoSconst,
bool rhoCconst) {
2584 std::vector<int> ConservedCharges = {
static_cast<int>(rhoBconst),
static_cast<int>(rhoQconst),
static_cast<int>(rhoSconst),
static_cast<int>(rhoCconst)};
2586 if (!TPS()->hasBaryons())
2587 ConservedCharges[0] = 0;
2588 if (!TPS()->hasCharged())
2589 ConservedCharges[1] = 0;
2590 if (!TPS()->hasStrange())
2591 ConservedCharges[2] = 0;
2592 if (!TPS()->hasCharmed())
2593 ConservedCharges[3] = 0;
2600 const double eps = 1e-14;
2601 for (
int i = 0; i < 4; ++i) {
2602 if (ConservedCharges[i] == 1
2604 ConservedCharges[i] = 0;
2609 double TdsdT = HeatCapacityMu();
2613 bool AllMuZero =
true;
2614 for(
int i = 0; i < ConservedCharges.size(); ++i)
2615 AllMuZero &= (ConservedCharges[i] == 0 || mus[i] == 0.0);
2621 if (!IsFluctuationsCalculated())
2625 double denominator = 1.;
2627 auto PiMatrInv = PiMatr.inverse();
2628 int N = PiMatr.rows();
2629 for(
int i = 1; i < N; ++i) {
2630 denominator -= PiMatr(0, i) * PiMatrInv(i, 0);
2633 double heatCapacity = TdsdT / denominator;
2634 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 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.