Tolerance problem in integration. Can I solve it with Functor?


ROOT Version (6.10/08):
Platform, compiler (Mac OSX,
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.5.0):


Hello!
I have a question concerning randomisation.
I have a function:

Double_t angle_f(Double_t *x, Double_t *par){

  Double_t tt =x[0]*1e-3;//mrad
  Double_t om=par[0];
  Double_t omf=par[1];
  Double_t omg=par[2];
  Double_t g=par[3];
  Double_t lf=par[4];
  Double_t lg=par[5];
  Double_t N=par[6];


  Double_t z1=4*h_h*c/om * 1/(pow(g,-2.)+pow(tt,2.)+pow(omf/om,2.));
  Double_t z2=4*h_h*c/om * 1/(pow(g,-2.)+pow(tt,2.)+pow(omg/om,2.));

  
  Double_t f_1=pow(sin(lf/z1),2.);
  Double_t f_N=pow(sin(N*(lf/z1+lg/z2)),2.)/pow(sin(lf/z1+lg/z2),2.);

  Double_t f=pow(om,2.)*pow(tt,3.)*pow(z1-z2,2.)*f_1*f_N;
  
  return f;

}

And I use it to generate distribution with FillRandom.

    TF1 *ang_f=new TF1("ang_f",angle_f,1e-5,4,7);
    ang_f->SetParameters(11200,  20.87,  0.73,   39139   ,   62.,    1984.6, 150);
    ang_f->SetParNames("omega","omegaf","omegag","gamma",  "lf",   "lg",  "N");
    TH1F h_tt=new TH1F("name","name",200,1e-5,4);    
    h_tt->FillRandom("ang_f",1e6);

This way I have an error

Error in : Error 18 in qags.c at 548 : cannot reach tolerance because of roundoff error
Warning in TF1::IntegralOneDim: Error found in integrating function ang_f in [2.740000,2.760000] using AdaptiveSingular. Result = 5.404230 +/- 0.000000 - status = 18
Info in TF1::IntegralOneDim: Function Parameters = { omega = 11200.000000 , omegaf = 20.870000 , omegag = 0.730000 , gamma = 39139.000000 , lf = 62.000000 , lg = 1984.666667 , N = 150.000000 }

It is clear that it is the problems with huge fluctuations of the function. And I want to avoid errors. Is it possible?
For example using Functor helps to integrate:

      Double_t par[] = {11200,  20.87,  0.73,   39139   ,   62.,    1984.6, 150.} ; 
      ROOT::Math::Functor func ( std::bind2nd ( std::ptr_fun(angle_f) , par ), 7 ) ; 
      ROOT::Math::OneDimMultiFunctionAdapter<> wf_ (func) ; 
      ROOT::Math::Integrator ig (wf_, ROOT::Math::IntegrationOneDim::kADAPTIVESINGULAR, 1e-9, 1e-6, 1000) ; 
      printf ("\n%e\n",(double)ang_f->Eval(T)/ig.Integral(1e-5,4)) ; 

This pice of code above works with no errors. Is it possible to combine those methods?

Cheers
Evgeny

Hi,

Unfortunately inside TH1::FillRandom the default integration tolerance is used (eps=1.E-12), while in your direct call to the Integrator class you use (1.E-9 and 1.E-6).
I think 1.E-12 is probably a tolerance too small in general and I will change the default and make it using the static values from ROOT::Math::IntegratorOneDimOptions

Lorenzo

Hello Lorenzo, thanx for the reply.
Can I do it my self?
Or you mean you want to improve the procedure?

Evgeny

Hi,

I have updated now the code in the master. You can now set a default tolerance before calling TH1::FillRandom, by doing for example:

ROOT::Math::IntegratorOneDimOptions::SetDefaultRelTolerance(1.E-6); 

Lorenzo

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.