00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef O2SCL_GSL_INTE_QAG_H
00024 #define O2SCL_GSL_INTE_QAG_H
00025
00026 #include <o2scl/inte.h>
00027 #include <o2scl/gsl_inte_qag_b.h>
00028
00029 #ifndef DOXYGENP
00030 namespace o2scl {
00031 #endif
00032
00033
00034
00035
00036
00037
00038
00039 template<class param_t, class func_t> class gsl_inte_qag :
00040 public gsl_inte_kronrod<param_t,func_t> {
00041
00042 #ifndef DOXYGEN_INTERNAL
00043
00044 protected:
00045
00046
00047 int lkey;
00048
00049 #endif
00050
00051 public:
00052
00053 gsl_inte_qag() {
00054 lkey=1;
00055 }
00056
00057 virtual ~gsl_inte_qag() {}
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 int set_key(int key) {
00074 if (key>=1 && key<=6){
00075 lkey=key;
00076 return 0;
00077 }
00078 lkey=1;
00079 set_err_ret("Invalid key in gsl_inte_qag::set_key().",gsl_einval);
00080 }
00081
00082
00083
00084 int get_key() { return lkey; }
00085
00086
00087
00088 virtual double integ(func_t &func, double a, double b, param_t &pa) {
00089 double res, err;
00090 integ_err(func,a,b,pa,res,err);
00091 this->interror=err;
00092 return res;
00093 }
00094
00095
00096
00097
00098 virtual int integ_err(func_t &func, double a, double b,
00099 param_t &pa, double &res, double &err2) {
00100
00101 int status;
00102 gsl_integration_rule * integration_rule = gsl_integration_qk15;
00103
00104 if (lkey < GSL_INTEG_GAUSS15) {
00105 lkey = GSL_INTEG_GAUSS15;
00106 } else if (lkey > GSL_INTEG_GAUSS61) {
00107 lkey = GSL_INTEG_GAUSS61;
00108 }
00109
00110 switch (lkey) {
00111 case GSL_INTEG_GAUSS15:
00112 {
00113 double fv1[8], fv2[8];
00114 status=qag(func,8,o2scl_inte_qag_coeffs::qk15_xgk,
00115 o2scl_inte_qag_coeffs::qk15_wg,
00116 o2scl_inte_qag_coeffs::qk15_wgk,
00117 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00118 &res,&err2,pa);
00119 }
00120 break;
00121 case GSL_INTEG_GAUSS21:
00122 {
00123 double fv1[11], fv2[11];
00124 status=qag(func,11,o2scl_inte_qag_coeffs::qk21_xgk,
00125 o2scl_inte_qag_coeffs::qk21_wg,
00126 o2scl_inte_qag_coeffs::qk21_wgk,
00127 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00128 &res,&err2,pa);
00129 }
00130 break;
00131 case GSL_INTEG_GAUSS31:
00132 {
00133 double fv1[16], fv2[16];
00134 status=qag(func,16,o2scl_inte_qag_coeffs::qk31_xgk,
00135 o2scl_inte_qag_coeffs::qk31_wg,
00136 o2scl_inte_qag_coeffs::qk31_wgk,
00137 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00138 &res,&err2,pa);
00139 }
00140 break;
00141 case GSL_INTEG_GAUSS41:
00142 {
00143 double fv1[21], fv2[21];
00144 status=qag(func,21,o2scl_inte_qag_coeffs::qk41_xgk,
00145 o2scl_inte_qag_coeffs::qk41_wg,
00146 o2scl_inte_qag_coeffs::qk41_wgk,
00147 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00148 &res,&err2,pa);
00149 }
00150 break;
00151 case GSL_INTEG_GAUSS51:
00152 {
00153 double fv1[26], fv2[26];
00154 status=qag(func,26,o2scl_inte_qag_coeffs::qk51_xgk,
00155 o2scl_inte_qag_coeffs::qk51_wg,
00156 o2scl_inte_qag_coeffs::qk51_wgk,
00157 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00158 &res,&err2,pa);
00159 }
00160 break;
00161 case GSL_INTEG_GAUSS61:
00162 {
00163 double fv1[31], fv2[31];
00164 status=qag(func,31,o2scl_inte_qag_coeffs::qk61_xgk,
00165 o2scl_inte_qag_coeffs::qk61_wg,
00166 o2scl_inte_qag_coeffs::qk61_wgk,
00167 fv1,fv2,a,b,this->tolx,this->tolf,this->wkspace,
00168 &res,&err2,pa);
00169 }
00170 break;
00171 default:
00172 GSL_ERROR("value of key does specify a known integration rule",
00173 GSL_EINVAL);
00174 }
00175
00176 return status;
00177
00178 }
00179
00180 #ifndef DOXYGEN_INTERNAL
00181
00182 protected:
00183
00184
00185
00186
00187
00188 int qag(func_t &func, const int qn, const double xgk[],
00189 const double wg[], const double wgk[], double fv1[],
00190 double fv2[], const double a, const double b,
00191 const double l_epsabs, const double l_epsrel, const size_t limit,
00192 double *result, double *abserr, param_t &pa)
00193 {
00194 double area, errsum;
00195 double result0, abserr0, resabs0, resasc0;
00196 double tolerance;
00197 size_t iteration = 0;
00198 int roundoff_type1 = 0, roundoff_type2 = 0, error_type = 0;
00199
00200 double round_off;
00201
00202
00203
00204 initialise (this->w, a, b);
00205
00206 *result = 0;
00207 *abserr = 0;
00208
00209 if (limit > this->w->limit) {
00210 GSL_ERROR("iteration limit exceeds available workspace",
00211 GSL_EINVAL);
00212 }
00213
00214 if (l_epsabs <= 0 &&
00215 (l_epsrel < 50 * GSL_DBL_EPSILON || l_epsrel < 0.5e-28)) {
00216 GSL_ERROR("tolerance can't be acheived with given tolx & tolf",
00217 GSL_EBADTOL);
00218 }
00219
00220
00221
00222 gsl_integration_qk_o2scl(func,qn,xgk,wg,wgk,fv1,fv2,a,b,
00223 &result0,&abserr0,&resabs0,&resasc0,pa);
00224
00225 set_initial_result(this->w,result0,abserr0);
00226
00227
00228
00229 tolerance = GSL_MAX_DBL(l_epsabs, l_epsrel * fabs (result0));
00230
00231
00232
00233 round_off=gsl_coerce_double(50 * GSL_DBL_EPSILON * resabs0);
00234
00235 if (abserr0 <= round_off && abserr0 > tolerance) {
00236 *result = result0;
00237 *abserr = abserr0;
00238
00239 GSL_ERROR ("cannot reach tolerance because of roundoff error "
00240 "on first attempt", GSL_EROUND);
00241 } else if ((abserr0 <= tolerance &&
00242 abserr0 != resasc0) || abserr0 == 0.0) {
00243 *result = result0;
00244 *abserr = abserr0;
00245
00246 return gsl_success;
00247 } else if (limit == 1) {
00248 *result = result0;
00249 *abserr = abserr0;
00250
00251 GSL_ERROR("a maximum of one iteration was insufficient",
00252 GSL_EMAXITER);
00253 }
00254
00255 area = result0;
00256 errsum = abserr0;
00257
00258 iteration = 1;
00259 do {
00260 double a1, b1, a2, b2;
00261 double a_i, b_i, r_i, e_i;
00262 double area1 = 0, area2 = 0, area12 = 0;
00263 double error1 = 0, error2 = 0, error12 = 0;
00264 double resasc1, resasc2;
00265 double resabs1, resabs2;
00266
00267
00268
00269 retrieve (this->w, &a_i, &b_i, &r_i, &e_i);
00270
00271 a1 = a_i;
00272 b1 = 0.5 * (a_i + b_i);
00273 a2 = b1;
00274 b2 = b_i;
00275
00276 gsl_integration_qk_o2scl(func,qn,xgk,wg,wgk,fv1,fv2,a1,b1,
00277 &area1,&error1,&resabs1,&resasc1,pa);
00278 gsl_integration_qk_o2scl(func,qn,xgk,wg,wgk,fv1,fv2,a2,b2,
00279 &area2,&error2,&resabs2,&resasc2,pa);
00280
00281 area12 = area1 + area2;
00282 error12 = error1 + error2;
00283
00284 errsum += (error12 - e_i);
00285 area += area12 - r_i;
00286
00287 if (resasc1 != error1 && resasc2 != error2)
00288 {
00289 double delta = r_i - area12;
00290
00291 if (fabs (delta) <= 1.0e-5 * fabs (area12) &&
00292 error12 >= 0.99 * e_i)
00293 {
00294 roundoff_type1++;
00295 }
00296 if (iteration >= 10 && error12 > e_i)
00297 {
00298 roundoff_type2++;
00299 }
00300 }
00301
00302 tolerance = GSL_MAX_DBL (l_epsabs, l_epsrel * fabs (area));
00303
00304 if (errsum > tolerance)
00305 {
00306 if (roundoff_type1 >= 6 || roundoff_type2 >= 20)
00307 {
00308 error_type = 2;
00309 }
00310
00311
00312
00313 if (this->subinterval_too_small (a1, a2, b2))
00314 {
00315 error_type = 3;
00316 }
00317 }
00318
00319 update (this->w, a1, b1, area1, error1, a2, b2, area2, error2);
00320
00321 retrieve (this->w, &a_i, &b_i, &r_i, &e_i);
00322
00323 if (this->verbose>0) {
00324 std::cout << "gsl_inte_qag Iter: " << iteration;
00325 std::cout.setf(std::ios::showpos);
00326 std::cout << " Res: " << area;
00327 std::cout.unsetf(std::ios::showpos);
00328 std::cout << " Err: " << errsum
00329 << " Tol: " << tolerance << std::endl;
00330 if (this->verbose>1) {
00331 char ch;
00332 std::cout << "Press a key and type enter to continue. " ;
00333 std::cin >> ch;
00334 }
00335 }
00336
00337 iteration++;
00338
00339 } while (iteration < limit && !error_type &&
00340 errsum > tolerance);
00341
00342 *result = sum_results (this->w);
00343 *abserr = errsum;
00344
00345 if (errsum <= tolerance) {
00346 return gsl_success;
00347 } else if (error_type == 2) {
00348 GSL_ERROR("roundoff error prevents tolerance from being achieved",
00349 GSL_EROUND);
00350 } else if (error_type == 3) {
00351 GSL_ERROR("bad integrand behavior found in integration interval",
00352 GSL_ESING);
00353 } else if (iteration == limit) {
00354 GSL_ERROR("maximum number of subdivisions reached",GSL_EMAXITER);
00355 } else {
00356 GSL_ERROR("could not integrate function",GSL_EFAILED);
00357 }
00358 }
00359
00360 #endif
00361
00362
00363 const char *type() { return "gsl_inte_qag"; }
00364
00365 };
00366
00367 #ifndef DOXYGENP
00368 }
00369 #endif
00370
00371 #endif