Thermal-FIST  1.3
Package for hadron resonance gas model applications
ThermalModelEVCrossterms.cpp
Go to the documentation of this file.
1 /*
2  * Thermal-FIST package
3  *
4  * Copyright (c) 2015-2019 Volodymyr Vovchenko
5  *
6  * GNU General Public License (GPLv3 or later)
7  */
9 
10 #ifdef USE_OPENMP
11 #include <omp.h>
12 #endif
13 
14 #include <vector>
15 #include <cmath>
16 #include <iostream>
17 #include <iomanip>
18 #include <algorithm>
19 #include <fstream>
20 #include <sstream>
21 
22 #include "HRGBase/xMath.h"
24 
25 #include <Eigen/Dense>
26 
27 using namespace Eigen;
28 
29 using namespace std;
30 
31 namespace thermalfist {
32 
33  ThermalModelEVCrossterms::ThermalModelEVCrossterms(ThermalParticleSystem *TPS, const ThermalModelParameters& params) :
34  ThermalModelBase(TPS, params)
35  {
36  m_densitiesid.resize(m_TPS->Particles().size());
37  m_Volume = params.V;
38  m_Ps.resize(m_TPS->Particles().size());
39  FillVirial(std::vector<double>(m_TPS->Particles().size(), 0.));
40  m_TAG = "ThermalModelEVCrossterms";
41 
42  m_Ensemble = GCE;
44  }
45 
47  {
48  }
49 
50  void ThermalModelEVCrossterms::FillVirial(const std::vector<double> & ri) {
51  if (ri.size() != m_TPS->Particles().size()) {
52  printf("**WARNING** %s::FillVirial(const std::vector<double> & ri): size %d of ri does not match number of hadrons %d in the list", m_TAG.c_str(), static_cast<int>(ri.size()), static_cast<int>(m_TPS->Particles().size()));
53  return;
54  }
55  m_Virial.resize(m_TPS->Particles().size());
56  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
57  m_Virial[i].resize(m_TPS->Particles().size());
58  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
59  m_Virial[i][j] = CuteHRGHelper::brr(ri[i], ri[j]);
60  }
61 
62  // Correction for non-diagonal terms R1=R2 and R2=0
63  std::vector< std::vector<double> > fVirialTmp = m_Virial;
64  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
65  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
66  if (i == j) m_Virial[i][j] = fVirialTmp[i][j];
67  else if ((fVirialTmp[i][i] + fVirialTmp[j][j]) > 0.0) m_Virial[i][j] = 2. * fVirialTmp[i][j] * fVirialTmp[i][i] / (fVirialTmp[i][i] + fVirialTmp[j][j]);
68  }
69  }
70 
71  void ThermalModelEVCrossterms::ReadInteractionParameters(const std::string & filename)
72  {
73  m_Virial = std::vector< std::vector<double> >(m_TPS->Particles().size(), std::vector<double>(m_TPS->Particles().size(), 0.));
74 
75  ifstream fin(filename.c_str());
76  char cc[2000];
77  while (!fin.eof()) {
78  fin.getline(cc, 2000);
79  string tmp = string(cc);
80  vector<string> elems = CuteHRGHelper::split(tmp, '#');
81  if (elems.size() < 1)
82  continue;
83  istringstream iss(elems[0]);
84  int pdgid1, pdgid2;
85  double b;
86  if (iss >> pdgid1 >> pdgid2 >> b) {
87  int ind1 = m_TPS->PdgToId(pdgid1);
88  int ind2 = m_TPS->PdgToId(pdgid2);
89  if (ind1 != -1 && ind2 != -1)
90  m_Virial[ind1][ind2] = b;
91  }
92  }
93  fin.close();
94  }
95 
96  void ThermalModelEVCrossterms::WriteInteractionParameters(const std::string & filename)
97  {
98  ofstream fout(filename.c_str());
99  fout << "# List of crossterms parameters to be used in the Crossterms excluded-volume HRG model"
100  << std::endl;
101  fout << "# Only particle pairs with a non-zero eigenvolume parameter are listed here"
102  << std::endl;
103  /*fout << "#" << std::setw(14) << "pdg_i"
104  << std::setw(15) << "pdg_j"
105  << std::setw(15) << "b_{ij}[fm^3]"
106  << std::endl;*/
107  fout << "#" << " " << "pdg_i"
108  << " " << "pdg_j"
109  << " " << "b_{ij}[fm^3]"
110  << std::endl;
111  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
112  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
113  if (m_Virial[i][j] != 0.) {
114  //fout << std::setw(15) << m_TPS->Particle(i).PdgId();
115  //fout << std::setw(15) << m_TPS->Particle(j).PdgId();
116  //fout << std::setw(15) << m_Virial[i][j];
117  fout << " " << m_TPS->Particle(i).PdgId();
118  fout << " " << m_TPS->Particle(j).PdgId();
119  fout << " " << m_Virial[i][j];
120  fout << std::endl;
121  }
122  }
123  }
124  fout.close();
125  }
126 
128  FillVirial(vector<double>(m_TPS->Particles().size(), rad));
129  }
130 
131  double ThermalModelEVCrossterms::VirialCoefficient(int i, int j) const {
132  if (i < 0 || i >= static_cast<int>(m_Virial.size()) || j < 0 || j > static_cast<int>(m_Virial.size()))
133  return 0.;
134  return m_Virial[i][j];
135  }
136 
137  void ThermalModelEVCrossterms::SetVirial(int i, int j, double b) {
138  if (i >= 0 && i < static_cast<int>(m_Virial.size()) && j >= 0 && j < static_cast<int>(m_Virial.size()))
139  m_Virial[i][j] = b;
140  else printf("**WARNING** Index overflow in ThermalModelEVCrossterms::SetVirial\n");
141  }
142 
145  m_densitiesid.resize(m_TPS->Particles().size());
146  FillVirial();
147  }
148 
149  double ThermalModelEVCrossterms::DensityId(int i, const std::vector<double>& pstars)
150  {
151  double dMu = 0.;
152  if (pstars.size() == m_TPS->Particles().size())
153  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
154  dMu += -m_Virial[i][j] * pstars[j];
155  else
156  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
157  dMu += -m_Virial[i][j] * m_Ps[j];
158 
160  }
161 
162  double ThermalModelEVCrossterms::Pressure(int i, const std::vector<double>& pstars)
163  {
164  double dMu = 0.;
165  if (pstars.size() == m_TPS->Particles().size())
166  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
167  dMu += -m_Virial[i][j] * pstars[j];
168  else
169  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
170  dMu += -m_Virial[i][j] * m_Ps[j];
171 
172  return m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_Chem[i] + dMu);
173  }
174 
176  double dMu = 0.;
177  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) dMu += -m_Virial[i][j] * m_Ps[j];
178 
179  return m_TPS->Particles()[i].ScaledVariance(m_Parameters, m_UseWidth, m_Chem[i] + dMu);
180  }
181 
183  double dMu = 0.;
184  dMu += -m_Virial[i][i] * P;
185 
186  return m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_Chem[i] + dMu);
187  }
188 
189 
191  double ret = 0.;
192  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
193  ret += PartialPressureDiagonal(i, P);
194  return ret;
195  }
196 
198  BroydenEquationsCRSDEV eqs(this);
199  BroydenJacobian jac(&eqs);
200  jac.SetDx(1.0E-8);
201  Broyden broydn(&eqs, &jac);
203 
204  m_Pressure = 0.;
205  double x0 = m_Pressure;
206  std::vector<double> x(1, x0);
207 
208  x = broydn.Solve(x, &crit);
209 
210  m_Pressure = x[0];
211  for (size_t i = 0; i < m_Ps.size(); ++i)
213  }
214 
215 
216  void ThermalModelEVCrossterms::SolvePressure(bool resetPartials) {
217  if (resetPartials) {
218  m_Ps.resize(m_TPS->Particles().size());
219  for (size_t i = 0; i < m_Ps.size(); ++i) m_Ps[i] = 0.;
220  SolveDiagonal();
221  }
222 
223  BroydenEquationsCRS eqs(this);
224  BroydenJacobianCRS jac(this);
225  Broyden broydn(&eqs, &jac);
226  BroydenSolutionCriteriumCRS crit(this);
227 
228  m_Ps = broydn.Solve(m_Ps, &crit);
229  m_Pressure = 0.;
230  for (size_t i = 0; i < m_Ps.size(); ++i)
231  m_Pressure += m_Ps[i];
232 
233  if (broydn.Iterations() == broydn.MaxIterations())
235  else m_LastCalculationSuccessFlag = true;
236 
237  m_MaxDiff = broydn.MaxDifference();
238  }
239 
241  m_FluctuationsCalculated = false;
242 
243  // Pressure
244  SolvePressure();
245  vector<double> tN(m_densities.size());
246  for (size_t i = 0; i < m_Ps.size(); ++i)
247  tN[i] = DensityId(i);
248 
249  // Densities
250 
251  int NN = m_densities.size();
252 
253  MatrixXd densMatrix(NN, NN);
254  VectorXd solVector(NN), xVector(NN);
255 
256  for (int i = 0; i < NN; ++i)
257  for (int j = 0; j < NN; ++j) {
258  densMatrix(i, j) = m_Virial[i][j] * tN[i];
259  if (i == j) densMatrix(i, j) += 1.;
260  }
261 
262  PartialPivLU<MatrixXd> decomp(densMatrix);
263 
264  for (int i = 0; i < NN; ++i) xVector[i] = 0.;
265  for (int i = 0; i < NN; ++i) {
266  xVector[i] = tN[i];
267  solVector = decomp.solve(xVector);
268  if (1) {
269  m_densities[i] = 0.;
270  for (int j = 0; j < NN; ++j)
271  m_densities[i] += solVector[j];
272  }
273  else {
274  cout << "Could not recover m_densities from partial pressures!\n";
275  }
276  xVector[i] = 0.;
277  }
278 
279  std::vector<double> fEntropyP(m_densities.size());
280  for (int i = 0; i < NN; ++i) {
281  double dMu = 0.;
282  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) dMu += -m_Virial[i][j] * m_Ps[j];
283  xVector[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EntropyDensity, m_UseWidth, m_Chem[i] + dMu);
284  }
285 
286  solVector = decomp.solve(xVector);
287 
288  if (1) {
290  for (int i = 0; i < NN; ++i)
291  m_TotalEntropyDensity += solVector[i];
292  }
293  else {
294  cout << "**ERROR** Could not recover m_densities from partial pressures!\n";
295  return;
296  }
297 
298  m_Calculated = true;
300  }
301 
303  // Pressure
304  SolvePressure(false);
305  vector<double> tN(m_densities.size());
306  for (size_t i = 0; i < m_Ps.size(); ++i)
307  tN[i] = DensityId(i);
308 
309  // Densities
310 
311  int NN = m_densities.size();
312 
313  MatrixXd densMatrix(NN, NN);
314  VectorXd solVector(NN), xVector(NN);
315 
316  for (int i = 0; i < NN; ++i)
317  for (int j = 0; j < NN; ++j) {
318  densMatrix(i, j) = m_Virial[i][j] * tN[i];
319  if (i == j) densMatrix(i, j) += 1.;
320  }
321 
322  PartialPivLU<MatrixXd> decomp(densMatrix);
323 
324  for (int i = 0; i < NN; ++i) xVector[i] = 0.;
325  for (int i = 0; i < NN; ++i) {
326  xVector[i] = tN[i];//m_Ps[i] / m_Parameters.T;
327  //solVector = lu.Solve(xVector, ok);
328  solVector = decomp.solve(xVector);
329  //if (ok) {
330  if (1) {
331  //if (decomp.info()==Eigen::Success) {
332  m_densities[i] = 0.;
333  for (int j = 0; j < NN; ++j)
334  m_densities[i] += solVector[j];
335  }
336  else {
337  cout << "**ERROR** Could not recover m_densities from partial pressures!\n";
338  return;
339  }
340  xVector[i] = 0.;
341  }
342 
343  std::vector<double> fEntropyP(m_densities.size());
344  for (int i = 0; i < NN; ++i) {
345  double dMu = 0.;
346  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) dMu += -m_Virial[i][j] * m_Ps[j];
347  xVector[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EntropyDensity, m_UseWidth, m_Chem[i] + dMu);
348  }
349 
350  solVector = decomp.solve(xVector);
351 
352  //if (ok) {
353  if (1) {
354  //if (decomp.info()==Eigen::Success) {
356  for (int i = 0; i < NN; ++i)
357  m_TotalEntropyDensity += solVector[i];
358  }
359  else {
360  cout << "**ERROR** Could not recover m_densities from partial pressures!\n";
361  return;
362  }
363 
364  // Decays
365 
367 
368  m_Calculated = true;
369  }
370 
372  m_Ps.resize(m_TPS->Particles().size());
373  for (size_t i = 0; i < m_Ps.size(); ++i)
374  m_Ps[i] = 0.;
375  SolveDiagonal();
376  vector<double> Pstmp = m_Ps;
377  int iter = 0;
378  double maxdiff = 0.;
379  for (iter = 0; iter < 1000; ++iter)
380  {
381  maxdiff = 0.;
382  for (size_t i = 0; i < m_Ps.size(); ++i) {
383  Pstmp[i] = Pressure(i);
384  maxdiff = max(maxdiff, fabs((Pstmp[i] - m_Ps[i]) / Pstmp[i]));
385  }
386  m_Ps = Pstmp;
387  //cout << iter << "\t" << maxdiff << "\n";
388  if (maxdiff < 1.e-10) break;
389  }
390  if (iter == 1000) cout << iter << "\t" << maxdiff << "\n";
391  m_Pressure = 0.;
392  for (size_t i = 0; i < m_Ps.size(); ++i)
393  m_Pressure += m_Ps[i];
394  }
395 
397  // Pressure
399 
400  int NN = m_densities.size();
401  vector<double> tN(NN);
402  for (int i = 0; i < NN; ++i) tN[i] = DensityId(i);
403 
404  MatrixXd densMatrix(NN, NN);
405  for (int i = 0; i < NN; ++i)
406  for (int j = 0; j < NN; ++j) {
407  densMatrix(i, j) = m_Virial[j][i] * tN[i];
408  if (i == j) densMatrix(i, j) += 1.;
409  }
410  //densMatrix.SetMatrixArray(matr.GetArray());
411 
412  VectorXd solVector(NN), xVector(NN);
413  for (int i = 0; i < NN; ++i) xVector[i] = tN[i];
414 
415  PartialPivLU<MatrixXd> decomp(densMatrix);
416 
417  solVector = decomp.solve(xVector);
418 
419  if (1) {
420  //if (decomp.info()==Eigen::Success) {
421  for (int i = 0; i < NN; ++i)
422  m_densities[i] = solVector[i];
423  }
424  else {
425  cout << "**ERROR** Could not recover m_densities from partial pressures!\n";
426  return;
427  }
428 
429  // Entropy
430  for (int i = 0; i < NN; ++i)
431  for (int j = 0; j < NN; ++j) {
432  densMatrix(i, j) = m_Virial[i][j] * tN[i];
433  if (i == j) densMatrix(i, j) += 1.;
434  }
435 
436  std::vector<double> fEntropyP(m_densities.size());
437  for (int i = 0; i < NN; ++i) {
438  double dMu = 0.;
439  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) dMu += -m_Virial[i][j] * m_Ps[j];
440  xVector[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EntropyDensity, m_UseWidth, m_Chem[i] + dMu);
441  }
442 
443  decomp = PartialPivLU<MatrixXd>(densMatrix);
444  solVector = decomp.solve(xVector);
445 
446  if (1) {
447  //if (decomp.info()==Eigen::Success) {
449  for (int i = 0; i < NN; ++i)
450  m_TotalEntropyDensity += solVector[i];
451  }
452  else {
453  cout << "Could not recover entropy m_densities from partial pressures!\n";
454  }
455 
456  m_Calculated = true;
457  }
458 
460  int NN = m_densities.size();
461  vector<double> tN(NN), tW(NN);
462  for (int i = 0; i < NN; ++i) tN[i] = DensityId(i);
463  for (int i = 0; i < NN; ++i) tW[i] = ScaledVarianceId(i);
464  MatrixXd densMatrix(NN, NN);
465  VectorXd solVector(NN), xVector(NN), xVector2(NN);
466 
467  for (int i = 0; i < NN; ++i)
468  for (int j = 0; j < NN; ++j) {
469  densMatrix(i, j) = m_Virial[i][j] * tN[i];
470  if (i == j) densMatrix(i, j) += 1.;
471  }
472 
473  PartialPivLU<MatrixXd> decomp(densMatrix);
474 
475  vector< vector<double> > ders, coefs;
476 
477  ders.resize(NN);
478  coefs.resize(NN);
479 
480  for (int i = 0; i < NN; ++i) {
481  ders[i].resize(NN);
482  coefs[i].resize(NN);
483  }
484 
485  for (int i = 0; i < NN; ++i) xVector[i] = 0.;
486  for (int i = 0; i < NN; ++i) {
487  xVector[i] = tN[i];
488  solVector = decomp.solve(xVector);
489  if (1) {
490  //if (decomp.info()==Eigen::Success) {
491  for (int j = 0; j < NN; ++j) {
492  ders[j][i] = solVector[j];
493  }
494 
495  for (int l = 0; l < NN; ++l) {
496  coefs[l][i] = 0.;
497  for (int k = 0; k < NN; ++k) {
498  coefs[l][i] += -m_Virial[l][k] * ders[k][i];
499  }
500  if (l == i) coefs[l][i] += 1.;
501  }
502  }
503  else {
504  cout << "**WARNING** Could not recover fluctuations!\n";
505  }
506  xVector[i] = 0.;
507  }
508 
509 
510  m_PrimCorrel.resize(NN);
511  for (int i = 0; i < NN; ++i) m_PrimCorrel[i].resize(NN);
513 
514  for (int i = 0; i < NN; ++i)
515  for (int j = i; j < NN; ++j) {
516  for (int l = 0; l < NN; ++l)
517  xVector[l] = tN[l] / m_Parameters.T * tW[l] * coefs[l][i] * coefs[l][j];
518  solVector = decomp.solve(xVector);
519  if (1) {
520  //if (decomp.info()==Eigen::Success) {
521  m_PrimCorrel[i][j] = 0.;
522  for (int k = 0; k < NN; ++k) {
523  m_PrimCorrel[i][j] += solVector[k];
524  }
525  m_PrimCorrel[j][i] = m_PrimCorrel[i][j];
526  }
527  else {
528  cout << "**WARNING** Could not recover fluctuations!\n";
529  }
530  }
531 
532  //cout << "Primaries solved!\n";
533 
534  for (int i = 0; i < NN; ++i) {
535  m_wprim[i] = m_PrimCorrel[i][i];
536  if (m_densities[i] > 0.) m_wprim[i] *= m_Parameters.T / m_densities[i];
537  else m_wprim[i] = 1.;
538  }
539 
540 
541  }
542 
543  // TODO include correlations
550 
552 
553  for (size_t i = 0; i < m_wprim.size(); ++i) {
554  m_skewprim[i] = 1.;
555  m_kurtprim[i] = 1.;
556  m_skewtot[i] = 1.;
557  m_kurttot[i] = 1.;
558  }
559  }
560 
561  std::vector<double> ThermalModelEVCrossterms::CalculateChargeFluctuations(const std::vector<double>& chgs, int order)
562  {
563  vector<double> ret(order + 1, 0.);
564 
565  // chi1
566  for (size_t i = 0; i < m_densities.size(); ++i)
567  ret[0] += chgs[i] * m_densities[i];
568 
569  ret[0] /= pow(m_Parameters.T * xMath::GeVtoifm(), 3);
570 
571  if (order < 2) return ret;
572  // Preparing matrix for system of linear equations
573  int NN = m_densities.size();
574 
575  vector<double> MuStar(NN, 0.);
576  for (int i = 0; i < NN; ++i) {
577  MuStar[i] = m_Chem[i] + MuShift(i);
578  }
579 
580  MatrixXd densMatrix(2 * NN, 2 * NN);
581  VectorXd solVector(2 * NN), xVector(2 * NN);
582 
583  vector<double> DensitiesId(m_densities.size()), chi2id(m_densities.size());
584  for (int i = 0; i < NN; ++i) {
585  DensitiesId[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, MuStar[i]);
586  chi2id[i] = m_TPS->Particles()[i].chi(2, m_Parameters, m_UseWidth, MuStar[i]);
587  }
588 
589  for (int i = 0; i < NN; ++i)
590  for (int j = 0; j < NN; ++j) {
591  densMatrix(i, j) = m_Virial[j][i] * DensitiesId[i];
592  if (i == j) densMatrix(i, j) += 1.;
593  }
594 
595  for (int i = 0; i < NN; ++i)
596  for (int j = 0; j < NN; ++j)
597  densMatrix(i, NN + j) = 0.;
598 
599  for (int i = 0; i < NN; ++i) {
600  densMatrix(i, NN + i) = 0.;
601  for (int k = 0; k < NN; ++k) {
602  densMatrix(i, NN + i) += m_Virial[k][i] * m_densities[k];
603  }
604  densMatrix(i, NN + i) = (densMatrix(i, NN + i) - 1.) * chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T;
605  }
606 
607  for (int i = 0; i < NN; ++i)
608  for (int j = 0; j < NN; ++j) {
609  densMatrix(NN + i, NN + j) = m_Virial[i][j] * DensitiesId[j];
610  if (i == j) densMatrix(NN + i, NN + j) += 1.;
611  }
612 
613 
614  PartialPivLU<MatrixXd> decomp(densMatrix);
615 
616  // chi2
617  vector<double> dni(NN, 0.), dmus(NN, 0.);
618 
619  for (int i = 0; i < NN; ++i) {
620  xVector[i] = 0.;
621  xVector[NN + i] = chgs[i];
622  }
623 
624  solVector = decomp.solve(xVector);
625 
626  for (int i = 0; i < NN; ++i) {
627  dni[i] = solVector[i];
628  dmus[i] = solVector[NN + i];
629  }
630 
631  for (int i = 0; i < NN; ++i)
632  ret[1] += chgs[i] * dni[i];
633 
634  ret[1] /= pow(m_Parameters.T, 2) * pow(xMath::GeVtoifm(), 3);
635 
636  if (order < 3) return ret;
637  // chi3
638  vector<double> d2ni(NN, 0.), d2mus(NN, 0.);
639 
640  vector<double> chi3id(m_densities.size());
641  for (int i = 0; i < NN; ++i)
642  chi3id[i] = m_TPS->Particles()[i].chi(3, m_Parameters, m_UseWidth, MuStar[i]);
643 
644  for (int i = 0; i < NN; ++i) {
645  xVector[i] = 0.;
646 
647  double tmp = 0.;
648  for (int j = 0; j < NN; ++j) tmp += m_Virial[j][i] * dni[j];
649  tmp = -2. * tmp * chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * dmus[i];
650  xVector[i] += tmp;
651 
652  tmp = 0.;
653  for (int j = 0; j < NN; ++j) tmp += m_Virial[j][i] * m_densities[j];
654  tmp = -(tmp - 1.) * chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * dmus[i] * dmus[i];
655  xVector[i] += tmp;
656  }
657  for (int i = 0; i < NN; ++i) {
658  xVector[NN + i] = 0.;
659 
660  double tmp = 0.;
661  for (int j = 0; j < NN; ++j) tmp += -m_Virial[i][j] * dmus[j] * chi2id[j] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * dmus[j];
662 
663  xVector[NN + i] = tmp;
664  }
665 
666  solVector = decomp.solve(xVector);
667 
668  for (int i = 0; i < NN; ++i) {
669  d2ni[i] = solVector[i];
670  d2mus[i] = solVector[NN + i];
671  }
672 
673  for (int i = 0; i < NN; ++i)
674  ret[2] += chgs[i] * d2ni[i];
675 
676  ret[2] /= m_Parameters.T * pow(xMath::GeVtoifm(), 3);
677 
678 
679  if (order < 4) return ret;
680 
681  // chi4
682  vector<double> d3ni(NN, 0.), d3mus(NN, 0.);
683 
684  vector<double> chi4id(m_densities.size());
685  for (int i = 0; i < NN; ++i)
686  chi4id[i] = m_TPS->Particles()[i].chi(4, m_Parameters, m_UseWidth, MuStar[i]);
687 
688  vector<double> dnis(NN, 0.);
689  for (int i = 0; i < NN; ++i) {
690  dnis[i] = chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * dmus[i];
691  }
692 
693  vector<double> d2nis(NN, 0.);
694  for (int i = 0; i < NN; ++i) {
695  d2nis[i] = chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * dmus[i] * dmus[i] +
696  chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * d2mus[i];
697  }
698 
699  for (int i = 0; i < NN; ++i) {
700  xVector[i] = 0.;
701 
702  double tmp = 0.;
703  for (int j = 0; j < NN; ++j) tmp += m_Virial[j][i] * dni[j];
704  tmp = -3. * tmp * d2nis[i];
705  xVector[i] += tmp;
706 
707  tmp = 0.;
708  for (int j = 0; j < NN; ++j) tmp += m_Virial[j][i] * d2ni[j];
709  tmp = -3. * tmp * dnis[i];
710  xVector[i] += tmp;
711 
712  double tmps = 0.;
713  for (int j = 0; j < NN; ++j) tmps += m_Virial[j][i] * m_densities[j];
714 
715  tmp = -(tmps - 1.) * chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * d2mus[i] * 3. * dmus[i];
716  xVector[i] += tmp;
717 
718  tmp = -(tmps - 1.) * chi4id[i] * pow(xMath::GeVtoifm(), 3) * dmus[i] * dmus[i] * dmus[i];
719  xVector[i] += tmp;
720  }
721  for (int i = 0; i < NN; ++i) {
722  xVector[NN + i] = 0.;
723 
724  double tmp = 0.;
725  for (int j = 0; j < NN; ++j) tmp += -2. * m_Virial[i][j] * d2mus[j] * dnis[j];
726  xVector[NN + i] += tmp;
727 
728  tmp = 0.;
729  for (int j = 0; j < NN; ++j) tmp += -m_Virial[i][j] * dmus[j] * d2nis[j];
730  xVector[NN + i] += tmp;
731  }
732 
733  solVector = decomp.solve(xVector);
734 
735  for (int i = 0; i < NN; ++i) {
736  d3ni[i] = solVector[i];
737  d3mus[i] = solVector[NN + i];
738  }
739 
740  for (int i = 0; i < NN; ++i)
741  ret[3] += chgs[i] * d3ni[i];
742 
743  ret[3] /= pow(xMath::GeVtoifm(), 3);
744 
745  return ret;
746  }
747 
749  double ret = 0.;
751  ret += -CalculatePressure();
752  for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
753  ret += m_Chem[i] * m_densities[i];
754  return ret;
755  }
756 
759  return m_TotalEntropyDensity;
760  }
761 
764  return m_Pressure;
765  }
766 
767 
769  {
770  if (id >= 0. && id < static_cast<int>(m_Virial.size())) {
771  double dMu = 0.;
772  for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
773  dMu += -m_Virial[id][j] * m_Ps[j];
774  return dMu;
775  }
776  else
777  return 0.0;
778  }
779 
780  std::vector<double> ThermalModelEVCrossterms::BroydenEquationsCRS::Equations(const std::vector<double>& x)
781  {
782  std::vector<double> ret(m_N);
783  for (size_t i = 0; i < x.size(); ++i)
784  ret[i] = x[i] - m_THM->Pressure(i, x);
785  return ret;
786  }
787 
788  std::vector<double> ThermalModelEVCrossterms::BroydenJacobianCRS::Jacobian(const std::vector<double>& x)
789  {
790  int N = x.size();
791 
792  vector<double> tN(N);
793  for (int i = 0; i < N; ++i) {
794  tN[i] = m_THM->DensityId(i, x);
795  }
796 
797  vector<double> ret(N*N, 0.);
798  for (int i = 0; i < N; ++i) {
799  for (int j = 0; j < N; ++j) {
800  if (i == j)
801  ret[i*N + j] += 1.;
802  ret[i*N + j] += m_THM->VirialCoefficient(i, j) * tN[i];
803  }
804  }
805 
806  return ret;
807  }
808 
809  bool ThermalModelEVCrossterms::BroydenSolutionCriteriumCRS::IsSolved(const std::vector<double>& x, const std::vector<double>& f, const std::vector<double>& /*xdelta*/) const
810  {
811  double maxdiff = 0.;
812  for (size_t i = 0; i < x.size(); ++i) {
813  maxdiff = std::max(maxdiff, fabs(f[i]) / x[i]);
814  }
815  return (maxdiff < m_MaximumError);
816  }
817 
818  std::vector<double> ThermalModelEVCrossterms::BroydenEquationsCRSDEV::Equations(const std::vector<double>& x)
819  {
820  std::vector<double> ret(1);
821  ret[0] = x[0] - m_THM->PressureDiagonalTotal(x[0]);
822  return ret;
823  }
824 } // namespace thermalfist
Abstract base class for an HRG model implementation.
virtual void ReadInteractionParameters(const std::string &filename)
Reads the QvdW interaction parameters from a file.
double ScaledVarianceId(int ind)
Calculate the ideal gas scaled variance of particle species i number fluctuations for the given value...
virtual void CalculateTwoParticleFluctuationsDecays()
Computes particle number correlations and fluctuations for all final-state particles which are marked...
virtual std::vector< double > CalculateChargeFluctuations(const std::vector< double > &chgs, int order=4)
Calculates fluctuations (diagonal susceptibilities) of an arbitrary "conserved" charge.
std::vector< std::string > split(const std::string &s, char delim)
std::vector< double > m_Chem
Class implementing the Broyden method to solve a system of non-linear equations.
Definition: Broyden.h:131
double GeVtoifm()
A constant to transform GeV into fm .
Definition: xMath.h:27
std::vector< double > m_kurttot
double VirialCoefficient(int i, int j) const
Excluded volume coefficient .
std::vector< double > m_wprim
const ThermalParticle & Particle(int id) const
ThermalParticle object corresponding to particle species with a provided 0-based index.
std::vector< double > m_skewprim
int PdgToId(long long pdgid)
Transforms PDG ID to a 0-based particle id number.
virtual void SolveDiagonal()
Solves the transcendental equation of the corresponding diagonal EV model.
long long PdgId() const
Particle&#39;s Particle Data Group (PDG) ID number.
Class containing the particle list.
Grand canonical ensemble.
ThermalModelParameters m_Parameters
Crossterms excluded volume model.
Structure containing all thermal parameters of the model.
int ComponentsNumber() const
Number of different particle species in the list.
void CalculateFluctuations()
Computes the fluctuation observables.
double PressureDiagonalTotal(double P)
The total pressure for the given input pressure in the diagonal model.
virtual void CalculateSusceptibilityMatrix()
Calculates the conserved charges susceptibility matrix.
Contains some extra mathematical functions used in the code.
ThermalParticleSystem * m_TPS
virtual void SolvePressure(bool resetPartials=true)
Solves the system of transcdental equations for the pressure using the Broyden&#39;s method.
int MaxIterations() const
Definition: Broyden.h:234
virtual void CalculateProxySusceptibilityMatrix()
Calculates the susceptibility matrix of conserved charges proxies.
virtual void WriteInteractionParameters(const std::string &filename)
Write the QvdW interaction parameters to a file.
virtual std::vector< double > Solve(const std::vector< double > &x0, BroydenSolutionCriterium *solcrit=NULL, int max_iterations=MAX_ITERS)
Definition: Broyden.cpp:77
Sub-class where it is determined whether the required accuracy is achieved in the Broyden&#39;s method...
Definition: Broyden.h:144
double brr(double r1, double r2)
Computes the symmetric 2nd virial coefficient of the classical hard spheres equation of state from t...
std::vector< double > m_kurtprim
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
virtual ~ThermalModelEVCrossterms(void)
Destroy the ThermalModelEVCrossterms object.
std::vector< std::vector< double > > m_TotalCorrel
ThermalModelInteraction m_InteractionModel
virtual void ValidateCalculation()
Checks whether issues have occured during the calculation of particle densities in the CalculateDensi...
Contains some functions do deal with excluded volumes.
double MaxDifference() const
Definition: Broyden.h:239
void SetDx(double dx)
Set the finite variable difference value used for calculating the Jacobian numerically.
Definition: Broyden.h:114
void SetVirial(int i, int j, double b)
Set the excluded volume coefficient .
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
std::vector< double > m_densities
Class which implements calculation of the Jacobian needed for the Broyden&#39;s method.
Definition: Broyden.h:76
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
std::vector< std::vector< double > > m_PrimCorrel
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 double MuShift(int i) const
The shift in the chemical potential of particle species i due to the excluded volume interactions...
ThermalModelEnsemble m_Ensemble
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 DensityId(int i, const std::vector< double > &pstars=std::vector< double >())
Calculate the ideal gas density of particle species i for the given values of partial pressures...
void SetRadius(double rad)
Set the same excluded volume radius parameter for all species.
double PartialPressureDiagonal(int i, double P)
The "partial pressure" of hadron species i for the given total pressure in the diagonal model...
double Pressure()
System pressure (GeV fm )
The main namespace where all classes and functions of the Thermal-FIST library reside.
virtual void CalculatePrimordialDensities()
Calculates the primordial densities of all species.
std::vector< std::vector< double > > m_Virial
ThermalParticleSystem * TPS()
virtual double CalculatePressure()
Implementation of the equation of state functions.
int Iterations() const
Definition: Broyden.h:229
void CalculateTwoParticleCorrelations()
Computes the fluctuations and correlations of the primordial particle numbers.