Skip to content

Code2:indexing

ardok-m edited this page Jun 27, 2017 · 6 revisions

Code 2: Indexing

When CLASS runs, it fills different arrays and tables so that each position is reserved to one variable. Nevertheless, there is nothing special in this. The elegant idea comes from the fact that, instead of using numbers to access those values, CLASS use "abstract" indices.

In other words, suppose you want to use the redshift value at a time. Say that its associated index number is 0, then to recover its value you would do pvecback[0]. Nevertheless, if you introduced a new variable and placed it before the redshift value, pvecback[0] would be the value of this new variable instead of that of 'z', which would be pvecback[1], having to check and update all your code. This will become messier as the number of variables grows and, specially, makes the code more dificult to debug and develop.

The CLASS approach, instead, is dynamically linking the index numbers, i.e. you would never access redshift value using the actual index value, but using a variable that links to it: pba->index_bg_z. Then, you would write pvecback[pba->index_bg_z] and would not have to update all your code in case a new variable was introduced.

This assotiation is done in all modules, except input.c which does not store any value in tables, by the functions xxx_indices(...). In addition, there is an specific macro to assing indices: class_define_index(...) (defined in include/common.h:234):

    /* macro for defining indices (usually one, sometimes a block) */
#define class_define_index(index,                                       \
                           condition,                                   \
                           running_index,                               \
                           number_of_indices) {                         \
    if (condition) {                                                    \
      index = running_index;                                            \
      running_index += number_of_indices;                               \
    }                                                                   \
  }

Note: number_of_indices is usually 1 but could be more if different species of the same kind were defined. A good example are these lines (source/background.c:766):

  /* - indices for ncdm. We only define the indices for ncdm1
     (density, pressure, pseudo-pressure), the other ncdm indices
     are contiguous */
  class_define_index(pba->index_bg_rho_ncdm1,pba->has_ncdm,index_bg,pba->N_ncdm);
  class_define_index(pba->index_bg_p_ncdm1,pba->has_ncdm,index_bg,pba->N_ncdm);
  class_define_index(pba->index_bg_pseudo_p_ncdm1,pba->has_ncdm,index_bg,pba->N_ncdm);

Adding new indices

Based on https://lesgourg.github.io/class-tour/Tokyo2014/lecture5_index_and_error.pdf

  • All indices are called index_xx_name-of-variable (e.g. index_bg_cdm).

  • They must be declared in the corresponding structure in the module header include/xxx.h

  • In the same structure, the associated new flag is declared (e.g. has_cdm) if the new variable will not be always stored.

  • In the corresponding xxx_indices(...) write the piece of code to assign the index to index_xx_name-of-variable, e.g. (source/background.c:690)

    int background_indices(
                         struct background *pba
                         ) {
    
    /** Summary: */
    
    /** - define local variables */
    
    /* a running index for the vector of background quantities */
    int index_bg;
    /* a running index for the vector of background quantities to be integrated */
    int index_bi;
    
    /** - initialize all flags: which species are present? */
    
    pba->has_cdm = _FALSE_;
    
      [...]
    
    if (pba->Omega0_cdm != 0.)
      pba->has_cdm = _TRUE_;
    
    /* - intialization of all indices */
    
    index_bg=0;
    
    [...]
    
    /* - index for rho_cdm */
     class_define_index(pba->index_bg_rho_cdm,pba->has_cdm,index_bg,1);