Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
GSLIntegrator.cxx
Go to the documentation of this file.
1 // @(#)root/mathmore:$Id$
2 // Authors: L. Moneta, A. Zsenei 08/2005
3 
4  /**********************************************************************
5  * *
6  * Copyright (c) 2004 ROOT Foundation, CERN/PH-SFT *
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License *
10  * as published by the Free Software Foundation; either version 2 *
11  * of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this library (see file COPYING); if not, write *
20  * to the Free Software Foundation, Inc., 59 Temple Place, Suite *
21  * 330, Boston, MA 02111-1307 USA, or contact the author. *
22  * *
23  **********************************************************************/
24 
25 // Implementation file for class GSLIntegrator
26 //
27 // Created by: Lorenzo Moneta at Thu Nov 11 14:22:32 2004
28 //
29 // Last update: Thu Nov 11 14:22:32 2004
30 //
31 
32 #include "Math/GSLIntegrator.h"
33 
34 #include "gsl/gsl_integration.h"
35 
36 #include "Math/IFunction.h"
38 #include "GSLFunctionWrapper.h"
39 
40 // for toupper
41 #include <algorithm>
42 #include <functional>
43 #include <ctype.h> // need to use c version of tolower defined here
44 
45 
46 #include <iostream>
47 
48 
49 
50 namespace ROOT {
51 namespace Math {
52 
53 
54 
55 
56 GSLIntegrator::GSLIntegrator(const Integration::Type type , const Integration::GKRule rule, double absTol, double relTol, size_t size) :
57  fType(type),
58  fRule(rule),
59  fAbsTol(absTol),
60  fRelTol(relTol),
61  fSize(size),
62  fMaxIntervals(size),
63  fResult(0),fError(0),fStatus(-1),fNEval(-1),
64  fFunction(0),
65  fWorkspace(0)
66 {
67  // constructor for all types of integrations
68  // allocate workspace (only if not adaptive algorithm)
69  if (type != Integration::kNONADAPTIVE)
70  fWorkspace = new GSLIntegrationWorkspace( fSize);
71 
72 
73 }
74 
75 
76 
77 GSLIntegrator::GSLIntegrator(double absTol, double relTol, size_t size) :
78  fType(Integration::kADAPTIVESINGULAR),
79  fRule(Integration::kGAUSS31),
80  fAbsTol(absTol),
81  fRelTol(relTol),
82  fSize(size),
83  fMaxIntervals(size),
84  fResult(0),fError(0),fStatus(-1),fNEval(-1),
85  fFunction(0),
86  fWorkspace(0)
87 {
88  // constructor with default type (ADaptiveSingular) , rule is not needed
89  fWorkspace = new GSLIntegrationWorkspace( fSize);
90 
91 }
92 
93 
94 
95 GSLIntegrator::GSLIntegrator(const Integration::Type type , double absTol, double relTol, size_t size) :
96  fType(type),
97  fRule(Integration::kGAUSS31),
98  fAbsTol(absTol),
99  fRelTol(relTol),
100  fSize(size),
101  fMaxIntervals(size),
102  fResult(0),fError(0),fStatus(-1),fNEval(-1),
103  fFunction(0),
104  fWorkspace(0)
105 {
106 
107  // constructor with default rule (gauss31) passing the type
108  // allocate workspace (only if not adaptive algorithm)
109  if (type != Integration::kNONADAPTIVE)
110  fWorkspace = new GSLIntegrationWorkspace( fSize);
111 
112 }
113 
114  GSLIntegrator::GSLIntegrator(const char * type , int rule, double absTol, double relTol, size_t size) :
115  fRule(Integration::kGAUSS31),
116  fAbsTol(absTol),
117  fRelTol(relTol),
118  fSize(size),
119  fMaxIntervals(size),
120  fResult(0),fError(0),fStatus(-1),fNEval(-1),
121  fFunction(0),
122  fWorkspace(0)
123 {
124  //std::cout << type << std::endl;
125 
126  fType = Integration::kADAPTIVESINGULAR; // default
127  if (type != 0) { // use this dafault
128  std::string typeName(type);
129  std::transform(typeName.begin(), typeName.end(), typeName.begin(), (int(*)(int)) toupper );
130  if (typeName == "NONADAPTIVE")
131  fType = Integration::kNONADAPTIVE;
132  else if (typeName == "ADAPTIVE")
133  fType = Integration::kADAPTIVE;
134  else {
135  if (typeName != "ADAPTIVESINGULAR")
136  MATH_WARN_MSG("GSLIntegrator","Use default type: AdaptiveSingular");
137  }
138  }
139 
140 
141  // constructor with default rule (gauss31) passing the type
142  // allocate workspace (only if not adaptive algorithm)
143  if (fType != Integration::kNONADAPTIVE)
144  fWorkspace = new GSLIntegrationWorkspace( fSize);
145 
146  if (rule >= Integration::kGAUSS15 && rule <= Integration::kGAUSS61) SetIntegrationRule((Integration::GKRule) rule);
147 
148 }
149 
150 
151 GSLIntegrator::~GSLIntegrator()
152 {
153  // delete workspace and function
154  if (fFunction) delete fFunction;
155  if (fWorkspace) delete fWorkspace;
156 }
157 
158 GSLIntegrator::GSLIntegrator(const GSLIntegrator &) :
159  VirtualIntegratorOneDim()
160 {
161  // dummy copy ctr
162 }
163 
164 GSLIntegrator & GSLIntegrator::operator = (const GSLIntegrator &rhs)
165 {
166  // dummy operator=
167  if (this == &rhs) return *this; // time saving self-test
168 
169  return *this;
170 }
171 
172 
173 
174 
175 void GSLIntegrator::SetFunction( GSLFuncPointer fp, void * p) {
176  // fill GSLFunctionWrapper with the pointer to the function
177  if (fFunction ==0) fFunction = new GSLFunctionWrapper();
178  fFunction->SetFuncPointer( fp );
179  fFunction->SetParams ( p );
180 }
181 
182 void GSLIntegrator::SetFunction(const IGenFunction &f ) {
183  // set function (make a copy of it)
184  if (fFunction ==0) fFunction = new GSLFunctionWrapper();
185  fFunction->SetFunction(f);
186 }
187 
188 // evaluation methods
189 
190 double GSLIntegrator::Integral(double a, double b) {
191  // defined integral evaluation
192  // need here look at all types of algorithms
193  // find more elegant solution ? Use template OK, but need to chose algorithm statically , t.b.i.
194 
195  if (!CheckFunction()) return 0;
196 
197  if ( fType == Integration::kNONADAPTIVE) {
198  size_t neval = 0; // need to export this ?
199  fStatus = gsl_integration_qng( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, &fResult, &fError, &neval);
200  fNEval = neval;
201  }
202  else if (fType == Integration::kADAPTIVE) {
203  fStatus = gsl_integration_qag( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fRule, fWorkspace->GetWS(), &fResult, &fError);
204  const int npts[6] = {15,21,31,41,51,61};
205  assert(fRule>=1 && fRule <=6);
206  fNEval = (fWorkspace->GetWS()->size)*npts[fRule-1]; // get size of workspace (number of iterations)
207  }
208  else if (fType == Integration::kADAPTIVESINGULAR) {
209 
210  // singular integration - look if we know about singular points
211 
212 
213  fStatus = gsl_integration_qags( fFunction->GetFunc(), a, b , fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
214  fNEval = (fWorkspace->GetWS()->size) * 21; //since 21 point rule is used in qags
215  }
216  else {
217 
218  fResult = 0;
219  fError = 0;
220  fStatus = -1;
221  std::cerr << "GSLIntegrator - Error: Unknown integration type" << std::endl;
222  throw std::exception(); //"Unknown integration type");
223  }
224 
225  return fResult;
226 
227 }
228 
229 //=============================
230 double GSLIntegrator::IntegralCauchy(double a, double b, double c) {
231  //eval integral with Cauchy principal value defined at the value c
232  if (!CheckFunction()) return 0;
233 
234  fStatus = gsl_integration_qawc( fFunction->GetFunc(), a, b , c, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
235  fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
236 
237  return fResult;
238 
239 }
240 
241 double GSLIntegrator::IntegralCauchy(const IGenFunction & f, double a, double b, double c) {
242  //eval integral with Cauchy principal value defined at the value c
243 
244  if (!CheckFunction()) return 0;
245  SetFunction(f);
246  return IntegralCauchy(a, b, c);
247 
248 }
249 
250 //==============================
251 
252 double GSLIntegrator::Integral( const std::vector<double> & pts) {
253  // integral eval with singularities
254 
255  if (!CheckFunction()) return 0;
256 
257  if (fType == Integration::kADAPTIVESINGULAR && pts.size() >= 2 ) {
258  // remove constness ( should be const in GSL ? )
259  double * p = const_cast<double *>(&pts.front() );
260  fStatus = gsl_integration_qagp( fFunction->GetFunc(), p, pts.size() , fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
261  fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
262  }
263  else {
264  fResult = 0;
265  fError = 0;
266  fStatus = -1;
267  std::cerr << "GSLIntegrator - Error: Unknown integration type or not enough singular points defined" << std::endl;
268  return 0;
269  }
270  return fResult;
271 }
272 
273 
274 double GSLIntegrator::Integral( ) {
275  // Eval for indefined integrals: use QAGI method
276  // if method was chosen NO_ADAPTIVE WS does not exist create it
277 
278  if (!CheckFunction()) return 0;
279 
280  if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
281 
282  fStatus = gsl_integration_qagi( fFunction->GetFunc(), fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
283  fNEval = (fWorkspace->GetWS()->size) * 15; // 15 point rule is used ?
284 
285  return fResult;
286 }
287 
288 
289 
290 double GSLIntegrator::IntegralUp( double a ) {
291  // Integral between [a, + inf]
292  // if method was chosen NO_ADAPTIVE WS does not exist create it
293 
294  if (!CheckFunction()) return 0;
295 
296  if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
297 
298  fStatus = gsl_integration_qagiu( fFunction->GetFunc(), a, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
299  fNEval = (fWorkspace->GetWS()->size) * 21; // 21 point rule is used ?
300 
301  return fResult;
302 }
303 
304 
305 
306 double GSLIntegrator::IntegralLow( double b ) {
307  // Integral between [-inf, + b]
308  // if method was chosen NO_ADAPTIVE WS does not exist create it
309 
310  if (!CheckFunction()) return 0;
311 
312  if (!fWorkspace) fWorkspace = new GSLIntegrationWorkspace( fSize);
313 
314  fStatus = gsl_integration_qagil( fFunction->GetFunc(), b, fAbsTol, fRelTol, fMaxIntervals, fWorkspace->GetWS(), &fResult, &fError);
315  fNEval = (fWorkspace->GetWS()->size) * 21; // 21 point rule is used ?
316 
317  return fResult;
318 }
319 
320 
321 
322 
323 double GSLIntegrator::Integral(const IGenFunction & f, double a, double b) {
324  // use generic function interface
325  SetFunction(f);
326  return Integral(a,b);
327 }
328 
329 double GSLIntegrator::Integral(const IGenFunction & f ) {
330  // use generic function interface
331  SetFunction(f);
332  return Integral();
333 }
334 
335 double GSLIntegrator::IntegralUp(const IGenFunction & f, double a) {
336  // use generic function interface
337  SetFunction(f);
338  return IntegralUp(a);
339 }
340 
341 double GSLIntegrator::IntegralLow(const IGenFunction & f, double b) {
342  // use generic function interface
343  SetFunction(f);
344  return IntegralLow(b);
345 }
346 
347 double GSLIntegrator::Integral(const IGenFunction & f, const std::vector<double> & pts) {
348  // use generic function interface
349  SetFunction(f);
350  return Integral(pts);
351 }
352 
353 
354 
355 
356 double GSLIntegrator::Integral( GSLFuncPointer f , void * p, double a, double b) {
357  // use c free function pointer
358  SetFunction( f, p);
359  return Integral(a,b);
360 }
361 
362 double GSLIntegrator::Integral( GSLFuncPointer f, void * p ) {
363  // use c free function pointer
364  SetFunction( f, p);
365  return Integral();
366 }
367 
368 double GSLIntegrator::IntegralUp( GSLFuncPointer f, void * p, double a ) {
369  // use c free function pointer
370  SetFunction( f, p);
371  return IntegralUp(a);
372 }
373 
374 double GSLIntegrator::IntegralLow( GSLFuncPointer f, void * p, double b ) {
375  // use c free function pointer
376  SetFunction( f, p);
377  return IntegralLow(b);
378 }
379 
380 double GSLIntegrator::Integral( GSLFuncPointer f, void * p, const std::vector<double> & pts ) {
381  // use c free function pointer
382  SetFunction( f, p);
383  return Integral(pts);
384 }
385 
386 
387 
388 double GSLIntegrator::Result() const { return fResult; }
389 
390 double GSLIntegrator::Error() const { return fError; }
391 
392 int GSLIntegrator::Status() const { return fStatus; }
393 
394 
395 // get and setter methods
396 
397 // double GSLIntegrator::getAbsTolerance() const { return fAbsTol; }
398 
399 void GSLIntegrator::SetAbsTolerance(double absTol){ this->fAbsTol = absTol; }
400 
401 // double GSLIntegrator::getRelTolerance() const { return fRelTol; }
402 
403 void GSLIntegrator::SetRelTolerance(double relTol){ this->fRelTol = relTol; }
404 
405 
406 void GSLIntegrator::SetIntegrationRule(Integration::GKRule rule){ this->fRule = rule; }
407 
408 bool GSLIntegrator::CheckFunction() {
409  // check if a function has been previously set.
410  if (fFunction && fFunction->IsValid()) return true;
411  fStatus = -1; fResult = 0; fError = 0;
412  std::cerr << "GSLIntegrator - Error : Function has not been specified " << std::endl;
413  return false;
414 }
415 
416 void GSLIntegrator::SetOptions(const ROOT::Math::IntegratorOneDimOptions & opt)
417 {
418  // set integration options
419  fType = opt.IntegratorType();
420  if (fType == IntegrationOneDim::kDEFAULT) fType = IntegrationOneDim::kADAPTIVESINGULAR;
421  if (fType != IntegrationOneDim::kADAPTIVE &&
422  fType != IntegrationOneDim::kADAPTIVESINGULAR &&
423  fType != IntegrationOneDim::kNONADAPTIVE ) {
424  MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default ADAPTIVESINGULAR");
425  fType = IntegrationOneDim::kADAPTIVESINGULAR;
426  }
427  SetAbsTolerance( opt.AbsTolerance() );
428  SetRelTolerance( opt.RelTolerance() );
429  fSize = opt.WKSize();
430  fMaxIntervals = fSize;
431  if (fType == Integration::kADAPTIVE) {
432  int npts = opt.NPoints();
433  if ( npts >= Integration::kGAUSS15 && npts <= Integration::kGAUSS61)
434  fRule = (Integration::GKRule) npts;
435  else {
436  MATH_WARN_MSG("GSLIntegrator::SetOptions","Invalid rule options - use default GAUSS31");
437  fRule = Integration::kGAUSS31;
438  }
439  }
440 }
441 
442 ROOT::Math::IntegratorOneDimOptions GSLIntegrator::Options() const {
443  ROOT::Math::IntegratorOneDimOptions opt;
444  opt.SetAbsTolerance(fAbsTol);
445  opt.SetRelTolerance(fRelTol);
446  opt.SetWKSize(fSize);
447  opt.SetIntegrator(GetTypeName() );
448 
449  if (fType == IntegrationOneDim::kADAPTIVE)
450  opt.SetNPoints(fRule);
451  else if (fType == IntegrationOneDim::kADAPTIVESINGULAR)
452  opt.SetNPoints( Integration::kGAUSS31 ); // fixed rule for adaptive singular
453  else
454  opt.SetNPoints( 0 ); // not available for the rest
455 
456  return opt;
457 }
458 
459 const char * GSLIntegrator::GetTypeName() const {
460  if (fType == IntegrationOneDim::kADAPTIVE) return "Adaptive";
461  if (fType == IntegrationOneDim::kADAPTIVESINGULAR) return "AdaptiveSingular";
462  if (fType == IntegrationOneDim::kNONADAPTIVE) return "NonAdaptive";
463  return "Undefined";
464 }
465 
466 
467 } // namespace Math
468 } // namespace ROOT