Version: SMASH-2.0
smash::ChemicalPotentialSolver Class Reference

#include <chemicalpotential.h>

A class which encapsulates a GSL algorithm for finding the effective chemical potential and supporting functions.

Definition at line 24 of file chemicalpotential.h.

Collaboration diagram for smash::ChemicalPotentialSolver:
[legend]

Classes

struct  ParametersForChemPotSolver
 Struct, root equations, and procedure for finding the effective chemical potential for a given particle species. More...
 

Public Member Functions

double effective_chemical_potential (double degeneracy, double mass, double number_density, double temperature, double statistics, double solution_precision)
 Convenience wrapper for finding the effective chemical potential for a given particle species and performing sanity checks on the result. More...
 

Static Public Member Functions

static double density_one_species (double degeneracy, double mass, double temperature, double effective_chemical_potential, double statistics, Integrator *integrator)
 Vector number density of one particle species, obtained through integrating the Juttner distribution function over the momentum space. More...
 
static double root_equation_effective_chemical_potential (double degeneracy, double mass, double number_density, double temperature, double effective_chemical_potential, double statistics, Integrator *integrator)
 Root equation for finding the value of the effective chemical potential for one particle species. More...
 
static int root_equation_effective_chemical_potential_for_GSL (const gsl_vector *roots_array, void *parameters, gsl_vector *function)
 Root equation for finding the value of the effective chemical potential for one particle species, suited for the GSL root finding procedure. More...
 
static void print_state_effective_chemical_potential (unsigned int iter, gsl_multiroot_fsolver *solver)
 A GSL utility which allows for printing out the status of the solver during the root finding procedure. More...
 
static int find_effective_chemical_potential (double degeneracy, double mass, double number_density, double temperature, double statistics, double mu_initial_guess, double solution_precision, Integrator *integrator, double *effective_chemical_potential)
 A GSL root solver for finding the effective chemical potential. More...
 

Private Attributes

Integrator integrator_ = Integrator(1E6)
 A wrapper for gsl numerical integration. More...
 

Member Function Documentation

◆ density_one_species()

double smash::ChemicalPotentialSolver::density_one_species ( double  degeneracy,
double  mass,
double  temperature,
double  effective_chemical_potential,
double  statistics,
Integrator integrator 
)
static

Vector number density of one particle species, obtained through integrating the Juttner distribution function over the momentum space.

Vector number density of one particle species.

Parameters
[in]degeneracydegeneracy g of the particle species
[in]mass(pole) mass m of the particle species [GeV]
[in]temperaturetemperature T of the system [GeV]
[in]effective_chemical_potentialeffective chemical potential of the system [GeV]
[in]statisticsquantum statistics of the particles species (+1 for Fermi, -1 for Bose, 0 for Boltzmann)
[in]integratorwrapper for gsl numerical integration
Returns
the vector number density for a given species of particles [GeV^3]

Definition at line 29 of file chemicalpotential.cc.

