Thermal-FIST 1.5
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
Susceptibilities.cpp
Go to the documentation of this file.
1/*
2 * Thermal-FIST package
3 *
4 * Copyright (c) 2019 Volodymyr Vovchenko
5 *
6 * GNU General Public License (GPLv3 or later)
7 */
9
10#include <iostream>
11#include <sstream>
12#include <cassert>
13
14#include "HRGBase/xMath.h"
15
16
17// For time keeping
18// Windows
19#ifdef _WIN32
20#include <Windows.h>
21#else
22#include <time.h>
23#include <sys/time.h>
24#endif
25
26using namespace std;
27
28namespace thermalfist {
29
30 std::map<std::vector<int>, double> ComputeBQSSusceptibilities(ThermalModelBase *model, int order, double dmuTnum) {
31 assert(order >= 0 && order <= 4);
32
33 std::map<std::vector<int>, double> ret;
34
35 double T = model->Parameters().T;
36 double muB = model->Parameters().muB;
37 double muQ = model->Parameters().muQ;
38 double muS = model->Parameters().muS;
39
41
42 // First the scaled pressure p/T^4
43 ret[std::vector<int>{0, 0, 0}] = model->Pressure() / xMath::GeVtoifm3() / pow(T, 4);
44
45 if (order == 0)
46 return ret;
47
48 // Next the scaled densities n/T^3
49 ret[std::vector<int>{1, 0, 0}] = model->BaryonDensity() / xMath::GeVtoifm3() / pow(T, 3);
50 ret[std::vector<int>{0, 1, 0}] = model->ElectricChargeDensity() / xMath::GeVtoifm3() / pow(T, 3);
51 ret[std::vector<int>{0, 0, 1}] = model->StrangenessDensity() / xMath::GeVtoifm3() / pow(T, 3);
52
53 if (order == 1)
54 return ret;
55
56 model->CalculateFluctuations();
57
58 // Next the scaled susceptibilities
59 ret[std::vector<int>{2, 0, 0}] = model->Susc(ConservedCharge::BaryonCharge, ConservedCharge::BaryonCharge);
60 ret[std::vector<int>{1, 1, 0}] = model->Susc(ConservedCharge::BaryonCharge, ConservedCharge::ElectricCharge);
61 ret[std::vector<int>{1, 0, 1}] = model->Susc(ConservedCharge::BaryonCharge, ConservedCharge::StrangenessCharge);
62 ret[std::vector<int>{0, 2, 0}] = model->Susc(ConservedCharge::ElectricCharge, ConservedCharge::ElectricCharge);
63 ret[std::vector<int>{0, 1, 1}] = model->Susc(ConservedCharge::ElectricCharge, ConservedCharge::StrangenessCharge);
64 ret[std::vector<int>{0, 0, 2}] = model->Susc(ConservedCharge::StrangenessCharge, ConservedCharge::StrangenessCharge);
65
66 if (order == 2)
67 return ret;
68
69 // Third order and above, need to use central finite difference method
70
71 // dmuB
72 model->SetBaryonChemicalPotential(muB + dmuTnum * T);
73 auto SuscmuBp = ComputeBQSSusceptibilities(model, 2);
74 model->SetBaryonChemicalPotential(muB - dmuTnum * T);
75 auto SuscmuBm = ComputeBQSSusceptibilities(model, 2);
77
78 // dmuQ
79 model->SetElectricChemicalPotential(muQ + dmuTnum * T);
80 auto SuscmuQp = ComputeBQSSusceptibilities(model, 2);
81 model->SetElectricChemicalPotential(muQ - dmuTnum * T);
82 auto SuscmuQm = ComputeBQSSusceptibilities(model, 2);
84
85 // dmuS
86 model->SetStrangenessChemicalPotential(muS + dmuTnum * T);
87 auto SuscmuSp = ComputeBQSSusceptibilities(model, 2);
88 model->SetStrangenessChemicalPotential(muS - dmuTnum * T);
89 auto SuscmuSm = ComputeBQSSusceptibilities(model, 2);
91
92 // Iterate over all the keys and calculate the third order susceptibilities
93 for(int imuB = 0; imuB <= 3; imuB++) {
94 for(int imuQ = 0; imuQ <= 3; imuQ++) {
95 for(int imuS = 0; imuS <= 3; imuS++) {
96 if(imuB + imuQ + imuS == 3) {
97 std::vector<int> key{imuB, imuQ, imuS};
98 if (imuB > 0) {
99 std::vector<int> key2 = std::vector<int>{imuB - 1, imuQ, imuS};
100 ret[key] = (SuscmuBp[key2] - SuscmuBm[key2]) / (2 * dmuTnum);
101 } else if (imuS > 0) {
102 std::vector<int> key2 = std::vector<int>{imuB, imuQ, imuS - 1};
103 ret[key] = (SuscmuSp[key2] - SuscmuSm[key2]) / (2 * dmuTnum);
104 } else {
105 assert(imuQ > 0);
106 std::vector<int> key2 = std::vector<int>{imuB, imuQ - 1, imuS};
107 ret[key] = (SuscmuQp[key2] - SuscmuQm[key2]) / (2 * dmuTnum);
108 }
109 }
110 }
111 }
112 }
113
114 if (order == 3)
115 return ret;
116
117 // Iterate over all the keys and calculate the fourth order susceptibilities
118 for(int imuB = 0; imuB <= 4; imuB++) {
119 for(int imuQ = 0; imuQ <= 4; imuQ++) {
120 for(int imuS = 0; imuS <= 4; imuS++) {
121 if(imuB + imuQ + imuS == 4) {
122 std::vector<int> key{imuB, imuQ, imuS};
123 if (imuB > 1) {
124 std::vector<int> key2 = std::vector<int>{imuB - 2, imuQ, imuS};
125 ret[key] = (SuscmuBp[key2] - 2 * ret[key2] + SuscmuBm[key2]) / (dmuTnum * dmuTnum);
126 } else if (imuS > 1) {
127 std::vector<int> key2 = std::vector<int>{imuB, imuQ, imuS - 2};
128 ret[key] = (SuscmuSp[key2] - 2 * ret[key2] + SuscmuSm[key2]) / (dmuTnum * dmuTnum);
129 } else {
130 assert(imuQ > 1);
131 std::vector<int> key2 = std::vector<int>{imuB, imuQ - 2, imuS};
132 ret[key] = (SuscmuQp[key2] - 2 * ret[key2] + SuscmuQm[key2]) / (dmuTnum * dmuTnum);
133 }
134 }
135 }
136 }
137 }
138
139 return ret;
140 }
141
142 std::map<std::vector<int>, double> ComputeBQSSusceptibilitiesDerivativeT(ThermalModelBase *model, int order, double dmuTnum) {
143 assert(order >= 0 && order <= 4);
144
145 std::map<std::vector<int>, double> ret;
146
147 double T = model->Parameters().T;
148 double muB = model->Parameters().muB;
149 double muQ = model->Parameters().muQ;
150 double muS = model->Parameters().muS;
151
153
154 // First the T derivative of the scaled pressure p/T^4
155 // The derivative of the scaled pressure p/T^4 with respect to temperature T
156 // is given by the expression: d(p/T^4)/dT = (s/T^4) - (4*p/T^5)
157 // where s is the entropy density and p is the pressure.
158 ret[std::vector<int>{0, 0, 0}] = (model->EntropyDensity() - 4. * model->Pressure() / T) / xMath::GeVtoifm3() / pow(T, 4);
159
160 if (order == 0)
161 return ret;
162
164
165 // Next the T-derivatives of the scaled densities n/T^3
166 // d(n/T^3)/dT = (dn/dT)/T^3 - 3*n/T^4
167 ret[std::vector<int>{1, 0, 0}] = (model->ConservedChargeDensitydT(ConservedCharge::BaryonCharge) - 3. * model->BaryonDensity() / T) / xMath::GeVtoifm3() / pow(T, 3);
168 ret[std::vector<int>{0, 1, 0}] = (model->ConservedChargeDensitydT(ConservedCharge::ElectricCharge) - 3. * model->ElectricChargeDensity() / T) / xMath::GeVtoifm3() / pow(T, 3);
169 ret[std::vector<int>{0, 0, 1}] = (model->ConservedChargeDensitydT(ConservedCharge::StrangenessCharge) - 3. * model->StrangenessDensity() / T) / xMath::GeVtoifm3() / pow(T, 3);
170
171 if (order == 1)
172 return ret;
173
174 model->CalculateFluctuations();
175
176 // Next the scaled susceptibilities
177 ret[std::vector<int>{2, 0, 0}] = model->dSuscdT(ConservedCharge::BaryonCharge, ConservedCharge::BaryonCharge);
178 ret[std::vector<int>{1, 1, 0}] = model->dSuscdT(ConservedCharge::BaryonCharge, ConservedCharge::ElectricCharge);
179 ret[std::vector<int>{1, 0, 1}] = model->dSuscdT(ConservedCharge::BaryonCharge, ConservedCharge::StrangenessCharge);
180 ret[std::vector<int>{0, 2, 0}] = model->dSuscdT(ConservedCharge::ElectricCharge, ConservedCharge::ElectricCharge);
181 ret[std::vector<int>{0, 1, 1}] = model->dSuscdT(ConservedCharge::ElectricCharge, ConservedCharge::StrangenessCharge);
182 ret[std::vector<int>{0, 0, 2}] = model->dSuscdT(ConservedCharge::StrangenessCharge, ConservedCharge::StrangenessCharge);
183
184 if (order == 2)
185 return ret;
186
187 // Third order and above, need to use central finite difference method
188
189 auto Susc = ComputeBQSSusceptibilities(model, order);
190
191 // dmuB
192 model->SetBaryonChemicalPotential(muB + dmuTnum * T);
193 auto dSuscmuBp = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
194 model->SetBaryonChemicalPotential(muB - dmuTnum * T);
195 auto dSuscmuBm = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
196 model->SetBaryonChemicalPotential(muB);
197
198 // dmuQ
199 model->SetElectricChemicalPotential(muQ + dmuTnum * T);
200 auto dSuscmuQp = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
201 model->SetElectricChemicalPotential(muQ - dmuTnum * T);
202 auto dSuscmuQm = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
204
205 // dmuS
206 model->SetStrangenessChemicalPotential(muS + dmuTnum * T);
207 auto dSuscmuSp = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
208 model->SetStrangenessChemicalPotential(muS - dmuTnum * T);
209 auto dSuscmuSm = ComputeBQSSusceptibilitiesDerivativeT(model, 2);
211
212 // Iterate over all the keys and calculate the third order susceptibilities
213 for(int imuB = 0; imuB <= 3; imuB++) {
214 for(int imuQ = 0; imuQ <= 3; imuQ++) {
215 for(int imuS = 0; imuS <= 3; imuS++) {
216 if(imuB + imuQ + imuS == 3) {
217 std::vector<int> key{imuB, imuQ, imuS};
218 ret[key] = Susc[key] / T;
219 if (imuB > 0) {
220 std::vector<int> key2 = std::vector<int>{imuB - 1, imuQ, imuS};
221 ret[key] += (dSuscmuBp[key2] - dSuscmuBm[key2]) / (2 * dmuTnum);
222 } else if (imuS > 0) {
223 std::vector<int> key2 = std::vector<int>{imuB, imuQ, imuS - 1};
224 ret[key] += (dSuscmuSp[key2] - dSuscmuSm[key2]) / (2 * dmuTnum);
225 } else {
226 assert(imuQ > 0);
227 std::vector<int> key2 = std::vector<int>{imuB, imuQ - 1, imuS};
228 ret[key] += (dSuscmuQp[key2] - dSuscmuQm[key2]) / (2 * dmuTnum);
229 }
230 }
231 }
232 }
233 }
234
235 if (order == 3)
236 return ret;
237
238 // Iterate over all the keys and calculate the fourth order susceptibilities
239 for(int imuB = 0; imuB <= 4; imuB++) {
240 for(int imuQ = 0; imuQ <= 4; imuQ++) {
241 for(int imuS = 0; imuS <= 4; imuS++) {
242 if(imuB + imuQ + imuS == 4) {
243 std::vector<int> key{imuB, imuQ, imuS};
244 ret[key] = 2. * Susc[key] / T;
245 if (imuB > 1) {
246 std::vector<int> key2 = std::vector<int>{imuB - 2, imuQ, imuS};
247 ret[key] += (dSuscmuBp[key2] - 2 * ret[key2] + dSuscmuBm[key2]) / (dmuTnum * dmuTnum);
248 } else if (imuS > 1) {
249 std::vector<int> key2 = std::vector<int>{imuB, imuQ, imuS - 2};
250 ret[key] += (dSuscmuSp[key2] - 2 * ret[key2] + dSuscmuSm[key2]) / (dmuTnum * dmuTnum);
251 } else {
252 assert(imuQ > 1);
253 std::vector<int> key2 = std::vector<int>{imuB, imuQ - 2, imuS};
254 ret[key] += (dSuscmuQp[key2] - 2 * ret[key2] + dSuscmuQm[key2]) / (dmuTnum * dmuTnum);
255 }
256 }
257 }
258 }
259 }
260
261 return ret;
262 }
263
264} // namespace thermalfist
Contains some helper functions for calculating (mixed) susceptibilities.
Abstract base class for an HRG model implementation.
virtual void CalculateFluctuations()
Computes the fluctuation observables.
virtual void CalculateTemperatureDerivatives()
Computes the temperature derivatives of densities, shifted chemical potentials, and primordial hadron...
virtual void SetBaryonChemicalPotential(double muB)
Set the baryon chemical potential.
virtual void SetElectricChemicalPotential(double muQ)
Set the electric chemical potential.
virtual void CalculatePrimordialDensities()=0
Calculates the primordial densities of all species.
virtual void SetStrangenessChemicalPotential(double muS)
Set the strangeness chemical potential.
const ThermalModelParameters & Parameters() const
constexpr double GeVtoifm3()
A constant to transform GeV into fm .
Definition xMath.h:31
The main namespace where all classes and functions of the Thermal-FIST library reside.
Definition CosmicEoS.h:9
std::map< std::vector< int >, double > ComputeBQSSusceptibilitiesDerivativeT(ThermalModelBase *model, int order=4, double dmuTnum=0.001)
std::map< std::vector< int >, double > ComputeBQSSusceptibilities(ThermalModelBase *model, int order=4, double dmuTnum=0.001)
@ ElectricCharge
Electric charge.
Contains some extra mathematical functions used in the code.