HepLib
HCubatureMP.cpp
Go to the documentation of this file.
1 
6 #include <math.h>
7 #include <complex>
8 extern "C" {
9 #include <quadmath.h>
10 }
11 #include "mpreal.h"
12 #include "SD.h"
13 
14 using namespace std;
15 typedef mpfr::mpreal mpREAL;
16 typedef complex<mpREAL> mpCOMPLEX;
17 
18 extern mpREAL mpPi;
19 extern mpREAL mpEuler;
20 extern mpCOMPLEX mpiEpsilon;
21 
22 #include "Lib3_HCubatureMP.h"
23 namespace HepLib::SD {
24 
25  ex HCubatureMP::mp2ex(const mpREAL & num) {
26  ostringstream oss;
27  oss.precision(MPDigits);
28  oss << num;
29  string sn = oss.str();
30  numeric ret(sn.c_str());
31  return ret;
32  }
33 
34  int HCubatureMP::Wrapper(unsigned int xdim, size_t npts, const mpREAL *x, void *fdata, unsigned int ydim, mpREAL *y) {
35  auto self = (HCubatureMP*)fdata;
36  bool NaNQ = false;
37 
38  unsigned int nthreads = self->Threads>0 ? self->Threads : omp_get_num_procs();
39  #pragma omp parallel for num_threads(nthreads) schedule(dynamic, 1)
40  for(int i=0; i<npts; i++) {
41  mpfr_free_cache();
42  mpfr::mpreal::set_default_prec(mpfr::digits2bits(self->MPDigits));
43  self->IntegrandMP(xdim, x+i*xdim, ydim, y+i*ydim, self->mpParameter, self->mpLambda);
44  // Final Check NaN/Inf
45  bool ok = true;
46  for(int j=0; j<ydim; j++) {
47  mpREAL ytmp = y[i*ydim+j];
48  if(isnan(ytmp) || isinf(ytmp)) { ok = false; break; }
49  }
50  if(!ok && (self->IntegrandMP!=NULL)) {
51  mpfr_free_cache();
52  mpfr::mpreal::set_default_prec(mpfr::digits2bits(self->MPDigits*10));
53  self->IntegrandMP(xdim, x+i*xdim, ydim, y+i*ydim, self->mpParameter, self->mpLambda);
54  mpfr::mpreal::set_default_prec(mpfr::digits2bits(self->MPDigits));
55  }
56 
57  // final check
58  for(int j=0; j<ydim; j++) {
59  mpREAL ytmp = y[i*ydim+j];
60  if(isnan(ytmp) || isinf(ytmp)) {
61  #pragma omp atomic
62  self->nNAN++;
63  if(self->nNAN > self->NANMax) { NaNQ = true; break; }
64  else y[i*ydim+j] = 0;
65  }
66  }
67  if(self->ReIm == 1) y[i*ydim+1] = 0;
68  else if(self->ReIm == 2) y[i*ydim+0] = 0;
69  mpfr_free_cache();
70  }
71 
72  return NaNQ ? 1 : 0;
73  }
74 
75  void HCubatureMP::DefaultPrintHooker(mpREAL* result, mpREAL* epsabs, size_t * nrun, void *fdata) {
76  auto self = (HCubatureMP*)fdata;
77  if(*nrun == self->MaxPTS + 1979) return;
78  if(self->RunTime>0) {
79  auto cur_timer = time(NULL);
80  auto used_time = difftime(cur_timer,self->StartTimer);
81  if(used_time>self->RunTime) {
82  self->NEval = *nrun;
83  *nrun = self->MaxPTS + 1979;
84  if(Verbose>10) cout << WarnColor << " Exit with Run out of Time: " << used_time << RESET << endl;
85  return;
86  }
87  }
88  if(Verbose>10 && (*nrun-self->NEval) >= self->RunPTS) {
89  auto r0 = result[0];
90  auto r1 = result[1];
91  auto e0 = epsabs[0].toString(3);
92  auto e1 = epsabs[1].toString(3);
93  cout << " N: " << (*nrun) << ", ";
94  if(self->ReIm==3 || self->ReIm==1) cout << "[" << r0 << ", " << e0 << "]";
95  if(self->ReIm==3 || self->ReIm==2) cout << "+I*[" << r1 << ", " << e1 << "]";
96  cout << endl;
97  }
98  if((*nrun-self->NEval) >= self->RunPTS) self->NEval = *nrun;
99 
100  if((isnan(result[0]) || isnan(result[1]) || isnan(epsabs[0]) || isnan(epsabs[1])) || (isinf(result[0]) || isinf(result[1]) || isinf(epsabs[0]) || isinf(epsabs[1]))) {
101  self->NEval = *nrun;
102  *nrun = self->MaxPTS + 1979;
103  if(self->LastState>0) self->LastState = -1;
104  if(Verbose>10) cout << ErrColor << " Exit with NaN, LastN=" << self->lastNRUN << RESET << endl;
105  return;
106  }
107 
108  if(epsabs[0] > 1E30*self->EpsAbs || epsabs[1] > 1E30*self->EpsAbs) {
109  self->NEval = *nrun;
110  *nrun = self->MaxPTS + 1979;
111  if(self->LastState>0) self->LastState = -1;
112  if(Verbose>10) cout << WarnColor << " Exit with EpsAbs, LastN=" << self->lastNRUN << RESET << endl;
113  return;
114  }
115 
116  if((self->LastState == 0) || (epsabs[0]<=2*self->LastAbsErr[0] && epsabs[1]<=2*self->LastAbsErr[1])) {
117  self->LastResult[0] = result[0];
118  self->LastResult[1] = result[1];
119  self->LastAbsErr[0] = epsabs[0];
120  self->LastAbsErr[1] = epsabs[1];
121  self->LastState = 1;
122  self->lastNRUN = *nrun;
123  self->lastnNAN = self->nNAN;
124  }
125 
126  bool rExit = (epsabs[0] < self->EpsAbs+1E-50Q) || (epsabs[0] < fabs(result[0])*self->EpsRel+1E-50Q);
127  bool iExit = (epsabs[1] < self->EpsAbs+1E-50Q) || (epsabs[1] < fabs(result[1])*self->EpsRel+1E-50Q);
128  if(rExit && iExit && (*nrun)>self->MinPTS) {
129  self->NEval = *nrun;
130  *nrun = self->MaxPTS + 1979;
131  return;
132  }
133 
134  auto pid = getpid();
135  ostringstream fn;
136  fn << pid << ".int.done";
137  if(file_exists(fn.str().c_str())) {
138  self->NEval = *nrun;
139  *nrun = self->MaxPTS + 1979;
140  ostringstream cmd;
141  cmd << "rm " << fn.str();
142  auto rc = system(cmd.str().c_str());
143  if(Verbose>10) cout << " Exit: " << fn.str() << endl;
144  }
145  }
146 
147  ex HCubatureMP::Integrate(size_t tn) {
148  if(mpfr_buildopt_tls_p()<=0) throw Error("Integrate: mpfr_buildopt_tls_p()<=0.");
149  mpfr_free_cache();
150  mpfr::mpreal::set_default_prec(mpfr::digits2bits(MPDigits));
151  mpPi = mpfr::const_pi();
152  mpEuler = mpfr::const_euler();
153  mpiEpsilon = complex<mpREAL>(0,mpfr::machine_epsilon()*100);
154 
155  unsigned int xdim = XDim;
156  unsigned int ydim = 2;
157  mpREAL result[ydim], estabs[ydim];
158 
159  mpREAL xmin[xdim], xmax[xdim];
160  for(int i=0; i<xdim; i++) {
161  xmin[i] = 0;
162  xmax[i] = 1;
163  }
164  LastState = 0;
165  NEval = 0;
166  nNAN = 0;
167 
168  size_t _MinPTS_, _RunPTS_;
169  if(tn==0) {
170  _RunPTS_ = RunPTS;
171  MaxPTS = RunPTS * RunMAX;
172  _MinPTS_ = MinPTS>0 ? MinPTS : _RunPTS_/10;
173  } else {
174  MaxPTS = tn;
175  if(MaxPTS<10000) MaxPTS = 10000;
176  _RunPTS_ = MaxPTS/5;
177  _MinPTS_ = MinPTS>0 ? MinPTS : _RunPTS_/10;
178  }
179  StartTimer = time(NULL);
180  StartTimer = time(NULL);
181 
182  Lib3_HCubatureMP::CPUCORES = omp_get_num_procs();
183  int nok = Lib3_HCubatureMP::hcubature_v(ydim, Wrapper, this, xdim, xmin, xmax, _MinPTS_, _RunPTS_, MaxPTS, EpsAbs, EpsRel, result, estabs, tn==0 ? PrintHooker : NULL);
184 
185  if(nok) {
186  mpREAL abs_res = sqrt(result[0]*result[0]+result[1]*result[1]);
187  mpREAL abs_est = sqrt(estabs[0]*estabs[0]+estabs[1]*estabs[1]);
188  mpREAL mpfr_eps = 10*mpfr::machine_epsilon();
189  if( (abs_res < mpfr_eps) && (abs_est < mpfr_eps) ) {
190  cout << ErrColor << "HCubatureMP Failed with 0 result returned!" << RESET << endl;
191  return NaN;
192  }
193  }
194 
195  if(LastState==-1 && use_last) {
196  result[0] = LastResult[0];
197  result[1] = LastResult[1];
198  estabs[0] = LastAbsErr[0];
199  estabs[1] = LastAbsErr[1];
200  NEval = lastNRUN;
201  nNAN = lastnNAN;
202  }
203 
204  ex FResult = 0;
205  if(isnan(result[0]) || isnan(result[1])) FResult += NaN;
206  else {
207  try{
208  FResult += VE(mp2ex(result[0]), mp2ex(estabs[0]));
209  FResult += VE(mp2ex(result[1]), mp2ex(estabs[1])) * I;
210  } catch(...) {
211  FResult += NaN;
212  }
213  }
214 
215  // Check nNAN / NEval
216  if(nNAN * 1000 > NEval && NEval>0) {
217  cout << ErrColor << "NAN=" << nNAN << " v.s. RUN=" << NEval << RESET << endl;
218  }
219 
220  return FResult;
221  }
222 
223 }
#define RESET
Definition: BASIC.h:79
complex< mpREAL > mpCOMPLEX
Definition: HCubatureMP.cpp:16
mpfr::mpreal mpREAL
Definition: HCubatureMP.cpp:15
mpREAL mpEuler
mpCOMPLEX mpiEpsilon
mpREAL mpPi
complex< mpREAL > mpCOMPLEX
Definition: HCubature.cpp:20
mpfr::mpreal mpREAL
Definition: HCubature.cpp:19
bool file_exists(const char *fn)
Definition: Process.cpp:9
SecDec header file.
class used to wrap error message
Definition: BASIC.h:242
numerical integrator using HCubatureMP
Definition: SD.h:204
namespace for Numerical integration with Sector Decomposition method
Definition: AsyMB.cpp:10
mpfr::mpreal mpREAL
Definition: SD.h:125
const char * ErrColor
Definition: BASIC.cpp:246
const char * WarnColor
Definition: BASIC.cpp:247
int Verbose
Definition: Init.cpp:139
const Symbol NaN