00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_GSL_INTE_QAWF_H 00024 #define O2SCL_GSL_INTE_QAWF_H 00025 00026 #include <o2scl/inte.h> 00027 #include <o2scl/gsl_inte_qawo.h> 00028 #include <o2scl/gsl_inte_qagiu.h> 00029 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /** 00035 \brief Adaptive integration for oscillatory integrals (GSL) 00036 00037 The number of subdivisions of the original interval which 00038 this class is allowed to make is dictated by the workspace 00039 size for the integration class, which can be set using 00040 \ref gsl_inte_table::set_wkspace() . 00041 00042 \todo Improve documentation a little 00043 */ 00044 template<class param_t, class func_t> class gsl_inte_qawf_sin : 00045 public gsl_inte_qawo_sin<param_t,func_t> { 00046 00047 public: 00048 00049 gsl_inte_qawf_sin() { 00050 } 00051 00052 virtual ~gsl_inte_qawf_sin() {} 00053 00054 /** \brief Integrate function \c func from \c a to \c b. 00055 */ 00056 virtual double integ(func_t &func, double a, double b, param_t &pa) { 00057 double res, err; 00058 integ_err(func,a,b,pa,res,err); 00059 this->interror=err; 00060 return res; 00061 } 00062 00063 /** \brief Integrate function \c func from \c a to \c b and place 00064 the result in \c res and the error in \c err 00065 */ 00066 virtual int integ_err(func_t &func, double a, double b, 00067 param_t &pa, double &res, double &err2) { 00068 00069 this->otable=gsl_integration_qawo_table_alloc 00070 (this->omega,1.0,GSL_INTEG_SINE,this->tab_size); 00071 cyclew=gsl_integration_workspace_alloc(this->wkspace); 00072 00073 int status=qawf(func,a,this->tolx,this->wkspace,&res,&err2,pa); 00074 00075 gsl_integration_qawo_table_free(this->otable); 00076 gsl_integration_workspace_free(cyclew); 00077 00078 return status; 00079 00080 } 00081 00082 #ifndef DOXYGEN_INTERNAL 00083 00084 protected: 00085 00086 /// The integration workspace 00087 gsl_integration_workspace *cyclew; 00088 00089 /** 00090 \brief The full GSL integration routine called by integ_err() 00091 */ 00092 int qawf(func_t &func, const double a, 00093 const double epsabs, const size_t limit, 00094 double *result, double *abserr, param_t &pa) { 00095 00096 double area, errsum; 00097 double res_ext, err_ext; 00098 double correc, total_error = 0.0, truncation_error; 00099 00100 size_t ktmin = 0; 00101 size_t iteration = 0; 00102 00103 struct extrapolation_table table; 00104 00105 double cycle; 00106 //double omega = this->otable->omega; 00107 00108 const double p = 0.9; 00109 double factor = 1; 00110 double initial_eps, eps; 00111 int error_type = 0; 00112 00113 /* Initialize results */ 00114 00115 initialise (this->w, a, a); 00116 00117 *result = 0; 00118 *abserr = 0; 00119 00120 if (limit > this->w->limit) { 00121 std::string estr="Iteration limit exceeds workspace "; 00122 estr+="in gsl_inte_qawf::qawf()."; 00123 O2SCL_ERR_RET(estr.c_str(),gsl_einval); 00124 } 00125 00126 /* Test on accuracy */ 00127 00128 if (epsabs <= 0) { 00129 std::string estr="The absolute tolerance must be positive "; 00130 estr+="in gsl_inte_qawf::qawf()."; 00131 O2SCL_ERR_RET(estr.c_str(),gsl_ebadtol); 00132 } 00133 00134 if (this->omega == 0.0) { 00135 if (this->otable->sine == GSL_INTEG_SINE) { 00136 /* The function sin(w x) f(x) is always zero for w = 0 */ 00137 00138 *result = 0; 00139 *abserr = 0; 00140 00141 return GSL_SUCCESS; 00142 } else { 00143 /* The function cos(w x) f(x) is always f(x) for w = 0 */ 00144 00145 gsl_inte_qagiu<param_t,func_t> iu; 00146 00147 int status=iu.integ_err(func,a,0.0,pa,*result,*abserr); 00148 00149 return status; 00150 } 00151 } 00152 00153 if (epsabs > GSL_DBL_MIN / (1 - p)) { 00154 eps = epsabs * (1 - p); 00155 } else { 00156 eps = epsabs; 00157 } 00158 00159 initial_eps = eps; 00160 00161 area = 0; 00162 errsum = 0; 00163 00164 res_ext = 0; 00165 err_ext = GSL_DBL_MAX; 00166 correc = 0; 00167 00168 cycle = (2 * floor (fabs (this->omega)) + 1) * M_PI / fabs (this->omega); 00169 00170 gsl_integration_qawo_table_set_length (this->otable, cycle); 00171 00172 initialise_table (&table); 00173 00174 for (iteration = 0; iteration < limit; iteration++) { 00175 double area1, error1, reseps, erreps; 00176 00177 double a1 = a + iteration * cycle; 00178 double b1 = a1 + cycle; 00179 00180 double epsabs1 = eps * factor; 00181 00182 int status=qawo(func,a1,epsabs1,0.0,limit,cyclew,this->otable, 00183 &area1,&error1,pa); 00184 00185 this->append_interval (this->w, a1, b1, area1, error1); 00186 00187 factor *= p; 00188 00189 area = area + area1; 00190 errsum = errsum + error1; 00191 00192 /* estimate the truncation error as 50 times the final term */ 00193 00194 truncation_error = 50 * fabs (area1); 00195 00196 total_error = errsum + truncation_error; 00197 00198 if (total_error < epsabs && iteration > 4) { 00199 goto compute_result; 00200 } 00201 00202 if (error1 > correc) { 00203 correc = error1; 00204 } 00205 00206 if (status) { 00207 eps = GSL_MAX_DBL (initial_eps, correc * (1.0 - p)); 00208 } 00209 00210 if (status && total_error < 10 * correc && iteration > 3) { 00211 goto compute_result; 00212 } 00213 00214 append_table (&table, area); 00215 00216 if (table.n < 2) { 00217 continue; 00218 } 00219 00220 qelg (&table, &reseps, &erreps); 00221 00222 ktmin++; 00223 00224 if (ktmin >= 15 && err_ext < 0.001 * total_error) { 00225 error_type = 4; 00226 } 00227 00228 if (erreps < err_ext) { 00229 ktmin = 0; 00230 err_ext = erreps; 00231 res_ext = reseps; 00232 00233 if (err_ext + 10 * correc <= epsabs) 00234 break; 00235 if (err_ext <= epsabs && 10 * correc >= epsabs) 00236 break; 00237 } 00238 00239 } 00240 00241 if (iteration == limit) error_type = 1; 00242 00243 if (err_ext == GSL_DBL_MAX) 00244 goto compute_result; 00245 00246 err_ext = err_ext + 10 * correc; 00247 00248 *result = res_ext; 00249 *abserr = err_ext; 00250 00251 if (error_type == 0) { 00252 return GSL_SUCCESS ; 00253 } 00254 00255 if (res_ext != 0.0 && area != 0.0) { 00256 if (err_ext / fabs (res_ext) > errsum / fabs (area)) 00257 goto compute_result; 00258 } else if (err_ext > errsum) { 00259 goto compute_result; 00260 } else if (area == 0.0) { 00261 goto return_error; 00262 } 00263 00264 if (error_type == 4) { 00265 err_ext = err_ext + truncation_error; 00266 } 00267 00268 goto return_error; 00269 00270 compute_result: 00271 00272 *result = area; 00273 *abserr = total_error; 00274 00275 return_error: 00276 00277 if (error_type > 2) 00278 error_type--; 00279 00280 if (error_type == 0) { 00281 return GSL_SUCCESS; 00282 } else if (error_type == 1) { 00283 std::string estr="Number of iterations was insufficient "; 00284 estr+=" in gsl_inte_qawf::qawf()."; 00285 O2SCL_ERR_RET(estr.c_str(),gsl_emaxiter); 00286 } else if (error_type == 2) { 00287 std::string estr="Roundoff error prevents tolerance "; 00288 estr+="from being achieved in gsl_inte_qawf::qawf()."; 00289 O2SCL_ERR_RET(estr.c_str(),gsl_eround); 00290 } else if (error_type == 3) { 00291 std::string estr="Bad integrand behavior "; 00292 estr+=" in gsl_inte_qawf::qawf()."; 00293 O2SCL_ERR_RET(estr.c_str(),gsl_esing); 00294 } else if (error_type == 4) { 00295 std::string estr="Roundoff error detected in extrapolation table "; 00296 estr+="in gsl_inte_qawf::qawf()."; 00297 O2SCL_ERR_RET(estr.c_str(),gsl_eround); 00298 } else if (error_type == 5) { 00299 std::string estr="Integral is divergent or slowly convergent "; 00300 estr+="in gsl_inte_qawf::qawf()."; 00301 O2SCL_ERR_RET(estr.c_str(),gsl_ediverge); 00302 } else { 00303 std::string estr="Could not integrate function in gsl_inte_qawf"; 00304 estr+="::qawf() (it may have returned a non-finite result)."; 00305 O2SCL_ERR_RET(estr.c_str(),gsl_efailed); 00306 } 00307 } 00308 00309 00310 /// Add the oscillating part to the integrand 00311 virtual double transform(func_t &func, double x, param_t &pa) { 00312 double wx = this->omega * x; 00313 double sinwx = sin(wx) ; 00314 double y; 00315 func(x,y,pa); 00316 return y*sinwx; 00317 } 00318 00319 #endif 00320 00321 /// Return string denoting type ("gsl_inte_qawf_sin") 00322 const char *type() { return "gsl_inte_qawf_sin"; } 00323 00324 }; 00325 00326 /** \brief Adaptive integration a function with finite limits of 00327 integration (GSL) 00328 00329 The number of subdivisions of the original interval which 00330 this class is allowed to make is dictated by the workspace 00331 size for the integration class, which can be set using 00332 \ref gsl_inte_table::set_wkspace() . 00333 00334 \todo Verbose output has been setup for this class, but this 00335 needs to be done for the other GSL-like integrators 00336 */ 00337 template<class param_t, class func_t> class gsl_inte_qawf_cos : 00338 public gsl_inte_qawf_sin<param_t,func_t> { 00339 00340 public: 00341 00342 gsl_inte_qawf_cos() { 00343 } 00344 00345 virtual ~gsl_inte_qawf_cos() {} 00346 00347 /** \brief Integrate function \c func from \c a to \c b and place 00348 the result in \c res and the error in \c err 00349 */ 00350 virtual int integ_err(func_t &func, double a, double b, 00351 param_t &pa, double &res, double &err2) { 00352 00353 this->otable=gsl_integration_qawo_table_alloc 00354 (this->omega,b-a,GSL_INTEG_COSINE,this->tab_size); 00355 this->cyclew=gsl_integration_workspace_alloc(this->wkspace); 00356 00357 int status=qawf(func,a,this->tolx,this->wkspace,&res,&err2,pa); 00358 00359 gsl_integration_qawo_table_free(this->otable); 00360 gsl_integration_workspace_free(this->cyclew); 00361 00362 return status; 00363 00364 } 00365 00366 #ifndef DOXYGEN_INTERNAL 00367 00368 protected: 00369 00370 /// Add the oscillating part to the integrand 00371 virtual double transform(func_t &func, double x, param_t &pa) { 00372 double wx = this->omega * x; 00373 double coswx = cos(wx) ; 00374 double y; 00375 func(x,y,pa); 00376 return y*coswx; 00377 } 00378 00379 #endif 00380 00381 /// Return string denoting type ("gsl_inte_qawf_cos") 00382 const char *type() { return "gsl_inte_qawf_cos"; } 00383 00384 }; 00385 00386 #ifndef DOXYGENP 00387 } 00388 #endif 00389 00390 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page