- #1
CAF123
Gold Member
- 2,948
- 88
I am trying to perform a four dimensional integration in cpp using gsl. I do this by nesting together the one-dimensional integration routines from gsl library. What I wrote seems to work for a few test integrands but I am having trouble with the integrand that I actually want a value for. See below for the full code I am using.
The code works okay for simpler integrands than the exp1*exp2 declared in the opening function declaration. E.g. for bx*by*bx1*by1 or sqrt[z1*z2+bx1*by1]. The problem is in r2, and in particular due to the combination in the sqrt: bx*bx-bx1*bx1 and the fact there is a relative minus (change this to a + and code is OK). I have however been able to my integral in mathematica so I am trying to understand why there is a problem here in gsl. I have played with the relative and absolute error accuracy parameters. Thanks in advance for any comments about this and/or if there is a way to do a multi dimensional integration in gsl more efficiently.
C++:
#include <iostream>
#include <gsl/gsl_integration.h>
#include <math.h>
#include <complex>
double b = 7.2;
double c = 0.130477;
double d = 0.549;
struct Params_t {
double z1, z2, bx1, by1, bx, by;
};
double f (double z1, void * params) {
Params_t& Params = *(Params_t *)(params);
double z2 = Params.z2;
double bx1 = Params.bx1;
double by1 = Params.by1;
double bx = Params.bx;
double by = Params.by;
double r1 = sqrt( z1*z1 + bx1*bx1 + by1*by1 );
double r2 = sqrt( z2*z2 + bx*bx-bx1*bx1 + by*by-by1*by1 );
double exp1 = c/(1. + exp( (r1-b)/d) );
double exp2 = c/(1. + exp( (r2-b)/d) );
return exp1*exp2;
}
double firstIntegrand(double z2, void * params) { //does the integration over z1 and sets up function ready for integration over z2 (with bx1,by1 kept fixed)
Params_t& Params = *(Params_t *)(params);
double epsabs = 1e-5;
double epsrel = 1e-5;
double lower = 0.;
double upper = 10;
double result, error;
Params_t custom_Params;
custom_Params.z2=z2;
double bx1 = Params.bx1;
double by1 = Params.by1;
double bx = Params.bx;
double by = Params.by;
custom_Params.bx1=bx1;
custom_Params.by1=by1;
custom_Params.bx=bx;
custom_Params.by=by;
gsl_integration_workspace * ws = gsl_integration_workspace_alloc (3e8);
gsl_function F;
F.function = &f;
F.params = &custom_Params;
gsl_integration_qags (&F, lower, upper, epsabs, epsrel, 3e8,
ws, &result, &error);
gsl_integration_workspace_free (ws);
return result;
}
double secondIntegrand(double bx1, void * params) { //does the integration over z2 and sets up function ready for integration over bx1 (with by1 kept fixed)
Params_t& Params = *(Params_t *)(params);
double epsabs = 0;
double epsrel = 1e-7;
double lower = 0;
double upper = 10;
double result, error;
Params_t custom_Params;
custom_Params.bx1=bx1;
double by1 = Params.by1;
double bx = Params.bx;
double by = Params.by;
custom_Params.by1=by1;
custom_Params.bx=bx;
custom_Params.by=by;
gsl_integration_workspace * ws = gsl_integration_workspace_alloc (3e8);
gsl_function F;
F.function = &firstIntegrand;
F.params = &custom_Params;
gsl_integration_qags (&F, lower, upper, epsabs, epsrel, 3e8,
ws, &result, &error);
gsl_integration_workspace_free (ws);
return result;
}
double thirdIntegrand(double by1, void * params) { //does the integration over bx1 and sets up function ready for integration over by1
Params_t& Params = *(Params_t *)(params);
double epsabs = 0;
double epsrel = 1e-7;
double lower = 0.;
double upper = 10;
double result, error;
Params_t custom_Params;
custom_Params.by1 = by1;
double bx = Params.bx;
double by = Params.by;
custom_Params.bx=bx;
custom_Params.by=by;
gsl_integration_workspace * ws = gsl_integration_workspace_alloc (3e8);
gsl_function F;
F.function = &secondIntegrand;
F.params = &custom_Params;
gsl_integration_qags (&F, lower, upper, epsabs, epsrel, 3e8,
ws, &result, &error);
gsl_integration_workspace_free (ws);
return result;
}
double fourthIntegrand(double bx, double by) { //does the integration over by1 finally
double epsabs = 0.;
double epsrel = 1e-7;
double lower = 0.;
double upper = 10;
double result, error;
Params_t custom_Params;
custom_Params.bx=bx;
custom_Params.by=by;
gsl_integration_workspace * ws = gsl_integration_workspace_alloc (3e8);
gsl_function F;
F.function = &thirdIntegrand;
F.params = &custom_Params;
gsl_integration_qags (&F, lower, upper, epsabs, epsrel, 3e8,
ws, &result, &error);
gsl_integration_workspace_free (ws);
return result;
}
int main(int argc, const char * argv[]) {
std::cout << fourthIntegrand(0.2,0.3) << std::endl; //prints out val of four dim integration for a particular value of bx and by
}