GSLIntegrator.cxx

Go to the documentation of this file.
00001 // @(#)root/mathmore:$Id: GSLIntegrator.cxx 36806 2010-11-20 11:09:14Z moneta $
00002 // Authors: L. Moneta, A. Zsenei   08/2005
00003 
00004  /**********************************************************************
00005   *                                                                    *
00006   * Copyright (c) 2004 ROOT Foundation,  CERN/PH-SFT                   *
00007   *                                                                    *
00008   * This library is free software; you can redistribute it and/or      *
00009   * modify it under the terms of the GNU General Public License        *
00010   * as published by the Free Software Foundation; either version 2     *
00011   * of the License, or (at your option) any later version.             *
00012   *                                                                    *
00013   * This library 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 GNU   *
00016   * General Public License for more details.                           *
00017   *                                                                    *
00018   * You should have received a copy of the GNU General Public License  *
00019   * along with this library (see file COPYING); if not, write          *
00020   * to the Free Software Foundation, Inc., 59 Temple Place, Suite      *
00021   * 330, Boston, MA 02111-1307 USA, or contact the author.             *
00022   *                                                                    *
00023   **********************************************************************/
00024 
00025 // Implementation file for class GSLIntegrator
00026 //
00027 // Created by: Lorenzo Moneta  at Thu Nov 11 14:22:32 2004
00028 //
00029 // Last update: Thu Nov 11 14:22:32 2004
00030 //
00031 
00032 #include "Math/GSLIntegrator.h"
00033 
00034 #include "gsl/gsl_integration.h"
00035 
00036 #include "Math/IFunction.h"
00037 #include "GSLIntegrationWorkspace.h"
00038 #include "GSLFunctionWrapper.h"
00039 
00040 // for toupper
00041 #include <algorithm>
00042 #include <functional>
00043 #include <ctype.h>   // need to use c version of tolower defined here
00044 
00045 
00046 #include <iostream>
00047 
00048 
00049 
00050 namespace ROOT {
00051 namespace Math {
00052 
00053 
00054  
00055 
00056 GSLIntegrator::GSLIntegrator(const Integration::Type type , const Integration::GKRule rule, double absTol, double relTol, size_t size) :
00057    fType(type),
00058    fRule(rule),
00059    fAbsTol(absTol),
00060    fRelTol(relTol),
00061    fSize(size),
00062    fMaxIntervals(size),
00063    fResult(0),fError(0),fStatus(-1),fNEval(-1),
00064    fFunction(0),
00065    fWorkspace(0)
00066 {
00067    // constructor for all types of integrations 
00068    // allocate workspace (only if not adaptive algorithm)
00069    if (type !=  Integration::kNONADAPTIVE)
00070       fWorkspace = new GSLIntegrationWorkspace( fSize);
00071       
00072       
00073 }
00074 
00075 
00076 
00077 GSLIntegrator::GSLIntegrator(double absTol, double relTol, size_t size) :
00078    fType(Integration::kADAPTIVESINGULAR),
00079    fRule(Integration::kGAUSS31),
00080    fAbsTol(absTol),
00081    fRelTol(relTol),
00082    fSize(size),
00083    fMaxIntervals(size),
00084    fResult(0),fError(0),fStatus(-1),fNEval(-1),
00085    fFunction(0),
00086    fWorkspace(0)
00087 {
00088    // constructor with default type (ADaptiveSingular) ,  rule is not needed  
00089    fWorkspace = new GSLIntegrationWorkspace( fSize);
00090    
00091 }
00092 
00093 
00094 
00095 GSLIntegrator::GSLIntegrator(const Integration::Type type , double absTol, double relTol, size_t size) :
00096    fType(type),
00097    fRule(Integration::kGAUSS31),
00098    fAbsTol(absTol),
00099    fRelTol(relTol),
00100    fSize(size),
00101    fMaxIntervals(size),
00102    fResult(0),fError(0),fStatus(-1),fNEval(-1),
00103    fFunction(0),
00104    fWorkspace(0)
00105 {
00106 
00107    // constructor with default rule (gauss31) passing the type
00108    // allocate workspace (only if not adaptive algorithm)
00109    if (type !=  Integration::kNONADAPTIVE)
00110       fWorkspace = new GSLIntegrationWorkspace( fSize);
00111    
00112 }
00113 
00114    GSLIntegrator::GSLIntegrator(const char * type , int rule, double absTol, double relTol, size_t size) :
00115    fRule(Integration::kGAUSS31),
00116    fAbsTol(absTol),
00117    fRelTol(relTol),
00118    fSize(size),
00119    fMaxIntervals(size),
00120    fResult(0),fError(0),fStatus(-1),fNEval(-1),
00121    fFunction(0),
00122    fWorkspace(0)
00123 {
00124    //std::cout << type << std::endl; 
00125 
00126    fType =  Integration::kADAPTIVESINGULAR;  // default
00127    if (type != 0) {  // use this dafault
00128       std::string typeName(type); 
00129       std::transform(typeName.begin(), typeName.end(), typeName.begin(), (int(*)(int)) toupper );  
00130       if (typeName == "NONADAPTIVE")
00131          fType =  Integration::kNONADAPTIVE;
00132       else if (typeName == "ADAPTIVE")
00133          fType =  Integration::kADAPTIVE;
00134       else { 
00135          if (typeName != "ADAPTIVESINGULAR") 
00136             MATH_WARN_MSG("GSLIntegrator","Use default type: AdaptiveSingular");
00137       }
00138    }
00139 
00140 
00141    // constructor with default rule (gauss31) passing the type
00142    // allocate workspace (only if not adaptive algorithm)
00143    if (fType !=  Integration::kNONADAPTIVE)
00144       fWorkspace = new GSLIntegrationWorkspace( fSize);
00145 
00146    if (rule >= Integration::kGAUSS15 && rule <= Integration::kGAUSS61) SetIntegrationRule((Integration::GKRule) rule);
00147    
00148 }
00149 
00150 
00151 GSLIntegrator::~GSLIntegrator()
00152 {
00153    // delete workspace and function
00154    if (fFunction) delete fFunction;
00155    if (fWorkspace) delete fWorkspace;
00156 }
00157 
00158 GSLIntegrator::GSLIntegrator(const GSLIntegrator &)  : 
00159    VirtualIntegratorOneDim() 
00160 {
00161    // dummy copy ctr
00162 }
00163 
00164 GSLIntegrator & GSLIntegrator::operator = (const GSLIntegrator &rhs)
00165 {
00166    // dummy operator=
00167    if (this == &rhs) return *this;  // time saving self-test
00168    
00169    return *this;
00170 }
00171 
00172 
00173 
00174 
00175 void  GSLIntegrator::SetFunction( GSLFuncPointer  fp, void * p) {
00176    // fill GSLFunctionWrapper with the pointer to the function 
00177    if (fFunction ==0) fFunction = new GSLFunctionWrapper();
00178    fFunction->SetFuncPointer( fp );
00179    fFunction->SetParams ( p );
00180 }
00181 
00182 void  GSLIntegrator::SetFunction(const IGenFunction &f ) {
00183    // set function (make a copy of it)
00184    if (fFunction ==0) fFunction = new GSLFunctionWrapper();
00185    fFunction->SetFunction(f);
00186 }
00187 
00188 // evaluation methods
00189 
00190 double  GSLIntegrator::Integral(double a, double b) {
00191    // defined integral evaluation
00192    // need here look at all types of algorithms
00193    // find more elegant solution ? Use template OK, but need to chose algorithm statically , t.b.i.
00194 
00195    if (!CheckFunction()) return 0;  
00196    
00197    if ( fType == Integration::kNONADAPTIVE) {
00198       size_t neval = 0; // need to export  this ?
00199       fStatus = gsl_integration_qng( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, &fResult, &fError, &neval);
00200       fNEval = neval;
00201    }
00202    else if (fType ==  Integration::kADAPTIVE) {
00203       fStatus = gsl_integration_qag( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fRule, fWorkspace->GetWS(), &fResult, &fError);
00204       const int npts[6] = {15,21,31,41,51,61}; 
00205       assert(fRule>=1 && fRule <=6);
00206       fNEval = (fWorkspace->GetWS()->size)*npts[fRule-1];   // get size of workspace (number of iterations)
00207    }
00208    else if (fType ==  Integration::kADAPTIVESINGULAR) {
00209       
00210       // singular integration - look if we know about singular points
00211       
00212       
00213       fStatus = gsl_integration_qags( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00214       fNEval = (fWorkspace->GetWS()->size) * 21; //since 21 point rule is used in qags
00215    }
00216    else {
00217       
00218       fResult = 0;
00219       fError = 0;
00220       fStatus = -1;
00221       std::cerr << "GSLIntegrator - Error: Unknown integration type" << std::endl;
00222       throw std::exception(); //"Unknown integration type");
00223    }
00224    
00225    return fResult;
00226    
00227 }
00228 
00229 //=============================
00230 double  GSLIntegrator::IntegralCauchy(double a, double b, double c) {
00231    //eval integral with Cauchy principal value defined at the value c
00232    if (!CheckFunction()) return 0;  
00233   
00234    fStatus = gsl_integration_qawc( fFunction->GetFunc(), a, b , c, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00235    fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
00236 
00237    return fResult;
00238    
00239 }
00240 
00241 double  GSLIntegrator::IntegralCauchy(const IGenFunction & f, double a, double b, double c) {
00242    //eval integral with Cauchy principal value defined at the value c
00243    
00244    if (!CheckFunction()) return 0;  
00245    SetFunction(f);
00246    return IntegralCauchy(a, b, c);
00247    
00248 }
00249 
00250 //==============================
00251 
00252 double  GSLIntegrator::Integral( const std::vector<double> & pts) {
00253    // integral eval with singularities
00254 
00255    if (!CheckFunction()) return 0;  
00256 
00257    if (fType == Integration::kADAPTIVESINGULAR && pts.size() >= 2 ) {
00258       // remove constness ( should be const in GSL ? )
00259       double * p = const_cast<double *>(&pts.front() );
00260       fStatus = gsl_integration_qagp( fFunction->GetFunc(), p, pts.size() , fAbsTol, fRelTol, fMaxIntervals,  fWorkspace->GetWS(), &fResult, &fError);
00261       fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
00262    }
00263    else {
00264       fResult = 0;
00265       fError = 0;
00266       fStatus = -1;
00267       std::cerr << "GSLIntegrator - Error: Unknown integration type or not enough singular points defined" << std::endl;
00268       return 0; 
00269    }
00270    return fResult;
00271 }
00272 
00273 
00274 double  GSLIntegrator::Integral( ) {
00275    // Eval for indefined integrals: use QAGI method
00276    // if method was choosen NO_ADAPTIVE WS does not exist create it
00277 
00278    if (!CheckFunction()) return 0;  
00279 
00280    if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00281    
00282    fStatus = gsl_integration_qagi( fFunction->GetFunc(), fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00283    fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
00284    
00285    return fResult;
00286 }
00287 
00288 
00289 
00290 double  GSLIntegrator::IntegralUp( double a ) {
00291    // Integral between [a, + inf]
00292    // if method was choosen NO_ADAPTIVE WS does not exist create it
00293 
00294    if (!CheckFunction()) return 0;  
00295 
00296    if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00297    
00298    fStatus = gsl_integration_qagiu( fFunction->GetFunc(), a, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00299    fNEval = (fWorkspace->GetWS()->size) * 21; // 21 point rule is used ?
00300    
00301    return fResult;
00302 }
00303 
00304 
00305 
00306 double  GSLIntegrator::IntegralLow( double b ) {
00307    // Integral between [-inf, + b]
00308    // if method was choosen NO_ADAPTIVE WS does not exist create it
00309 
00310    if (!CheckFunction()) return 0;  
00311 
00312    if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
00313    
00314    fStatus = gsl_integration_qagil( fFunction->GetFunc(), b, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
00315    fNEval = (fWorkspace->GetWS()->size) * 21; // 21 point rule is used ?
00316    
00317    return fResult;
00318 }
00319 
00320 
00321 
00322 
00323 double  GSLIntegrator::Integral(const IGenFunction & f, double a, double b) {
00324    // use generic function interface
00325    SetFunction(f);
00326    return Integral(a,b);
00327 }
00328 
00329 double  GSLIntegrator::Integral(const IGenFunction & f ) {
00330    // use generic function interface
00331    SetFunction(f);
00332    return Integral();
00333 }
00334 
00335 double  GSLIntegrator::IntegralUp(const IGenFunction & f, double a) {
00336    // use generic function interface
00337    SetFunction(f);
00338    return IntegralUp(a);
00339 }
00340 
00341 double  GSLIntegrator::IntegralLow(const IGenFunction & f, double b) {
00342    // use generic function interface
00343    SetFunction(f);
00344    return IntegralLow(b);
00345 }
00346 
00347 double  GSLIntegrator::Integral(const IGenFunction & f, const std::vector<double> & pts) {
00348    // use generic function interface
00349    SetFunction(f);
00350    return Integral(pts);
00351 }
00352 
00353 
00354 
00355 
00356 double  GSLIntegrator::Integral( GSLFuncPointer f , void * p, double a, double b) {
00357    // use c free function pointer
00358    SetFunction( f, p);
00359    return Integral(a,b);
00360 }
00361 
00362 double  GSLIntegrator::Integral( GSLFuncPointer f, void * p ) {
00363    // use c free function pointer
00364    SetFunction( f, p);
00365    return Integral();
00366 }
00367 
00368 double  GSLIntegrator::IntegralUp( GSLFuncPointer f, void * p, double a ) {
00369    // use c free function pointer
00370    SetFunction( f, p);
00371    return IntegralUp(a);
00372 }
00373 
00374 double  GSLIntegrator::IntegralLow( GSLFuncPointer f, void * p, double b ) {
00375    // use c free function pointer
00376    SetFunction( f, p);
00377    return IntegralLow(b);
00378 }
00379 
00380 double  GSLIntegrator::Integral( GSLFuncPointer f, void * p, const std::vector<double> & pts ) {
00381    // use c free function pointer
00382    SetFunction( f, p);
00383    return Integral(pts);
00384 }
00385 
00386 
00387 
00388 double GSLIntegrator::Result() const { return fResult; }
00389 
00390 double GSLIntegrator::Error() const { return fError; }
00391 
00392 int GSLIntegrator::Status() const { return fStatus; }
00393 
00394 
00395 // get and setter methods
00396 
00397 //   double GSLIntegrator::getAbsTolerance() const { return fAbsTol; }
00398 
00399 void GSLIntegrator::SetAbsTolerance(double absTol){ this->fAbsTol = absTol; }
00400 
00401 //   double GSLIntegrator::getRelTolerance() const { return fRelTol; }
00402 
00403 void GSLIntegrator::SetRelTolerance(double relTol){ this->fRelTol = relTol; }
00404 
00405 
00406 void GSLIntegrator::SetIntegrationRule(Integration::GKRule rule){ this->fRule = rule; }
00407 
00408 bool GSLIntegrator::CheckFunction() { 
00409    // check if a function has been previously set.
00410    if (fFunction->IsValid()) return true; 
00411    fStatus = -1; fResult = 0; fError = 0;
00412    std::cerr << "GSLIntegrator - Error : Function has not been specified " << std::endl; 
00413    return false; 
00414 }
00415 
00416 void GSLIntegrator::SetOptions(const ROOT::Math::IntegratorOneDimOptions & opt)
00417 {
00418    //   set integration options
00419    fType = opt.IntegratorType();
00420    if (fType == IntegrationOneDim::kDEFAULT) fType = IntegrationOneDim::kADAPTIVESINGULAR; 
00421    if (fType != IntegrationOneDim::kADAPTIVE && 
00422        fType != IntegrationOneDim::kADAPTIVESINGULAR && 
00423        fType != IntegrationOneDim::kNONADAPTIVE ) {
00424       MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default ADAPTIVESINGULAR");
00425       fType = IntegrationOneDim::kADAPTIVESINGULAR; 
00426    }
00427    SetAbsTolerance( opt.AbsTolerance() );
00428    SetRelTolerance( opt.RelTolerance() );
00429    fSize = opt.WKSize();
00430    fMaxIntervals = fSize; 
00431    if (fType == Integration::kADAPTIVE) { 
00432       int npts = opt.NPoints();
00433       if  ( npts >= Integration::kGAUSS15 && npts <= Integration::kGAUSS61) 
00434          fRule = (Integration::GKRule) npts;
00435       else { 
00436          MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default GAUSS31");
00437          fRule = Integration::kGAUSS31;
00438       }
00439    }
00440 }
00441 
00442 ROOT::Math::IntegratorOneDimOptions  GSLIntegrator::Options() const { 
00443    ROOT::Math::IntegratorOneDimOptions opt; 
00444    opt.SetAbsTolerance(fAbsTol); 
00445    opt.SetRelTolerance(fRelTol); 
00446    opt.SetWKSize(fSize); 
00447    opt.SetIntegrator(GetTypeName() );
00448 
00449    if (fType == IntegrationOneDim::kADAPTIVE) 
00450       opt.SetNPoints(fRule);       
00451    else if (fType == IntegrationOneDim::kADAPTIVESINGULAR) 
00452       opt.SetNPoints( Integration::kGAUSS31 ); // fixed rule for adaptive singular
00453    else 
00454       opt.SetNPoints( 0 ); // not available for the rest
00455 
00456    return opt; 
00457 }
00458 
00459 const char * GSLIntegrator::GetTypeName() const { 
00460    if (fType == IntegrationOneDim::kADAPTIVE) return "Adaptive";
00461    if (fType == IntegrationOneDim::kADAPTIVESINGULAR) return "AdaptiveSingular";
00462    if (fType == IntegrationOneDim::kNONADAPTIVE) return "NonAdaptive";
00463    return "Undefined";
00464 }    
00465 
00466 
00467 } // namespace Math
00468 } // namespace ROOT

Generated on Tue Jul 5 14:34:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1