Skip to content

Integrating gp4c with CLASS

This guide explains how to use gp4c (GP sampler for f, integral, derivative) inside CLASS, the Cosmic Linear Anisotropy Solving System.

Prerequisites

  • CLASS source code
  • GSL (GNU Scientific Library) - CLASS already requires this
  • gp4c source files (gp4c.c and gp4c.h)

The simplest approach is to copy the two source files directly into your CLASS project.

Step 1: Copy files

# From the gp4c repository root
cp gp4c/gp4c.c gp4c/gp4c.h /path/to/class/external/gp4c/

Or create the directory if it doesn't exist:

mkdir -p /path/to/class/external/gp4c
cp gp4c/gp4c.c gp4c/gp4c.h /path/to/class/external/gp4c/

Step 2: Modify CLASS Makefile

Add to your CLASS Makefile:

# Add to INCLUDES
INCLUDES += -I../external/gp4c

# Add to vpath for source files
vpath %.c ../external/gp4c

# Add to object files
EXTERNAL += gp4c.o

Note: GSL is already linked by CLASS, so no additional library flags are needed.

Step 3: Use in your CLASS code

#include "gp4c.h"

// Example: Sample GP prior for f and its integral g
void my_gp_sampling_function() {
    int n = 100;
    double x[100];
    for (int i = 0; i < n; i++) {
        x[i] = 10.0 * i / (n - 1);  // 0 to 10
    }

    double *f_samples = malloc(n * sizeof(double));
    double *g_samples = malloc(n * sizeof(double));

    int status = draw_joint_gp_samples(
        x, n,           // f evaluation points
        x, n,           // g evaluation points
        1.0, 0.5,       // sigma2, ell
        KERNEL_RBF,     // kernel type
        1, 42,          // n_samples, seed
        f_samples,
        g_samples,
        NULL            // zero mean
    );

    if (status != 0) {
        // Handle error
    }

    // Use f_samples and g_samples...

    free(f_samples);
    free(g_samples);
}

Method 2: System Install via pkg-config

If you prefer a system-wide installation:

Step 1: Install gp4c

# From the gp4c repository root
./install_library.sh --user   # Installs to ~/.local
# OR
sudo ./install_library.sh     # Installs to /usr/local

Step 2: Configure environment (for --user install)

Add to your ~/.bashrc or ~/.zshrc:

export PKG_CONFIG_PATH="$HOME/.local/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$HOME/.local/lib:$LD_LIBRARY_PATH"      # Linux only
# Note: DYLD_LIBRARY_PATH not needed on macOS (install_name is set correctly)

Step 3: Modify CLASS Makefile

# Add to CCFLAG
CCFLAG += $(shell pkg-config --cflags gp4c)

# Add to LDFLAG
LDFLAG += $(shell pkg-config --libs gp4c)

Step 4: Verify installation

pkg-config --modversion gp4c  # Should print 2.0.0
pkg-config --cflags gp4c      # Should print -I/path/to/include
pkg-config --libs gp4c        # Should print -L/path/to/lib -lgp4c

Method 3: CMake (for CMake-based CLASS builds)

If using CMake:

find_package(gp4c REQUIRED)
target_link_libraries(class PRIVATE gp4c::gp4c)

API Quick Reference

Basic Sampling (f and integral g)

int draw_joint_gp_samples(
    const double *x_f, int n_f,     // f evaluation points
    const double *x_g, int n_g,     // g evaluation points
    double sigma2, double ell,      // kernel parameters
    KernelType kernel,              // KERNEL_RBF, KERNEL_MATERN52, KERNEL_MATERN32
    int n_samples, unsigned long seed,
    double *f_samples,              // output: (n_samples x n_f)
    double *g_samples,              // output: (n_samples x n_g)
    const GPMeanSpec *mean          // NULL for zero mean
);

Flexible Sampling (f, g, and derivative h)

int draw_gp_samples_flexible(
    const GPSamplingSpec *spec,     // specification struct
    double sigma2, double ell,
    KernelType kernel,
    int n_samples, unsigned long seed,
    double *f_samples,              // may be NULL
    double *g_samples,              // may be NULL
    double *h_samples,              // may be NULL (derivative)
    const GPMeanSpec *mean
);

Posterior Sampling (conditioned on observations)

int draw_gp_posterior_samples(
    const GPObservations *obs,      // observations
    const GPSamplingSpec *pred,     // prediction points
    double sigma2, double ell,
    KernelType kernel,
    int n_samples, unsigned long seed,
    double *f_samples, double *g_samples, double *h_samples,
    double *f_mean, double *g_mean, double *h_mean,
    const GPMeanSpec *mean
);

Kernel Types

typedef enum {
    KERNEL_RBF = 0,       // RBF/Squared Exponential (infinitely differentiable)
    KERNEL_MATERN52 = 1,  // Matern 5/2 (twice differentiable)
    KERNEL_MATERN32 = 2   // Matern 3/2 (once mean-square differentiable)
} KernelType;

Mean Specification

// For zero mean, pass NULL

// For constant mean:
GPMeanSpec mean;
mean.type = MEAN_CONSTANT;
mean.params.constant.value = 2.5;  // constant value

Example: Cosmological Application

Sample a GP for the dark energy equation of state w(z) and its integral:

#include "gp4c.h"

void sample_dark_energy_eos() {
    // Redshift grid
    int n_z = 50;
    double z[50];
    for (int i = 0; i < n_z; i++) {
        z[i] = 3.0 * i / (n_z - 1);  // z = 0 to 3
    }

    // GP hyperparameters
    double sigma2 = 0.1;   // Variance (controls amplitude of deviations)
    double ell = 0.5;      // Length scale (controls smoothness)

    // Allocate samples
    int n_samples = 100;
    double *w_samples = malloc(n_samples * n_z * sizeof(double));
    double *int_w_samples = malloc(n_samples * n_z * sizeof(double));

    // Sample from GP prior
    int status = draw_joint_gp_samples(
        z, n_z, z, n_z,
        sigma2, ell,
        KERNEL_MATERN52,    // Matern 5/2 for physical smoothness
        n_samples, 12345,
        w_samples,
        int_w_samples,
        NULL                // Zero mean (w = -1 + GP)
    );

    if (status == 0) {
        // Use samples for cosmological calculations
        // w(z) = -1 + w_samples[i]
        // integral of w(z) available in int_w_samples
    }

    free(w_samples);
    free(int_w_samples);
}

Troubleshooting

"undefined reference to draw_joint_gp_samples"

Make sure gp4c.o is being compiled and linked: - Check that gp4c.c is in the vpath - Check that gp4c.o is in the object file list

"gsl/gsl_rng.h: No such file or directory"

GSL headers not found. CLASS requires GSL, so this shouldn't happen if CLASS builds correctly. Check your GSL installation.

Numerical issues (singular matrix, NaN values)

  • Try increasing the length scale ell
  • The library uses adaptive jitter for numerical stability
  • For very small length scales, consider using fewer evaluation points

License

gp4c is released under the MIT License. See the main repository for details.