Chapter 4: C Interface

4.1: Functions

The integrand function has to be defined with the following arguments:
typedef void (*C_Integrand)(double x[], int k[], double* wgt,
                            double aux[], double f[]);

void fxn(double x[], int k[], double* wgt, double aux[], double f[]);

The array x[] contains the random numbers for the continuous dimensions, the array k[] contains the random numbers for the discrete dimensions, the array aux[] contains the auxilliary random numbers. The VEGAS weight (For each iteration the sum of the weights is normalized to 1.) is passed in variable wgt, so that it can be passed on to functions that fill histograms, for example. The function *fxn is expected to fill the array f[] with the function values that correspond to the arguments x[0], x[1], ..., k[0], k[1], ... and aux[0], aux[1], ... The value of the first function is assigned to f[0]. The integration is optimized for this function according to the VEGAS algorithm. Secondary functions can simultaneously be integrated and their values are expected to be returned as f[1], f[2], etc.

First this function has to be called:

void dvegas_init_(int* cdim, int* nsdim, int* cnbin, int* ddim, int* adim,
                  int nvals[], int* fn, C_Integrand fxn);
which sets the following (internal) variables:

cdim: number of continuous dimensions
nsdim: number of non-separable continuous dimensions (first nsdim dimensions)
cnbin: number of bins for each continuous dimension
ddim: number of discrete dimensions
adim: number of auxilliary dimensions (no adaptation)
nvals[]: number of values for each discrete dimension (see below)
fn: number of functions to integrate
fxn: pointer to integrand function

The default integration/summation range is

  • for continuous dimensions: (0, 1)
  • for discrete dimensions: {0, 1, 2, ..., nvals[dim]-1}
  • Random numbers in (0, 1) are provided to facilitate the addition of auxilliary dimensions that are not VEGAS driven.

    The parameters ddim or adim can be set to zero if no discrete or auxilliary dimensions are needed.

    Optional initialization calls:

    void dvegas_init_parallel_(int* ncpu);
    
    specify number of CPUs for multiprocessor machines (see section 5.1)
    void dvegas_init_output_();
    
    save status (init. parameters and weights) to file dvegas.dat-new after next dvegas_ call
    void dvegas_init_files_(char* outfile_, char* infile_, int outfile_len,
                            int infile_len);
    
    restore previously saved status from file inputfile and save new status to file outputfile
    Comment: The arguments outfile_len and infile_len are not really necessary in C, because C strings are NULL terminated. Fortran strings are unfortunately not terminated. Thus, in a C program it is sufficient that the values passed for outfile_len and infile_len are equal or larger than the actual string sizes. The exact values are irrelevant.

    After dVegas has been initialized you can make multiple calls to dvegas_:

    void dvegas_(longint* ncall, int* iterats, int* init, double integral[],
                 double error[], double redchi2[]);
    
    ncall: type longint, request ncall shots per iteration
    iterats, init: request iterats iterations, init is explained below
    integral[], error[], redchi2[]: accumulated results, errors and "reduced chi^2" = chi^2/(nr of estimates-1)

    The parameter init has the same meaning as in the original VEGAS program:

    init = 0: fresh start (no prior information)
    init = 1: use previous adaptation info, but discard shot data
    init = 2: use previous adaptation info and build on previous shots data

    4.2: C header

    The C header include/c_dvegas.h needs to be included in each program that uses dVegas. The C interface is implemented in src/c_dvegas.cpp. Note that c_dvegas does not stand for "C language dVegas", but rather for "C linkage dVegas", and is also the basis of the Fortran interface.

    4.3: Sample program

    #include <math.h>
    #include <stdio.h>
    #include "c_dvegas.h"
    
    void fxn2(double x[], int k[], double* wgt, double aux[], double f[]);
    
    int main()
    {
      int cdim  =  5 ;
      int nsdim =  0 ;
      int cnbin = 50 ;
      int ddim  =  1 ;
      int adim  =  0 ;
      int nvals[1] = { 100 };
      int fn    =  1 ;
    
      longint ncalls = 100000 ;
      int iterats ;
      int init ;
      double integral[1];
      double error[1];
      double redchi2[1];
      char inputfile[21] = "run2.in" ;
      char outputfile[21] = "run2.out" ;
      
      dvegas_init_(&cdim, &nsdim, &cnbin, &ddim, &adim, nvals, &fn, fxn2);
      /* 2 iterations with init = 0, no initial adaptation */
      iterats = 2 ; init = 0 ;
      dvegas_(&ncalls, &iterats, &init, integral, error, redchi2);
      /* result is 199.0 */
      printf("Result:\n");
      printf("integral = %f\n", integral[0]);
      printf("error    = %f\n", error[0]);
      printf("chi2/itn = %f\n\n", redchi2[0]);
      fflush(NULL);
      /* now 1 iteration with init = 1, use previous adaptation */
      iterats = 1 ; init = 1 ;
      /* save grid                                              */
      dvegas_init_output_();
      dvegas_(&ncalls, &iterats, &init, integral, error, redchi2);
      /* now another run after restoring adaptation from file */
      dvegas_init_files_(outputfile, inputfile, 20, 20);
      dvegas_(&ncalls, &iterats, &init, integral, error, redchi2);
    }
    
    void fxn2(double x[], int k[], double* wgt, double aux[], double f[])
    {
      if (k[0] < 99)
        f[0] =   1.0 * x[0]*x[1]*x[2]*x[3]*x[4]*pow(2.0,5.0);
      else if (k[0] == 99)
        f[0] = 100.0 * x[0]*x[1]*x[2]*x[3]*x[4]*pow(2.0,5.0);
    }