25 #include <Eigen/Dense> 27 using namespace Eigen;
40 m_TAG =
"ThermalModelEVCrossterms";
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()));
63 std::vector< std::vector<double> > fVirialTmp =
m_Virial;
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]);
75 ifstream fin(filename.c_str());
78 fin.getline(cc, 2000);
79 string tmp = string(cc);
83 istringstream iss(elems[0]);
86 if (iss >> pdgid1 >> pdgid2 >> b) {
89 if (ind1 != -1 && ind2 != -1)
98 ofstream fout(filename.c_str());
99 fout <<
"# List of crossterms parameters to be used in the Crossterms excluded-volume HRG model" 101 fout <<
"# Only particle pairs with a non-zero eigenvolume parameter are listed here" 107 fout <<
"#" <<
" " <<
"pdg_i" 109 <<
" " <<
"b_{ij}[fm^3]" 132 if (i < 0 || i >= static_cast<int>(
m_Virial.size()) || j < 0 || j > static_cast<int>(
m_Virial.size()))
138 if (i >= 0 && i < static_cast<int>(
m_Virial.size()) && j >= 0 && j < static_cast<int>(
m_Virial.size()))
140 else printf(
"**WARNING** Index overflow in ThermalModelEVCrossterms::SetVirial\n");
198 BroydenEquationsCRSDEV eqs(
this);
206 std::vector<double> x(1, x0);
208 x = broydn.
Solve(x, &crit);
211 for (
size_t i = 0; i <
m_Ps.size(); ++i)
219 for (
size_t i = 0; i <
m_Ps.size(); ++i)
m_Ps[i] = 0.;
223 BroydenEquationsCRS eqs(
this);
224 BroydenJacobianCRS jac(
this);
226 BroydenSolutionCriteriumCRS crit(
this);
230 for (
size_t i = 0; i <
m_Ps.size(); ++i)
246 for (
size_t i = 0; i <
m_Ps.size(); ++i)
253 MatrixXd densMatrix(NN, NN);
254 VectorXd solVector(NN), xVector(NN);
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.;
262 PartialPivLU<MatrixXd> decomp(densMatrix);
264 for (
int i = 0; i < NN; ++i) xVector[i] = 0.;
265 for (
int i = 0; i < NN; ++i) {
267 solVector = decomp.solve(xVector);
270 for (
int j = 0; j < NN; ++j)
274 cout <<
"Could not recover m_densities from partial pressures!\n";
280 for (
int i = 0; i < NN; ++i) {
286 solVector = decomp.solve(xVector);
290 for (
int i = 0; i < NN; ++i)
294 cout <<
"**ERROR** Could not recover m_densities from partial pressures!\n";
306 for (
size_t i = 0; i <
m_Ps.size(); ++i)
313 MatrixXd densMatrix(NN, NN);
314 VectorXd solVector(NN), xVector(NN);
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.;
322 PartialPivLU<MatrixXd> decomp(densMatrix);
324 for (
int i = 0; i < NN; ++i) xVector[i] = 0.;
325 for (
int i = 0; i < NN; ++i) {
328 solVector = decomp.solve(xVector);
333 for (
int j = 0; j < NN; ++j)
337 cout <<
"**ERROR** Could not recover m_densities from partial pressures!\n";
344 for (
int i = 0; i < NN; ++i) {
350 solVector = decomp.solve(xVector);
356 for (
int i = 0; i < NN; ++i)
360 cout <<
"**ERROR** Could not recover m_densities from partial pressures!\n";
373 for (
size_t i = 0; i <
m_Ps.size(); ++i)
376 vector<double> Pstmp =
m_Ps;
379 for (iter = 0; iter < 1000; ++iter)
382 for (
size_t i = 0; i <
m_Ps.size(); ++i) {
384 maxdiff = max(maxdiff, fabs((Pstmp[i] -
m_Ps[i]) / Pstmp[i]));
388 if (maxdiff < 1.e-10)
break;
390 if (iter == 1000) cout << iter <<
"\t" << maxdiff <<
"\n";
392 for (
size_t i = 0; i <
m_Ps.size(); ++i)
401 vector<double> tN(NN);
402 for (
int i = 0; i < NN; ++i) tN[i] =
DensityId(i);
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.;
412 VectorXd solVector(NN), xVector(NN);
413 for (
int i = 0; i < NN; ++i) xVector[i] = tN[i];
415 PartialPivLU<MatrixXd> decomp(densMatrix);
417 solVector = decomp.solve(xVector);
421 for (
int i = 0; i < NN; ++i)
425 cout <<
"**ERROR** Could not recover m_densities from partial pressures!\n";
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.;
437 for (
int i = 0; i < NN; ++i) {
443 decomp = PartialPivLU<MatrixXd>(densMatrix);
444 solVector = decomp.solve(xVector);
449 for (
int i = 0; i < NN; ++i)
453 cout <<
"Could not recover entropy m_densities from partial pressures!\n";
461 vector<double> tN(NN), tW(NN);
462 for (
int i = 0; i < NN; ++i) tN[i] =
DensityId(i);
464 MatrixXd densMatrix(NN, NN);
465 VectorXd solVector(NN), xVector(NN), xVector2(NN);
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.;
473 PartialPivLU<MatrixXd> decomp(densMatrix);
475 vector< vector<double> > ders, coefs;
480 for (
int i = 0; i < NN; ++i) {
485 for (
int i = 0; i < NN; ++i) xVector[i] = 0.;
486 for (
int i = 0; i < NN; ++i) {
488 solVector = decomp.solve(xVector);
491 for (
int j = 0; j < NN; ++j) {
492 ders[j][i] = solVector[j];
495 for (
int l = 0; l < NN; ++l) {
497 for (
int k = 0; k < NN; ++k) {
498 coefs[l][i] += -
m_Virial[l][k] * ders[k][i];
500 if (l == i) coefs[l][i] += 1.;
504 cout <<
"**WARNING** Could not recover fluctuations!\n";
511 for (
int i = 0; i < NN; ++i)
m_PrimCorrel[i].resize(NN);
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);
522 for (
int k = 0; k < NN; ++k) {
528 cout <<
"**WARNING** Could not recover fluctuations!\n";
534 for (
int i = 0; i < NN; ++i) {
553 for (
size_t i = 0; i <
m_wprim.size(); ++i) {
563 vector<double> ret(order + 1, 0.);
571 if (order < 2)
return ret;
575 vector<double> MuStar(NN, 0.);
576 for (
int i = 0; i < NN; ++i) {
580 MatrixXd densMatrix(2 * NN, 2 * NN);
581 VectorXd solVector(2 * NN), xVector(2 * NN);
584 for (
int i = 0; i < NN; ++i) {
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.;
595 for (
int i = 0; i < NN; ++i)
596 for (
int j = 0; j < NN; ++j)
597 densMatrix(i, NN + j) = 0.;
599 for (
int i = 0; i < NN; ++i) {
600 densMatrix(i, NN + i) = 0.;
601 for (
int k = 0; k < NN; ++k) {
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.;
614 PartialPivLU<MatrixXd> decomp(densMatrix);
617 vector<double> dni(NN, 0.), dmus(NN, 0.);
619 for (
int i = 0; i < NN; ++i) {
621 xVector[NN + i] = chgs[i];
624 solVector = decomp.solve(xVector);
626 for (
int i = 0; i < NN; ++i) {
627 dni[i] = solVector[i];
628 dmus[i] = solVector[NN + i];
631 for (
int i = 0; i < NN; ++i)
632 ret[1] += chgs[i] * dni[i];
636 if (order < 3)
return ret;
638 vector<double> d2ni(NN, 0.), d2mus(NN, 0.);
641 for (
int i = 0; i < NN; ++i)
644 for (
int i = 0; i < NN; ++i) {
648 for (
int j = 0; j < NN; ++j) tmp +=
m_Virial[j][i] * dni[j];
657 for (
int i = 0; i < NN; ++i) {
658 xVector[NN + i] = 0.;
663 xVector[NN + i] = tmp;
666 solVector = decomp.solve(xVector);
668 for (
int i = 0; i < NN; ++i) {
669 d2ni[i] = solVector[i];
670 d2mus[i] = solVector[NN + i];
673 for (
int i = 0; i < NN; ++i)
674 ret[2] += chgs[i] * d2ni[i];
679 if (order < 4)
return ret;
682 vector<double> d3ni(NN, 0.), d3mus(NN, 0.);
685 for (
int i = 0; i < NN; ++i)
688 vector<double> dnis(NN, 0.);
689 for (
int i = 0; i < NN; ++i) {
693 vector<double> d2nis(NN, 0.);
694 for (
int i = 0; i < NN; ++i) {
699 for (
int i = 0; i < NN; ++i) {
703 for (
int j = 0; j < NN; ++j) tmp +=
m_Virial[j][i] * dni[j];
704 tmp = -3. * tmp * d2nis[i];
708 for (
int j = 0; j < NN; ++j) tmp +=
m_Virial[j][i] * d2ni[j];
709 tmp = -3. * tmp * dnis[i];
718 tmp = -(tmps - 1.) * chi4id[i] * pow(
xMath::GeVtoifm(), 3) * dmus[i] * dmus[i] * dmus[i];
721 for (
int i = 0; i < NN; ++i) {
722 xVector[NN + i] = 0.;
725 for (
int j = 0; j < NN; ++j) tmp += -2. *
m_Virial[i][j] * d2mus[j] * dnis[j];
726 xVector[NN + i] += tmp;
729 for (
int j = 0; j < NN; ++j) tmp += -
m_Virial[i][j] * dmus[j] * d2nis[j];
730 xVector[NN + i] += tmp;
733 solVector = decomp.solve(xVector);
735 for (
int i = 0; i < NN; ++i) {
736 d3ni[i] = solVector[i];
737 d3mus[i] = solVector[NN + i];
740 for (
int i = 0; i < NN; ++i)
741 ret[3] += chgs[i] * d3ni[i];
770 if (
id >= 0. &&
id < static_cast<int>(
m_Virial.size())) {
780 std::vector<double> ThermalModelEVCrossterms::BroydenEquationsCRS::Equations(
const std::vector<double>& x)
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);
788 std::vector<double> ThermalModelEVCrossterms::BroydenJacobianCRS::Jacobian(
const std::vector<double>& x)
792 vector<double> tN(N);
793 for (
int i = 0; i < N; ++i) {
794 tN[i] = m_THM->DensityId(i, x);
797 vector<double> ret(N*N, 0.);
798 for (
int i = 0; i < N; ++i) {
799 for (
int j = 0; j < N; ++j) {
802 ret[i*N + j] += m_THM->VirialCoefficient(i, j) * tN[i];
809 bool ThermalModelEVCrossterms::BroydenSolutionCriteriumCRS::IsSolved(
const std::vector<double>& x,
const std::vector<double>& f,
const std::vector<double>& )
const 812 for (
size_t i = 0; i < x.size(); ++i) {
813 maxdiff = std::max(maxdiff, fabs(f[i]) / x[i]);
815 return (maxdiff < m_MaximumError);
818 std::vector<double> ThermalModelEVCrossterms::BroydenEquationsCRSDEV::Equations(
const std::vector<double>& x)
820 std::vector<double> ret(1);
821 ret[0] = x[0] - m_THM->PressureDiagonalTotal(x[0]);
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.
double GeVtoifm()
A constant to transform GeV into fm .
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
bool m_FluctuationsCalculated
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's Particle Data Group (PDG) ID number.
Class containing the particle list.
Grand canonical ensemble.
ThermalModelParameters m_Parameters
Crossterms excluded volume model.
virtual double CalculateEntropyDensity()
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.
double m_TotalEntropyDensity
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's method.
int MaxIterations() const
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)
Sub-class where it is determined whether the required accuracy is achieved in the Broyden's method...
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...
virtual void CalculatePrimordialDensitiesNoReset()
Contains some functions do deal with excluded volumes.
double MaxDifference() const
std::vector< double > m_densitiesid
void SetDx(double dx)
Set the finite variable difference value used for calculating the Jacobian numerically.
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's method.
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 double CalculateEnergyDensity()
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.
std::vector< double > m_Ps
double PartialPressureDiagonal(int i, double P)
The "partial pressure" of hadron species i for the given total pressure in the diagonal model...
bool m_LastCalculationSuccessFlag
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.
void CalculateTwoParticleCorrelations()
Computes the fluctuations and correlations of the primordial particle numbers.
virtual void CalculatePrimordialDensitiesIter()