-
Notifications
You must be signed in to change notification settings - Fork 32
Extending hi_class
How to add a new gravity model to hi_class v3, either a covariant (Lagrangian-based) theory or a parametrization of the α-functions. The short version: covariant models are specified by filling one struct of Horndeski G-functions, and everything else — background equations, α-functions, perturbations, stability tests — is derived from it automatically.
All modified-gravity code lives in the gravity_smg/ directory, kept separate from the standard CLASS modules in source/ (which only contain thin hooks calling into it):
-
gravity_smg/gravity_models_smg.c— everything that is model-specific: parsinggravity_modelfrom the ini file, reading and validatingparameters_smg, the G-functions of each covariant theory, the α-functions of each parametrization, expansion histories, initial conditions, and the "Modified gravity: …" banner printed at startup. This is where most of a new model goes. -
gravity_smg/gravity_functions_smg.c— model-independent machinery that turns the G-functions into everything else:gravity_functions_Es_from_Gs_smg(coefficients of the Friedmann constraint E0 + E1·H + E3·H³ = E2·H², solved algebraically for H),gravity_functions_Ps_and_Rs_from_Gs_smg(coefficients of the coupled H′ and φ″ equations),gravity_functions_building_blocks_from_Gs_smg(ρ_smg, p_smg, the effective Planck mass M² and the α-functions), andgravity_functions_As_from_alphas_smg/..._Bs_from_Gs_smg/..._Cs_from_Bs_smg(the coefficients entering the perturbation equations). You should not need to touch this file for a Horndeski model. -
gravity_smg/background_smg.c— the background driver:background_gravity_functions_smginitializes a G-functions struct to its GR defaults, calls the model dispatch to fill it, and chains thegravity_functions_*routines; also initial-condition plumbing (background_initial_conditions_smg), the background output columns (background_store_columntitles_smg,background_output_data_smg) and the post-integrationstability_tests_smg. -
gravity_smg/perturbations_smg.c— the linear perturbation equations (perturbations_einstein_scalar_smg,perturbations_einstein_tensor_smg), the scalar-field initial conditions and their consistency tests (perturbations_tests_smg), and the quasi-static approximation machinery. Model-independent; new Horndeski models never touch it. -
gravity_smg/input_smg.c— ini-file plumbing:input_read_parameters_smgreads the common flags and delegates model parsing togravity_models_gravity_properties_smgandgravity_models_expansion_properties_smg;input_default_params_smgholds the defaults for every_smgswitch. -
gravity_smg/hmcode_smg.c— the_smgcorrections used by the nonlinear (HMcode / fourier) module. -
gravity_smg/include/— one header per file with the prototypes, plushi_class.hand theG_functions_and_derivsstruct ingravity_models_smg.h.
A covariant model in hi_class is a Horndeski (or GLPV) Lagrangian
L = G₂(φ,X) − G₃(φ,X) □φ + G₄(φ,X) R + … + G₅ and beyond-Horndeski F₄, F₅ terms,
and the code represents it as struct G_functions_and_derivs, defined in gravity_smg/include/gravity_models_smg.h. Its members are the values of G₂, G₃, G₄, G₅, F₄, F₅ and all the partial derivatives with respect to φ and the kinetic term X that the equations of motion need — G2, G2_X, G2_phi, G2_Xphi, … up to fourth derivatives for G₄/G₅ (e.g. G4_XXXphi). The macro DEFAULT_G_FUNCTIONS_AND_DERIVS in the same header initializes every entry to zero except G4 = 1/2, i.e. exactly General Relativity in the code's units (there is also DG4 = G4 − 1/2, the deviation from GR, which improves numerical precision when G₄ is close to ½).
A new Horndeski model is specified entirely by overwriting the nonzero entries of this struct as functions of φ, φ′ and the model parameters. That happens in one place: gravity_models_get_Gs_smg in gravity_models_smg.c, a chain of if (pba->gravity_model_smg == …) blocks, one per model, each computing X = (φ′/a)²/2 from the integrator variables and filling in its G's. Every quantity downstream — H, φ″, ρ_smg, the α-functions, the perturbation coefficients, the stability variables — is computed from the struct by generic code. You never write the equations of motion yourself.
Derivatives you leave untouched stay at their GR value, so a minimally coupled quintessence model sets only four entries and a conformally coupled cubic galileon about eight. Consistency matters: if you set G4, also set DG4 and every φ/X derivative of your G₄ that is nonzero.
The complete list of places a new model touches, taken from the most recent worked example — commit 31382d65 in the development repository, which adds the conformally coupled cubic galileon (cccg_exp). That commit changes exactly six files:
gravity_models/cccg_exp.ini
gravity_models/cccg_exp_canonical.ini
gravity_smg/gravity_models_smg.c
gravity_smg/input_smg.c
hi_class.ini
include/background.h
Working through them in a sensible order:
1. Register the model enum — include/background.h. Add your model's name to enum gravity_model. If your model has variants (branches, sub-cases fixing some parameters), add them to enum gravity_submodel; the parsed value is stored in pba->gravity_submodel_smg (its default, unspecified, is set in input_default_params_smg in input_smg.c).
2. Parse the parameters — gravity_models_gravity_properties_smg in gravity_models_smg.c. This function is a chain of if (strcmp(string1,"model_name") == 0) blocks. Yours must:
- set
pba->gravity_model_smgto your enum value andflag2 = _TRUE_(the flag that marks the model name as recognized); - set
pba->field_evolution_smg = _TRUE_— this is what tells the code to integrate φ and solve the Friedmann equation self-consistently, so covariant models need noexpansion_model; - set
pba->parameters_size_smgand read the parameter vector withclass_read_list_of_doubles("parameters_smg", pba->parameters_smg, pba->parameters_size_smg)(the macro also checks the user supplied the right number); - set the shooting defaults:
pba->tuning_index_smg(which entry ofparameters_smgthe code varies to hit the requested Ω_smg today) andpba->tuning_dxdy_guess_smg(an estimate of d(parameter)/dΩ_smg to start the shooting), guarded byhas_tuning_index_smgso a user-supplied choice wins. The shooting itself lives insource/input.cand needs nothing model-specific beyond these two numbers. - optionally handle submodels: read
gravity_submodelwithparser_read_string, translate the user-facing parameters of each branch into the internalparameters_smgordering, and setpba->gravity_submodel_smg. Thecccg_expblock is a full example, including a secondary shooting parameter (tuning_index_2_smg) that tunes the Planck mass today.
Also extend the class_test at the bottom of the function — the error string listing all valid gravity_model values — so a typo in another model's name produces an up-to-date message.
3. The G-functions — gravity_models_get_Gs_smg in gravity_models_smg.c. Add an else if (pba->gravity_model_smg == your_model) block that unpacks pba->parameters_smg and fills the G_functions_and_derivs struct, as described above. For cccg_exp this block is ~25 lines: G₂ = c₂X − 3V₀H₀², G3_X, and G₄ = e^{βφ}/2 with DG4, G4_phi, G4_phiphi.
4. Initial conditions — gravity_models_initial_conditions_smg in gravity_models_smg.c. A switch (pba->gravity_model_smg) over models; add a case that sets pvecback_integration[pba->index_bi_phi_smg] and pvecback_integration[pba->index_bi_phi_prime_smg] at the initial scale factor a (deep in radiation domination; rho_rad is passed in for attractor-type conditions). This is called from background_initial_conditions_smg in background_smg.c, which adds generic sanity checks — you normally only touch the gravity_models_ side. Prefer physically meaningful IC parameters: cccg_exp takes Ω_smg(z = 10¹⁰) and M²(a_ini) from the user and converts them to φ_ini, φ′_ini on the early-time attractor.
5. Startup banner — gravity_models_print_stdout_smg in gravity_models_smg.c. Add a case printing the model name and parameters when background_verbose > 0.
6. Expansion history — usually nothing. Because field_evolution_smg = _TRUE_, the expansion is computed from your Lagrangian and the expansion_model machinery (gravity_models_expansion_properties_smg, gravity_models_get_back_par_smg) is bypassed entirely. Only parametrized models use it.
7. Documentation — hi_class.ini. Add one line to the enumerated list of covariant theories under the gravity_model explanation.
8. Example ini — gravity_models/your_model.ini. Ship a runnable example: a comment block stating the Lagrangian and the meaning/ordering of parameters_smg, the gravity_model (+ gravity_submodel) and parameters_smg lines, and — crucially — any stability workarounds the model needs, with comments explaining why (e.g. cccg_exp.ini sets a_min_stability_test_smg = 1e-6 and zero scalar-field perturbation ICs because at early times its kinetic determinant is at machine-noise level). Remember Omega_Lambda = 0, Omega_fld = 0, Omega_smg = -1 (the −1 requests shooting on Ω_smg).
Parametrizations skip the Lagrangian: they keep pba->field_evolution_smg = _FALSE_, choose an expansion_model for the background, and specify the α-functions directly as functions of time. Two places in gravity_models_smg.c:
-
Parsing, again in
gravity_models_gravity_properties_smg: likepropto_omega, set the model enum,field_evolution_smg = _FALSE_,M2_evolution_smg = _TRUE_(so the running of M² is integrated),parameters_2_size_smg, and read intopba->parameters_2_smg(parametrizations use theparameters_2_smgvector;parameters_smgbelongs to the expansion history). -
The α-functions, in
gravity_models_get_alphas_par_smg: a chain ofif (pba->gravity_model_smg == …)blocks, each fillingpvecback[pba->index_bg_kineticity_smg],index_bg_braiding_smg,index_bg_tensor_excess_smg,index_bg_M2_running_smgand the Planck-mass entries at the given scale factor. Thepropto_omegablock (each α proportional to Ω_smg(a)) is the template. Quantities like Ω_smg = ρ_smg/ρ_tot are already available inpvecback.
If you also need a new background evolution, add it to enum expansion_model in include/background.h, its parsing to gravity_models_expansion_properties_smg, and its ρ_smg, p_smg to gravity_models_get_back_par_smg. See Models: Parametrized alphas and Models: Expansion history for the user-facing side.
-
Watch the background. Run with
background_verbose = 4or higher: you get the shooting iterations, the initial φ, φ′, and (at high verbosity) the M²-tuning steps.gravity_models_print_stdout_smgconfirms the parameters were parsed as you intended. -
Dump the diagnostics. Set
write_background = yesandoutput_background_smg = 3: the background table then includes the α-functions, the stability variables c_s², D, M², c_t², the field variables φ, φ′, φ″ with the Friedmann-constraint residual, and the perturbation coefficients λ_i. Column meanings are in Output files. -
Respect the stability tests. After integration,
stability_tests_smg(inbackground_smg.c) aborts on ghost (D < 0, M² < 0) or gradient (c_s² < 0, c_t² < 0) instabilities, andperturbations_tests_smgchecks the scalar-field initial conditions. If a healthy model trips them through early-time rounding noise (common when Ω_smg starts at ~10⁻¹⁵), the sanctioned knobs area_min_stability_test_smg, the*_safe_smgtolerances and the choice ofpert_initial_conditions_smg— document whichever you use in the example ini. See Stability and precision. -
Compare limits. Every new model should reproduce a known one in some corner of its parameter space: couplings → 0 should give ΛCDM/quintessence, and special parameter choices often reduce to a shipped model (e.g.
cccg_expwith β = 0 contains the cubic galileon). Compare C_ℓ, P(k) and H(z) against the limit model at the 10⁻⁴ level or better, and against an independent implementation if one exists.
Commit 31382d65 in the development repository adds a complete model (cccg_exp, the conformally coupled cubic galileon of arXiv:2003.06396) in a single self-contained diff — enum, parsing with two submodels and a secondary tuning, G-functions, attractor initial conditions, documentation and two example inis — and can be read as a template for all of the above. The user-facing documentation of the shipped covariant models is in Models: Covariant theories.
Getting started
Models
Reference
Development
Background
External