Thermal-FIST 1.5
Package for hadron resonance gas model applications
Loading...
Searching...
No Matches
ThermalModelVDW.cpp
Go to the documentation of this file.
1/*
2 * Thermal-FIST package
3 *
4 * Copyright (c) 2016-2019 Volodymyr Vovchenko
5 *
6 * GNU General Public License (GPLv3 or later)
7 */
9
10#include <vector>
11#include <cmath>
12#include <iostream>
13#include <ctime>
14#include <iomanip>
15#include <fstream>
16#include <sstream>
17
18#include "HRGBase/xMath.h"
20
21#ifdef USE_OPENMP
22#include <omp.h>
23#endif
24
25
26#include <Eigen/Dense>
27
28using namespace Eigen;
29
30using namespace std;
31
32namespace thermalfist {
33
36 {
37 m_chi.resize(6);
38 for(int i=0;i<6;++i) m_chi[i].resize(3);
39 m_chiarb.resize(6);
40 m_DensitiesId.resize(m_densities.size());
41 m_MuStar.resize(m_densities.size());
42 m_Virial.resize(m_densities.size(), vector<double>(m_densities.size(),0.));
46 m_Volume = params.V;
47 m_TAG = "ThermalModelVDW";
48
49 m_Ensemble = GCE;
50 m_InteractionModel = QvdW;
51 }
52
53
57
60 for(size_t i = 0; i < m_MuStar.size(); ++i)
61 m_MuStar[i] = m_Chem[i];
62 }
63
64 void ThermalModelVDW::SetChemicalPotentials(const vector<double>& chem)
65 {
67 for (size_t i = 0; i < m_MuStar.size(); ++i)
68 m_MuStar[i] = m_Chem[i];
69 }
70
71 void ThermalModelVDW::FillVirial(const vector<double> & ri) {
72 if (ri.size() != m_TPS->Particles().size()) {
73 std::cerr << "**WARNING** " << m_TAG << "::FillVirial(const vector<double> & ri): size of ri does not match number of hadrons in the list" << std::endl;
74 return;
75 }
76 m_Virial.resize(m_TPS->Particles().size());
77 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
78 m_Virial[i].resize(m_TPS->Particles().size());
79 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j)
80 m_Virial[i][j] = CuteHRGHelper::brr(ri[i], ri[j]);
81 }
82
83 // Correct R1=R2 and R2=0
84 vector< vector<double> > fVirialTmp = m_Virial;
85 for(int i=0;i<m_TPS->ComponentsNumber();++i)
86 for(int j=0;j<m_TPS->ComponentsNumber();++j) {
87 if (i==j) m_Virial[i][j] = fVirialTmp[i][j];
88 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]);
89 }
90
91 m_VirialdT = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(),0.));
92 m_AttrdT = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
93
95 }
96
97 void ThermalModelVDW::FillVirialEV(const vector< vector<double> >& bij)
98 {
99 if (bij.size() != m_TPS->Particles().size()) {
100 std::cerr << "**WARNING** " << m_TAG << "::FillVirialEV(const vector<double> & bij): size of bij does not match number of hadrons in the list" << std::endl;
101 return;
102 }
103 m_Virial = bij;
104
106 }
107
108 void ThermalModelVDW::FillAttraction(const vector<vector<double> >& aij)
109 {
110 if (aij.size() != m_TPS->Particles().size()) {
111 std::cerr << "**WARNING** " << m_TAG << "::FillAttraction(const vector<double> & aij): size of aij does not match number of hadrons in the list" << std::endl;
112 return;
113 }
114 m_Attr = aij;
115
117 }
118
119 void ThermalModelVDW::ReadInteractionParameters(const string & filename)
120 {
121 m_Virial = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
122 m_Attr = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
123
124 ifstream fin(filename.c_str());
125 char cc[2000];
126 while (!fin.eof()) {
127 fin.getline(cc, 2000);
128 string tmp = string(cc);
129 vector<string> elems = CuteHRGHelper::split(tmp, '#');
130 if (elems.size() < 1)
131 continue;
132 istringstream iss(elems[0]);
133 long long pdgid1, pdgid2;
134 double b, a;
135 if (iss >> pdgid1 >> pdgid2 >> b) {
136 if (!(iss >> a))
137 a = 0.;
138 int ind1 = m_TPS->PdgToId(pdgid1);
139 int ind2 = m_TPS->PdgToId(pdgid2);
140 if (ind1 != -1 && ind2 != -1) {
141 m_Virial[ind1][ind2] = b;
142 m_Attr[ind1][ind2] = a;
143 }
144 }
145 }
146 fin.close();
147
149 }
150
152 {
153 ofstream fout(filename.c_str());
154 fout << "# List of the van dar Waals interaction parameters to be used in the QvdW-HRG model"
155 << std::endl;
156 fout << "# Only particle pairs with a non-zero QvdW interaction are listed here"
157 << std::endl;
158 /*fout << "#" << std::setw(14) << "pdg_i"
159 << std::setw(15) << "pdg_j"
160 << std::setw(15) << "b_{ij}[fm^3]"
161 << std::setw(20) << "a_{ij}[GeV*fm^3]"
162 << std::endl;*/
163 fout << "#" << " " << "pdg_i"
164 << " " << "pdg_j"
165 << " " << "b_{ij}[fm^3]"
166 << " " << "a_{ij}[GeV*fm^3]"
167 << std::endl;
168 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
169 for (int j = 0; j < m_TPS->ComponentsNumber(); ++j) {
170 if (m_Virial[i][j] != 0. || m_Attr[i][j] != 0.) {
171 //fout << setw(15) << m_TPS->Particle(i).PdgId();
172 //fout << setw(15) << m_TPS->Particle(j).PdgId();
173 //fout << setw(15) << m_Virial[i][j];
174 //fout << setw(20) << m_Attr[i][j];
175 //fout << endl;
176 fout << " " << m_TPS->Particle(i).PdgId();
177 fout << " " << m_TPS->Particle(j).PdgId();
178 fout << " " << m_Virial[i][j];
179 fout << " " << m_Attr[i][j];
180 fout << endl;
181 }
182 }
183 }
184 fout.close();
185 }
186
189 m_Virial = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
190 m_Attr = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
191 m_VirialdT = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
192 m_AttrdT = vector< vector<double> >(m_TPS->Particles().size(), vector<double>(m_TPS->Particles().size(), 0.));
194 }
195
196 std::vector<double> ThermalModelVDW::ComputeNp(const std::vector<double>& dmustar)
197 {
198 vector<double> ns(m_densities.size(), 0.);
199 for (size_t i = 0; i < m_densities.size(); ++i)
200 ns[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, m_Chem[i] + dmustar[m_MapTodMuStar[i]]);
201
202 return ComputeNp(dmustar, ns);
203 }
204
205 std::vector<double> ThermalModelVDW::ComputeNp(const std::vector<double>& /*dmustar*/, const std::vector<double>& ns)
206 {
207 int NN = m_densities.size();
208 int NNdmu = m_MapFromdMuStar.size();
209
210 MatrixXd densMatrix(NNdmu, NNdmu);
211 VectorXd solVector(NNdmu), xVector(NNdmu);
212
213 for (int i = 0; i < NNdmu; ++i) {
214 for (int j = 0; j < NNdmu; ++j) {
215 densMatrix(i, j) = 0.;
216 if (i == j)
217 densMatrix(i, j) += 1.;
218
219 for (size_t m = 0; m < m_dMuStarIndices[i].size(); ++m) {
220 densMatrix(i, j) += m_Virial[m_MapFromdMuStar[j]][m_dMuStarIndices[i][m]] * ns[m_dMuStarIndices[i][m]];
221 }
222 }
223 }
224
225 PartialPivLU<MatrixXd> decomp(densMatrix);
226
227 for (int kp = 0; kp < NNdmu; ++kp) {
228 xVector[kp] = 0.;
229 for (size_t m = 0; m < m_dMuStarIndices[kp].size(); ++m) {
230 xVector[kp] += ns[m_dMuStarIndices[kp][m]];
231 }
232 }
233
234
235 solVector = decomp.solve(xVector);
236
237 vector<double> ntildek(NNdmu, 0.);
238 for (int i = 0; i < NNdmu; ++i)
239 ntildek[i] = solVector[i];
240
241 vector<double> np(m_densities.size(), 0.);
242 for (int i = 0; i < NN; ++i) {
243 np[i] = 0.;
244 for (int k = 0; k < NNdmu; ++k) {
245 np[i] += m_Virial[m_MapFromdMuStar[k]][i] * solVector[k];
246 }
247 np[i] = (1. - np[i]) * ns[i];
248 }
249
250 return np;
251 }
252
254 {
255 map< vector<double>, int> MapVDW;
256
257 int NN = m_densities.size();
258
259 m_MapTodMuStar.resize(NN);
260 m_MapFromdMuStar.clear();
261 MapVDW.clear();
262 m_dMuStarIndices.clear();
263
264 int tind = 0;
265 for (int i = 0; i < NN; ++i) {
266 vector<double> VDWParam(0);
267 for (int j = 0; j < NN; ++j) {
268 VDWParam.push_back(m_Virial[i][j]);
269 }
270 for (int j = 0; j < NN; ++j) {
271 VDWParam.push_back(m_Attr[i][j] + m_Attr[j][i]);
272 }
273
274 if (MapVDW.count(VDWParam) == 0) {
275 MapVDW[VDWParam] = tind;
276 m_MapTodMuStar[i] = tind;
277 m_MapFromdMuStar.push_back(i);
278 m_dMuStarIndices.push_back(vector<int>(1, i));
279 tind++;
280 }
281 else {
282 m_MapTodMuStar[i] = MapVDW[VDWParam];
283 m_dMuStarIndices[MapVDW[VDWParam]].push_back(i);
284 }
285 }
286
288 }
289
290 vector<double> ThermalModelVDW::SearchSingleSolution(const vector<double>& muStarInit)
291 {
292 int NN = m_densities.size();
293 int NNdmu = m_MapFromdMuStar.size();
294
295 vector<double> dmuscur(NNdmu, 0.);
296 for (int i = 0; i < NNdmu; ++i)
297 dmuscur[i] = muStarInit[m_MapFromdMuStar[i]] - m_Chem[m_MapFromdMuStar[i]];
298
299 BroydenEquationsVDW eqs(this);
300 BroydenJacobianVDW jac(this);
301 Broyden broydn(&eqs, &jac);
302 BroydenSolutionCriteriumVDW crit(this);
303
304 dmuscur = broydn.Solve(dmuscur, &crit);
305
306 if (broydn.Iterations() == broydn.MaxIterations())
308 else m_LastBroydenSuccessFlag = true;
309
310 m_MaxDiff = broydn.MaxDifference();
311
312 vector<double> ret(NN);
313 for (int i = 0; i < NN; ++i)
314 ret[i] = m_Chem[i] + dmuscur[m_MapTodMuStar[i]];
315
316 return ret;
317 }
318
320 vector<double> csol(m_densities.size(), 0.);
321 double Psol = 0.;
322 bool solved = false;
323 double muBmin = m_Parameters.muB - 0.5 * xMath::mnucleon();
324 double muBmax = m_Parameters.muB + 0.5 * xMath::mnucleon();
325 double dmu = (muBmax - muBmin) / iters;
326 vector<double> curmust(m_densities.size(), 0.);
327 double maxdif = 0.;
328 for(int isol = 0; isol < iters; ++isol) {
329 double tmu = muBmin + (0.5 + isol) * dmu;
330 for(size_t j = 0; j < curmust.size(); ++j) {
331 curmust[j] = m_Chem[j] + (tmu - m_Parameters.muB) * m_Chem[j] / m_Parameters.muB;
332 if (m_TPS->Particles()[j].Statistics()==-1 && curmust[j] > m_TPS->Particles()[j].Mass())
333 curmust[j] = 0.98 * m_TPS->Particles()[j].Mass();
334 }
335
336 vector<double> sol = SearchSingleSolution(curmust);
337
338 bool fl = true;
339 for(size_t i = 0; i < sol.size(); ++i)
340 if (sol[i] != sol[i]) fl = false;
342 if (!fl) continue;
343
344 for(int i = 0; i < m_TPS->ComponentsNumber(); ++i)
345 m_DensitiesId[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, sol[i]);
346
347 int NN = m_densities.size();
348
349 MatrixXd densMatrix(NN, NN);
350 VectorXd solVector(NN), xVector(NN);
351
352 for(int i=0;i<NN;++i)
353 for(int j=0;j<NN;++j) {
354 densMatrix(i,j) = m_Virial[j][i] * m_DensitiesId[i];
355 if (i==j) densMatrix(i,j) += 1.;
356 }
357
358 PartialPivLU<MatrixXd> decomp(densMatrix);
359
360 for(int i=0;i<NN;++i)
361 xVector[i] = m_DensitiesId[i];
362 solVector = decomp.solve(xVector);
363 for(int i=0;i<NN;++i)
364 m_densities[i] = solVector[i];
365
366 double tP = 0.;
367 for(size_t i=0;i<m_densities.size();++i)
368 tP += m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, sol[i]);
369 for(size_t i=0;i<m_densities.size();++i)
370 for(size_t j=0;j<m_densities.size();++j)
371 tP += -m_Attr[i][j] * m_densities[i] * m_densities[j];
372
373 if (!solved || tP > Psol) {
374 solved = true;
375 Psol = tP;
376 csol = sol;
377 maxdif = m_MaxDiff;
378 }
379 }
381 m_MaxDiff = maxdif;
382 return csol;
383 }
384
387
388 vector<double> muStarInit = m_MuStar;
389
390 for(size_t i=0;i<muStarInit.size();++i) {
391 if (m_TPS->Particles()[i].Statistics()==-1 && muStarInit[i] > m_TPS->Particles()[i].Mass())
392 muStarInit[i] = 0.98 * m_TPS->Particles()[i].Mass();
393 }
394 m_MuStar = SearchSingleSolution(muStarInit);
395 }
396 else {
398 }
399 }
400
402 CalculatePrimordialDensitiesNew();
404 }
405
406 void ThermalModelVDW::CalculatePrimordialDensitiesOld() {
407 m_FluctuationsCalculated = false;
408
411
412 int NN = m_densities.size();
413
414 //map< vector<double>, int> m_MapVDW;
415 //{
416 // m_MapTodMuStar.resize(NN);
417 // m_MapFromdMuStar.clear();
418 // m_MapVDW.clear();
419 // m_dMuStarIndices.clear();
420
421 // int tind = 0;
422 // for (int i = 0; i < NN; ++i) {
423 // vector<double> VDWParam(0);
424 // for (int j = 0; j < NN; ++j) {
425 // VDWParam.push_back(m_Virial[i][j]);
426 // }
427 // for (int j = 0; j < NN; ++j) {
428 // VDWParam.push_back(m_Attr[i][j] + m_Attr[j][i]);
429 // }
430
431 // if (m_MapVDW.count(VDWParam) == 0) {
432 // m_MapVDW[VDWParam] = tind;
433 // m_MapTodMuStar[i] = tind;
434 // m_MapFromdMuStar.push_back(i);
435 // m_dMuStarIndices.push_back(vector<int>(1, i));
436 // tind++;
437 // }
438 // else {
439 // m_MapTodMuStar[i] = m_MapVDW[VDWParam];
440 // m_dMuStarIndices[m_MapVDW[VDWParam]].push_back(i);
441 // }
442 // }
443
444 // printf("Optimization: %d --> %d\n", NN, static_cast<int>(m_MapFromdMuStar.size()));
445 //}
446
447 clock_t tbeg = clock();
448
449 {
450
451 vector<double> muStarInit = m_MuStar;
452
453 for (size_t i = 0; i<muStarInit.size(); ++i) {
454 if (m_TPS->Particles()[i].Statistics() == -1 && muStarInit[i] > m_TPS->Particles()[i].Mass())
455 muStarInit[i] = 0.98 * m_TPS->Particles()[i].Mass();
456 }
457
458
459 m_MuStar = SearchSingleSolution(muStarInit);
460 }
461
462
463 printf("Solution time = %lf ms\n", (clock() - tbeg) / (double)(CLOCKS_PER_SEC) * 1.e3);
464
465 tbeg = clock();
466
467 for(int i=0;i<m_TPS->ComponentsNumber();++i)
468 m_DensitiesId[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, m_MuStar[i]);
469
470 MatrixXd densMatrix(NN, NN);
471 VectorXd solVector(NN), xVector(NN);
472
473 for(int i=0;i<NN;++i)
474 for(int j=0;j<NN;++j) {
475 densMatrix(i,j) = m_Virial[j][i] * m_DensitiesId[i];
476 if (i==j) densMatrix(i,j) += 1.;
477 }
478
479 PartialPivLU<MatrixXd> decomp(densMatrix);
480
481 for(int i=0;i<NN;++i) xVector[i] = m_DensitiesId[i];
482 solVector = decomp.solve(xVector);
483 for(int i=0;i<NN;++i) m_densities[i] = solVector[i];
484
485 // TODO: Scalar density properly
486 for(int i=0;i<NN;++i) xVector[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ScalarDensity, m_UseWidth, m_MuStar[i]);
487 solVector = decomp.solve(xVector);
488 m_scaldens.resize(m_densities.size());
489 for(int i=0;i<NN;++i) m_scaldens[i] = solVector[i];
490
491
492 tbeg = clock();
493
494 m_Calculated = true;
495 }
496
497 void ThermalModelVDW::CalculatePrimordialDensitiesNew() {
498 m_FluctuationsCalculated = false;
499
502
503 int NN = m_densities.size();
504
505 clock_t tbeg = clock();
506
508
509 tbeg = clock();
510
511 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i)
512 m_DensitiesId[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, m_MuStar[i]);
513
514
515 int NNdmu = m_MapFromdMuStar.size();
516
517 MatrixXd densMatrix(NNdmu, NNdmu);
518 VectorXd solVector(NNdmu), xVector(NNdmu);
519
520 for (int i = 0; i < NNdmu; ++i) {
521 for (int j = 0; j < NNdmu; ++j) {
522 densMatrix(i, j) = 0.;
523 if (i == j)
524 densMatrix(i, j) += 1.;
525
526 for (size_t m = 0; m < m_dMuStarIndices[i].size(); ++m) {
527 densMatrix(i, j) += m_Virial[m_MapFromdMuStar[j]][m_dMuStarIndices[i][m]] * m_DensitiesId[m_dMuStarIndices[i][m]];
528 }
529 }
530 }
531
532 PartialPivLU<MatrixXd> decomp(densMatrix);
533
534 for (int kp = 0; kp < NNdmu; ++kp) {
535 xVector[kp] = 0.;
536 for (size_t m = 0; m < m_dMuStarIndices[kp].size(); ++m) {
537 xVector[kp] += m_DensitiesId[m_dMuStarIndices[kp][m]];
538 }
539 }
540
541 solVector = decomp.solve(xVector);
542
543 vector<double> ntildek(NNdmu, 0.);
544 for (int i = 0; i < NNdmu; ++i)
545 ntildek[i] = solVector[i];
546
547 //vector<double> np(m_densities.size(), 0.);
548 for (int i = 0; i < NN; ++i) {
549 m_densities[i] = 0.;
550 for (int k = 0; k < NNdmu; ++k) {
551 m_densities[i] += m_Virial[m_MapFromdMuStar[k]][i] * solVector[k];
552 }
553 m_densities[i] = (1. - m_densities[i]) * m_DensitiesId[i];
554 }
555
556 // TODO: Scalar density properly
557 m_scaldens = m_densities;
558
559 m_Calculated = true;
560 }
561
562 vector<double> ThermalModelVDW::CalculateChargeFluctuations(const vector<double> &chgs, int order) {
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 MatrixXd densMatrix(2*NN, 2*NN);
575 VectorXd solVector(2*NN), xVector(2*NN);
576
577 vector<double> chi2id(m_densities.size());
578 for(int i=0;i<NN;++i)
579 chi2id[i] = m_TPS->Particles()[i].chi(2, m_Parameters, m_UseWidth, m_MuStar[i]);
580
581 for(int i=0;i<NN;++i)
582 for(int j=0;j<NN;++j) {
583 densMatrix(i,j) = m_Virial[j][i] * m_DensitiesId[i];
584 if (i==j) densMatrix(i,j) += 1.;
585 }
586
587 for(int i=0;i<NN;++i)
588 for(int j=0;j<NN;++j)
589 densMatrix(i,NN+j) = 0.;
590
591 for(int i=0;i<NN;++i) {
592 densMatrix(i,NN+i) = 0.;
593 for(int k=0;k<NN;++k) {
594 densMatrix(i,NN+i) += m_Virial[k][i] * m_densities[k];
595 }
596 densMatrix(i,NN+i) = (densMatrix(i,NN+i) - 1.) * chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T;
597 }
598
599 for(int i=0;i<NN;++i)
600 for(int j=0;j<NN;++j) {
601 densMatrix(NN+i,j) = -(m_Attr[i][j] + m_Attr[j][i]);
602 }
603
604 for(int i=0;i<NN;++i)
605 for(int j=0;j<NN;++j) {
606 densMatrix(NN+i,NN+j) = m_Virial[i][j] * m_DensitiesId[j];
607 if (i==j) densMatrix(NN+i,NN+j) += 1.;
608 }
609
610
611 PartialPivLU<MatrixXd> decomp(densMatrix);
612
613 // chi2
614 vector<double> dni(NN, 0.), dmus(NN, 0.);
615
616 for(int i=0;i<NN;++i) {
617 xVector[i] = 0.;
618 xVector[NN+i] = chgs[i];
619 }
620
621 solVector = decomp.solve(xVector);
622
623 for(int i=0;i<NN;++i) {
624 dni[i] = solVector[i];
625 dmus[i] = solVector[NN+i];
626 }
627
628 for(int i=0;i<NN;++i)
629 ret[1] += chgs[i] * dni[i];
630
631 ret[1] /= pow(m_Parameters.T, 2) * pow(xMath::GeVtoifm(), 3);
632
633 if (order<3) return ret;
634
635 // chi3
636 vector<double> d2ni(NN, 0.), d2mus(NN, 0.);
637
638 vector<double> chi3id(m_densities.size());
639 for(int i=0;i<NN;++i)
640 chi3id[i] = m_TPS->Particles()[i].chi(3, m_Parameters, m_UseWidth, m_MuStar[i]);
641
642 for(int i=0;i<NN;++i) {
643 xVector[i] = 0.;
644
645 double tmp = 0.;
646 for(int j=0;j<NN;++j) tmp += m_Virial[j][i] * dni[j];
647 tmp = -2. * tmp * chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * dmus[i];
648 xVector[i] += tmp;
649
650 tmp = 0.;
651 for(int j=0;j<NN;++j) tmp += m_Virial[j][i] * m_densities[j];
652 tmp = -(tmp - 1.) * chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * dmus[i] * dmus[i];
653 xVector[i] += tmp;
654 }
655 for(int i=0;i<NN;++i) {
656 xVector[NN+i] = 0.;
657
658 double tmp = 0.;
659 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];
660
661 xVector[NN+i] = tmp;
662 }
663
664 solVector = decomp.solve(xVector);
665
666 for(int i=0;i<NN;++i) {
667 d2ni[i] = solVector[i];
668 d2mus[i] = solVector[NN+i];
669 }
670
671 for(int i=0;i<NN;++i)
672 ret[2] += chgs[i] * d2ni[i];
673
674 ret[2] /= m_Parameters.T * pow(xMath::GeVtoifm(), 3);
675
676
677 if (order<4) return ret;
678
679 // chi4
680 vector<double> d3ni(NN, 0.), d3mus(NN, 0.);
681
682 vector<double> chi4id(m_densities.size());
683 for (int i = 0; i < NN; ++i)
684 chi4id[i] = m_TPS->Particles()[i].chi(4, m_Parameters, m_UseWidth, m_MuStar[i]);
685
686 vector<double> dnis(NN, 0.);
687 for(int i=0;i<NN;++i) {
688 dnis[i] = chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * dmus[i];
689 }
690
691 vector<double> d2nis(NN, 0.);
692 for(int i=0;i<NN;++i) {
693 d2nis[i] = chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * dmus[i] * dmus[i] +
694 chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T * d2mus[i];
695 }
696
697 for(int i=0;i<NN;++i) {
698 xVector[i] = 0.;
699
700 double tmp = 0.;
701 for(int j=0;j<NN;++j) tmp += m_Virial[j][i] * dni[j];
702 tmp = -3. * tmp * d2nis[i];
703 xVector[i] += tmp;
704
705 tmp = 0.;
706 for(int j=0;j<NN;++j) tmp += m_Virial[j][i] * d2ni[j];
707 tmp = -3. * tmp * dnis[i];
708 xVector[i] += tmp;
709
710 double tmps = 0.;
711 for(int j=0;j<NN;++j) tmps += m_Virial[j][i] * m_densities[j];
712
713 tmp = -(tmps - 1.) * chi3id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * d2mus[i] * 3. * dmus[i];
714 xVector[i] += tmp;
715
716 tmp = -(tmps - 1.) * chi4id[i] * pow(xMath::GeVtoifm(), 3) * dmus[i] * dmus[i] * dmus[i];
717 xVector[i] += tmp;
718 }
719 for(int i=0;i<NN;++i) {
720 xVector[NN+i] = 0.;
721
722 double tmp = 0.;
723 for(int j=0;j<NN;++j) tmp += -2. * m_Virial[i][j] * d2mus[j] * dnis[j];
724 xVector[NN+i] += tmp;
725
726 tmp = 0.;
727 for(int j=0;j<NN;++j) tmp += -m_Virial[i][j] * dmus[j] * d2nis[j];
728 xVector[NN+i] += tmp;
729 }
730
731 solVector = decomp.solve(xVector);
732
733 for(int i=0;i<NN;++i) {
734 d3ni[i] = solVector[i];
735 d3mus[i] = solVector[NN+i];
736 }
737
738 for(int i=0;i<NN;++i)
739 ret[3] += chgs[i] * d3ni[i];
740
741 ret[3] /= pow(xMath::GeVtoifm(), 3);
742
743 return ret;
744 }
745
746 // TODO include correlations
747 vector< vector<double> > ThermalModelVDW::CalculateFluctuations(int order) {
748 if (order<1) return m_chi;
749
750 vector<double> chgs(m_densities.size());
751 vector<double> chis;
752
753 // Baryon charge
754 for(size_t i=0;i<chgs.size();++i)
755 chgs[i] = m_TPS->Particles()[i].BaryonCharge();
756 chis = CalculateChargeFluctuations(chgs, order);
757 for(int i=0;i<order;++i) m_chi[i][0] = chis[i];
758
759 // Electric charge
760 for(size_t i=0;i<chgs.size();++i)
761 chgs[i] = m_TPS->Particles()[i].ElectricCharge();
762 chis = CalculateChargeFluctuations(chgs, order);
763 for(int i=0;i<order;++i) m_chi[i][1] = chis[i];
764
765 // Strangeness charge
766 for(size_t i=0;i<chgs.size();++i)
767 chgs[i] = m_TPS->Particles()[i].Strangeness();
768 chis = CalculateChargeFluctuations(chgs, order);
769 for(int i=0;i<order;++i) m_chi[i][2] = chis[i];
770
771 // Arbitrary charge
772 for(size_t i=0;i<chgs.size();++i)
773 chgs[i] = m_TPS->Particles()[i].ArbitraryCharge();
774 chis = CalculateChargeFluctuations(chgs, order);
775 for(int i=0;i<order;++i) m_chiarb[i] = chis[i];
776
777 return m_chi;
778 }
779
781 {
782 int NN = m_densities.size();
783
784 m_PrimCorrel.resize(NN);
785 for (int i = 0; i < NN; ++i)
786 m_PrimCorrel[i].resize(NN);
787 m_dmusdmu = m_PrimCorrel;
788 m_TotalCorrel = m_PrimCorrel;
789
790 MatrixXd densMatrix(2 * NN, 2 * NN);
791 VectorXd solVector(2 * NN), xVector(2 * NN);
792
793 vector<double> chi2id(m_densities.size());
794 for (int i = 0; i<NN; ++i)
795 //chi2id[i] = m_TPS->Particles()[i].chi(2, m_Parameters, m_UseWidth, m_MuStar[i]);
796 chi2id[i] = m_TPS->Particles()[i].chiDimensionfull(2, m_Parameters, m_UseWidth, m_MuStar[i]);
797
798 for (int i = 0; i<NN; ++i)
799 for (int j = 0; j<NN; ++j) {
800 densMatrix(i, j) = m_Virial[j][i] * m_DensitiesId[i];
801 if (i == j) densMatrix(i, j) += 1.;
802 }
803
804 for (int i = 0; i<NN; ++i)
805 for (int j = 0; j<NN; ++j)
806 densMatrix(i, NN + j) = 0.;
807
808 for (int i = 0; i<NN; ++i) {
809 densMatrix(i, NN + i) = 0.;
810 for (int k = 0; k<NN; ++k) {
811 densMatrix(i, NN + i) += m_Virial[k][i] * m_densities[k];
812 }
813 //densMatrix(i, NN + i) = (densMatrix(i, NN + i) - 1.) * chi2id[i] * pow(xMath::GeVtoifm(), 3) * m_Parameters.T * m_Parameters.T;
814 densMatrix(i, NN + i) = (densMatrix(i, NN + i) - 1.) * chi2id[i] * pow(xMath::GeVtoifm(), 3);
815 }
816
817 for (int i = 0; i<NN; ++i)
818 for (int j = 0; j<NN; ++j) {
819 densMatrix(NN + i, j) = -(m_Attr[i][j] + m_Attr[j][i]);
820 }
821
822 for (int i = 0; i<NN; ++i)
823 for (int j = 0; j<NN; ++j) {
824 densMatrix(NN + i, NN + j) = m_Virial[i][j] * m_DensitiesId[j];
825 if (i == j) densMatrix(NN + i, NN + j) += 1.;
826 }
827
828 PartialPivLU<MatrixXd> decomp(densMatrix);
829
830 for (int k = 0; k < NN; ++k) {
831 vector<double> dni(NN, 0.), dmus(NN, 0.);
832
833 for (int i = 0; i < NN; ++i) {
834 xVector[i] = 0.;
835 xVector[NN + i] = static_cast<int>(i == k);
836 }
837
838 solVector = decomp.solve(xVector);
839
840 for (int i = 0; i < NN; ++i) {
841 dni[i] = solVector[i];
842 dmus[i] = solVector[NN + i];
843 m_dmusdmu[i][k] = dmus[i];
844 }
845
846 for (int j = 0; j < NN; ++j) {
847 m_PrimCorrel[j][k] = dni[j];
848 }
849 }
850
851 for (int i = 0; i < NN; ++i) {
852 m_wprim[i] = m_PrimCorrel[i][i];
853 if (m_densities[i] > 0.) m_wprim[i] *= m_Parameters.T / m_densities[i];
854 else m_wprim[i] = 1.;
855 }
856
857 }
858
860 {
866
867 for (size_t i = 0; i < m_wprim.size(); ++i) {
868 m_skewprim[i] = 1.;
869 m_kurtprim[i] = 1.;
870 m_skewtot[i] = 1.;
871 m_kurttot[i] = 1.;
872 }
873
874 m_FluctuationsCalculated = true;
875
876 if (IsTemperatureDerivativesCalculated()) {
877 m_TemperatureDerivativesCalculated = false;
879 }
880 }
881
883 if (!IsTemperatureDerivativesCalculated())
885
886 // Compute dE/dT
887 double ret = 0.;
888
889 for (int i = 0; i < m_TPS->ComponentsNumber(); ++i) {
890 const ThermalParticle &part = m_TPS->Particles()[i];
891 double fi = 1., dvi = 0.;
892 // Term 1
893 for (int k = 0; k < m_TPS->ComponentsNumber(); ++k) {
894 double dfik = -m_Virial[k][i];
895 ret += dfik * m_dndT[k] * part.Density(m_Parameters, IdealGasFunctions::EnergyDensity, m_UseWidth, m_MuStar[i]);
896 fi -= m_Virial[k][i] * m_densities[k];
897 dvi += -(m_Attr[k][i] + m_Attr[i][k]) * m_densities[k];
898 }
899
900 // Term 2
901 ret += fi * part.Density(m_Parameters, IdealGasFunctions::dedT, m_UseWidth, m_MuStar[i]);
902
903 // Term 3
904 ret += fi * part.Density(m_Parameters, IdealGasFunctions::dedmu, m_UseWidth, m_MuStar[i]) * m_dmusdT[i];
905
906 // Term 4
907 ret += dvi * m_dndT[i];
908 }
909
910 return ret;
911 }
912
914 if (!IsCalculated())
916
917 int N = m_TPS->ComponentsNumber();
918 m_dndT = vector<double>(N, 0.);
919 m_dmusdT = vector<double>(N, 0.);
920 m_PrimChi2sdT = vector<vector<double>>(N, vector<double>(N, 0.));
921
922 double T = m_Parameters.T;
923
924 vector<double> nids(N, 0.), dniddTs(N, 0.), chi2ids(N, 0.), dchi2idsdT(N, 0.), chi3ids(N, 0.);
925 for (int i = 0; i < N; ++i) {
926 nids[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::ParticleDensity, m_UseWidth, m_MuStar[i]);
927 dniddTs[i] = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::dndT, m_UseWidth, m_MuStar[i]);
928 chi2ids[i] = m_TPS->Particles()[i].chiDimensionfull(2, m_Parameters, m_UseWidth, m_MuStar[i]) * xMath::GeVtoifm3();
929 // chi2til = chi2 * T^2
930 // dchi2til/dT = T^2 * dchi2/dT + 2 * T * chi2 = T^2 * dchi2/dT + 2 * chi2til / T
931 dchi2idsdT[i] = (T * T * m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::dchi2dT, m_UseWidth, m_MuStar[i]) * xMath::GeVtoifm3() + 2. * T * chi2ids[i] / T / T);
932 chi3ids[i] = m_TPS->Particles()[i].chiDimensionfull(3, m_Parameters, m_UseWidth, m_MuStar[i]) * xMath::GeVtoifm3();
933 }
934
935 int NN = m_densities.size();
936
937 MatrixXd densMatrix(2 * NN, 2 * NN);
938 VectorXd solVector(2 * NN), xVector(2 * NN);
939
940 //vector<double> chi2id(m_densities.size());
941
942 for (int i = 0; i<NN; ++i)
943 for (int j = 0; j<NN; ++j) {
944 densMatrix(i, j) = m_Virial[j][i] * m_DensitiesId[i];
945 if (i == j) densMatrix(i, j) += 1.;
946 }
947
948 for (int i = 0; i<NN; ++i)
949 for (int j = 0; j<NN; ++j)
950 densMatrix(i, NN + j) = 0.;
951
952 for (int i = 0; i<NN; ++i) {
953 densMatrix(i, NN + i) = 0.;
954 for (int k = 0; k<NN; ++k) {
955 densMatrix(i, NN + i) += m_Virial[k][i] * m_densities[k];
956 }
957 densMatrix(i, NN + i) = (densMatrix(i, NN + i) - 1.) * chi2ids[i];
958 }
959
960 for (int i = 0; i<NN; ++i)
961 for (int j = 0; j<NN; ++j) {
962 densMatrix(NN + i, j) = -(m_Attr[i][j] + m_Attr[j][i]);
963 }
964
965 for (int i = 0; i<NN; ++i)
966 for (int j = 0; j<NN; ++j) {
967 densMatrix(NN + i, NN + j) = m_Virial[i][j] * m_DensitiesId[j];
968 if (i == j) densMatrix(NN + i, NN + j) += 1.;
969 }
970
971 PartialPivLU<MatrixXd> decomp(densMatrix);
972
973 for(int i=0;i<NN;++i) {
974 double fi = 1.;
975 for(int k=0;k<NN;++k) {
976 fi -= m_Virial[k][i] * m_densities[k];
977 }
978 xVector[i] = fi * dniddTs[i];
979 xVector[NN + i] = 0.;
980 for(int j = 0; j < NN; ++j) {
981 xVector[NN + i] += -m_Virial[i][j] * m_TPS->Particles()[j].Density(m_Parameters, IdealGasFunctions::EntropyDensity, m_UseWidth, m_MuStar[j]);
982 }
983 }
984
985 solVector = decomp.solve(xVector);
986
987 for(int i=0;i<NN;++i) {
988 m_dndT[i] = solVector[i];
989 m_dmusdT[i] = solVector[NN+i];
990 }
991
992
993 // dchi2's
994 if (IsSusceptibilitiesCalculated()) {
995
996 // TODO: Faaster implementation
997 // int NNdmu = m_MapFromdMuStar.size();
998 // vector<vector<double>> dfij = vector<vector<double>>(NNdmu, vector<double>(NNdmu, 0.));
999 // vector<double> fi = vector<double>(NNdmu, 0.);
1000 // vector<double> tsum1 = vector<double>(NNdmu, 0.);
1001 // vector<double> tsumdndT = vector<double>(NNdmu, 0.);
1002
1003 // for (int j = 0; j < NN; ++j) {
1004 // for (int i = 0; i < NN; ++i) {
1005 // dfij[m_MapTodMuStar[i]][m_MapTodMuStar[j]] += m_Virial[j][i];
1006 // fi[m_MapTodMuStar[i]] += m_Virial[j][i] * m_densities[j];
1007 // }
1008 // tsum1[m_MapTodMuStar[j]] += (dniddTs[j] + chi2ids[j] * m_dmusdT[j]);
1009 // tsumdndT[m_MapTodMuStar[j]] += m_dndT[j];
1010 // }
1011
1012 for (int j = 0; j < NN; ++j) {
1013 // vector<double> PrimCorrelkjsum = vector<double>(NNdmu, 0.);
1014 // for(int k = 0; k < NN; ++k) {
1015 // PrimCorrelkjsum[m_MapTodMuStar[k]] += m_PrimCorrel[k][j];
1016 // }
1017 for (int i = 0; i < NN; ++i) {
1018
1019 // Faster calculation, to be checked
1020 // // a1
1021 // double a1 = 0.;
1022 // for (int k = 0; k < NNdmu; ++k) {
1023 // a1 += PrimCorrelkjsum[m_MapFromdMuStar[k]] * dfij[k][m_MapTodMuStar[i]] * (dniddTs[i] + chi2ids[i] * m_dmusdT[i]);
1024 // a1 += m_dmusdmu[i][j] * dfij[m_MapTodMuStar[i]][k] * tsumdndT[k] * chi2ids[i];
1025 // }
1026 // a1 += m_dmusdmu[i][j] * fi[m_MapTodMuStar[i]] * (dchi2idsdT[i] + chi3ids[i] * m_dmusdT[i]);
1027 // xVector[i] = a1;
1028
1029 // // a2
1030 // double a2 = 0.;
1031 // for (int k = 0; k < NNdmu; ++k) {
1032 // a2 += m_dmusdmu[m_MapFromdMuStar[k]][j] * (-m_Virial[i][m_MapFromdMuStar[k]]) * tsum1[k]; // To be checked
1033 // }
1034 // xVector[i + NN] = a2;
1035
1036 double fi = 1.;
1037 vector<double> dfik = vector<double>(NN, 0.);
1038 //vector<vector<double>> d2fikl = vector<vector<double>>(NN, vector<double>(NN, 0.));
1039 for (int k = 0; k < NN; ++k) {
1040 dfik[k] = -m_Virial[k][i];
1041 fi -= m_Virial[k][i] * m_densities[k];
1042 }
1043
1044 // a1
1045 double a1 = 0.;
1046 for (int k = 0; k < NN; ++k) {
1047 a1 += m_PrimCorrel[k][j] * dfik[k] * (dniddTs[i] + chi2ids[i] * m_dmusdT[i]);
1048 a1 += m_dmusdmu[i][j] * dfik[k] * m_dndT[k] * chi2ids[i];
1049 }
1050 a1 += m_dmusdmu[i][j] * fi * (dchi2idsdT[i] + chi3ids[i] * m_dmusdT[i]);
1051 xVector[i] = a1;
1052
1053 // a2
1054 double a2 = 0.;
1055 for (int k = 0; k < NN; ++k) {
1056 a2 += m_dmusdmu[k][j] * (-m_Virial[i][k]) * (dniddTs[k] + chi2ids[k] * m_dmusdT[k]);
1057 }
1058 xVector[i + NN] = a2;
1059 }
1060
1061 solVector = decomp.solve(xVector);
1062
1063 for (int i = 0; i < NN; ++i) {
1064 // chi2 = chi2til / T^2
1065 // dchi2/dT = dchi2til/dT / T^2 - 2 * chi2til / T / T / T
1066 m_PrimChi2sdT[i][j] = solVector[i] / (xMath::GeVtoifm3() * T * T) - 2. * m_PrimCorrel[i][j] / T / T / T / xMath::GeVtoifm3();
1067 }
1068 }
1069
1070 m_TemperatureDerivativesCalculated = true;
1072 }
1073
1074 m_TemperatureDerivativesCalculated = true;
1075 }
1076
1077
1078
1080 if (!m_Calculated) CalculateDensities();
1081 double ret = 0.;
1082 for(size_t i=0;i<m_densities.size();++i)
1083 if (m_densities[i]>0.)
1084 ret += m_densities[i] / m_DensitiesId[i] * m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EnergyDensity, m_UseWidth, m_MuStar[i]);
1085 for(size_t i=0;i<m_densities.size();++i)
1086 for(size_t j=0;j<m_densities.size();++j)
1087 ret += -m_Attr[i][j] * m_densities[i] * m_densities[j];
1088
1090 for (size_t i = 0; i < m_densities.size(); ++i) {
1091 double tPid = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_MuStar[i]);
1092 for (size_t j = 0; j < m_densities.size(); ++j) {
1093 ret += -tPid * m_densities[j] * m_Parameters.T * m_VirialdT[j][i];
1094 ret += m_Parameters.T * m_AttrdT[i][j] * m_densities[i] * m_densities[j];
1095 }
1096 }
1097 }
1098
1099 return ret;
1100 }
1101
1103 if (!m_Calculated) CalculateDensities();
1104 double ret = 0.;
1105 for(size_t i=0;i<m_densities.size();++i)
1106 if (m_densities[i]>0.)
1107 ret += m_densities[i] / m_DensitiesId[i] * m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::EntropyDensity, m_UseWidth, m_MuStar[i]);
1108
1110 for (size_t i = 0; i < m_densities.size(); ++i) {
1111 double tPid = m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_MuStar[i]);
1112 for (size_t j = 0; j < m_densities.size(); ++j) {
1113 ret += -tPid * m_densities[j] * m_VirialdT[j][i];
1114 ret += m_AttrdT[i][j] * m_densities[i] * m_densities[j];
1115 }
1116 }
1117 }
1118
1119 return ret;
1120 }
1121
1123 if (!m_Calculated) CalculateDensities();
1124 double ret = 0.;
1125 for(size_t i=0;i<m_densities.size();++i)
1126 ret += m_TPS->Particles()[i].Density(m_Parameters, IdealGasFunctions::Pressure, m_UseWidth, m_MuStar[i]);
1127 for(size_t i=0;i<m_densities.size();++i)
1128 for(size_t j=0;j<m_densities.size();++j)
1129 ret += -m_Attr[i][j] * m_densities[i] * m_densities[j];
1130 return ret;
1131 }
1132
1133
1135 if (!m_Calculated) CalculateDensities();
1136
1137 return m_scaldens[part];
1138 }
1139
1140 double ThermalModelVDW::MuShift(int id) const
1141 {
1142 if (id >= 0. && id < static_cast<int>(m_Virial.size()))
1143 return m_MuStar[id] - m_Chem[id];
1144 else
1145 return 0.0;
1146 }
1147
1148 double ThermalModelVDW::VirialCoefficient(int i, int j) const
1149 {
1150 if (i<0 || i >= static_cast<int>(m_Virial.size()) || j < 0 || j >= static_cast<int>(m_Virial.size()))
1151 return 0.;
1152 return m_Virial[i][j];
1153 }
1154
1156 {
1157 if (i<0 || i >= static_cast<int>(m_Attr.size()) || j < 0 || j >= static_cast<int>(m_Attr.size()))
1158 return 0.;
1159 return m_Attr[i][j];
1160 }
1161
1162 double ThermalModelVDW::VirialCoefficientdT(int i, int j) const
1163 {
1164 if (i<0 || i >= static_cast<int>(m_VirialdT.size()) || j < 0 || j >= static_cast<int>(m_VirialdT.size()))
1165 return 0.;
1166 return m_VirialdT[i][j];
1167 }
1168
1170 {
1171 if (i<0 || i >= static_cast<int>(m_AttrdT.size()) || j < 0 || j >= static_cast<int>(m_AttrdT.size()))
1172 return 0.;
1173 return m_AttrdT[i][j];
1174 }
1175
1176 std::vector<double> ThermalModelVDW::BroydenEquationsVDW::Equations(const std::vector<double>& x)
1177 {
1178 int NN = m_THM->Densities().size();
1179 vector<double> Ps(NN, 0.);
1180 for (int i = 0; i < NN; ++i) {
1181 Ps[i] = m_THM->TPS()->Particles()[i].Density(m_THM->Parameters(),
1183 m_THM->UseWidth(),
1184 m_THM->ChemicalPotential(i) + x[m_THM->m_MapTodMuStar[i]]
1185 );
1186 }
1187
1188 vector<double> ns(NN, 0.);
1189 for (int i = 0; i < NN; ++i) {
1190 ns[i] = m_THM->TPS()->Particles()[i].Density(m_THM->Parameters(),
1192 m_THM->UseWidth(),
1193 m_THM->ChemicalPotential(i) + x[m_THM->m_MapTodMuStar[i]]
1194 );
1195 }
1196
1197 vector<double> np = m_THM->ComputeNp(x, ns);
1198
1199
1200 vector<double> ret(m_N, 0.);
1201 for (size_t i = 0; i < ret.size(); ++i) {
1202 ret[i] = x[i];
1203 for (int j = 0; j < NN; ++j)
1204 ret[i] += m_THM->VirialCoefficient(m_THM->m_MapFromdMuStar[i], j) * Ps[j]
1205 - (m_THM->AttractionCoefficient(m_THM->m_MapFromdMuStar[i], j)
1206 + m_THM->AttractionCoefficient(j, m_THM->m_MapFromdMuStar[i])) * np[j];
1207 }
1208 return ret;
1209 }
1210
1211 std::vector<double> ThermalModelVDW::BroydenJacobianVDW::Jacobian(const std::vector<double>& x)
1212 {
1213 int NN = m_THM->m_densities.size();
1214 int NNdmu = m_THM->m_MapFromdMuStar.size();
1215
1216 bool attrfl = false;
1217 for (int i = 0; i < NN; ++i) {
1218 for (int j = 0; j < NN; ++j) {
1219 if (m_THM->AttractionCoefficient(i, j) != 0.0) {
1220 attrfl = true;
1221 break;
1222 }
1223 }
1224 if (attrfl) break;
1225 }
1226
1227 MatrixXd densMatrix(NNdmu, NNdmu);
1228 VectorXd solVector(NNdmu), xVector(NNdmu);
1229
1230 std::vector<double> ret(NNdmu*NNdmu, 0.);
1231 {
1232 vector<double> Ps(NN, 0.);
1233 for (int i = 0; i<NN; ++i)
1234 Ps[i] = m_THM->TPS()->Particles()[i].Density(m_THM->Parameters(),
1236 m_THM->UseWidth(),
1237 m_THM->ChemicalPotential(i) + x[m_THM->m_MapTodMuStar[i]]
1238 );
1239
1240 vector<double> ns(NN, 0.);
1241 for (int i = 0; i<NN; ++i)
1242 ns[i] = m_THM->TPS()->Particles()[i].Density(m_THM->Parameters(),
1244 m_THM->UseWidth(),
1245 m_THM->ChemicalPotential(i) + x[m_THM->m_MapTodMuStar[i]]
1246 );
1247
1248 vector<double> chi2s(NN, 0.);
1249 for (int i = 0; i<NN; ++i)
1250 chi2s[i] = m_THM->TPS()->Particles()[i].chiDimensionfull(2, m_THM->Parameters(),
1251 m_THM->UseWidth(),
1252 m_THM->ChemicalPotential(i) + x[m_THM->m_MapTodMuStar[i]]
1253 );
1254
1255 for (int i = 0; i < NNdmu; ++i) {
1256 for (int j = 0; j < NNdmu; ++j) {
1257 densMatrix(i, j) = 0.;
1258 if (i == j)
1259 densMatrix(i, j) += 1.;
1260
1261 for (size_t m = 0; m < m_THM->m_dMuStarIndices[i].size(); ++m) {
1262 densMatrix(i, j) += m_THM->m_Virial[m_THM->m_MapFromdMuStar[j]][m_THM->m_dMuStarIndices[i][m]] * ns[m_THM->m_dMuStarIndices[i][m]];
1263 }
1264 }
1265 }
1266
1267 PartialPivLU<MatrixXd> decomp(densMatrix);
1268
1269
1270 for (int kp = 0; kp < NNdmu; ++kp) {
1271 xVector[kp] = 0.;
1272 for (size_t m = 0; m < m_THM->m_dMuStarIndices[kp].size(); ++m) {
1273 xVector[kp] += ns[m_THM->m_dMuStarIndices[kp][m]];
1274 }
1275 }
1276
1277
1278 solVector = decomp.solve(xVector);
1279
1280 vector<double> ntildek(NNdmu, 0.);
1281 for (int i = 0; i < NNdmu; ++i)
1282 ntildek[i] = solVector[i];
1283
1284 vector<double> np(NN, 0.);
1285 for (int i = 0; i < NN; ++i) {
1286 np[i] = 0.;
1287 for (int k = 0; k < NNdmu; ++k) {
1288 np[i] += m_THM->m_Virial[m_THM->m_MapFromdMuStar[k]][i] * solVector[k];
1289 }
1290 np[i] = (1. - np[i]) * ns[i];
1291 }
1292
1293 for (int kp = 0; kp < NNdmu; ++kp) {
1294
1295 if (attrfl) {
1296 for (int l = 0; l < NNdmu; ++l) {
1297 xVector[l] = 0.;
1298 for (size_t m = 0; m < m_THM->m_dMuStarIndices[l].size(); ++m) {
1299 int ti = m_THM->m_dMuStarIndices[l][m];
1300 if (m_THM->m_MapTodMuStar[ti] != kp)
1301 continue;
1302
1303 double tmps = 1.;
1304 if (ns[ti] != 0.)
1305 tmps = np[ti] / ns[ti];
1306 xVector[l] += chi2s[ti] * pow(xMath::GeVtoifm(), 3) * tmps;
1307 }
1308 }
1309
1310 solVector = decomp.solve(xVector);
1311 for (int i = 0; i < NNdmu; ++i)
1312 if (solVector[i] > 1.) solVector[i] = 1.; // Stabilizer
1313 }
1314
1315 vector<double> dnjdmukp(NN, 0.);
1316 if (attrfl) {
1317 for (int j = 0; j < NN; ++j) {
1318 for (int kk = 0; kk < NNdmu; ++kk) {
1319 dnjdmukp[j] += -m_THM->m_Virial[m_THM->m_MapFromdMuStar[kk]][j] * solVector[kk] * ns[j];
1320 }
1321
1322 if (m_THM->m_MapTodMuStar[j] == kp) {
1323 double tmps = 1.;
1324 if (ns[j] != 0.)
1325 tmps = np[j] / ns[j];
1326 dnjdmukp[j] += tmps * chi2s[j] * pow(xMath::GeVtoifm(), 3);
1327 }
1328 }
1329 }
1330
1331
1332 for (int k = 0; k < NNdmu; ++k) {
1333 if (k == kp)
1334 ret[k*NNdmu + kp] += 1.;
1335 for (size_t m = 0; m < m_THM->m_dMuStarIndices[kp].size(); ++m) {
1336 int tj = m_THM->m_dMuStarIndices[kp][m];
1337 ret[k*NNdmu + kp] += m_THM->m_Virial[m_THM->m_MapFromdMuStar[k]][tj] * ns[tj];
1338 }
1339
1340 if (attrfl) {
1341 for (int j = 0; j < NN; ++j) {
1342 ret[k*NNdmu + kp] += -(m_THM->m_Attr[m_THM->m_MapFromdMuStar[k]][j] + m_THM->m_Attr[j][m_THM->m_MapFromdMuStar[k]]) * dnjdmukp[j];
1343 }
1344 }
1345 }
1346
1347 }
1348 }
1349
1350 return ret;
1351 }
1352
1353 bool ThermalModelVDW::BroydenSolutionCriteriumVDW::IsSolved(const std::vector<double>& x, const std::vector<double>& f, const std::vector<double>& xdelta) const
1354 {
1355 if (xdelta.size() == x.size()) {
1356 double maxdiff = 0.;
1357 for (size_t i = 0; i < xdelta.size(); ++i) {
1358 maxdiff = std::max(maxdiff, fabs(xdelta[i]));
1359 maxdiff = std::max(maxdiff, fabs(f[i]));
1360 }
1361 return (maxdiff < m_MaximumError);
1362 }
1363 else {
1365 }
1366 }
1367
1368 void SetVDWHRGInteractionParameters(ThermalModelBase *model, double a, double b)
1369 {
1370 auto vdWa = GetBaryonBaryonInteractionMatrix(model->TPS(), a);
1371 auto vdWb = GetBaryonBaryonInteractionMatrix(model->TPS(), b);
1372 // Iterate over all hadron pairs
1373 for (int i1 = 0; i1 < model->TPS()->Particles().size(); ++i1) {
1374 for (int i2 = 0; i2 < model->TPS()->Particles().size(); ++i2) {
1375 model->SetAttraction(i1, i2, vdWa[i1][i2]);
1376 model->SetVirial(i1, i2, vdWb[i1][i2]);
1377 }
1378 }
1379 }
1380
1381} // namespace thermalfist
Contains some functions to deal with excluded volumes.
map< string, double > params
virtual bool IsSolved(const std::vector< double > &x, const std::vector< double > &f, const std::vector< double > &xdelta=std::vector< double >()) const
Definition Broyden.cpp:181
int m_N
The number of equations.
Definition Broyden.h:66
Class implementing the Broyden method to solve a system of non-linear equations.
Definition Broyden.h:132
double MaxDifference() const
Definition Broyden.h:239
virtual std::vector< double > Solve(const std::vector< double > &x0, BroydenSolutionCriterium *solcrit=NULL, int max_iterations=MAX_ITERS)
Definition Broyden.cpp:83
int Iterations() const
Definition Broyden.h:229
int MaxIterations() const
Definition Broyden.h:234
Abstract base class for an HRG model implementation.
virtual void CalculateSusceptibilityMatrix()
Calculates the conserved charges susceptibility matrix.
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
virtual void CalculateParticleChargeCorrelationMatrix()
Calculates the matrix of correlators between primordial (and also final) particle numbers and conserv...
virtual void SetVirial(int, int, double)
Set the excluded volume coefficient .
virtual void FillChemicalPotentials()
Sets the chemical potentials of all particles.
@ QvdW
Quantum van der Waals model.
virtual void SetChemicalPotentials(const std::vector< double > &chem=std::vector< double >(0))
Sets the chemical potentials of all particles.
double ChemicalPotential(int i) const
Chemical potential of particle species i.
virtual void ValidateCalculation()
Checks whether issues have occured during the calculation of particle densities in the CalculateDensi...
virtual void CalculateProxySusceptibilityMatrix()
Calculates the susceptibility matrix of conserved charges proxies.
ThermalModelBase(ThermalParticleSystem *TPS, const ThermalModelParameters &params=ThermalModelParameters())
Construct a new ThermalModelBase object.
bool UseWidth() const
Whether finite resonance widths are considered.
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
virtual void SetAttraction(int, int, double)
Set the vdW mean field attraction coefficient .
const ThermalModelParameters & Parameters() const
@ GCE
Grand canonical ensemble.
virtual void CalculateTwoParticleFluctuationsDecays()
Computes particle number correlations and fluctuations for all final-state particles which are marked...
virtual void SetChemicalPotentials(const std::vector< double > &chem=std::vector< double >(0))
Sets the chemical potentials of all particles.
std::vector< double > m_chiarb
virtual double CalculateEnergyDensityDerivativeT()
virtual void WriteInteractionParameters(const std::string &filename)
Write the QvdW interaction parameters to a file.
double VirialCoefficientdT(int i, int j) const
The temperature derivative of the eigenvolume parameter .
virtual void ChangeTPS(ThermalParticleSystem *TPS)
Change the particle list.
bool m_VDWComponentMapCalculated
Whether the mapping to components with the same VDW parameters has been calculated.
virtual std::vector< double > CalculateChargeFluctuations(const std::vector< double > &chgs, int order=4)
Calculates fluctuations (diagonal susceptibilities) of an arbitrary "conserved" charge.
virtual std::vector< double > SearchSingleSolution(const std::vector< double > &muStarInit)
Uses the Broyden method with a provided initial guess to determine the shifted chemical potentials by...
virtual double MuShift(int id) const
The shift in the chemical potential of particle species i due to the QvdW interactions.
std::vector< double > m_DensitiesId
Vector of ideal gas densities with shifted chemical potentials.
virtual void ReadInteractionParameters(const std::string &filename)
Reads the QvdW interaction parameters from a file.
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.
double AttractionCoefficient(int i, int j) const
QvdW mean field attraction coefficient .
std::vector< int > m_MapTodMuStar
void CalculateVDWComponentsMap()
Partitions particles species into sets that have identical VDW parameters.
void FillChemicalPotentials()
Sets the chemical potentials of all particles.
std::vector< std::vector< double > > m_AttrdT
void CalculateTwoParticleCorrelations()
Computes the fluctuations and correlations of the primordial particle numbers.
std::vector< double > ComputeNp(const std::vector< double > &dmustar)
virtual void FillAttraction(const std::vector< std::vector< double > > &aij=std::vector< std::vector< double > >(0))
double AttractionCoefficientdT(int i, int j) const
The temperature derivative of the QvdW attraction parameter .
std::vector< std::vector< int > > m_dMuStarIndices
virtual ~ThermalModelVDW(void)
Destroy the ThermalModelVDW object.
virtual void CalculateTemperatureDerivatives()
Computes the temperature derivatives of densities, shifted chemical potentials, and primordial hadron...
std::vector< int > m_MapFromdMuStar
std::vector< std::vector< double > > m_Virial
std::vector< double > m_MuStar
Vector of the shifted chemical potentials.
void CalculateFluctuations()
Computes the fluctuation observables.
virtual double ParticleScalarDensity(int part)
std::vector< double > m_scaldens
Vector of scalar densities. Not used.
virtual void CalculatePrimordialDensities()
Calculates the primordial densities of all species.
std::vector< std::vector< double > > m_chi
std::vector< std::vector< double > > m_VirialdT
bool m_SearchMultipleSolutions
Whether multiple solutions are considered.
ThermalModelVDW(ThermalParticleSystem *TPS_, const ThermalModelParameters &params=ThermalModelParameters())
Construct a new ThermalModelVDW object.
bool m_LastBroydenSuccessFlag
Whether Broyden's method was successfull.
double VirialCoefficient(int i, int j) const
Excluded volume coefficient .
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.
std::vector< std::vector< double > > m_Attr
Matrix of the attractive QvdW coefficients .
std::vector< double > SearchMultipleSolutions(int iters=300)
Uses the Broyden method with different initial guesses to look for different possible solutions of th...
Class containing all information about a particle specie.
double Density(const ThermalModelParameters &params, IdealGasFunctions::Quantity type=IdealGasFunctions::ParticleDensity, bool useWidth=0, double mu=0.) const
Computes a specified ideal gas thermodynamic function.
Class containing the particle list.
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...
constexpr double GeVtoifm()
A constant to transform GeV into fm .
Definition xMath.h:25
constexpr double GeVtoifm3()
A constant to transform GeV into fm .
Definition xMath.h:31
constexpr double mnucleon()
Nucleon's mass. Value as in UrQMD.
Definition xMath.h:34
The main namespace where all classes and functions of the Thermal-FIST library reside.
Definition CosmicEoS.h:9
std::vector< std::vector< double > > GetBaryonBaryonInteractionMatrix(const ThermalParticleSystem *TPS, double param)
Returns the matrix of attraction and repulsion parameters for baryon-baryon and antibaryon-antibaryon...
void SetVDWHRGInteractionParameters(ThermalModelBase *model, double a, double b)
Sets vdW interactions for baryon-baryon and antibaryon-antibaryon pairs as in https://arxiv....
Structure containing all thermal parameters of the model.
Contains some extra mathematical functions used in the code.