-
Notifications
You must be signed in to change notification settings - Fork 0
Attractor Solutions
Quintessence models can exhibit tracking behaviour at early times, where the equation of state satisfies
Since the attractor solution in CLASS provides only the starting value for the scalar field
The tracking condition follows from Copeland et al. (1998, arXiv:gr-qc/9711068). For a tracking attractor, the scalar field energy density is related to the background via:
where
From the attractor condition
For the field value
This is potential-dependent and may not always yield closed-form solutions. In our Mathematica notebook Attractor Solutions.nb we derive the large- and small-field attractors, which we implement or approximate in background.c in CLASS.
The implementation is controlled by the flag attractor_ic_scf. When enabled, it computes
A potential can have true large-field or small-field attractor solutions, as well as approximate attractors, e.g. if the potential can be approximated by an exponential function. To assess which regime is dominant during an MCMC, each solution has a tag attractor_regime_scf:
- 0: no attractor (using given initial field values)
- 1: true large-field attractor
- 2: approximate large-field attractor
- 3: true small-field attractor
- 4: approximate small-field attractor
If, for example, the MCMC reveals that the 'best-fit' value for attractor_regime_scf is 2, we'd know that the large-field attractor is preferred, though the conditions for the true large-field attractor solution are not met, yet the initial conditions approximating an exponential attractor solution work well. This can then be used to further investigate the tracking condition, e.g. by plotting
All implemented dark energy potentials have an overall scaling factor
We first retrieve the potential parameters from the user input and set the background to be radiation dominated.
double c1 = pba->scf_parameters[0];
double c2 = pba->scf_parameters[1];
double c3 = pba->scf_parameters[2];
double c4 = pba->scf_parameters[3];
double scf_gamma = 4. / 3.; // radiation domination
double omega_background = 1. / 3.; // radiation domination
double rho_background = rho_rad; // assuming only radiation at initial time
double rho_tracking = 0.;Each potential has their own attractor solution (or no tracking behaviour).
This potential does not have an attractor solution, as
Therefore, the initial conditions have to be provided, instead of using an attractor.
case 1: // power-law
// pvecback_integration[pba->index_bi_phi_prime_scf] = 0;
class_stop(pba->error_message, "scf_potential=%d does not have an attractor solution", pba->scf_potential);
break;This potential does not have an attractor solution, as
Therefore, the initial conditions have to be provided, instead of using an attractor.
case 2: // cosine
class_stop(pba->error_message, "scf_potential=%d does not have an attractor solution", pba->scf_potential);
break;The potential has
as a general attractor condition. There is no small-field attractor, since
case 3: // hyperbolic
scf_lambda = -c2;
/** Reject if no tracking attractor exists (lambda^2 <= 3*gamma implies Omega_scf >= 0.5. CLASS would reject it because radiation is not domiant enough.). */
class_test(1. <= 3. * scf_gamma / scf_lambda / scf_lambda,
pba->error_message,
"No tracking attractor exists for potential %d: "
"|lambda| = %e < sqrt(3*gamma) = %.4f. "
"Use non-tracking ICs (attractor_ic_scf = no) or increase |lambda|.",
pba->scf_potential, fabs(scf_lambda), sqrt(3. * scf_gamma));
{
rho_tracking = rho_background * 3. * scf_gamma / (scf_lambda * scf_lambda) / (1. - 3. * scf_gamma / scf_lambda / scf_lambda);
/** The tracking fraction Omega_phi = 3*gamma/lambda^2 is an exact
* (non-perturbative) solution of the full Friedmann + Klein-Gordon
* system. It does not require subdominance. During RD the tracking
* field has w = 1/3 and is correctly counted as radiation in
* background_functions (conditional rho_r/rho_m decomposition),
* so Omega_r ~ 1 at a_ini regardless of the tracking fraction.
* The only physical constraint is lambda^2 > 3*gamma (attractor
* existence), already checked above. */
pvecback_integration[pba->index_bi_phi_prime_scf] = a * sqrt(rho_tracking * scf_gamma); The class_test is performed to avoid NaN from a complex root.
Solving
under the condition that the denominator is non-zero and the argument of
if (c2 > 0.0 && (
/* c1 > 0 branches */
(
c1 > 0.0 &&
scf_gamma > (4.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0 &&
omega_background < (1.0 / (3.0 * scf_gamma * rho_tracking)) * (-16.0 * c1 * c2 * c2 + 12.0 * c1 * scf_gamma + 3.0 * scf_gamma * rho_tracking)) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (4.0 / 3.0) * c2 * c2 &&
rho_tracking > (1.0 / (3.0 * scf_gamma)) * (16.0 * c1 * c2 * c2 - 12.0 * c1 * scf_gamma) &&
omega_background > (1.0 / (3.0 * scf_gamma * rho_tracking)) * (-16.0 * c1 * c2 * c2 + 12.0 * c1 * scf_gamma + 3.0 * scf_gamma * rho_tracking) &&
omega_background < 1.0) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (4.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 && rho_tracking <= (1.0 / (3.0 * scf_gamma)) * (16.0 * c1 * c2 * c2 - 12.0 * c1 * scf_gamma) &&
omega_background > 0.0 && omega_background < 1.0) ||
/* c1 < 0 branches */
(
c1 < 0.0 &&
scf_gamma > (4.0 / 3.0) * c2 * c2 &&
rho_tracking > (1.0 / (3.0 * scf_gamma)) * (16.0 * c1 * c2 * c2 - 12.0 * c1 * scf_gamma) &&
omega_background > (1.0 / (3.0 * scf_gamma * rho_tracking)) * (-16.0 * c1 * c2 * c2 + 12.0 * c1 * scf_gamma + 3.0 * scf_gamma * rho_tracking) &&
omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > (4.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 && rho_tracking <= (1.0 / (3.0 * scf_gamma)) * (16.0 * c1 * c2 * c2 - 12.0 * c1 * scf_gamma) &&
omega_background > 0.0 && omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > 0.0 && scf_gamma < (4.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0 &&
omega_background < (1.0 / (3.0 * scf_gamma * rho_tracking)) * (-16.0 * c1 * c2 * c2 + 12.0 * c1 * scf_gamma + 3.0 * scf_gamma * rho_tracking))))
{
pvecback_integration[pba->index_bi_phi_scf] = atanh(
(8.0 * c1 * c2 * c2 - 6.0 * c1 * scf_gamma - 3.0 * scf_gamma * rho_tracking + 3.0 * scf_gamma * rho_tracking * omega_background) / (2.0 * c1 * (4.0 * c2 * c2 - 3.0 * scf_gamma))) /
c2;
}If these conditions are not met, the behaviour can still be approximated by the attractor of the single exponential, which is the dominant term:
else if (
/* c1 > 0 branches */
(
c1 > 0.0 &&
scf_gamma > (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
/* c1 < 0 branches */
(
c1 < 0.0 &&
scf_gamma > (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0))
{
pvecback_integration[pba->index_bi_phi_scf] =
log(
-2.0 * (c1 * c2 * c2 - 3.0 * c1 * scf_gamma) / (3.0 * scf_gamma * rho_tracking * (-1.0 + omega_background))) /
c2;
}If these conditions are also not met, we still need to assign a value to avoid NaN errors. Since it is only a starting point from which the field then evolves, we consider another attractor solution a save bet: the small-field attractor which exists unconditionally for this potential,
else
pvecback_integration[pba->index_bi_phi_scf] = (2.0 * c1 * c2 * c2 - 6.0 * c1 * scf_gamma - 3.0 * scf_gamma * rho_tracking + 3.0 * scf_gamma * rho_tracking * omega_background) /
(2.0 * c1 * c2 * c2 * c2 - 6.0 * c1 * c2 * scf_gamma);
break;This completes the case for this potential.
Since
is never 1 or bigger, there is no attractor solution for this potential.
case 4: // pNG
class_stop(pba->error_message, "scf_potential=%d does not have an attractor solution", pba->scf_potential);
break;While the inverse power-law potential
there is no analytic, closed-form solution for
case 5: // iPL
// pvecback_integration[pba->index_bi_phi_prime_scf] = 0.;
// pvecback_integration[pba->index_bi_phi_scf] = 0.;
class_stop(pba->error_message, "An attractor solution for the inverse power-law potential exists, however, it requires shooting to match the energy budget. Using MCMC, it's equally efficient to just brute-force it by finding phi_ini and setting phi_prime_ini=0.");
break;There is always an attractor solution. We have
As we explained above, class_test that stops the computation if class_test avoids complex roots.
case 6: // exponential
/* KBL: For V = c1*exp(-c2*phi), every attractor IC branch computes
phi = log(f(params)/c1)/(-c2), so V(phi_ini) = f(params) is
independent of c1. Shooting on c1 therefore sees a flat target
function (dOmega_scf/dc1 = 0) and cannot converge. */
class_test(pba->scf_tuning_index == 0,
pba->error_message,
"Exponential potential (case 6) with attractor_ic_scf = yes: "
"attractor ICs cancel c1 from V(phi_ini), so shooting on c1 "
"(scf_tuning_index = 0) cannot converge. "
"Either set attractor_ic_scf = no, or shoot on a different "
"parameter (scf_tuning_index != 0).");
scf_lambda = -c2;
class_test(1. <= 3. * scf_gamma / scf_lambda / scf_lambda,
pba->error_message,
"No tracking attractor exists for potential %d: "
"|lambda| = %e < sqrt(3*gamma) = %.4f. "
"Use non-tracking ICs (attractor_ic_scf = no) or increase |lambda|.",
pba->scf_potential, fabs(scf_lambda), sqrt(3. * scf_gamma));
{
rho_tracking = rho_background * 3. * scf_gamma / (scf_lambda * scf_lambda) / (1. - 3. * scf_gamma / scf_lambda / scf_lambda);
pvecback_integration[pba->index_bi_phi_prime_scf] = a * sqrt(rho_tracking * (1. + omega_background));
if (
/* c1 > 0 branches */
(
c1 > 0.0 &&
scf_gamma > (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
/* c1 < 0 branches */
(
c1 < 0.0 &&
scf_gamma > (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c2 * c2 &&
rho_tracking > 0.0 &&
omega_background > 1.0))
{
pvecback_integration[pba->index_bi_phi_scf] =
log(
-2.0 * (c1 * c2 * c2 - 3.0 * c1 * scf_gamma) / (3.0 * scf_gamma * rho_tracking * (-1.0 + omega_background))) /
c2;
}
// If these conditions are not met, we still need to assign some value. The small-field attractor solution avoids NaN.
else
pvecback_integration[pba->index_bi_phi_scf] = (2.0 * c1 * c2 * c2 - 6.0 * c1 * scf_gamma - 3.0 * scf_gamma * rho_tracking + 3.0 * scf_gamma * rho_tracking * omega_background) /
(2.0 * c1 * c2 * c2 * c2 - 6.0 * c1 * c2 * scf_gamma);
}
break;From
we can deduce that there is always an attractor solution, since the large-field limit is
case 7: // SqE
// pvecback_integration[pba->index_bi_phi_prime_scf] = 0.;
// pvecback_integration[pba->index_bi_phi_scf] = 0.;
class_stop(pba->error_message, "An attractor solution for the squared exponential potential exists, however, it requires shooting to match the energy budget. Using MCMC, it's equally efficient to just brute-force it by finding phi_ini phi_prime_ini.");
break;If
class_test(1. <= 3. * scf_gamma / scf_lambda / scf_lambda,
pba->error_message,
"No tracking attractor exists for potential %d: "
"|lambda| = %e < sqrt(3*gamma) = %.4f. "
"Use non-tracking ICs (attractor_ic_scf = no) or increase |lambda|.",
pba->scf_potential, fabs(scf_lambda), sqrt(3. * scf_gamma));Furthermore, as we approximate the large-field attractor by the exponential potential attractor,
class_test(pba->scf_tuning_index == 0,
pba->error_message,
"Bean potential (case 8) with attractor_ic_scf = yes: "
"attractor ICs make Omega_scf(today) independent of c1 "
"(tracking trajectory depends only on c2, c3, c4). "
"Shooting on c1 (scf_tuning_index = 0) cannot converge. "
"Use non-tracking ICs (attractor_ic_scf = no) instead.");There are small- and large-field attractors, as NaN.
rho_tracking = rho_background * 3. * scf_gamma / (scf_lambda * scf_lambda) / (1. - 3. * scf_gamma / scf_lambda / scf_lambda);
pvecback_integration[pba->index_bi_phi_prime_scf] = a * sqrt(rho_tracking * (1. + omega_background));
// There is no analytic solution for the large-field attractor in this potential. It is approximated by the exponential potential attractor.
if (
/* c1 > 0 branches */
(
c1 > 0.0 &&
scf_gamma > (1.0 / 3.0) * c3 * c3 &&
rho_tracking > 0.0 &&
omega_background > 1.0) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c3 * c3 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
/* c1 < 0 branches */
(
c1 < 0.0 &&
scf_gamma > (1.0 / 3.0) * c3 * c3 &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * c3 * c3 &&
rho_tracking > 0.0 &&
omega_background > 1.0))
{
pvecback_integration[pba->index_bi_phi_scf] =
log(
-2.0 * (c1 * c3 * c3 - 3.0 * c1 * scf_gamma) / (3.0 * scf_gamma * rho_tracking * (-1.0 + omega_background))) /
c3;
}
}
// If these conditions are not met, we still need to assign some value. The small-field attractor solution---which exists for this potential and is not equal to the small-field attractor of the exponential---avoids NaN. Phi_prime_ini is identical and does not need to be changed.
else
pvecback_integration[pba->index_bi_phi_scf] = (-2.0 * c1 * c2 * c2 * c2 * c3 * c3 + 6.0 * c1 * c2 * c2 * c2 * scf_gamma + 3.0 * c2 * c2 * scf_gamma * rho_tracking - 3.0 * c2 * c2 * scf_gamma * rho_tracking * omega_background) /
(-2.0 * c1 * c2 * c2 * c2 * c3 * c3 * c3 + 6.0 * c1 * c2 * c2 * c2 * c3 * scf_gamma);
break;If
class_test(1. <= 3. * scf_gamma / scf_lambda / scf_lambda,
pba->error_message,
"No tracking attractor exists for potential %d: "
"|lambda| = %e < sqrt(3*gamma) = %.4f. "
"Use non-tracking ICs (attractor_ic_scf = no) or increase |lambda|.",
pba->scf_potential, fabs(scf_lambda), sqrt(3. * scf_gamma));Otherwise, the double exponential has early-times as well as late-times attractors:
class_test(pba->scf_tuning_index == 0,
pba->error_message,
"DoubleExp potential (case 9) with attractor_ic_scf = yes: "
"attractor ICs make Omega_scf(today) independent of c1 "
"(tracking trajectory depends only on c2, c3, c4). "
"Shooting on c1 (scf_tuning_index = 0) cannot converge. "
"Use non-tracking ICs (attractor_ic_scf = no) instead.");Besides that, we have
NaN.
When we first implemented this, we used
case 9: // DoubleExp
// scf_lambda = -(c1 * c2 + c3 * c4) / (c1 + c3);
// printf("Double exponential potential selected for attractor ICs\n");
c3 = c1 * c3; // For the shooting to work, we need an overall factor for the entire potential. To achieve this in the double exponential potential, I choose to put c1 in front of the sum of both exponentials. This changes the meaning of c3, which was initially implemented for the potential c1*exp(c2*phi)+c3*exp(c4*phi). Now it is c1*exp(c2*phi)+ (c1*c3)*exp(c4*phi).
if (c2 > c4)
scf_lambda = -c4;
else
scf_lambda = -c2;
/* KBL: DoubleExp attractor ICs + shooting on c1 is non-viable,
exactly as for the exponential (case 6) and Bean (case 8).
On the tracking attractor with lambda = min(c2, c4), the shallower
exponential dominates: V ~ c1 * exp(-lambda*phi). The attractor IC
formula computes phi_ini = ln(c1 * f(lambda, gamma)) / lambda, so
c1 * exp(-lambda * phi_ini) = rho_tracking / g is c1-independent.
The steeper exponential is subdominant and its coefficient c3 is
already absorbed into c1*c3 above. No late-time transition exists:
the field permanently tracks at Omega_phi = 3*gamma/lambda^2,
making the full trajectory and Omega_scf(today) c1-independent.
Unlike Bean (where c4 controls a late-time exit from tracking),
DoubleExp has no structural feature that breaks the c1-degeneracy.
Shooting on c2 or c4 (the slopes) is technically feasible but
physically equivalent to the pure exponential — the tracker has
w = w_bg at all times and never acts as dark energy.
Use non-tracking ICs (attractor_ic_scf = no) instead. */
class_test(pba->scf_tuning_index == 0,
pba->error_message,
"DoubleExp potential (case 9) with attractor_ic_scf = yes: "
"attractor ICs make Omega_scf(today) independent of c1 "
"(tracking trajectory depends only on c2, c3, c4). "
"Shooting on c1 (scf_tuning_index = 0) cannot converge. "
"Use non-tracking ICs (attractor_ic_scf = no) instead.");
/** Reject if no tracking attractor exists (lambda^2 <= 3*gamma implies Omega_scf >= 0.5). */
class_test(1. <= 3. * scf_gamma / scf_lambda / scf_lambda,
pba->error_message,
"No tracking attractor exists for potential %d: "
"|lambda| = %e < sqrt(3*gamma) = %.4f. "
"Use non-tracking ICs (attractor_ic_scf = no) or increase |lambda|.",
pba->scf_potential, fabs(scf_lambda), sqrt(3. * scf_gamma));
{
rho_tracking = rho_background * 3. * scf_gamma / (scf_lambda * scf_lambda) / (1. - 3. * scf_gamma / scf_lambda / scf_lambda);
/** See case 3 (hyperbolic) for why no subdominance check is needed. */
pvecback_integration[pba->index_bi_phi_prime_scf] = a * sqrt(rho_tracking * scf_gamma);
// There is no analytic solution for the large-field attractor in this potential. It is approximated by the single exponential potential attractor.
if (
/* c1 > 0 branches */
(
c1 > 0.0 &&
scf_gamma > (1.0 / 3.0) * scf_lambda * scf_lambda &&
rho_tracking > 0.0 &&
omega_background > 1.0) ||
(c1 > 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * scf_lambda * scf_lambda &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
/* c1 < 0 branches */
(
c1 < 0.0 &&
scf_gamma > (1.0 / 3.0) * scf_lambda * scf_lambda &&
rho_tracking > 0.0 &&
omega_background > 0.0 && omega_background < 1.0) ||
(c1 < 0.0 &&
scf_gamma > 0.0 && scf_gamma < (1.0 / 3.0) * scf_lambda * scf_lambda &&
rho_tracking > 0.0 &&
omega_background > 1.0))
{
pvecback_integration[pba->index_bi_phi_scf] =
log(
-2.0 * (c1 * scf_lambda * scf_lambda - 3.0 * c1 * scf_gamma) / (3.0 * scf_gamma * rho_tracking * (-1.0 + omega_background))) /
scf_lambda;
pba->attractor_regime_scf = 2; // large-field attractor (DoubleExp, approx by single exponential)
if (pba->background_verbose > 0)
{
printf("Large-field attractor (approximated by single exponential) is used. We assign phi_ini_scf=%e and phi_prime_ini_scf=%e.\n", pvecback_integration[pba->index_bi_phi_scf], pvecback_integration[pba->index_bi_phi_prime_scf]);
}
}
// If the conditions are not met, we assign the small field attractor solution of the double exponential to avoid NaN.
else if (((c1 + c3) * scf_gamma * rho_tracking * (1.0 + omega_background)) /
(c1 * c2 + c3 * c4 + 3.0 * c1 * scf_gamma + 3.0 * c3 * scf_gamma) <
0.0)
{
// The small-field attractor solution has a different phi_prime_ini. This was not the case for Bean's exponential.
pvecback_integration[pba->index_bi_phi_prime_scf] =
sqrt(
-3.0 * (((c1 + c3) * scf_gamma * rho_tracking * (1.0 + omega_background)) /
(c1 * c2 + c3 * c4 + 3.0 * c1 * scf_gamma + 3.0 * c3 * scf_gamma)));
pvecback_integration[pba->index_bi_phi_scf] = (2.0 * c1 * c1 * c1 * c2 * c2 + 2.0 * c1 * c1 * c2 * c2 * c3 + 4.0 * c1 * c1 * c2 * c3 * c4 + 4.0 * c1 * c2 * c3 * c3 * c4 + 2.0 * c1 * c3 * c3 * c4 * c4 + 2.0 * c3 * c3 * c3 * c4 * c4 - 6.0 * c1 * c1 * c1 * scf_gamma - 18.0 * c1 * c1 * c3 * scf_gamma - 18.0 * c1 * c3 * c3 * scf_gamma - 6.0 * c3 * c3 * c3 * scf_gamma - 3.0 * c1 * c1 * scf_gamma * rho_tracking - 6.0 * c1 * c3 * scf_gamma * rho_tracking - 3.0 * c3 * c3 * scf_gamma * rho_tracking + 3.0 * c1 * c1 * scf_gamma * rho_tracking * omega_background + 6.0 * c1 * c3 * scf_gamma * rho_tracking * omega_background + 3.0 * c3 * c3 * scf_gamma * rho_tracking * omega_background) /
(2.0 * c1 * c1 * c1 * c2 * c2 * c2 + 6.0 * c1 * c1 * c2 * c2 * c3 * c4 + 6.0 * c1 * c2 * c3 * c3 * c4 * c4 + 2.0 * c3 * c3 * c3 * c4 * c4 * c4 - 6.0 * c1 * c1 * c1 * c2 * scf_gamma - 12.0 * c1 * c1 * c2 * c3 * scf_gamma - 6.0 * c1 * c2 * c3 * c3 * scf_gamma - 6.0 * c1 * c1 * c3 * c4 * scf_gamma - 12.0 * c1 * c3 * c3 * c4 * scf_gamma - 6.0 * c3 * c3 * c3 * c4 * scf_gamma);
pba->attractor_regime_scf = 3; // approximate small-field attractor (DoubleExp-specific)
if (pba->background_verbose > 0)
{
printf("Small-field attractor (DoubleExp-specific) is used. We assign phi_ini_scf=%e and phi_prime_ini_scf=%e.\n", pvecback_integration[pba->index_bi_phi_scf], pvecback_integration[pba->index_bi_phi_prime_scf]);
}
}
// If these conditions are not met, we still need to assign some value. The small-field attractor solution of the simple exponential avoids NaN. It has again the 'old' phi_prime_ini, which does not need to be changed.
else
{
pvecback_integration[pba->index_bi_phi_scf] = (2.0 * c1 * c2 * c2 - 6.0 * c1 * scf_gamma - 3.0 * scf_gamma * rho_tracking + 3.0 * scf_gamma * rho_tracking * omega_background) /
(2.0 * c1 * c2 * c2 * c2 - 6.0 * c1 * c2 * scf_gamma);
pba->attractor_regime_scf = 4; // small-field attractor (simple exponential)
if (pba->background_verbose > 0)
{
printf("Approximate small-field attractor (simple exponential) is used. We assign phi_ini_scf=%e and phi_prime_ini_scf=%e.\n", pvecback_integration[pba->index_bi_phi_scf], pvecback_integration[pba->index_bi_phi_prime_scf]);
}
}
}
break;In case we run into numerical errors with the initial conditions, we abort the computation.
class_test(!isfinite(pvecback_integration[pba->index_bi_phi_scf]) ||
!isfinite(pvecback_integration[pba->index_bi_phi_prime_scf]),
pba->error_message,
"initial phi = %e phi_prime = %e -> check initial conditions",
pvecback_integration[pba->index_bi_phi_scf],
pvecback_integration[pba->index_bi_phi_prime_scf]);