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.candgp4c.h)
Method 1: Direct Copy (Recommended)¶
The simplest approach is to copy the two source files directly into your CLASS project.
Step 1: Copy files¶
Or create the directory if it doesn't exist:
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:
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.