|
PISM, A Parallel Ice Sheet Model
stable v0.5
|
00001 00002 /* 00003 Usage: ./test_cube <dim> <tol> <integrand> <maxeval> 00004 00005 where <dim> = # dimensions, <tol> = relative tolerance, 00006 <integrand> is either 0/1/2 for the three test integrands (see below), 00007 and <maxeval> is the maximum # function evaluations (0 for none). 00008 */ 00009 00010 /* author Steven G. Johnson */ 00011 00012 #include "cubature.h" 00013 #include <math.h> 00014 00015 int count = 0; 00016 int which_integrand = 0; 00017 const double radius = 0.50124145262344534123412; /* random */ 00018 00019 double f_test(unsigned dim, const double *x, void *data) 00020 { 00021 double val; 00022 unsigned i; 00023 ++count; 00024 switch (which_integrand) { 00025 case 0: /* discontinuous objective: volume of hypersphere */ 00026 val = 0; 00027 for (i = 0; i < dim; ++i) 00028 val += x[i] * x[i]; 00029 val = val < radius * radius; 00030 break; 00031 case 1: /* simple smooth (separable) objective: prod. cos(x[i]). */ 00032 val = 1; 00033 for (i = 0; i < dim; ++i) 00034 val *= cos(x[i]); 00035 break; 00036 case 2: { /* integral of exp(-x^2), rescaled to (0,infinity) limits */ 00037 double scale = 1.0; 00038 val = 0; 00039 for (i = 0; i < dim; ++i) { 00040 double z = (1 - x[i]) / x[i]; 00041 val += z * z; 00042 scale *= M_2_SQRTPI / (x[i] * x[i]); 00043 } 00044 val = exp(-val) * scale; 00045 break; 00046 } 00047 00048 default: 00049 fprintf(stderr, "unknown integrand %d\n", which_integrand); 00050 exit(EXIT_FAILURE); 00051 } 00052 /* if (count < 100) printf("%d: f(%g, ...) = %g\n", count, x[0], val); */ 00053 return val; 00054 } 00055 00056 /* surface area of n-dimensional unit hypersphere */ 00057 static double S(unsigned n) 00058 { 00059 double val; 00060 int fact = 1; 00061 if (n % 2 == 0) { /* n even */ 00062 val = 2 * pow(M_PI, n * 0.5); 00063 n = n / 2; 00064 while (n > 1) fact *= (n -= 1); 00065 val /= fact; 00066 } 00067 else { /* n odd */ 00068 val = (1 << (n/2 + 1)) * pow(M_PI, n/2); 00069 while (n > 2) fact *= (n -= 2); 00070 val /= fact; 00071 } 00072 return val; 00073 } 00074 00075 static double exact_integral(unsigned dim, const double *xmax) { 00076 unsigned i; 00077 double val; 00078 switch(which_integrand) { 00079 case 0: 00080 val = dim == 0 ? 1 : S(dim) * pow(radius * 0.5, dim) / dim; 00081 break; 00082 case 1: 00083 val = 1; 00084 for (i = 0; i < dim; ++i) 00085 val *= sin(xmax[i]); 00086 break; 00087 case 2: 00088 val = 1; 00089 break; 00090 default: 00091 fprintf(stderr, "unknown integrand %d\n", which_integrand); 00092 exit(EXIT_FAILURE); 00093 } 00094 return val; 00095 } 00096 00097 int main(int argc, char **argv) 00098 { 00099 double *xmin, *xmax; 00100 double tol, val, err; 00101 unsigned i, dim, maxEval; 00102 00103 dim = argc > 1 ? atoi(argv[1]) : 2; 00104 tol = argc > 2 ? atof(argv[2]) : 1e-2; 00105 which_integrand = argc > 3 ? atoi(argv[3]) : 1; 00106 maxEval = argc > 4 ? atoi(argv[4]) : 0; 00107 00108 xmin = (double *) malloc(dim * sizeof(double)); 00109 xmax = (double *) malloc(dim * sizeof(double)); 00110 for (i = 0; i < dim; ++i) { 00111 xmin[i] = 0; 00112 xmax[i] = 1 + (which_integrand == 2 ? 0 : 0.4 * sin(i)); 00113 } 00114 00115 printf("%u-dim integral, tolerance = %g, integrand = %d\n", 00116 dim, tol, which_integrand); 00117 adapt_integrate(f_test, 0, dim, xmin, xmax, maxEval, 0, tol, &val, &err); 00118 printf("integration val = %g, est. err = %g, true err = %g\n", 00119 val, err, fabs(val - exact_integral(dim, xmax))); 00120 printf("#evals = %d\n", count); 00121 00122 free(xmax); 00123 free(xmin); 00124 00125 return 0; 00126 } 00127
1.7.5.1