Thermal-FIST 1.5
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
ThermalModelVDWCanonicalStrangeness.cpp
Go to the documentation of this file.
1/*
2 * Thermal-FIST package
3 *
4 * Copyright (c) 2018-2019 Volodymyr Vovchenko
5 *
6 * GNU General Public License (GPLv3 or later)
7 */
9
10#include <iostream>
11#include <iomanip>
12#include <fstream>
13#include <sstream>
14#include <cassert>
15#include <stdexcept>
16
17#include "HRGBase/xMath.h"
19
20using namespace std;
21
22namespace thermalfist {
23
26 {
27 m_modelVDW = NULL;
28 m_MuStar.resize(m_densities.size());
29 m_Virial.resize(m_densities.size(), vector<double>(m_densities.size(), 0.));
31 m_TAG = "ThermalModelVDWCanonicalStrangeness";
32
33 m_Ensemble = SCE;
34 m_InteractionModel = QvdW;
35 }
36
41
43 if (m_modelVDW == NULL)
45
46 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
47 m_densitiesGCE[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, m_MuStar[i]);
48 }
49
50 m_GCECalculated = true;
51 }
52
54 if (m_modelVDW == NULL)
56
58 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
59 m_energydensitiesGCE[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EnergyDensity, m_UseWidth, m_MuStar[i]);
60 }
61 }
62
64 {
65 if (m_modelVDW == NULL)
67
68 m_pressuresGCE.resize(m_densitiesGCE.size());
69 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
70 m_pressuresGCE[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_MuStar[i]);
71 }
72 }
73
74 void ThermalModelVDWCanonicalStrangeness::CalculateSums(const std::vector<double>& Vcs)
75 {
76 if (!m_GCECalculated)
78
79 m_Zsum.resize(m_StrVals.size());
80
81 m_partialS.resize(m_StrVals.size());
82 vector<double> xi(3, 0.), yi(3, 0.);
83
84 for (size_t i = 0; i < m_StrVals.size(); ++i) {
85 m_partialS[i] = 0.;
86 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
87 if (m_StrVals[i] == m_TPS->Particles()[j].Strangeness())
88 m_partialS[i] += m_densitiesGCE[j] * Vcs[j];
89 }
90
91 for (int i = 0; i < 3; ++i) {
92 xi[i] = 2. * sqrt(m_partialS[m_StrMap[i + 1]] * m_partialS[m_StrMap[-(i + 1)]]);
93 yi[i] = sqrt(m_partialS[m_StrMap[i + 1]] / m_partialS[m_StrMap[-(i + 1)]]);
94 }
95
96 // TODO: Choose iters dynamically based on total strangeness
97 int iters = 20;
98
99 for (unsigned int i = 0; i < m_StrVals.size(); ++i) {
100 double res = 0.;
101
102 for (int m = -iters; m <= iters; ++m)
103 for (int n = -iters; n <= iters; ++n) {
104 double tmp = xMath::BesselI(abs(3 * m + 2 * n - m_StrVals[i]), xi[0]) *
105 xMath::BesselI(abs(n), xi[1]) *
106 xMath::BesselI(abs(m), xi[2]) *
107 pow(yi[0], m_StrVals[i] - 3 * m - 2 * n) *
108 pow(yi[1], n) *
109 pow(yi[2], m);
110 if (tmp != tmp) continue;
111 res += tmp;
112 }
113 m_Zsum[i] = res;
114 }
115 }
116
117
119 assert(m_IGFExtraConfig.MagneticField.B == 0.); // No magnetic field supported currently
120
121 m_FluctuationsCalculated = false;
122
123 m_energydensitiesGCE.resize(0);
124 m_pressuresGCE.resize(0);
125
127
129
130 std::vector<double> Vcs(m_TPS->Particles().size(), 0.);
131 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
132 Vcs[i] = m_Parameters.SVc * m_Suppression[i];
133
134 CalculateSums(Vcs);
135
136 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
137 if (m_StrMap.count(-m_TPS->Particles()[i].Strangeness()))
138 m_densities[i] = m_Suppression[i] * (m_Zsum[m_StrMap[-m_TPS->Particles()[i].Strangeness()]] / m_Zsum[m_StrMap[0]]) * m_densitiesGCE[i];
139 }
140
141 double tP = CalculatePressure();
142 //printf("VDW-SCE calculation: The following parameter must be much smaller than unity. Otherwise we are in trouble...\n");
143 printf("%s%lf\n", "PS/P = ", (tP - m_PNS) / tP);
144
146
147 m_Calculated = true;
148 m_LastCalculationSuccessFlag = true;
149 }
150
151
152
154 double ret = 0.;
155
156 if (!m_Calculated)
158
159 if (m_energydensitiesGCE.size() == 0)
161
162 ret += m_modelVDW->CalculateEnergyDensity();
163
164 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
165 if (m_TPS->Particles()[i].Strangeness() != 0)
166 if (m_StrMap.count(-m_TPS->Particles()[i].Strangeness()))
167 ret += m_Suppression[i] * (m_Zsum[m_StrMap[-m_TPS->Particles()[i].Strangeness()]] / m_Zsum[m_StrMap[0]]) * m_energydensitiesGCE[i];
168 return ret;
169 }
170
171
173 double ret = 0.;
174
175 if (m_energydensitiesGCE.size() == 0)
177
178 ret += m_modelVDW->CalculateEntropyDensity();
179
180 ret += log(m_Zsum[m_StrMap[0]]) / m_Parameters.SVc;
181
182 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
183 if (m_TPS->Particles()[i].Strangeness() != 0)
184 if (m_StrMap.count(-m_TPS->Particles()[i].Strangeness()))
185 ret += m_Suppression[i] * (m_Zsum[m_StrMap[-m_TPS->Particles()[i].Strangeness()]] / m_Zsum[m_StrMap[0]]) * ((m_energydensitiesGCE[i] - (m_MuStar[i]) * m_densitiesGCE[i]) / m_Parameters.T);
186
187 return ret;
188 }
189
190
192 double ret = 0.;
193 if (m_pressuresGCE.size() == 0)
195
196 ret += m_modelVDW->CalculatePressure();
197
198 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
199 if (m_TPS->Particles()[i].Strangeness() != 0)
200 if (m_StrMap.count(-m_TPS->Particles()[i].Strangeness()))
201 ret += (m_Zsum[m_StrMap[-m_TPS->Particles()[i].Strangeness()]] / m_Zsum[m_StrMap[0]]) * m_pressuresGCE[i];
202 return ret;
203 }
204
206 {
207 if (id >= 0. && id < static_cast<int>(m_Virial.size()))
208 return m_MuStar[id] - m_Chem[id];
209 else
210 return 0.0;
211 }
212
213
215 {
217
218 ThermalParticleSystem *TPSnew = new ThermalParticleSystem(*m_TPS);
219
220 // "Switch off" all strange particles
221 for (size_t i = 0; i < TPSnew->Particles().size(); ++i) {
222 ThermalParticle &part = TPSnew->Particle(i);
223 if (part.Strangeness() != 0)
224 part.SetDegeneracy(0.);
225 }
226
227 m_modelVDW = new ThermalModelVDWFull(TPSnew);
228 m_modelVDW->FillVirialEV(m_Virial);
229 m_modelVDW->FillAttraction(m_Attr);
230 m_modelVDW->SetUseWidth(m_UseWidth);
231 m_modelVDW->SetParameters(m_Parameters);
232 m_modelVDW->SetVolume(m_Parameters.SVc);
233 m_modelVDW->SetChemicalPotentials(m_Chem);
234
235 m_modelVDW->CalculateDensities();
236
237 std::vector<double> PidNS(m_modelVDW->Densities().size(), 0.);
238 for (size_t j = 0; j < m_modelVDW->Densities().size(); ++j) {
239 PidNS[j] = m_modelVDW->TPS()->Particles()[j].Density(m_modelVDW->Parameters(), IdealGasFunctions::Pressure, m_modelVDW->UseWidth(), m_modelVDW->MuStar(j));
240 }
241
242 m_PNS = m_modelVDW->CalculatePressure();
243
244 m_Suppression.resize(TPS()->Particles().size());
245 m_MuStar.resize(TPS()->Particles().size());
246 for (size_t i = 0; i < m_Suppression.size(); ++i) {
247 m_Suppression[i] = 1.0;
248 for (size_t j = 0; j < m_modelVDW->Densities().size(); ++j) {
249 m_Suppression[i] += -m_Virial[j][i] * m_modelVDW->Densities()[j];
250 }
251
252 m_MuStar[i] = m_Chem[i];
253 for (size_t j = 0; j < m_modelVDW->Densities().size(); ++j) {
254 m_MuStar[i] += -m_Virial[i][j] * PidNS[j];
255 m_MuStar[i] += (m_Attr[i][j] + m_Attr[j][i]) * m_modelVDW->Densities()[j];
256 }
257 }
258 }
259
261 {
262 if (m_modelVDW != NULL) {
263 ThermalParticleSystem *TPSold = m_modelVDW->TPS();
264 if (TPSold != NULL)
265 delete TPSold;
266 delete m_modelVDW;
267 m_modelVDW = NULL;
268 }
269 }
270
271 void ThermalModelVDWCanonicalStrangeness::FillVirial(const std::vector<double>& ri)
272 {
273 if (ri.size() != m_TPS->Particles().size()) {
274 throw std::invalid_argument(m_TAG + "::FillVirial(const std::vector<double> & ri): size of ri does not match number of hadrons in the list");
275 }
276 m_Virial.resize(m_TPS->Particles().size());
277 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
278 m_Virial[i].resize(m_TPS->Particles().size());
279 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
280 m_Virial[i][j] = CuteHRGHelper::brr(ri[i], ri[j]);
281 }
282
283 // Correct R1=R2 and R2=0
284 std::vector< std::vector<double> > fVirialTmp = m_Virial;
285 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
286 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
287 if (i == j) m_Virial[i][j] = fVirialTmp[i][j];
288 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]);
289 }
290 }
291
292 void ThermalModelVDWCanonicalStrangeness::FillVirialEV(const std::vector< std::vector<double> > & bij)
293 {
294 if (bij.size() != m_TPS->Particles().size()) {
295 throw std::invalid_argument(m_TAG + "::FillVirialEV(const std::vector<double> & bij): size of bij does not match number of hadrons in the list");
296 }
297 m_Virial = bij;
298 }
299
300 void ThermalModelVDWCanonicalStrangeness::FillAttraction(const std::vector< std::vector<double> > & aij)
301 {
302 if (aij.size() != m_TPS->Particles().size()) {
303 throw std::invalid_argument(m_TAG + "::FillAttraction(const std::vector<double> & aij): size of aij does not match number of hadrons in the list");
304 }
305 m_Attr = aij;
306 }
307
309 {
310 m_Virial = std::vector< std::vector<double> >(m_TPS->Particles().size(), std::vector<double>(m_TPS->Particles().size(), 0.));
311 m_Attr = std::vector< std::vector<double> >(m_TPS->Particles().size(), std::vector<double>(m_TPS->Particles().size(), 0.));
312
313 ifstream fin(filename.c_str());
314 char cc[2000];
315 while (!fin.eof()) {
316 fin.getline(cc, 2000);
317 string tmp = string(cc);
318 vector<string> elems = CuteHRGHelper::split(tmp, '#');
319 if (elems.size() < 1)
320 continue;
321 istringstream iss(elems[0]);
322 int pdgid1, pdgid2;
323 double b, a;
324 if (iss >> pdgid1 >> pdgid2 >> b) {
325 if (!(iss >> a))
326 a = 0.;
327 int ind1 = m_TPS->PdgToId(pdgid1);
328 int ind2 = m_TPS->PdgToId(pdgid2);
329 if (ind1 != -1 && ind2 != -1) {
330 m_Virial[ind1][ind2] = b;
331 m_Attr[ind1][ind2] = a;
332 }
333 }
334 }
335 fin.close();
336 }
337
339 {
340 ofstream fout(filename.c_str());
341 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
342 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
343 fout << std::setw(15) << m_TPS->Particle(i).PdgId();
344 fout << std::setw(15) << m_TPS->Particle(j).PdgId();
345 fout << std::setw(15) << m_Virial[i][j];
346 fout << std::setw(15) << m_Attr[i][j];
347 fout << std::endl;
348 }
349 }
350 fout.close();
351 }
352
354 {
355 if (i < 0 || i >= static_cast<int>(m_Virial.size()) || j < 0 || j >= static_cast<int>(m_Virial.size()))
356 return 0.;
357 return m_Virial[i][j];
358 }
359
361 {
362 if (i < 0 || i >= static_cast<int>(m_Attr.size()) || j < 0 || j >= static_cast<int>(m_Attr.size()))
363 return 0.;
364 return m_Attr[i][j];
365 }
366
370
371} // namespace thermalfist
Contains some functions to deal with excluded volumes.
map< string, double > params
@ QvdW
Quantum van der Waals model.
virtual void CalculateFeeddown()
Calculates the total densities which include feeddown contributions.
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
@ SCE
Strangeness-canonical ensemble.
ThermalModelCanonicalStrangeness(ThermalParticleSystem *TPS, const ThermalModelParameters &params=ThermalModelParameters())
Construct a new ThermalModelCanonicalStrangeness object.
virtual bool IsConservedChargeCanonical(ConservedCharge::Name charge) const
virtual void WriteInteractionParameters(const std::string &filename)
Write the QvdW interaction parameters to a file.
virtual double MuShift(int id) const
The shift in the chemical potential of particle species i due to the QvdW interactions.
void FillVirial(const std::vector< double > &ri=std::vector< double >(0))
Fills the excluded volume coefficients based on the provided radii parameters for all species.
virtual void CalculateSums(const std::vector< double > &Vcs)
Calculates the necessary strangeness-canonical partition functions.
double VirialCoefficient(int i, int j) const
Excluded volume coefficient .
virtual void CalculateDensitiesGCE()
Calculates the particle densities in a grand-canonical ensemble.
virtual void CalculatePrimordialDensities()
Calculates the primordial densities of all species.
double AttractionCoefficient(int i, int j) const
QvdW mean field attraction coefficient .
virtual void CalculatePressuresGCE()
Calculates the grand-canonical pressures.
void FillVirialEV(const std::vector< std::vector< double > > &bij=std::vector< std::vector< double > >(0))
Same as FillVirial() but uses the matrix of excluded-volume coefficients as input instead of radii.
ThermalModelVDWCanonicalStrangeness(ThermalParticleSystem *TPS, const ThermalModelParameters &params=ThermalModelParameters())
Construct a new Thermal ModelEVCanonicalStrangeness object.
void FillAttraction(const std::vector< std::vector< double > > &aij=std::vector< std::vector< double > >(0))
virtual void CalculateEnergyDensitiesGCE()
Calculates the grand-canonical energy densities.
virtual void ReadInteractionParameters(const std::string &filename)
Reads the QvdW interaction parameters from a file.
virtual ~ThermalModelVDWCanonicalStrangeness(void)
Destroy the ThermalModelEVCanonicalStrangeness object.
Class containing all information about a particle specie.
int Strangeness() const
Particle's strangeness.
void SetDegeneracy(double deg)
Set particle's internal degeneracy factor.
Class containing the particle list.
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
const ThermalParticle & Particle(int id) const
ThermalParticle object corresponding to particle species with a provided 0-based index.
std::vector< std::string > split(const std::string &s, char delim)
double brr(double r1, double r2)
Computes the symmetric 2nd virial coefficient of the classical hard spheres equation of state from t...
double BesselI(int n, double x)
Integer order modified Bessel function I_n(x)
Definition xMath.cpp:192
The main namespace where all classes and functions of the Thermal-FIST library reside.
Definition CosmicEoS.h:9
ThermalModelVDW ThermalModelVDWFull
For backward compatibility.
Name
Set of all conserved charges considered.
Structure containing all thermal parameters of the model.
Contains some extra mathematical functions used in the code.