Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooAdaptiveIntegratorND.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * @(#)root/roofitcore:$Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 /**
18 \file RooAdaptiveIntegratorND.cxx
19 \class RooAdaptiveIntegratorND
20 \ingroup Roofitcore
21 
22 RooAdaptiveIntegratorND implements an adaptive one-dimensional
23 numerical integration algorithm.
24 **/
25 
26 
27 #include "RooFit.h"
28 #include "Riostream.h"
29 
30 #include "TClass.h"
32 #include "RooArgSet.h"
33 #include "RooRealVar.h"
34 #include "RooNumber.h"
35 #include "RooMsgService.h"
36 #include "RooNumIntFactory.h"
37 #include "RooMultiGenFunction.h"
39 
40 #include <assert.h>
41 
42 
43 
44 using namespace std;
45 
46 ClassImp(RooAdaptiveIntegratorND);
47 ;
48 
49 // Register this class with RooNumIntConfig
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// Register RooAdaptiveIntegratorND, its parameters, dependencies and capabilities with RooNumIntFactory
53 
54 void RooAdaptiveIntegratorND::registerIntegrator(RooNumIntFactory& fact)
55 {
56  RooRealVar maxEval2D("maxEval2D","Max number of function evaluations for 2-dim integrals",100000) ;
57  RooRealVar maxEval3D("maxEval3D","Max number of function evaluations for 3-dim integrals",1000000) ;
58  RooRealVar maxEvalND("maxEvalND","Max number of function evaluations for >3-dim integrals",10000000) ;
59  RooRealVar maxWarn("maxWarn","Max number of warnings on precision not reached that is printed",5) ;
60 
61  fact.storeProtoIntegrator(new RooAdaptiveIntegratorND(),RooArgSet(maxEval2D,maxEval3D,maxEvalND,maxWarn)) ;
62 }
63 
64 
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// Default ctor
68 
69 RooAdaptiveIntegratorND::RooAdaptiveIntegratorND()
70 {
71  _xmin = 0 ;
72  _xmax = 0 ;
73  _epsRel = 1e-7 ;
74  _epsAbs = 1e-7 ;
75  _nmax = 10000 ;
76  _func = 0 ;
77  _integrator = 0 ;
78  _nError = 0 ;
79  _nWarn = 0 ;
80  _useIntegrandLimits = kTRUE ;
81  _intName = "(none)" ;
82 }
83 
84 
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Constructor of integral on given function binding and with given configuration. The
88 /// integration limits are taken from the definition in the function binding
89 ///_func = function.
90 
91 RooAdaptiveIntegratorND::RooAdaptiveIntegratorND(const RooAbsFunc& function, const RooNumIntConfig& config) :
92  RooAbsIntegrator(function)
93 {
94 
95  _func = new RooMultiGenFunction(function) ;
96  _nWarn = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxWarn")) ;
97  switch (_func->NDim()) {
98  case 1: throw string(Form("RooAdaptiveIntegratorND::ctor ERROR dimension of function must be at least 2")) ;
99  case 2: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEval2D")) ; break ;
100  case 3: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEval3D")) ; break ;
101  default: _nmax = static_cast<Int_t>(config.getConfigSection("RooAdaptiveIntegratorND").getRealValue("maxEvalND")) ; break ;
102  }
103  // by default do not use absolute tolerance (see https://root.cern.ch/phpBB3/viewtopic.php?f=15&t=20071 )
104  _epsAbs = 0.0;
105  _epsRel = config.epsRel();
106  _integrator = new ROOT::Math::AdaptiveIntegratorMultiDim(_epsAbs,_epsRel,_nmax) ;
107  _integrator->SetFunction(*_func) ;
108  _useIntegrandLimits=kTRUE ;
109 
110  _xmin = 0 ;
111  _xmax = 0 ;
112  _nError = 0 ;
113  _nWarn = 0 ;
114  checkLimits() ;
115  _intName = function.getName() ;
116 }
117 
118 
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Virtual constructor with given function and configuration. Needed by RooNumIntFactory
122 
123 RooAbsIntegrator* RooAdaptiveIntegratorND::clone(const RooAbsFunc& function, const RooNumIntConfig& config) const
124 {
125  RooAbsIntegrator* ret = new RooAdaptiveIntegratorND(function,config) ;
126 
127  return ret ;
128 }
129 
130 
131 
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// Destructor
135 
136 RooAdaptiveIntegratorND::~RooAdaptiveIntegratorND()
137 {
138  delete[] _xmin ;
139  delete[] _xmax ;
140  delete _integrator ;
141  delete _func ;
142  if (_nError>_nWarn) {
143  coutW(NumIntegration) << "RooAdaptiveIntegratorND::dtor(" << _intName
144  << ") WARNING: Number of suppressed warningings about integral evaluations where target precision was not reached is " << _nError-_nWarn << endl ;
145  }
146 
147 }
148 
149 
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// Check that our integration range is finite and otherwise return kFALSE.
153 /// Update the limits from the integrand if requested.
154 
155 Bool_t RooAdaptiveIntegratorND::checkLimits() const
156 {
157  if (!_xmin) {
158  _xmin = new Double_t[_func->NDim()] ;
159  _xmax = new Double_t[_func->NDim()] ;
160  }
161 
162  if (_useIntegrandLimits) {
163  for (UInt_t i=0 ; i<_func->NDim() ; i++) {
164  _xmin[i]= integrand()->getMinLimit(i);
165  _xmax[i]= integrand()->getMaxLimit(i);
166  }
167  }
168 
169  return kTRUE ;
170 }
171 
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Change our integration limits. Return kTRUE if the new limits are
175 /// ok, or otherwise kFALSE. Always returns kFALSE and does nothing
176 /// if this object was constructed to always use our integrand's limits.
177 
178 Bool_t RooAdaptiveIntegratorND::setLimits(Double_t *xmin, Double_t *xmax)
179 {
180  if(_useIntegrandLimits) {
181  oocoutE((TObject*)0,Integration) << "RooAdaptiveIntegratorND::setLimits: cannot override integrand's limits" << endl;
182  return kFALSE;
183  }
184  for (UInt_t i=0 ; i<_func->NDim() ; i++) {
185  _xmin[i]= xmin[i];
186  _xmax[i]= xmax[i];
187  }
188 
189  return checkLimits();
190 }
191 
192 
193 
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Evaluate integral at given function binding parameter values
197 
198 Double_t RooAdaptiveIntegratorND::integral(const Double_t* /*yvec*/)
199 {
200  Double_t ret = _integrator->Integral(_xmin,_xmax) ;
201  if (_integrator->Status()==1) {
202  _nError++ ;
203  if (_nError<=_nWarn) {
204  coutW(NumIntegration) << "RooAdaptiveIntegratorND::integral(" << integrand()->getName() << ") WARNING: target rel. precision not reached due to nEval limit of "
205  << _nmax << ", estimated rel. precision is " << Form("%3.1e",_integrator->RelError()) << endl ;
206  }
207  if (_nError==_nWarn) {
208  coutW(NumIntegration) << "RooAdaptiveIntegratorND::integral(" << integrand()->getName()
209  << ") Further warnings on target precision are suppressed conform specification in integrator specification" << endl ;
210  }
211  }
212  return ret ;
213 }
214