Thermal-FIST  1.3
Package for hadron resonance gas model applications
ThermalModelBase.cpp
Go to the documentation of this file.
1 /*
2  * Thermal-FIST package
3  *
4  * Copyright (c) 2014-2019 Volodymyr Vovchenko
5  *
6  * GNU General Public License (GPLv3 or later)
7  */
9 
10 #include <cstdio>
11 #include <algorithm>
12 
13 #include <Eigen/Dense>
14 
15 #include "HRGBase/Utility.h"
17 
18 using namespace Eigen;
19 
20 using namespace std;
21 
22 namespace thermalfist {
23 
24  ThermalModelBase::ThermalModelBase(ThermalParticleSystem *TPS_, const ThermalModelParameters& params) :
25  m_TPS(TPS_),
26  m_Parameters(params),
27  m_UseWidth(false),
28  m_PCE(false),
29  m_Calculated(false),
30  m_FeeddownCalculated(false),
31  m_FluctuationsCalculated(false),
32  m_GCECalculated(false),
33  m_NormBratio(false),
34  m_QuantumStats(true),
35  m_MaxDiff(0.),
36  m_useOpenMP(0)
37  {
40 
41  m_QBgoal = 0.4;
42  m_SBgoal = 50.;
43  m_Chem.resize(m_TPS->Particles().size());
44  m_Volume = params.V;
45  m_densities.resize(m_TPS->Particles().size());
46  m_densitiestotal.resize(m_TPS->Particles().size());
48 
49  m_wprim.resize(m_TPS->Particles().size());
50  m_wtot.resize(m_TPS->Particles().size());
51  m_skewprim.resize(m_TPS->Particles().size());
52  m_skewtot.resize(m_TPS->Particles().size());
53  m_kurtprim.resize(m_TPS->Particles().size());
54  m_kurttot.resize(m_TPS->Particles().size());
55 
56  m_ConstrainMuB = false;
58 
59  m_Susc.resize(4);
60  for (int i = 0; i < 4; ++i) m_Susc[i].resize(4);
61 
62  m_NormBratio = false;
63 
64  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
65  const ThermalParticle &tpart = m_TPS->Particles()[i];
66  for (size_t j = 0; j < tpart.Decays().size(); ++j) {
67  if (tpart.DecaysOriginal().size() == tpart.Decays().size() && tpart.Decays()[j].mBratio != tpart.DecaysOriginal()[j].mBratio)
68  m_NormBratio = true;
69  }
70  }
71 
72  m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->ComponentsNumber(), 0.));
73  m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->ComponentsNumber(), 0.));
74  m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
75  m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
76 
77  m_Ensemble = GCE;
79 
80  //SetStatistics(m_QuantumStats);
81  //SetCalculationType(IdealGasFunctions::Quadratures);
82  SetUseWidth(TPS()->ResonanceWidthIntegrationType());
83 
85 
86  m_ValidityLog = "";
87  }
88 
89 
90  void ThermalModelBase::FillVirial(const std::vector<double>& /*ri*/)
91  {
92  }
93 
94  void ThermalModelBase::SetUseWidth(bool useWidth)
95  {
98  //m_TPS->ProcessDecays();
99  }
102  }
103  m_UseWidth = useWidth;
104  }
105 
107  {
110  }
111 
112 
113  void ThermalModelBase::SetNormBratio(bool normBratio) {
114  if (normBratio != m_NormBratio) {
115  m_NormBratio = normBratio;
116  if (m_NormBratio) {
118  }
119  else {
121  }
122  }
123  }
124 
125 
126  void ThermalModelBase::ResetChemicalPotentials() {
128  m_Parameters.muQ = -m_Parameters.muB / 50.;
129  m_Parameters.muC = 0.;
130  }
131 
132 
134  m_Parameters = params;
137  }
138 
140  {
141  m_Parameters.T = T;
143  }
144 
146  {
147  m_Parameters.muB = muB;
150  }
151 
153  {
154  m_Parameters.muQ = muQ;
157  }
158 
160  {
161  m_Parameters.muS = muS;
164  }
165 
167  {
168  m_Parameters.muC = muC;
171  }
172 
173  void ThermalModelBase::SetGammaS(double gammaS)
174  {
175  m_Parameters.gammaS = gammaS;
177  }
178 
179  void ThermalModelBase::SetGammaC(double gammaC)
180  {
181  m_Parameters.gammaC = gammaC;
183  }
184 
186  {
187  m_Parameters.B = B;
189  }
190 
192  {
193  m_Parameters.Q = Q;
195  }
196 
198  {
199  m_Parameters.S = S;
201  }
202 
204  {
205  m_Parameters.C = C;
207  }
208 
210  {
211  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
212  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
213  const ThermalParticle &part1 = TPS()->Particles()[i];
214  const ThermalParticle &part2 = TPS()->Particles()[j];
215  if (part1.BaryonCharge() == 0 && part2.BaryonCharge() == 0)
216  SetVirial(i, j, 0.);
217  }
218  }
219  }
220 
222  {
223  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
224  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
225  const ThermalParticle &part1 = TPS()->Particles()[i];
226  const ThermalParticle &part2 = TPS()->Particles()[j];
227  if (part1.BaryonCharge() == 0 && part2.BaryonCharge() == 0)
228  SetAttraction(i, j, 0.);
229  }
230  }
231  }
232 
234  {
235  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
236  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
237  const ThermalParticle &part1 = TPS()->Particles()[i];
238  const ThermalParticle &part2 = TPS()->Particles()[j];
239  if ((part1.BaryonCharge() == 0 && part2.BaryonCharge() != 0)
240  || (part1.BaryonCharge() != 0 && part2.BaryonCharge() == 0))
241  SetVirial(i, j, 0.);
242  }
243  }
244  }
245 
247  {
248  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
249  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
250  const ThermalParticle &part1 = TPS()->Particles()[i];
251  const ThermalParticle &part2 = TPS()->Particles()[j];
252  if ((part1.BaryonCharge() == 0 && part2.BaryonCharge() != 0)
253  || (part1.BaryonCharge() != 0 && part2.BaryonCharge() == 0))
254  SetAttraction(i, j, 0.);
255  }
256  }
257  }
258 
260  {
261  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
262  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
263  const ThermalParticle &part1 = TPS()->Particles()[i];
264  const ThermalParticle &part2 = TPS()->Particles()[j];
265  if ((part1.BaryonCharge() > 0 && part2.BaryonCharge() > 0)
266  || (part1.BaryonCharge() < 0 && part2.BaryonCharge() < 0))
267  SetVirial(i, j, 0.);
268  }
269  }
270  }
271 
273  {
274  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
275  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
276  const ThermalParticle &part1 = TPS()->Particles()[i];
277  const ThermalParticle &part2 = TPS()->Particles()[j];
278  if ((part1.BaryonCharge() > 0 && part2.BaryonCharge() > 0)
279  || (part1.BaryonCharge() < 0 && part2.BaryonCharge() < 0))
280  SetAttraction(i, j, 0.);
281  }
282  }
283  }
284 
286  {
287  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
288  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
289  const ThermalParticle &part1 = TPS()->Particles()[i];
290  const ThermalParticle &part2 = TPS()->Particles()[j];
291  if ((part1.BaryonCharge() > 0 && part2.BaryonCharge() < 0)
292  || (part1.BaryonCharge() < 0 && part2.BaryonCharge() > 0))
293  SetVirial(i, j, 0.);
294  }
295  }
296  }
297 
299  {
300  for (int i = 0; i < TPS()->ComponentsNumber(); ++i) {
301  for (int j = 0; j < TPS()->ComponentsNumber(); ++j) {
302  const ThermalParticle &part1 = TPS()->Particles()[i];
303  const ThermalParticle &part2 = TPS()->Particles()[j];
304  if ((part1.BaryonCharge() > 0 && part2.BaryonCharge() < 0)
305  || (part1.BaryonCharge() < 0 && part2.BaryonCharge() > 0))
306  SetAttraction(i, j, 0.);
307  }
308  }
309  }
310 
311  void ThermalModelBase::SetGammaq(double gammaq)
312  {
313  m_Parameters.gammaq = gammaq;
315  }
316 
317 
319  m_TPS = TPS_;
320  m_Chem.resize(m_TPS->Particles().size());
321  m_densities.resize(m_TPS->Particles().size());
322  m_densitiestotal.resize(m_TPS->Particles().size());
324  m_wprim.resize(m_TPS->Particles().size());
325  m_wtot.resize(m_TPS->Particles().size());
326  m_skewprim.resize(m_TPS->Particles().size());
327  m_skewtot.resize(m_TPS->Particles().size());
328  m_kurtprim.resize(m_TPS->Particles().size());
329  m_kurttot.resize(m_TPS->Particles().size());
330  m_PrimCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->ComponentsNumber(), 0.));
331  m_TotalCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(TPS()->ComponentsNumber(), 0.));
332  m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
333  m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
335  }
336 
338  m_QuantumStats = stats;
339  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
340  m_TPS->Particle(i).UseStatistics(stats);
341  }
342 
344  {
345  if (!m_UseWidth) {
346  printf("**WARNING** ThermalModelBase::SetResonanceWidthIntegrationType: Using resonance widths is switched off!\n");
348  }
349  else
351  }
352 
354  m_Chem.resize(m_TPS->Particles().size());
355  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
356  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;
357  }
358 
359  void ThermalModelBase::SetChemicalPotentials(const std::vector<double>& chem)
360  {
361  if (chem.size() != m_TPS->Particles().size()) {
362  printf("**WARNING** %s::SetChemicalPotentials(const std::vector<double> & chem): size of chem does not match number of hadrons in the list", m_TAG.c_str());
363  return;
364  }
365  m_Chem = chem;
366  }
367 
369  {
370  if (i < 0 || i >= static_cast<int>(m_Chem.size())) {
371  printf("**ERROR** ThermalModelBase::ChemicalPotential(int i): i is out of bounds!");
372  exit(1);
373  }
374  return m_Chem[i];
375  }
376 
378  {
379  if (i < 0 || i >= static_cast<int>(m_Chem.size())) {
380  printf("**ERROR** ThermalModelBase::FullIdealChemicalPotential(int i): i is out of bounds!");
381  exit(1);
382  }
383 
384  double ret = ChemicalPotential(i);
385 
386  ret += MuShift(i);
387 
388  const ThermalParticle& part = m_TPS->Particles()[i];
389 
390  if (!(m_Parameters.gammaq == 1.)) ret += log(m_Parameters.gammaq) * part.AbsoluteQuark() * m_Parameters.T;
391  if (!(m_Parameters.gammaS == 1. || part.AbsoluteStrangeness() == 0.)) ret += log(m_Parameters.gammaS) * part.AbsoluteStrangeness() * m_Parameters.T;
392  if (!(m_Parameters.gammaC == 1. || part.AbsoluteCharm() == 0.)) ret += log(m_Parameters.gammaC) * part.AbsoluteCharm() * m_Parameters.T;
393 
394  return ret;
395  }
396 
399  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
401  }
402  m_TPS->ProcessDecays();
403  }
404 
405  // Primordial
407 
408  // According to stability flags
409  int feed_index = static_cast<int>(Feeddown::StabilityFlag);
410  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
412  //const std::vector< std::pair<double, int> >& decayContributions = m_TPS->Particles()[i].DecayContributionsByFeeddown()[feed_index];
413  const ThermalParticleSystem::DecayContributionsToParticle& decayContributions = m_TPS->DecayContributionsByFeeddown()[feed_index][i];
414  for (size_t j = 0; j < decayContributions.size(); ++j)
415  if (i != decayContributions[j].second)
416  m_densitiestotal[i] += decayContributions[j].first * m_densities[decayContributions[j].second];
417  }
418 
420 
421  // Weak, EM, strong
422  for (feed_index = static_cast<int>(Feeddown::Weak); feed_index <= static_cast<int>(Feeddown::Strong); ++feed_index) {
423  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
424  m_densitiesbyfeeddown[feed_index][i] = m_densities[i];
425  //const std::vector< std::pair<double, int> >& decayContributions = m_TPS->Particles()[i].DecayContributionsByFeeddown()[feed_index];
426  const ThermalParticleSystem::DecayContributionsToParticle& decayContributions = m_TPS->DecayContributionsByFeeddown()[feed_index][i];
427  for (size_t j = 0; j < decayContributions.size(); ++j)
428  if (i != decayContributions[j].second)
429  m_densitiesbyfeeddown[feed_index][i] += decayContributions[j].first * m_densities[decayContributions[j].second];
430  }
431  }
432 
433  m_FeeddownCalculated = true;
434  }
435 
436 
437  void ThermalModelBase::ConstrainChemicalPotentials(bool resetInitialValues)
438  {
439  if (resetInitialValues)
440  FixParameters();
441  else
443  }
444 
446  if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
447  if (m_ConstrainMuS)
448  m_Parameters.muS = 0.;
449  if (m_ConstrainMuQ)
450  m_Parameters.muQ = 0.;
451  if (m_ConstrainMuC)
452  m_Parameters.muC = 0.;
455  return;
456  }
457  if (m_ConstrainMuB) {
459  }
460  double suppr = 10;
461  if (m_Parameters.muB > 0.150) suppr = 8.;
462  if (m_Parameters.muB > 0.300) suppr = 7.;
463  if (m_Parameters.muB > 0.450) suppr = 6.;
464  if (m_Parameters.muB > 0.600) suppr = 6.;
465  if (m_Parameters.muB > 0.750) suppr = 5.;
466  if (m_Parameters.muB > 0.900) suppr = 4.;
467  if (m_Parameters.muB > 1.000) suppr = 3.;
468  if (m_ConstrainMuS)
469  m_Parameters.muS = m_Parameters.muB / suppr;
470  if (m_ConstrainMuQ)
471  m_Parameters.muQ = -m_Parameters.muB / suppr / 10.;
472  if (m_ConstrainMuC)
474 
476  }
477 
479  if (fabs(m_Parameters.muB) < 1e-6 && !m_ConstrainMuB) {
483  return;
484  }
485 
490 
491  vector<double> x22(4);
492  x22[0] = m_Parameters.muB;
493  x22[1] = m_Parameters.muQ;
494  x22[2] = m_Parameters.muS;
495  x22[3] = m_Parameters.muC;
496  vector<double> x2(4), xinit(4);
497  xinit[0] = x2[0] = m_Parameters.muB;
498  xinit[1] = x2[1] = m_Parameters.muQ;
499  xinit[2] = x2[2] = m_Parameters.muS;
500  xinit[3] = x2[3] = m_Parameters.muC;
501  int iter = 0, iterMAX = 2;
502  while (iter < iterMAX) {
503  BroydenEquationsChem eqs(this);
504  BroydenJacobianChem jaco(this);
505  BroydenChem broydn(this, &eqs, &jaco);
507  broydn.Solve(x22, &crit);
508  break;
509  }
510  }
511 
512  bool ThermalModelBase::SolveChemicalPotentials(double totB, double totQ, double totS, double totC,
513  double muBinit, double muQinit, double muSinit, double muCinit,
514  bool ConstrMuB, bool ConstrMuQ, bool ConstrMuS, bool ConstrMuC) {
516  printf("**WARNING** PCE enabled, cannot assume chemical equilibrium to do optimization...");
517  return false;
518  }
519 
520  m_Parameters.muB = muBinit;
521  m_Parameters.muS = muSinit;
522  m_Parameters.muQ = muQinit;
523  m_Parameters.muC = muCinit;
524  bool allzero = true;
525  allzero &= (totB == 0.0 && ConstrMuB) || (muBinit == 0 && !ConstrMuB);
526  allzero &= (totQ == 0.0 && ConstrMuQ) || (muQinit == 0 && !ConstrMuQ);
527  allzero &= (totS == 0.0 && ConstrMuS) || (muSinit == 0 && !ConstrMuS);
528  allzero &= (totC == 0.0 && ConstrMuC) || (muCinit == 0 && !ConstrMuC);
529  if (allzero) {
530  m_Parameters.muB = 0.;
531  m_Parameters.muS = 0.;
532  m_Parameters.muQ = 0.;
533  m_Parameters.muC = 0.;
536  return true;
537  }
538  vector<int> vConstr(4, 1);
539  vector<int> vType(4, 0);
540 
541  vConstr[0] = m_TPS->hasBaryons() && ConstrMuB;
542  vConstr[1] = m_TPS->hasCharged() && ConstrMuQ;
543  vConstr[2] = m_TPS->hasStrange() && ConstrMuS;
544  vConstr[3] = m_TPS->hasCharmed() && ConstrMuC;
545 
546  vType[0] = (int)(totB == 0.0);
547  vType[1] = (int)(totQ == 0.0);
548  vType[2] = (int)(totS == 0.0);
549  vType[3] = (int)(totC == 0.0);
550 
551  vector<double> vTotals(4);
552  vTotals[0] = totB;
553  vTotals[1] = totQ;
554  vTotals[2] = totS;
555  vTotals[3] = totC;
556 
557  vector<double> xin(4, 0.);
558  xin[0] = muBinit;
559  xin[1] = muQinit;
560  xin[2] = muSinit;
561  xin[3] = muCinit;
562 
563  vector<double> xinactual;
564  for (int i = 0; i < 4; ++i) {
565  if (vConstr[i]) {
566  xinactual.push_back(xin[i]);
567  }
568  }
569 
570  BroydenEquationsChemTotals eqs(vConstr, vType, vTotals, this);
571  BroydenJacobianChemTotals jaco(vConstr, vType, vTotals, this);
572  Broyden broydn(&eqs, &jaco);
574  broydn.Solve(xinactual, &crit);
575 
576  return (broydn.Iterations() < broydn.MaxIterations());
577  }
578 
580  {
582 
584  }
585 
587  {
588  m_ValidityLog = "";
589 
590  char cc[1000];
591 
593  for (size_t i = 0; i < m_densities.size(); ++i) {
594  if (m_densities[i] != m_densities[i]) {
596 
597  sprintf(cc, "**WARNING** Density for particle %lld (%s) is NaN!\n\n", m_TPS->Particle(i).PdgId(), m_TPS->Particle(i).Name().c_str());
598  printf("%s", cc);
599 
600  m_ValidityLog.append(cc);
601  }
602  //m_LastCalculationSuccessFlag &= (m_densities[i] == m_densities[i]);
603  }
604  }
605 
606  std::vector<double> ThermalModelBase::CalculateChargeFluctuations(const std::vector<double>& /*chgs*/, int /*order*/)
607  {
608  printf("**WARNING** %s::CalculateChargeFluctuations(const std::vector<double>& chgs, int order) not implemented!\n", m_TAG.c_str());
609  return std::vector<double>();
610  }
611 
614  double ret = 0.;
615  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
616  ret += m_densities[i];
617 
618  return ret;
619  }
620 
623  double ret = 0.;
624  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
625  ret += m_TPS->Particles()[i].BaryonCharge() * m_densities[i];
626 
627  return ret;
628  }
629 
632  double ret = 0.;
633  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
634  ret += m_TPS->Particles()[i].ElectricCharge() * m_densities[i];
635 
636  return ret;
637  }
638 
641  double ret = 0.;
642  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
643  ret += m_TPS->Particles()[i].Strangeness() * m_densities[i];
644 
645  return ret;
646  }
647 
650  double ret = 0.;
651  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
652  ret += m_TPS->Particles()[i].Charm() * m_densities[i];
653  return ret;
654  }
655 
658  double ret = 0.;
659  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
660  ret += fabs((double)m_TPS->Particles()[i].BaryonCharge()) * m_densities[i];
661  return ret;
662  }
663 
666  double ret = 0.;
667  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
668  ret += fabs((double)m_TPS->Particles()[i].ElectricCharge()) * m_densities[i];
669  return ret;
670  }
671 
674  double ret = 0.;
675  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
676  ret += m_TPS->Particles()[i].AbsoluteStrangeness() * m_densities[i];
677  return ret;
678  }
679 
682  double ret = 0.;
683  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
684  ret += m_TPS->Particles()[i].AbsoluteCharm() * m_densities[i];
685  return ret;
686  }
687 
690  double ret = 0.;
691  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
692  ret += m_TPS->Particles()[i].ArbitraryCharge() * m_densities[i];
693  return ret;
694  }
695 
696 
697  double ThermalModelBase::GetDensity(long long PDGID, const std::vector<double> *dens)
698  {
699  if (m_TPS->PdgToId(PDGID) != -1)
700  return dens->operator[](m_TPS->PdgToId(PDGID));
701 
702  // 1 - Npart
703  if (PDGID == 1) return CalculateBaryonDensity();
704 
705  // K0S or K0L
706  if (PDGID == 310 || PDGID == 130)
707  if (m_TPS->PdgToId(311) != -1 && m_TPS->PdgToId(-311) != -1)
708  return (dens->operator[](m_TPS->PdgToId(311)) + dens->operator[](m_TPS->PdgToId(-311))) / 2.;
709 
710  // Id Pdg code has a trailing zero, try to construct a particle + anti-particle yield
711  if (PDGID % 10 == 0) {
712  long long tpdgid = PDGID / 10;
713  if (m_TPS->PdgToId(tpdgid) != -1 && m_TPS->PdgToId(-tpdgid) != -1)
714  return dens->operator[](m_TPS->PdgToId(tpdgid)) + dens->operator[](m_TPS->PdgToId(-tpdgid));
715  }
716 
717  // 22122112 - nucleons
718  if (PDGID == 22122112 && m_TPS->PdgToId(2212) != -1 && m_TPS->PdgToId(2112) != -1)
719  return dens->operator[](m_TPS->PdgToId(2212)) + dens->operator[](m_TPS->PdgToId(2112));
720 
721  printf("**WARNING** %s: Density with PDG ID %lld not found!\n", m_TAG.c_str(), PDGID);
722 
723  return 0.;
724  }
725 
726  double ThermalModelBase::GetDensity(long long PDGID, Feeddown::Type feeddown)
727  {
728  std::vector<double> *dens = NULL;
729  if (feeddown == Feeddown::Primordial)
730  dens = &m_densities;
731  else if (feeddown == Feeddown::StabilityFlag)
732  dens = &m_densitiestotal;
733  else if (static_cast<size_t>(feeddown) < m_densitiesbyfeeddown.size())
734  dens = &m_densitiesbyfeeddown[static_cast<int>(feeddown)];
735  else {
736  printf("**WARNING** %s: GetDensity: Unknown feeddown: %d\n", m_TAG.c_str(), static_cast<int>(feeddown));
737  return 0.;
738  }
739 
740  if (!m_Calculated)
742 
743  if (feeddown != Feeddown::Primordial && !m_FeeddownCalculated)
745 
746  return GetDensity(PDGID, dens);
747  }
748 
749 
750  std::vector<double> ThermalModelBase::GetIdealGasDensities() const {
751  std::vector<double> ret = m_densities;
752  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
754  }
755  return ret;
756  }
757 
759  {
760  m_Calculated = false;
761  m_FeeddownCalculated = false;
762  m_FluctuationsCalculated = false;
763  m_GCECalculated = false;
764  }
765 
767  {
769  return BaryonDensity();
771  return ElectricChargeDensity();
773  return StrangenessDensity();
774  if (chg == ConservedCharge::CharmCharge)
775  return CharmDensity();
776  return 0.0;
777  }
778 
780  {
782  double ret = 0.0;
783  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
784  int tQ = m_TPS->Particles()[i].ElectricCharge();
785  bool fl = false;
786  if (type == 0 && tQ != 0)
787  fl = true;
788  if (type == 1 && tQ > 0)
789  fl = true;
790  if (type == -1 && tQ < 0)
791  fl = true;
792  if (fl)
793  ret += m_densities[i];
794  }
795  return ret * Volume();
796  }
797 
799  {
801  printf("**WARNING** %s: ChargedScaledVariance(int): Fluctuations were not calculated\n", m_TAG.c_str());
802  return 1.;
803  }
804  double ret = 0.0;
805  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
806  int tQ = m_TPS->Particles()[i].ElectricCharge();
807  bool fl = false;
808  if (type == 0 && tQ != 0)
809  fl = true;
810  if (type == 1 && tQ > 0)
811  fl = true;
812  if (type == -1 && tQ < 0)
813  fl = true;
814  if (fl) {
815  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
816  int tQ2 = m_TPS->Particles()[j].ElectricCharge();
817  bool fl2 = false;
818  if (type == 0 && tQ2 != 0)
819  fl2 = true;
820  if (type == 1 && tQ2 > 0)
821  fl2 = true;
822  if (type == -1 && tQ2 < 0)
823  fl2 = true;
824 
825  if (fl2) {
826  ret += m_PrimCorrel[i][j];
827  }
828  }
829  }
830  }
831  return ret * m_Parameters.T * Volume() / ChargedMultiplicity(type);
832  }
833 
835  {
837 
838  int op = type;
839  if (type == -1)
840  op = 2;
841 
842  double ret = 0.0;
843  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
844  ret += m_densities[i] * m_TPS->Particles()[i].Nch()[op];
845  }
846  return ret * Volume();
847  }
848 
850  {
852  printf("**WARNING** %s: ChargedScaledVarianceFinal(int): Fluctuations were not calculated\n", m_TAG.c_str());
853  return 1.;
854  }
855  int op = type;
856  if (type == -1)
857  op = 2;
858  double ret = 0.0;
859  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
860  ret += m_densities[i] * Volume() * m_TPS->Particles()[i].DeltaNch()[op];
861  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
862  ret += m_PrimCorrel[i][j] * m_Parameters.T * Volume() * m_TPS->Particles()[i].Nch()[op] * m_TPS->Particles()[j].Nch()[op];
863  }
864  }
865  return ret / ChargedMultiplicityFinal(type);
866  }
867 
869  printf("**WARNING** %s: Calculation of two-particle correlations and fluctuations is not implemented\n", m_TAG.c_str());
870  }
871 
872 
874  {
875  // Decay contributions here are done according to Eq. (47) in nucl-th/0606036
876 
877  int NN = m_densities.size();
878 
879  // Fluctuations for all
880  for (int i = 0; i < NN; ++i)
881  //for(int j=0;j<NN;++j)
882  {
883  m_TotalCorrel[i][i] = m_PrimCorrel[i][i];
884  //for (int r = 0; r < m_TPS->Particles()[i].DecayContributions().size(); ++r) {
886  for (size_t r = 0; r < decayContributions.size(); ++r) {
887  int rr = decayContributions[r].second;
888 
889  m_TotalCorrel[i][i] += m_densities[rr] / m_Parameters.T * m_TPS->DecayCumulants()[i][r].first[1];
890  //m_TotalCorrel[i][i] += m_densities[rr] / m_Parameters.T * m_TPS->Particles()[i].DecayCumulants()[r].first[1];
891 
892  m_TotalCorrel[i][i] += 2. * m_PrimCorrel[i][rr] * decayContributions[r].first;
893 
894  for (size_t r2 = 0; r2 < decayContributions.size(); ++r2) {
895  int rr2 = decayContributions[r2].second;
896  m_TotalCorrel[i][i] += m_PrimCorrel[rr][rr2] * decayContributions[r].first * decayContributions[r2].first;
897  }
898  }
899  }
900 
901 
902  // Correlations only for stable
903  for (int i = 0; i < NN; ++i) {
904  if (m_TPS->Particles()[i].IsStable()) {
905  for (int j = 0; j < NN; ++j) {
906  if (j != i && m_TPS->Particles()[j].IsStable()) {
907  m_TotalCorrel[i][j] = m_PrimCorrel[i][j];
908 
911 
912  for (size_t r = 0; r < decayContributionsJ.size(); ++r) {
913  int rr = decayContributionsJ[r].second;
914  m_TotalCorrel[i][j] += m_PrimCorrel[i][rr] * decayContributionsJ[r].first;
915  }
916 
917  for (size_t r = 0; r < decayContributionsI.size(); ++r) {
918  int rr = decayContributionsI[r].second;
919  m_TotalCorrel[i][j] += m_PrimCorrel[j][rr] * decayContributionsI[r].first;
920  }
921 
922  for (size_t r = 0; r < decayContributionsI.size(); ++r) {
923  int rr = decayContributionsI[r].second;
924 
925  for (size_t r2 = 0; r2 < decayContributionsJ.size(); ++r2) {
926  int rr2 = decayContributionsJ[r2].second;
927  m_TotalCorrel[i][j] += m_PrimCorrel[rr][rr2] * decayContributionsI[r].first * decayContributionsJ[r2].first;
928  }
929  }
930 
931 
932  for (int r = 0; r < m_TPS->ComponentsNumber(); ++r) {
933  if (r != i && r != j) { // && !m_TPS->Particles()[r].IsStable()) {
934  double nij = 0., ni = 0., nj = 0., dnij = 0.;
935  //const ThermalParticle &tpart = m_TPS->Particle(r);
937  for (size_t br = 0; br < decayDistributions.size(); ++br) {
938  nij += decayDistributions[br].first * decayDistributions[br].second[i] * decayDistributions[br].second[j];
939  ni += decayDistributions[br].first * decayDistributions[br].second[i];
940  nj += decayDistributions[br].first * decayDistributions[br].second[j];
941  }
942  dnij = nij - ni * nj;
943  m_TotalCorrel[i][j] += m_densities[r] / m_Parameters.T * dnij;
944  }
945  }
946 
947  }
948  }
949  }
950  }
951 
952  for (int i = 0; i < NN; ++i) {
953  m_wtot[i] = m_TotalCorrel[i][i];
954  if (m_densitiestotal[i] > 0.) m_wtot[i] *= m_Parameters.T / m_densitiestotal[i];
955  else m_wtot[i] = 1.;
956  }
957  }
958 
960  {
961  if (!IsFluctuationsCalculated()) {
962  printf("**ERROR** ThermalModelBase::TwoParticleSusceptibilityPrimordial: fluctuations were not computed beforehand! Quitting...\n");
963  exit(1);
964  }
965 
967  }
968 
970  {
971  int i = TPS()->PdgToId(id1);
972  int j = TPS()->PdgToId(id2);
973 
974  if (i == -1) {
975  printf("**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code %lld", id1);
976  return 0.;
977  }
978  if (j == -1) {
979  printf("**WARNING** ThermalModelBase::TwoParticleSusceptibilityPrimordialByPdg: unknown pdg code %lld", id2);
980  return 0.;
981  }
982 
984  }
985 
987  {
988  int i1 = TPS()->PdgToId(id1);
989  int j1 = TPS()->PdgToId(id2);
990 
991  if (i1 == -1) {
992  printf("**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code %lld", id1);
993  return 0.;
994  }
995  if (j1 == -1) {
996  printf("**WARNING** ThermalModelBase::NetParticleSusceptibilityPrimordialByPdg: unknown pdg code %lld", id2);
997  return 0.;
998  }
999 
1000  int i2 = TPS()->PdgToId(-id1);
1001  int j2 = TPS()->PdgToId(-id2);
1002 
1003  // Both particles are neutral
1004  if (i2 == -1 && j2 == -1) {
1005  return TwoParticleSusceptibilityPrimordial(i1, j1);
1006  }
1007 
1008  // First particle species is neutral
1009  if (i2 == -1) {
1011  }
1012 
1013  // Second particle species is neutral
1014  if (j2 == -1) {
1016  }
1017 
1018  // Both particles have antiparticles
1020  }
1021 
1023  {
1024  if (!IsFluctuationsCalculated()) {
1025  printf("**ERROR** ThermalModelBase::TwoParticleSusceptibilityFinal: fluctuations were not computed beforehand! Quitting...\n");
1026  exit(1);
1027  }
1028 
1029  if (!m_TPS->Particle(i).IsStable() || !m_TPS->Particle(j).IsStable()) {
1030  int tid = i;
1031  if (!m_TPS->Particle(j).IsStable())
1032  tid = j;
1033  printf("**ERROR** ThermalModelBase::TwoParticleSusceptibilityFinal: Particle %d is not stable! Final correlations not computed for unstable particles. Quitting...\n", tid);
1034  exit(1);
1035  }
1036 
1038  }
1039 
1040  double ThermalModelBase::TwoParticleSusceptibilityFinalByPdg(long long id1, long long id2)
1041  {
1042  int i = TPS()->PdgToId(id1);
1043  int j = TPS()->PdgToId(id2);
1044 
1045  if (i == -1) {
1046  printf("**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code %lld", id1);
1047  return 0.;
1048  }
1049  if (j == -1) {
1050  printf("**WARNING** ThermalModelBase::TwoParticleSusceptibilityFinalByPdg: unknown pdg code %lld", id2);
1051  return 0.;
1052  }
1053 
1054  return TwoParticleSusceptibilityFinal(i, j);
1055  }
1056 
1057  double ThermalModelBase::NetParticleSusceptibilityFinalByPdg(long long id1, long long id2)
1058  {
1059  int i1 = TPS()->PdgToId(id1);
1060  int j1 = TPS()->PdgToId(id2);
1061 
1062  if (i1 == -1) {
1063  printf("**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code %lld", id1);
1064  return 0.;
1065  }
1066  if (j1 == -1) {
1067  printf("**WARNING** ThermalModelBase::NetParticleSusceptibilityFinalByPdg: unknown pdg code %lld", id2);
1068  return 0.;
1069  }
1070 
1071  int i2 = TPS()->PdgToId(-id1);
1072  int j2 = TPS()->PdgToId(-id2);
1073 
1074  // Both particles are neutral
1075  if (i2 == -1 && j2 == -1) {
1076  return TwoParticleSusceptibilityFinal(i1, j1);
1077  }
1078 
1079  // First particle species is neutral
1080  if (i2 == -1) {
1082  }
1083 
1084  // Second particle species is neutral
1085  if (j2 == -1) {
1087  }
1088 
1089  // Both particles have antiparticles
1091  }
1092 
1094  {
1095  if (!IsFluctuationsCalculated()) {
1096  printf("**ERROR** ThermalModelBase::PrimordialParticleChargeSusceptibility: fluctuations were not computed beforehand! Quitting...\n");
1097  exit(1);
1098  }
1099 
1100  return m_PrimChargesCorrel[i][static_cast<int>(chg)] / m_Parameters.T / m_Parameters.T / xMath::GeVtoifm() / xMath::GeVtoifm() / xMath::GeVtoifm();
1101  }
1102 
1104  {
1105  int i = TPS()->PdgToId(id1);
1106  if (i == -1) {
1107  printf("**WARNING** ThermalModelBase::PrimordialParticleChargeSusceptibilityByPdg: unknown pdg code %lld", id1);
1108  return 0.;
1109  }
1110 
1112  }
1113 
1115  {
1116  int i1 = TPS()->PdgToId(id1);
1117  if (i1 == -1) {
1118  printf("**WARNING** ThermalModelBase::PrimordialNetParticleChargeSusceptibilityByPdg: unknown pdg code %lld", id1);
1119  return 0.;
1120  }
1121 
1122  int i2 = TPS()->PdgToId(-id1);
1123  if (i2 == -1)
1125 
1127  }
1128 
1130  {
1131  if (!IsFluctuationsCalculated()) {
1132  printf("**ERROR** ThermalModelBase::FinalParticleChargeSusceptibility: fluctuations were not computed beforehand! Quitting...\n");
1133  exit(1);
1134  }
1135 
1136  return m_FinalChargesCorrel[i][static_cast<int>(chg)] / m_Parameters.T / m_Parameters.T / xMath::GeVtoifm() / xMath::GeVtoifm() / xMath::GeVtoifm();
1137  }
1138 
1140  {
1141  int i = TPS()->PdgToId(id1);
1142  if (i == -1) {
1143  printf("**WARNING** ThermalModelBase::FinalParticleChargeSusceptibilityByPdg: unknown pdg code %lld", id1);
1144  return 0.;
1145  }
1146 
1147  return FinalParticleChargeSusceptibility(i, chg);
1148  }
1149 
1151  {
1152  int i1 = TPS()->PdgToId(id1);
1153  if (i1 == -1) {
1154  printf("**WARNING** ThermalModelBase::FinalNetParticleChargeSusceptibilityByPdg: unknown pdg code %lld", id1);
1155  return 0.;
1156  }
1157 
1158  int i2 = TPS()->PdgToId(-id1);
1159  if (i2 == -1)
1160  return FinalParticleChargeSusceptibility(i1, chg);
1161 
1163  }
1164 
1166  {
1167  m_Susc.resize(4);
1168  for (int i = 0; i < 4; ++i) m_Susc[i].resize(4);
1169 
1170  for (int i = 0; i < 4; ++i) {
1171  for (int j = 0; j < 4; ++j) {
1172  m_Susc[i][j] = 0.;
1173  for (size_t k = 0; k < m_PrimCorrel.size(); ++k) {
1174  int c1 = 0;
1175  if (i == 0) c1 = m_TPS->Particles()[k].BaryonCharge();
1176  if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1177  if (i == 2) c1 = m_TPS->Particles()[k].Strangeness();
1178  if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1179  for (size_t kp = 0; kp < m_PrimCorrel.size(); ++kp) {
1180  int c2 = 0;
1181  if (j == 0) c2 = m_TPS->Particles()[kp].BaryonCharge();
1182  if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1183  if (j == 2) c2 = m_TPS->Particles()[kp].Strangeness();
1184  if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1185  m_Susc[i][j] += c1 * c2 * m_PrimCorrel[k][kp];
1186  }
1187  }
1189  }
1190  }
1191  }
1192 
1194  {
1195  m_ProxySusc.resize(4);
1196  for (int i = 0; i < 4; ++i)
1197  m_ProxySusc[i].resize(4);
1198 
1199  // Up to 3, no charm here yet
1200  for (int i = 0; i < 3; ++i) {
1201  for (int j = 0; j < 3; ++j) {
1202  m_ProxySusc[i][j] = 0.;
1203  for (size_t k = 0; k < m_TotalCorrel.size(); ++k) {
1204  if (m_TPS->Particles()[k].IsStable()) {
1205  int c1 = 0;
1206  //if (i == 0) c1 = m_TPS->Particles()[k].BaryonCharge();
1207  if (i == 0) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 2212) - 1 * (m_TPS->Particles()[k].PdgId() == -2212);
1208  if (i == 1) c1 = m_TPS->Particles()[k].ElectricCharge();
1209  //if (i == 1) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 211) - 1 * (m_TPS->Particles()[k].PdgId() == -211);
1210  if (i == 2) c1 = 1 * (m_TPS->Particles()[k].PdgId() == 321) - 1 * (m_TPS->Particles()[k].PdgId() == -321);
1211  if (i == 3) c1 = m_TPS->Particles()[k].Charm();
1212  for (size_t kp = 0; kp < m_TotalCorrel.size(); ++kp) {
1213  if (m_TPS->Particles()[kp].IsStable()) {
1214  int c2 = 0;
1215  //if (j == 0) c2 = m_TPS->Particles()[kp].BaryonCharge();
1216  if (j == 0) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 2212) - 1 * (m_TPS->Particles()[kp].PdgId() == -2212);
1217  if (j == 1) c2 = m_TPS->Particles()[kp].ElectricCharge();
1218  //if (j == 1) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 211) - 1 * (m_TPS->Particles()[kp].PdgId() == -211);
1219  if (j == 2) c2 = 1 * (m_TPS->Particles()[kp].PdgId() == 321) - 1 * (m_TPS->Particles()[kp].PdgId() == -321);
1220  if (j == 3) c2 = m_TPS->Particles()[kp].Charm();
1221  m_ProxySusc[i][j] += c1 * c2 * m_TotalCorrel[k][kp];
1222  }
1223  }
1224  }
1225  }
1227  }
1228  }
1229 
1230  //printf("chi2netp/chi2skellam = %lf\n", m_ProxySusc[0][0] / (m_densitiestotal[m_TPS->PdgToId(2212)] + m_densitiestotal[m_TPS->PdgToId(-2212)]) * pow(m_Parameters.T * xMath::GeVtoifm(), 3));
1231  //printf("chi2netpi/chi2skellam = %lf\n", m_ProxySusc[1][1] / (m_densitiestotal[m_TPS->PdgToId(211)] + m_densitiestotal[m_TPS->PdgToId(-211)]) * pow(m_Parameters.T * xMath::GeVtoifm(), 3));
1232  }
1233 
1235  {
1236  m_PrimChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1237  m_FinalChargesCorrel = std::vector< std::vector<double> >(TPS()->ComponentsNumber(), std::vector<double>(4, 0.));
1238 
1239  for (size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1240  int c1 = 1;
1241  for (int chg = 0; chg < 4; ++chg) {
1242  for (size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1243  int c2 = TPS()->Particle(j).ConservedCharge((ConservedCharge::Name)chg);
1244  m_PrimChargesCorrel[i][chg] += c1 * c2 * m_PrimCorrel[i][j];
1245  }
1246  }
1247  }
1248 
1249  for (size_t i = 0; i < TPS()->ComponentsNumber(); ++i) {
1250  if (m_TPS->Particles()[i].IsStable()) {
1251  int c1 = 1;
1252  for (int chg = 0; chg < 4; ++chg) {
1253  for (size_t j = 0; j < TPS()->ComponentsNumber(); ++j) {
1254  if (m_TPS->Particles()[j].IsStable()) {
1255  int c2 = TPS()->Particle(j).ConservedCharge((ConservedCharge::Name)chg);
1256  m_FinalChargesCorrel[i][chg] += c1 * c2 * m_TotalCorrel[i][j];
1257  }
1258  }
1259  }
1260  }
1261  }
1262  }
1263 
1265  printf("**WARNING** %s: Calculation of fluctuations is not implemented\n", m_TAG.c_str());
1266  }
1267 
1268  std::vector<double> ThermalModelBase::BroydenEquationsChem::Equations(const std::vector<double>& x)
1269  {
1270  std::vector<double> ret(m_N, 0.);
1271 
1272  int i1 = 0;
1273  if (m_THM->ConstrainMuB()) { m_THM->SetBaryonChemicalPotential(x[i1]); i1++; }
1274  if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1275  if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1276  if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1277  m_THM->FillChemicalPotentials();
1278  m_THM->CalculatePrimordialDensities();
1279 
1280  i1 = 0;
1281 
1282  // Baryon charge
1283  if (m_THM->ConstrainMuB()) {
1284  double fBd = m_THM->CalculateBaryonDensity();
1285  double fSd = m_THM->CalculateEntropyDensity();
1286 
1287  ret[i1] = (fBd / fSd - 1. / m_THM->SoverB()) * m_THM->SoverB();
1288 
1289  i1++;
1290  }
1291 
1292  // Electric charge
1293  if (m_THM->ConstrainMuQ()) {
1294  double fBd = m_THM->CalculateBaryonDensity();
1295  double fQd = m_THM->CalculateChargeDensity();
1296 
1297  // Update: remove division by Q/B to allow for charge neutrality
1298  ret[i1] = (fQd / fBd - m_THM->QoverB());
1299  //ret[i1] = (fQd / fBd - m_THM->QoverB()) / m_THM->QoverB();
1300 
1301  i1++;
1302  }
1303 
1304 
1305  // Strangeness
1306  if (m_THM->ConstrainMuS()) {
1307  double fSd = m_THM->CalculateStrangenessDensity();
1308  double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1309 
1310  ret[i1] = fSd / fASd;
1311 
1312  i1++;
1313  }
1314 
1315 
1316  // Charm
1317  if (m_THM->ConstrainMuC()) {
1318  double fCd = m_THM->CalculateCharmDensity();
1319  double fACd = m_THM->CalculateAbsoluteCharmDensity();
1320 
1321  ret[i1] = fCd / fACd;
1322 
1323  i1++;
1324  }
1325 
1326  return ret;
1327  }
1328 
1329  std::vector<double> ThermalModelBase::BroydenJacobianChem::Jacobian(const std::vector<double>& x)
1330  {
1331  int i1 = 0;
1332  // Analytic calculations of Jacobian not yet supported if entropy per baryon is involved
1333  if (m_THM->ConstrainMuB()) {
1334  printf("**ERROR** Constraining chemical potentials: analytic calculation of the Jacobian not supported if muB is constrained\n");
1335  exit(1);
1336  }
1337 
1338  if (m_THM->ConstrainMuQ()) { m_THM->SetElectricChemicalPotential(x[i1]); i1++; }
1339  if (m_THM->ConstrainMuS()) { m_THM->SetStrangenessChemicalPotential(x[i1]); i1++; }
1340  if (m_THM->ConstrainMuC()) { m_THM->SetCharmChemicalPotential(x[i1]); i1++; }
1341  m_THM->FillChemicalPotentials();
1342  m_THM->CalculatePrimordialDensities();
1343 
1344  double fBd = m_THM->CalculateBaryonDensity();
1345  double fQd = m_THM->CalculateChargeDensity();
1346  double fSd = m_THM->CalculateStrangenessDensity();
1347  double fASd = m_THM->CalculateAbsoluteStrangenessDensity();
1348  double fCd = m_THM->CalculateCharmDensity();
1349  double fACd = m_THM->CalculateAbsoluteCharmDensity();
1350 
1351  vector<double> wprim;
1352  wprim.resize(m_THM->Densities().size());
1353  for (size_t i = 0; i < wprim.size(); ++i)
1354  wprim[i] = m_THM->ParticleScaledVariance(i);
1355 
1356  int NNN = 0;
1357  if (m_THM->ConstrainMuQ()) NNN++;
1358  if (m_THM->ConstrainMuS()) NNN++;
1359  if (m_THM->ConstrainMuC()) NNN++;
1360  MatrixXd ret(NNN, NNN);
1361 
1362  i1 = 0;
1363  // Electric charge derivatives
1364  if (m_THM->ConstrainMuQ()) {
1365  int i2 = 0;
1366 
1367  double d1 = 0., d2 = 0.;
1368 
1369  if (m_THM->ConstrainMuQ()) {
1370  d1 = 0.;
1371  for (size_t i = 0; i < wprim.size(); ++i)
1372  d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1373  d1 /= m_THM->Parameters().T;
1374 
1375  d2 = 0.;
1376  for (size_t i = 0; i < wprim.size(); ++i)
1377  d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1378  d2 /= m_THM->Parameters().T;
1379 
1380  // Update: remove division by Q/B to allow for charge neutrality
1381  ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1382  //ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2) / m_THM->QoverB();
1383 
1384  i2++;
1385  }
1386 
1387 
1388  if (m_THM->ConstrainMuS()) {
1389  d1 = 0.;
1390  for (size_t i = 0; i < wprim.size(); ++i)
1391  d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1392  d1 /= m_THM->Parameters().T;
1393 
1394  d2 = 0.;
1395  for (size_t i = 0; i < wprim.size(); ++i)
1396  d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1397  d2 /= m_THM->Parameters().T;
1398 
1399  // Update: remove division by Q/B to allow for charge neutrality
1400  ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1401  //ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2) / m_THM->QoverB();
1402 
1403  i2++;
1404  }
1405 
1406 
1407  if (m_THM->ConstrainMuC()) {
1408  d1 = 0.;
1409  for (size_t i = 0; i < wprim.size(); ++i)
1410  d1 += m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1411  d1 /= m_THM->Parameters().T;
1412 
1413  d2 = 0.;
1414  for (size_t i = 0; i < wprim.size(); ++i)
1415  d2 += m_THM->TPS()->Particle(i).BaryonCharge() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1416  d2 /= m_THM->Parameters().T;
1417 
1418  // Update: remove division by Q/B to allow for charge neutrality
1419  ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2);
1420  //ret(i1, i2) = (d1 / fBd - fQd / fBd / fBd * d2) / m_THM->QoverB();
1421 
1422  i2++;
1423  }
1424 
1425  i1++;
1426  }
1427 
1428 
1429  // Strangeness derivatives
1430  if (m_THM->ConstrainMuS()) {
1431  int i2 = 0;
1432 
1433  double d1 = 0., d2 = 0.;
1434 
1435  if (m_THM->ConstrainMuQ()) {
1436  d1 = 0.;
1437  for (size_t i = 0; i < wprim.size(); ++i)
1438  d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1439  d1 /= m_THM->Parameters().T;
1440 
1441  d2 = 0.;
1442  for (size_t i = 0; i < wprim.size(); ++i)
1443  d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1444  d2 /= m_THM->Parameters().T;
1445 
1446  ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1447 
1448  i2++;
1449  }
1450 
1451 
1452  if (m_THM->ConstrainMuS()) {
1453  d1 = 0.;
1454  for (size_t i = 0; i < wprim.size(); ++i)
1455  d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1456  d1 /= m_THM->Parameters().T;
1457 
1458  d2 = 0.;
1459  for (size_t i = 0; i < wprim.size(); ++i)
1460  d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1461  d2 /= m_THM->Parameters().T;
1462 
1463  ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1464 
1465  i2++;
1466  }
1467 
1468 
1469  if (m_THM->ConstrainMuC()) {
1470  d1 = 0.;
1471  for (size_t i = 0; i < wprim.size(); ++i)
1472  d1 += m_THM->TPS()->Particle(i).Strangeness() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1473  d1 /= m_THM->Parameters().T;
1474 
1475  d2 = 0.;
1476  for (size_t i = 0; i < wprim.size(); ++i)
1477  d2 += m_THM->TPS()->Particle(i).AbsoluteStrangeness() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1478  d2 /= m_THM->Parameters().T;
1479 
1480  ret(i1, i2) = d1 / fASd - fSd / fASd / fASd * d2;
1481 
1482  i2++;
1483  }
1484 
1485  i1++;
1486  }
1487 
1488 
1489  // Charm derivatives
1490  if (m_THM->ConstrainMuC()) {
1491  int i2 = 0;
1492 
1493  double d1 = 0., d2 = 0.;
1494 
1495  if (m_THM->ConstrainMuQ()) {
1496  d1 = 0.;
1497  for (size_t i = 0; i < wprim.size(); ++i)
1498  d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1499  d1 /= m_THM->Parameters().T;
1500 
1501  d2 = 0.;
1502  for (size_t i = 0; i < wprim.size(); ++i)
1503  d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).ElectricCharge() * m_THM->Densities()[i] * wprim[i];
1504  d2 /= m_THM->Parameters().T;
1505 
1506  ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1507 
1508  i2++;
1509  }
1510 
1511 
1512  if (m_THM->ConstrainMuS()) {
1513  d1 = 0.;
1514  for (size_t i = 0; i < wprim.size(); ++i)
1515  d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1516  d1 /= m_THM->Parameters().T;
1517 
1518  d2 = 0.;
1519  for (size_t i = 0; i < wprim.size(); ++i)
1520  d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Strangeness() * m_THM->Densities()[i] * wprim[i];
1521  d2 /= m_THM->Parameters().T;
1522 
1523  ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1524 
1525  i2++;
1526  }
1527 
1528 
1529  if (m_THM->ConstrainMuC()) {
1530  d1 = 0.;
1531  for (size_t i = 0; i < wprim.size(); ++i)
1532  d1 += m_THM->TPS()->Particle(i).Charm() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1533  d1 /= m_THM->Parameters().T;
1534 
1535  d2 = 0.;
1536  for (size_t i = 0; i < wprim.size(); ++i)
1537  d2 += m_THM->TPS()->Particle(i).AbsoluteCharm() * m_THM->TPS()->Particle(i).Charm() * m_THM->Densities()[i] * wprim[i];
1538  d2 /= m_THM->Parameters().T;
1539 
1540  ret(i1, i2) = d1 / fACd - fCd / fACd / fACd * d2;
1541 
1542  i2++;
1543  }
1544 
1545  i1++;
1546  }
1547 
1548  std::vector<double> retVec(NNN*NNN, 0);
1549  for (int i = 0; i < NNN; ++i)
1550  for (int j = 0; j < NNN; ++j)
1551  retVec[i*NNN + j] = ret(i, j);
1552 
1553 
1554  return retVec;
1555  }
1556 
1557  std::vector<double> ThermalModelBase::BroydenChem::Solve(const std::vector<double>& x0, BroydenSolutionCriterium * solcrit, int max_iterations)
1558  {
1559  if (m_Equations == NULL) {
1560  printf("**ERROR** Broyden::Solve: Equations to solve not specified!\n");
1561  exit(1);
1562  }
1563 
1564  int NNN = 0;
1565  std::vector<double> xcur;
1566  if (m_THM->ConstrainMuB()) { xcur.push_back(x0[0]); NNN++; }
1567  if (m_THM->ConstrainMuQ()) { xcur.push_back(x0[1]); NNN++; }
1568  if (m_THM->ConstrainMuS()) { xcur.push_back(x0[2]); NNN++; }
1569  if (m_THM->ConstrainMuC()) { xcur.push_back(x0[3]); NNN++; }
1570  if (NNN == 0) {
1571  m_THM->FillChemicalPotentials();
1572  return xcur;
1573  }
1574 
1575  m_Equations->SetDimension(NNN);
1576 
1577  m_MaxIterations = max_iterations;
1578 
1579  BroydenSolutionCriterium *SolutionCriterium = solcrit;
1580  bool UseDefaultSolutionCriterium = false;
1581  if (SolutionCriterium == NULL) {
1582  SolutionCriterium = new BroydenSolutionCriterium(TOL);
1583  UseDefaultSolutionCriterium = true;
1584  }
1585 
1586  BroydenJacobian *JacobianInUse = m_Jacobian;
1587  bool UseDefaultJacobian = false;
1588  if (JacobianInUse == NULL || m_THM->ConstrainMuB()) {
1589  JacobianInUse = new BroydenJacobian(m_Equations);
1590  UseDefaultJacobian = true;
1591  }
1592  m_Iterations = 0;
1593  double &maxdiff = m_MaxDifference;
1594  int N = m_Equations->Dimension();
1595 
1596 
1597 
1598  std::vector<double> tmpvec, xdeltavec = xcur;
1599  VectorXd xold(N), xnew(N), xdelta(N);
1600  VectorXd fold(N), fnew(N), fdelta(N);
1601 
1602  xold = VectorXd::Map(&xcur[0], xcur.size());
1603 
1604  MatrixXd Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
1605 
1606  bool constrmuB = m_THM->ConstrainMuB();
1607  bool constrmuQ = m_THM->ConstrainMuQ();
1608  bool constrmuS = m_THM->ConstrainMuS();
1609  bool constrmuC = m_THM->ConstrainMuC();
1610  bool repeat = false;
1611  NNN = 0;
1612  if (m_THM->ConstrainMuB()) {
1613  for (int j = 0; j < Jac.rows(); ++j)
1614  if (Jac(NNN, j) > 1.e8) { repeat = true; m_THM->ConstrainMuB(false); }
1615  double S = m_THM->CalculateEntropyDensity();
1616  double nB = m_THM->CalculateBaryonDensity();
1617  if (abs(S) < 1.e-25 || abs(nB) < 1.e-25) { repeat = true; m_THM->ConstrainMuB(false); }
1618  NNN++;
1619  }
1620  if (m_THM->ConstrainMuQ()) {
1621  for (int j = 0; j < Jac.rows(); ++j)
1622  if (Jac(NNN, j) > 1.e8) { repeat = true; m_THM->ConstrainMuQ(false); }
1623  double nQ = m_THM->CalculateChargeDensity();
1624  double nB = m_THM->CalculateBaryonDensity();
1625  if (abs(nQ) < 1.e-25 || abs(nB) < 1.e-25) { repeat = true; m_THM->ConstrainMuQ(false); }
1626  NNN++;
1627  }
1628  if (m_THM->ConstrainMuS()) {
1629  for (int j = 0; j < Jac.rows(); ++j)
1630  if (Jac(NNN, j) > 1.e8) { repeat = true; m_THM->ConstrainMuS(false); }
1631 
1632  double nS = m_THM->CalculateAbsoluteStrangenessDensity();
1633  if (abs(nS) < 1.e-25) { repeat = true; m_THM->ConstrainMuS(false); }
1634  NNN++;
1635  }
1636  if (m_THM->ConstrainMuC()) {
1637  for (int j = 0; j < Jac.rows(); ++j)
1638  if (Jac(NNN, j) > 1.e8) { repeat = true; m_THM->ConstrainMuC(false); }
1639  double nC = m_THM->CalculateAbsoluteCharmDensity();
1640  if (abs(nC) < 1.e-25) { repeat = true; m_THM->ConstrainMuC(false); }
1641  NNN++;
1642  }
1643  if (repeat) {
1644  std::vector<double> ret = Solve(x0, solcrit, max_iterations);
1645  m_THM->ConstrainMuQ(constrmuB);
1646  m_THM->ConstrainMuQ(constrmuQ);
1647  m_THM->ConstrainMuS(constrmuS);
1648  m_THM->ConstrainMuC(constrmuC);
1649  return ret;
1650  }
1651 
1652  if (Jac.determinant() == 0.0)
1653  {
1654  printf("**WARNING** Singular Jacobian in Broyden::Solve\n");
1655  return xcur;
1656  }
1657 
1658  MatrixXd Jinv = Jac.inverse();
1659  tmpvec = m_Equations->Equations(xcur);
1660  fold = VectorXd::Map(&tmpvec[0], tmpvec.size());
1661 
1662  for (m_Iterations = 1; m_Iterations < max_iterations; ++m_Iterations) {
1663  xnew = xold - Jinv * fold;
1664 
1665  VectorXd::Map(&xcur[0], xcur.size()) = xnew;
1666 
1667  tmpvec = m_Equations->Equations(xcur);
1668  fnew = VectorXd::Map(&tmpvec[0], tmpvec.size());
1669 
1670 
1671  maxdiff = 0.;
1672  for (size_t i = 0; i < xcur.size(); ++i) {
1673  maxdiff = std::max(maxdiff, fabs(fnew[i]));
1674  }
1675 
1676  xdelta = xnew - xold;
1677  fdelta = fnew - fold;
1678 
1679  VectorXd::Map(&xdeltavec[0], xdeltavec.size()) = xdelta;
1680 
1681  if (SolutionCriterium->IsSolved(xcur, tmpvec, xdeltavec))
1682  break;
1683 
1684  if (!m_UseNewton) // Use Broyden's method
1685  {
1686 
1687  double norm = 0.;
1688  for (int i = 0; i < N; ++i)
1689  for (int j = 0; j < N; ++j)
1690  norm += xdelta[i] * Jinv(i, j) * fdelta[j];
1691  VectorXd p1(N);
1692  p1 = (xdelta - Jinv * fdelta);
1693  for (int i = 0; i < N; ++i) p1[i] *= 1. / norm;
1694  Jinv = Jinv + (p1 * xdelta.transpose()) * Jinv;
1695  }
1696  else // Use Newton's method
1697  {
1698  Jac = Eigen::Map< Matrix<double, Dynamic, Dynamic, RowMajor> >(&JacobianInUse->Jacobian(xcur)[0], N, N);
1699  Jinv = Jac.inverse();
1700  }
1701 
1702  xold = xnew;
1703  fold = fnew;
1704  }
1705 
1706  if (m_Iterations == max_iterations) {
1707  printf("**WARNING** Reached maximum number of iterations in Broyden procedure\n");
1708  }
1709 
1710  if (UseDefaultSolutionCriterium) {
1711  delete SolutionCriterium;
1712  SolutionCriterium = NULL;
1713  }
1714  if (UseDefaultJacobian) {
1715  delete JacobianInUse;
1716  JacobianInUse = NULL;
1717  }
1718  return xcur;
1719  }
1720 
1721 
1722  ThermalModelBase::BroydenEquationsChemTotals::BroydenEquationsChemTotals(const std::vector<int>& vConstr, const std::vector<int>& vType, const std::vector<double>& vTotals, ThermalModelBase * model) :
1723  BroydenEquations(), m_Constr(vConstr), m_Type(vType), m_Totals(vTotals), m_THM(model)
1724  {
1725  m_N = 0;
1726  for (size_t i = 0; i < m_Constr.size(); ++i)
1727  m_N += m_Constr[i];
1728  }
1729 
1730  std::vector<double> ThermalModelBase::BroydenEquationsChemTotals::Equations(const std::vector<double>& x)
1731  {
1732  std::vector<double> ret(m_N, 0.);
1733 
1734  int i1 = 0;
1735  for (int i = 0; i < 4; ++i) {
1736  if (m_Constr[i]) {
1737  if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
1738  if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
1739  if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
1740  if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
1741  i1++;
1742  }
1743  }
1744  m_THM->FillChemicalPotentials();
1745  m_THM->CalculatePrimordialDensities();
1746 
1747  vector<double> dens(4, 0.), absdens(4, 0.);
1748  if (m_Constr[0]) {
1749  dens[0] = m_THM->CalculateBaryonDensity();
1750  absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
1751  }
1752  if (m_Constr[1]) {
1753  dens[1] = m_THM->CalculateChargeDensity();
1754  absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
1755  }
1756  if (m_Constr[2]) {
1757  dens[2] = m_THM->CalculateStrangenessDensity();
1758  absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
1759  }
1760  if (m_Constr[3]) {
1761  dens[3] = m_THM->CalculateCharmDensity();
1762  absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
1763  }
1764 
1765  i1 = 0;
1766 
1767  for (int i = 0; i < 4; ++i) {
1768  if (m_Constr[i]) {
1769  if (m_Type[i] == 0)
1770  ret[i1] = (dens[i] * m_THM->Parameters().V - m_Totals[i]) / m_Totals[i];
1771  else
1772  ret[i1] = dens[i] / absdens[i];
1773  i1++;
1774  }
1775  }
1776 
1777  return ret;
1778  }
1779 
1780  std::vector<double> ThermalModelBase::BroydenJacobianChemTotals::Jacobian(const std::vector<double>& x)
1781  {
1782  int NNN = 0;
1783  for (int i = 0; i < 4; ++i) NNN += m_Constr[i];
1784 
1785  int i1 = 0;
1786 
1787  for (int i = 0; i < 4; ++i) {
1788  if (m_Constr[i]) {
1789  if (i == 0) m_THM->SetBaryonChemicalPotential(x[i1]);
1790  if (i == 1) m_THM->SetElectricChemicalPotential(x[i1]);
1791  if (i == 2) m_THM->SetStrangenessChemicalPotential(x[i1]);
1792  if (i == 3) m_THM->SetCharmChemicalPotential(x[i1]);
1793  i1++;
1794  }
1795  }
1796 
1797  vector<double> tfug(4, 0.);
1798  tfug[0] = exp(m_THM->Parameters().muB / m_THM->Parameters().T);
1799  tfug[1] = exp(m_THM->Parameters().muQ / m_THM->Parameters().T);
1800  tfug[2] = exp(m_THM->Parameters().muS / m_THM->Parameters().T);
1801  tfug[3] = exp(m_THM->Parameters().muC / m_THM->Parameters().T);
1802 
1803  m_THM->FillChemicalPotentials();
1804  m_THM->CalculatePrimordialDensities();
1805 
1806  vector<double> dens(4, 0.), absdens(4, 0.);
1807  if (m_Constr[0]) {
1808  dens[0] = m_THM->CalculateBaryonDensity();
1809  absdens[0] = m_THM->CalculateAbsoluteBaryonDensity();
1810  }
1811  if (m_Constr[1]) {
1812  dens[1] = m_THM->CalculateChargeDensity();
1813  absdens[1] = m_THM->CalculateAbsoluteChargeDensity();
1814  }
1815  if (m_Constr[2]) {
1816  dens[2] = m_THM->CalculateStrangenessDensity();
1817  absdens[2] = m_THM->CalculateAbsoluteStrangenessDensity();
1818  }
1819  if (m_Constr[3]) {
1820  dens[3] = m_THM->CalculateCharmDensity();
1821  absdens[3] = m_THM->CalculateAbsoluteCharmDensity();
1822  }
1823 
1824  vector<double> wprim;
1825  wprim.resize(m_THM->Densities().size());
1826  for (size_t i = 0; i < wprim.size(); ++i) wprim[i] = m_THM->ParticleScaledVariance(i);
1827 
1828  vector< vector<double> > deriv(4, vector<double>(4)), derivabs(4, vector<double>(4));
1829  for (int i = 0; i < 4; ++i)
1830  for (int j = 0; j < 4; ++j) {
1831  deriv[i][j] = 0.;
1832  for (size_t part = 0; part < wprim.size(); ++part)
1833  deriv[i][j] += m_THM->TPS()->Particles()[part].GetCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * m_THM->Densities()[part] * wprim[part];
1834  deriv[i][j] /= m_THM->Parameters().T;
1835 
1836  derivabs[i][j] = 0.;
1837  for (size_t part = 0; part < wprim.size(); ++part)
1838  derivabs[i][j] += m_THM->TPS()->Particles()[part].GetAbsCharge(i) * m_THM->TPS()->Particles()[part].GetCharge(j) * m_THM->Densities()[part] * wprim[part];
1839  derivabs[i][j] /= m_THM->Parameters().T;
1840  }
1841 
1842 
1843  MatrixXd ret(NNN, NNN);
1844 
1845  i1 = 0;
1846 
1847  for (int i = 0; i < 4; ++i) {
1848  if (m_Constr[i]) {
1849  int i2 = 0;
1850  for (int j = 0; j < 4; ++j)
1851  if (m_Constr[j]) {
1852  ret(i1, i2) = 0.;
1853  if (m_Type[i] == 0)
1854  ret(i1, i2) = deriv[i][j] * m_THM->Parameters().V / m_Totals[i];
1855  else
1856  ret(i1, i2) = deriv[i][j] / absdens[i] - dens[i] / absdens[i] / absdens[i] * derivabs[i][j];
1857  i2++;
1858  }
1859  i1++;
1860  }
1861  }
1862 
1863  std::vector<double> retVec(NNN*NNN, 0);
1864  for (int i = 0; i < NNN; ++i)
1865  for (int j = 0; j < NNN; ++j)
1866  retVec[i*NNN + j] = ret(i, j);
1867 
1868 
1869  return retVec;
1870  }
1871 
1872 } // namespace thermalfist
Feeddown from strong, electromagnetic, and weak decays.
Definition: ParticleDecay.h:38
void ConstrainChemicalPotentials(bool resetInitialValues=true)
Constrains the chemical potentials by the conservation laws imposed.
const ParticleDecaysVector & DecaysOriginal() const
A backup copy of particle&#39;s decays.
Abstract base class for an HRG model implementation.
virtual double PrimordialParticleChargeSusceptibility(int i, ConservedCharge::Name chg) const
Returns the computed primordial particle vs conserved charge (cross-)susceptibility for particle wit...
virtual double CalculateArbitraryChargeDensity()
Computes the density of the auxiliary ArbitraryCharge()
virtual void CalculateTwoParticleFluctuationsDecays()
Computes particle number correlations and fluctuations for all final-state particles which are marked...
virtual double PrimordialNetParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed primordial net particle vs conserved charge (cross-)susceptibility for particle...
virtual void SetStrangenessChemicalPotential(double muS)
Set the strangeness chemical potential.
std::vector< double > m_Chem
virtual double FinalParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed final (after decays) particle vs conserved charge (cross-)susceptibility for pa...
virtual double FinalNetParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed final (after decays) net particle vs conserved charge (cross-)susceptibility fo...
virtual double NetParticleSusceptibilityFinalByPdg(long long id1, long long id2)
Returns the computed (cross-)susceptibility between final net-particle numbers for pdg codes id1 and...
double AbsoluteStrangeness() const
Absolute strange quark content |s|.
virtual void SetGammaS(double gammaS)
Set the strange quark fugacity factor.
Class implementing the Broyden method to solve a system of non-linear equations.
Definition: Broyden.h:131
static bool PrintDisclaimer()
Definition: Utility.cpp:47
double GeVtoifm()
A constant to transform GeV into fm .
Definition: xMath.h:27
virtual void SetElectricChemicalPotential(double muQ)
Set the electric chemical potential.
virtual void SetElectricCharge(int Q)
Set the total electric charge (for canonical ensemble only)
std::vector< double > m_kurttot
std::vector< double > m_wprim
virtual void SetBaryonCharge(int B)
Set the total baryon number (for canonical ensemble only)
virtual double CalculateAbsoluteCharmDensity()
virtual void SetBaryonChemicalPotential(double muB)
Set the baryon chemical potential.
std::vector< std::vector< double > > m_FinalChargesCorrel
const ThermalParticle & Particle(int id) const
ThermalParticle object corresponding to particle species with a provided 0-based index.
std::vector< double > m_skewprim
virtual void SetStatistics(bool stats)
virtual void FixParameters()
Method which actually implements ConstrainChemicalPotentials() (for backward compatibility).
Contains some helper functions.
virtual void SetStrangeness(int S)
Set the total strangeness (for canonical ensemble only)
std::vector< std::vector< double > > m_ProxySusc
virtual void DisableBaryonAntiBaryonAttraction()
void SetUseWidth(bool useWidth)
Sets whether finite resonance widths are used. Deprecated.
int PdgToId(long long pdgid)
Transforms PDG ID to a 0-based particle id number.
static bool DisclaimerPrinted
Definition: Utility.h:27
std::vector< std::vector< double > > m_Susc
virtual double TwoParticleSusceptibilityPrimordial(int i, int j) const
Returns the computed primordial particle number (cross-)susceptibility for particles with ids i and ...
Energy-independent Breit-Wigner in +-2 interval.
Feeddown from strong decays.
Definition: ParticleDecay.h:40
long long PdgId() const
Particle&#39;s Particle Data Group (PDG) ID number.
double ChargedMultiplicity(int type=0)
Multiplicity of charged particles.
virtual double CalculateAbsoluteChargeDensity()
virtual void SetGammaC(double gammaC)
Set the charm quark fugacity factor.
Class containing the particle list.
virtual void CalculatePrimordialDensities()=0
Calculates the primordial densities of all species.
virtual std::vector< double > Jacobian(const std::vector< double > &x)
Evaluates the Jacobian for given values of the variables.
Definition: Broyden.cpp:27
Grand canonical ensemble.
Energy-dependent Breit-Wigner scheme (eBW)
virtual void SetParameters(const ThermalModelParameters &params)
The thermal parameters.
ThermalModelParameters m_Parameters
Structure containing all thermal parameters of the model.
virtual double CalculateStrangenessDensity()
Abstract class which defines the system of non-linear equations to be solved by the Broyden&#39;s method...
Definition: Broyden.h:31
int ComponentsNumber() const
Number of different particle species in the list.
virtual void SetTemperature(double T)
Set the temperature.
virtual double MuShift(int) const
Shift in chemical potential of particle species id due to interactions.
void NormalizeBranchingRatios()
Normalize branching ratios for all particles such that they add up to 100%.
virtual void SetGammaq(double gammaq)
Set the light quark fugacity factor.
void SetNormBratio(bool normBratio)
Whether branching ratios are renormalized to 100%.
static const int NumberOfDecayTypes
Definition: ParticleDecay.h:67
virtual void SetVirial(int, int, double)
Set the excluded volume coefficient .
virtual double FullIdealChemicalPotential(int i) const
Chemical potential entering the ideal gas expressions of particle species i.
virtual void CalculateSusceptibilityMatrix()
Calculates the conserved charges susceptibility matrix.
ThermalParticleSystem * m_TPS
std::vector< double > m_wtot
double ChargedMultiplicityFinal(int type=0)
Multiplicity of charged particles including the feeddown contributions in accordance with the stabili...
virtual void DisableBaryonBaryonAttraction()
virtual void FillChemicalPotentials()
Sets the chemical potentials of all particles.
std::vector< std::pair< double, std::vector< int > > > ResonanceFinalStatesDistribution
void ResetCalculatedFlags()
Reset all flags which correspond to a calculation status.
virtual void FixParametersNoReset()
Method which actually implements ConstrainChemicalPotentialsNoReset() (for backward compatibility)...
int BaryonCharge() const
Particle&#39;s baryon number.
int MaxIterations() const
Definition: Broyden.h:234
double ChemicalPotential(int i) const
Chemical potential of particle species i.
ResonanceWidthIntegration
Treatment of finite resonance widths.
Class containing all information about a particle specie.
double ChargedScaledVarianceFinal(int type=0)
Scaled variance of charged particles including the feeddown contributions in accordance with the stab...
std::vector< SingleDecayContribution > DecayContributionsToParticle
A vector of SingleDecayContribution where each element corresponds to a certain resonance species...
virtual void CalculateProxySusceptibilityMatrix()
Calculates the susceptibility matrix of conserved charges proxies.
virtual std::vector< double > Solve(const std::vector< double > &x0, BroydenSolutionCriterium *solcrit=NULL, int max_iterations=MAX_ITERS)
Definition: Broyden.cpp:77
virtual double PrimordialParticleChargeSusceptibilityByPdg(long long id1, ConservedCharge::Name chg)
Returns the computed primordial particle vs conserved charge (cross-)susceptibility for particle wit...
Sub-class where it is determined whether the required accuracy is achieved in the Broyden&#39;s method...
Definition: Broyden.h:144
virtual void CalculateTwoParticleCorrelations()
Computes the fluctuations and correlations of the primordial particle numbers.
void SetResonanceWidthIntegrationType(ThermalParticle::ResonanceWidthIntegration type)
Set the ThermalParticle::ResonanceWidthIntegration scheme for all particles. Calls the corresponding ...
double GetDensity(long long PDGID, int feeddown)
Same as GetDensity(int,Feeddown::Type)
const std::string & Name() const
Particle&#39;s name.
std::vector< double > m_kurtprim
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
std::vector< std::vector< double > > m_TotalCorrel
double ConservedChargeDensity(ConservedCharge::Name chg)
A density of a conserved charge (in fm^-3)
double ChargedScaledVariance(int type=0)
Scaled variance of charged particles.
ThermalModelInteraction m_InteractionModel
virtual void ValidateCalculation()
Checks whether issues have occured during the calculation of particle densities in the CalculateDensi...
const std::vector< ResonanceFinalStatesDistribution > & ResonanceFinalStatesDistributions() const
Final state particle number distributions for resonance decays.
virtual double CalculateAbsoluteStrangenessDensity()
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 void SetCharmChemicalPotential(double muC)
Set the charm chemical potential.
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...
void UseStatistics(bool enable)
Use quantum statistics.
virtual double TwoParticleSusceptibilityPrimordialByPdg(long long id1, long long id2)
Returns the computed primordial particle number (cross-)susceptibility for particles with pdg codes ...
void CalculateThermalBranchingRatios(const ThermalModelParameters &params, bool useWidth=0, double mu=0.)
Computes average decay branching ratios by integrating over the thermal mass distribution.
virtual double TwoParticleSusceptibilityFinal(int i, int j) const
Returns the computed final particle number (cross-)susceptibility for particles with ids i and j...
Name
Set of all conserved charges considered.
double ElectricChargeDensity()
Electric charge density (fm )
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
double BaryonDensity()
Net baryon density (fm )
virtual void SetCharm(int C)
Set the total charm (for canonical ensemble only)
const DecayCumulantsContributionsToAllParticles & DecayCumulants() const
Cumulants of particle number distributions of from decays.
double CharmDensity()
Net charm density (fm )
std::vector< double > m_densities
virtual double FinalParticleChargeSusceptibility(int i, ConservedCharge::Name chg) const
Returns the computed final (after decays) particle vs conserved charge (cross-)susceptibility for pa...
Class which implements calculation of the Jacobian needed for the Broyden&#39;s method.
Definition: Broyden.h:76
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 CalculateFluctuations()
Computes the fluctuation observables.
double AbsoluteQuark() const
Absolute light quark content |u,d|.
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
std::vector< std::vector< double > > m_PrimCorrel
bool UsePartialChemicalEquilibrium()
Whether partial chemical equilibrium with additional chemical potentials is used. ...
virtual std::vector< double > CalculateChargeFluctuations(const std::vector< double > &chgs, int order=4)
Calculates fluctuations (diagonal susceptibilities) of an arbitrary "conserved" charge.
ThermalModelEnsemble m_Ensemble
bool IsStable() const
Return particle stability flag.
virtual void SetAttraction(int, int, double)
Set the vdW mean field attraction coefficient .
std::vector< double > GetIdealGasDensities() const
std::vector< std::vector< double > > m_densitiesbyfeeddown
virtual void CalculateFeeddown()
Calculates the total densities which include feeddown contributions.
std::vector< double > m_skewtot
virtual void CalculateParticleChargeCorrelationMatrix()
Calculates the matrix of correlators between primordial (and also final) particle numbers and conserv...
virtual double TwoParticleSusceptibilityFinalByPdg(long long id1, long long id2)
Returns the computed final particle number (cross-)susceptibility for particles with pdg codes id1 a...
const std::vector< DecayContributionsToAllParticles > & DecayContributionsByFeeddown() const
virtual void DisableBaryonAntiBaryonVirial()
std::vector< double > m_densitiestotal
ThermalParticle::ResonanceWidthIntegration ResonanceWidthIntegrationType() const
void ProcessDecays()
Computes the decay contributions of decaying resonances to all particle yields.
int ConservedCharge(ConservedCharge::Name chg) const
One of the four QCD conserved charges.
virtual double CalculateAbsoluteBaryonDensity()
const ParticleDecaysVector & Decays() const
A vector of particle&#39;s decays.
double mnucleon()
Nucleon&#39;s mass. Value as in UrQMD.
Definition: xMath.h:36
double AbsoluteCharm() const
Absolute charm quark content |s|.
void SetResonanceWidthIntegrationType(ThermalParticle::ResonanceWidthIntegration type)
Set (or get) the ThermalParticle::ResonanceWidthIntegration scheme for all particles.
The main namespace where all classes and functions of the Thermal-FIST library reside.
virtual void SetChemicalPotentials(const std::vector< double > &chem=std::vector< double >(0))
Sets the chemical potentials of all particles.
Feeddown from all particles marked as unstable.
Definition: ParticleDecay.h:37
double StrangenessDensity()
Net strangeness density (fm )
double Volume() const
System volume (fm )
ThermalParticleSystem * TPS()
int Iterations() const
Definition: Broyden.h:229
void RestoreBranchingRatios()
Restore the original values of all the branching ratios.
std::vector< std::vector< double > > m_PrimChargesCorrel