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