32  {
33  const auto integral = (*integrator)(0.0, 1.0, [&](double x) {
34  return ((1.0 - x) * (1.0 - x) / (x * x * x * x)) *
35  juttner_distribution_func((1.0 - x) / x, mass, temperature,
36  effective_chemical_potential, statistics);
37  });
38  const double integrated_number_density =
39  (degeneracy / (2.0 * M_PI * M_PI)) * integral;
40 
41  return integrated_number_density;
42 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ root_equation_effective_chemical_potential()

double smash::ChemicalPotentialSolver::root_equation_effective_chemical_potential ( double  degeneracy,
double  mass,
double  number_density,
double  temperature,
double  effective_chemical_potential,
double  statistics,
Integrator integrator 
)
static

Root equation for finding the value of the effective chemical potential for one particle species.

Parameters
[in]degeneracydegeneracy g of the particle species
[in]mass(pole) mass m of the particle species
[in]number_densitynumber density n of the particle species [GeV^3]
[in]temperaturetemperature T of the system [GeV]
[in]effective_chemical_potentialeffective chemical potential of the system [GeV]
[in]statisticsquantum statistics of the particles species (+1 for Fermi, -1 for Bose, 0 for Boltzmann)
[in]integratorwrapper for gsl numerical integration
Returns
the root equation

Definition at line 49 of file chemicalpotential.cc.

52  {
53  const double integrated_number_density =
54  density_one_species(degeneracy, mass, temperature,
55  effective_chemical_potential, statistics, integrator);
56 
57  return number_density - integrated_number_density;
58 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ root_equation_effective_chemical_potential_for_GSL()

int smash::ChemicalPotentialSolver::root_equation_effective_chemical_potential_for_GSL ( const gsl_vector *  roots_array,
void *  parameters,
gsl_vector *  function 
)
static

Root equation for finding the value of the effective chemical potential for one particle species, suited for the GSL root finding procedure.

Parameters
[in]roots_arrayan array holding the current best estimate of the roots of the solved equation
[in]parametersrefers to the parameters as provided in the GSL root solving procedure
[in]functionrefers to the root equation(s) as provided in the GSL root solving procedure (where it's called "function")
Returns
the root equation suited for GSL root finding procedure

Definition at line 60 of file chemicalpotential.cc.

61  {
62  struct ParametersForChemPotSolver *par =
63  static_cast<ParametersForChemPotSolver *>(parameters);
64 
65  const double degeneracy = (par->degeneracy);
66  const double mass = (par->mass);
67  const double number_density = (par->number_density);
68  const double temperature = (par->temperature);
69  const double statistics = (par->statistics);
70  Integrator *integrator = (par->integrator);
71 
72  const double effective_chemical_potential = gsl_vector_get(roots_array, 0);
73 
74  gsl_vector_set(function, 0,
76  degeneracy, mass, number_density, temperature,
77  effective_chemical_potential, statistics, integrator));
78 
79  return GSL_SUCCESS;
80 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_state_effective_chemical_potential()

void smash::ChemicalPotentialSolver::print_state_effective_chemical_potential ( unsigned int  iter,
gsl_multiroot_fsolver *  solver 
)
static

A GSL utility which allows for printing out the status of the solver during the root finding procedure.

Parameters
[in]itervariable keeping track of how many steps in the root solving procedure have been taken
[in]solverGSL solver object, which has access to the current best estimate of the roots and the corresponding function values
Returns
message about the current state of the solver

Definition at line 82 of file chemicalpotential.cc.

83  {
84  printf(
85  "\n***\nfind_effective_chemical_potential(): iter = %3u \t"
86  "x = % .3f \t"
87  "f(x) = % .3e \n",
88  iter, gsl_vector_get(solver->x, 0), gsl_vector_get(solver->f, 0));
89 }

◆ find_effective_chemical_potential()

int smash::ChemicalPotentialSolver::find_effective_chemical_potential ( double  degeneracy,
double  mass,
double  number_density,
double  temperature,
double  statistics,
double  mu_initial_guess,
double  solution_precision,
Integrator integrator,
double *  effective_chemical_potential 
)
static

A GSL root solver for finding the effective chemical potential.

In practice one should use the convenience wrapper effective_chemical_potential(), which also performs sanity checks on the obtained solution.

Solver of the equation for chemical potential \( \mu \)

\[ n = \frac{g}{2 \pi^2} \int \frac{p^2 dp}{ e^{(\sqrt{p^2 + m^2} - \mu)/T} \pm 1} \]

given the density \( n \), and temperature \( T \).

Parameters
[in]degeneracydegeneracy g of the particle species
[in]massm (pole) mass m of the particle species [GeV]
[in]number_densitynumber density n of the particle species n [GeV^3]
[in]temperaturetemperature T of the system in GeV
[in]statisticsquantum statistics of the particles species (+1 for Fermi, -1 for Bose, 0 for Boltzmann)
[in]mu_initial_guessthe initial guess for the value of the effective chemical potential [GeV]
[in]solution_precisionprecision with which the solution is found; note that this precision also goes into the precision of integrals calculated in the process
[in]integratorwrapper for gsl numerical integration
[out]effective_chemical_potentialthe solution stored in an array object (we use an array in anticipation of generalizing to multidimensional root finding, needed for example when scalar interactions are present and effective mass is calculated at the same time as the effective chemical potential)

Definition at line 91 of file chemicalpotential.cc.

94  {
95  const gsl_multiroot_fsolver_type *Solver_name;
96  gsl_multiroot_fsolver *Root_finder;
97 
98  int status;
99  size_t iter = 0;
100 
101  const size_t problem_dimension = 1;
102 
103  struct ParametersForChemPotSolver parameters = {
104  degeneracy, mass, number_density, temperature, statistics, integrator};
105 
106  gsl_multiroot_function EffectiveChemicalPotential = {
109  problem_dimension, &parameters};
110 
111  double roots_array_initial[problem_dimension] = {mu_initial_guess};
112 
113  gsl_vector *roots_array = gsl_vector_alloc(problem_dimension);
114  gsl_vector_set(roots_array, 0, roots_array_initial[0]);
115 
116  Solver_name = gsl_multiroot_fsolver_hybrids;
117  Root_finder = gsl_multiroot_fsolver_alloc(Solver_name, problem_dimension);
118  gsl_multiroot_fsolver_set(Root_finder, &EffectiveChemicalPotential,
119  roots_array);
120 
121  // print_state_effective_chemical_potential (iter, Root_finder);
122 
123  do {
124  iter++;
125 
126  /*
127  * gsl_multiroot_fsolver_iterate returns either 0 for a correct behavior,
128  * or an error code (a positive integer) when the solver is stuck
129  */
130  status = gsl_multiroot_fsolver_iterate(Root_finder);
131 
132  // print_state_effective_chemical_potential (iter, Root_finder);
133 
134  /*
135  * Check whether the solver is stuck
136  */
137  if (status) {
138  std::cout << "\nGSL error message:\n"
139  << gsl_strerror(status) << "\n\n"
140  << std::endl;
141  const double conversion_factor =
143  logg[LogArea::Main::id].warn(
144  "\n\nThe GSL solver\nfind_effective_chemical_potential\nis stuck!"
145  "\n\nInput parameters:"
146  "\n degeneracy = ",
147  degeneracy, "\n mass [GeV] = ", mass,
148  "\nnumber_density [fm^-3] = ", number_density / (conversion_factor),
149  "\n temperature [GeV] = ", temperature,
150  "\n statistics = ", statistics,
151  "\n solution_precision = ", solution_precision,
152  "\n\n"
153  "Initialization cannot continue without calculating the "
154  "chemical potential. \nTry adjusting the initial "
155  "guess or the solution precision.\n\n\n");
156  throw std::runtime_error(
157  "Chemical potential calculation returned no result.\n\n");
158  continue;
159  }
160 
161  status = gsl_multiroot_test_residual(Root_finder->f, solution_precision);
162 
163  if (status == GSL_SUCCESS) {
164  effective_chemical_potential[0] = gsl_vector_get(Root_finder->x, 0);
165  }
166  } while (status == GSL_CONTINUE && iter < 100000);
167 
168  gsl_multiroot_fsolver_free(Root_finder);
169  gsl_vector_free(roots_array);
170 
171  return 0;
172 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ effective_chemical_potential()

double smash::ChemicalPotentialSolver::effective_chemical_potential ( double  degeneracy,
double  mass,
double  number_density,
double  temperature,
double  statistics,
double  solution_precision 
)

Convenience wrapper for finding the effective chemical potential for a given particle species and performing sanity checks on the result.

Parameters
[in]degeneracydegeneracy g of the particle species
[in]mass(pole) mass m of the particle species [GeV]
[in]number_densitynumber density n of the particle species [GeV^3]
[in]temperaturetemperature T of the system [GeV]
[in]statisticsquantum statistics of the particles species (+1 for Fermi, -1 for Bose, 0 for Boltzmann)
[in]solution_precisionprecision with which the solution is found; note that this precision also goes into the precision of integrals calculated in the process
Returns
effective chemical potential mu, the solution [GeV]

Integration precision should be better than solving precision

value of small_p in GeV; value is chosen to be small (arbitrary choice)

Definition at line 179 of file chemicalpotential.cc.

181  {
182  assert(temperature > 0); // zero temperature case is not considered here
183  assert(degeneracy > 0);
184  assert(mass > 0);
185  /*
186  * The initial guess for the GSL chemical potential finding
187  * procedure; the guess has to be different for Bose and Fermi
188  * particles.
189  */
190  double initial_guess = 0.0;
191  if (statistics == -1.0) {
192  /*
193  * Such initial guess allows one to sample really close to the Bose
194  * condensate region; at the same time, it works fine in other regions.
195  */
196  initial_guess = 0.999999 * mass;
197  } else {
198  initial_guess = 1.05 * mass;
199  }
200 
202  const double integration_precision = 0.1 * solution_precision;
203  integrator_.set_precision(integration_precision, integration_precision);
204 
205  /*
206  * Array for the GSL chemical potential finder.
207  * Use of array is motivated by anticipating a generalization or overloading
208  * of this solver to include effective mass calculation, which will lead to
209  * multidimensional root finding, in which case the result is best passed as
210  * an array.
211  */
212  double chemical_potential[1];
213  chemical_potential[0] = 0.0;
214 
215  /*
216  * Call the GSL effective chemical potential finding procedure.
217  */
219  degeneracy, mass, number_density, temperature, statistics, initial_guess,
220  solution_precision, &integrator_, chemical_potential);
221 
222  /*
223  * Sanity checks are performed for the obtained value of the chemical
224  * potential .
225  */
226 
227  /*
228  * Check that the calculated chemical potential reproduces the input number
229  * density within acceptable error.
230  */
231  // precision for number density in units of fm^-3
232  const double precision_fm = 1e-3;
233  const double conversion_factor = smash::hbarc * smash::hbarc * smash::hbarc;
234  double nDensityCheck =
235  density_one_species(degeneracy, mass, temperature, chemical_potential[0],
236  statistics, &integrator_);
237 
238  if (abs((number_density - nDensityCheck) / conversion_factor) >
239  precision_fm) {
240  logg[LogArea::Main::id].warn(
241  "\n\nThe calculated chemical potential = ", chemical_potential[0],
242  " [GeV] does not reproduce the input number density to within ",
243  precision_fm,
244  "!"
245  "\nnumber_density [GeV^3] = ",
246  number_density, "\n nDensityCheck [GeV^3] = ", nDensityCheck,
247  "\nnumber_density [fm^-3] = ", number_density / (conversion_factor),
248  "\n nDensityCheck [fm^-3] = ", nDensityCheck / (conversion_factor),
249  "\n\n"
250  "Input parameters:"
251  "\n degeneracy = ",
252  degeneracy, "\n mass [GeV] = ", mass,
253  "\nnumber_density [fm^-3] = ", number_density / (conversion_factor),
254  "\n temperature [GeV] = ", temperature,
255  "\n statistics = ", statistics,
256  "\n solution_precision = ", solution_precision,
257  "\n\n"
258  "Initialization cannot continue without a correct "
259  "calculation of the chemical potential."
260  "\nTry adjusting the initial guess or the solution precision.\n\n\n");
261  throw std::runtime_error(
262  "Chemical potential calculation does not reproduce the "
263  "input number density.\n\n");
264  }
265 
266  /*
267  * Check if the obtained value of the effective chemical potential indicates
268  * that the number density is such that for bosons one has encountered the
269  * Bose-Einstein condensate. We need mu < mass in order for the system NOT to
270  * be in the Bose-Einstein condensate region.
271  */
272  if ((statistics == -1) && (chemical_potential[0] > mass)) {
273  logg[LogArea::Main::id].warn(
274  "\n\nThe calculated chemical potential indicates the "
275  "input number density is such that Bose-Einstein "
276  "condensate is encountered."
277  "Input parameters:"
278  "\n degeneracy = ",
279  degeneracy, "\n mass [GeV] = ", mass,
280  "\nnumber_density [fm^-3] = ", number_density / (conversion_factor),
281  "\n temperature [GeV] = ", temperature,
282  "\n statistics = ", statistics,
283  "\n solution_precision = ", solution_precision,
284  "\n\n"
285  "Initialization cannot proceed with a pathological "
286  "distribution function leading to the Bose-Einstein "
287  "condensate. \nTry increasing the temperature or "
288  "decreasing the number density.\n\n\n");
289  throw std::runtime_error(
290  "Chemical potential calculation indicates that the Bose-Einstein "
291  "condensate is produced.");
292  }
293 
294  /*
295  * Check if the distribution is pathological, i.e., has negative values
296  * for low momenta (Bose statistics, in the Bose-Einstein condensate regime,
297  * may produce pathological distributions for which f(p) < 0 ).
298  */
300  const double small_p = 0.005;
301  const double distribution_at_small_p = juttner_distribution_func(
302  small_p, mass, temperature, chemical_potential[0], statistics);
303  if (distribution_at_small_p < 0.0) {
304  logg[LogArea::Main::id].warn(
305  "\n\nNegative values of the distribution function at "
306  "small momenta indicate that Bose-Einstein "
307  "condensate is encountered."
308  "Input parameters:"
309  "\n degeneracy = ",
310  degeneracy, "\n mass [GeV] = ", mass,
311  "\nnumber_density [fm^-3] = ", number_density / (conversion_factor),
312  "\n temperature [GeV] = ", temperature,
313  "\n statistics = ", statistics,
314  "\n solution_precision = ", solution_precision, "\n\nf(p=", small_p,
315  ") = ", distribution_at_small_p,
316  "\n\n"
317  "Initialization cannot proceed with a pathological "
318  "distribution function leading to the Bose-Einstein "
319  "condensate. \nTry increasing the temperature or "
320  "decreasing the number density.\n\n\n");
321  throw std::runtime_error(
322  "Negative values of the distribution function at low momenta "
323  "indicate that the Bose-Einstein condensate is produced.");
324  }
325 
326  return chemical_potential[0];
327 }
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ integrator_

Integrator smash::ChemicalPotentialSolver::integrator_ = Integrator(1E6)
private

A wrapper for gsl numerical integration.

Definition at line 184 of file chemicalpotential.h.


The documentation for this class was generated from the following files:
smash::ChemicalPotentialSolver::integrator_
Integrator integrator_
A wrapper for gsl numerical integration.
Definition: chemicalpotential.h:184
smash::ChemicalPotentialSolver::effective_chemical_potential
double effective_chemical_potential(double degeneracy, double mass, double number_density, double temperature, double statistics, double solution_precision)
Convenience wrapper for finding the effective chemical potential for a given particle species and per...
Definition: chemicalpotential.cc:179
smash::ChemicalPotentialSolver::density_one_species
static double density_one_species(double degeneracy, double mass, double temperature, double effective_chemical_potential, double statistics, Integrator *integrator)
Vector number density of one particle species, obtained through integrating the Juttner distribution ...
Definition: chemicalpotential.cc:29
smash::Integrator::set_precision
void set_precision(double absolute, double relative)
Set precision for the absolute and relative error of the integration.
Definition: integrate.h:168
smash::ChemicalPotentialSolver::root_equation_effective_chemical_potential_for_GSL
static int root_equation_effective_chemical_potential_for_GSL(const gsl_vector *roots_array, void *parameters, gsl_vector *function)
Root equation for finding the value of the effective chemical potential for one particle species,...
Definition: chemicalpotential.cc:60
smash::hbarc
constexpr double hbarc
GeV <-> fm conversion factor.
Definition: constants.h:25
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::ChemicalPotentialSolver::root_equation_effective_chemical_potential
static double root_equation_effective_chemical_potential(double degeneracy, double mass, double number_density, double temperature, double effective_chemical_potential, double statistics, Integrator *integrator)
Root equation for finding the value of the effective chemical potential for one particle species.
Definition: chemicalpotential.cc:49
smash::juttner_distribution_func
double juttner_distribution_func(double momentum_radial, double mass, double temperature, double effective_chemical_potential, double statistics)
Relativistic Juttner distribution function is just a convenience wrapper for displaying Fermi,...
Definition: distributions.cc:79
smash::ChemicalPotentialSolver::find_effective_chemical_potential
static int find_effective_chemical_potential(double degeneracy, double mass, double number_density, double temperature, double statistics, double mu_initial_guess, double solution_precision, Integrator *integrator, double *effective_chemical_potential)
A GSL root solver for finding the effective chemical potential.
Definition: chemicalpotential.cc:91