HepLib
Loading...
Searching...
No Matches
HCubature.cpp
Go to the documentation of this file.
1
6#include <math.h>
7#include <complex>
8extern "C" {
9#include <quadmath.h>
10}
11#include "mpreal.h"
12#include "SD.h"
13
14using namespace std;
15typedef __float128 qREAL;
16typedef __complex128 qCOMPLEX;
17typedef long double dREAL;
18typedef complex<dREAL> dCOMPLEX;
19typedef mpfr::mpreal mpREAL;
20typedef complex<mpREAL> mpCOMPLEX;
21
22extern const qCOMPLEX qiEpsilon;
23extern mpREAL mpPi;
24extern mpREAL mpEuler;
26
27#include "Lib3_HCubature.h"
28namespace HepLib::SD {
29
30/*-----------------------------------------------------*/
31// HCubature Classes
32/*-----------------------------------------------------*/
33
34 int HCubature::Wrapper(unsigned int xdim, size_t npts, const qREAL *x, void *fdata, unsigned int ydim, qREAL *y) {
35 auto self = (HCubature*)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 auto pbit = mpfr::digits2bits(self->MPDigits);
43 if(mpfr::mpreal::get_default_prec()!=pbit) mpfr::mpreal::set_default_prec(pbit);
44 int iDQMP = self->XDQMP(x+i*xdim);
45 if( (self->IntegrandMP!=NULL) && (self->DQMP>2 || iDQMP>2) ) {
46 mpREAL mpx[xdim], mpy[ydim];
47 for(int j=0; j<xdim; j++) mpx[j] = x[i*xdim+j];
48 self->IntegrandMP(xdim, mpx, ydim, mpy, self->mpParameter, self->mpLambda);
49 for(int j=0; j<ydim; j++) y[i*ydim+j] = mpy[j].toFloat128();
50 } else if(self->DQMP>1 || iDQMP>1) {
51 self->IntegrandQ(xdim, x+i*xdim, ydim, y+i*ydim, self->qParameter, self->qLambda);
52 bool ok = true;
53 for(int j=0; j<ydim; j++) {
54 qREAL ytmp = y[i*ydim+j];
55 if(isnanq(ytmp) || isinfq(ytmp)) { ok = false; break; }
56 }
57
58 if(!ok && (self->IntegrandMP!=NULL)) {
59 mpREAL mpx[xdim], mpy[ydim];
60 for(int j=0; j<xdim; j++) mpx[j] = x[i*xdim+j];
61 self->IntegrandMP(xdim, mpx, ydim, mpy, self->mpParameter, self->mpLambda);
62 for(int j=0; j<ydim; j++) y[i*ydim+j] = mpy[j].toFloat128();
63 }
64 } else {
65 dREAL dx[xdim], dy[ydim];
66 for(int j=0; j<xdim; j++) dx[j] = (dREAL)x[i*xdim+j];
67 self->IntegrandD(xdim, dx, ydim, dy, self->dParameter, self->dLambda);
68 for(int j=0; j<ydim; j++) y[i*ydim+j] = dy[j];
69 bool ok = true;
70 for(int j=0; j<ydim; j++) {
71 qREAL ytmp = y[i*ydim+j];
72 if(isnanq(ytmp) || isinfq(ytmp)) { ok = false; break; }
73 }
74
75 if(!ok) self->IntegrandQ(xdim, x+i*xdim, ydim, y+i*ydim, self->qParameter, self->qLambda);
76
77 ok = true;
78 for(int j=0; j<ydim; j++) {
79 qREAL ytmp = y[i*ydim+j];
80 if(isnanq(ytmp) || isinfq(ytmp)) { ok = false; break; }
81 }
82 if(!ok && (self->IntegrandMP!=NULL)) {
83 mpREAL mpx[xdim], mpy[ydim];
84 for(int j=0; j<xdim; j++) mpx[j] = x[i*xdim+j];
85 self->IntegrandMP(xdim, mpx, ydim, mpy, self->mpParameter, self->mpLambda);
86 for(int j=0; j<ydim; j++) y[i*ydim+j] = mpy[j].toFloat128();
87 }
88 }
89
90 // Final Check NaN/Inf
91 bool ok = true;
92 for(int j=0; j<ydim; j++) {
93 qREAL ytmp = y[i*ydim+j];
94 if(isnanq(ytmp) || isinfq(ytmp)) { ok = false; break; }
95 }
96 if(!ok && (self->IntegrandMP!=NULL)) {
97 mpfr_free_cache();
98 auto pbit = mpfr::digits2bits(self->MPDigits*10);
99 if(mpfr::mpreal::get_default_prec()!=pbit) mpfr::mpreal::set_default_prec(pbit);
100 mpREAL mpx[xdim], mpy[ydim];
101 for(int j=0; j<xdim; j++) mpx[j] = x[i*xdim+j];
102 self->IntegrandMP(xdim, mpx, ydim, mpy, self->mpParameter, self->mpLambda);
103 for(int j=0; j<ydim; j++) y[i*ydim+j] = mpy[j].toFloat128();
104 pbit = mpfr::digits2bits(self->MPDigits);
105 if(mpfr::mpreal::get_default_prec()!=pbit) mpfr::mpreal::set_default_prec(pbit);
106 }
107
108 // final check
109 for(int j=0; j<ydim; j++) {
110 qREAL ytmp = y[i*ydim+j];
111 if(isnanq(ytmp) || isinfq(ytmp)) {
112 #pragma omp atomic
113 self->nNAN++;
114 if(self->nNAN > self->NANMax) { NaNQ = true; break; }
115 else y[i*ydim+j] = 0;
116 }
117 }
118 if(self->YDim==2) {
119 if(self->ReIm == 1) y[i*ydim+1] = 0;
120 else if(self->ReIm == 2) y[i*ydim+0] = 0;
121 }
122 mpfr_free_cache();
123 }
124
125 return NaNQ ? 1 : 0;
126 }
127
128 void HCubature::DefaultPrintHooker(qREAL *result, qREAL *epsabs, size_t *nrun, void *fdata) {
129 auto self = (HCubature*)fdata;
130 if(*nrun == self->MaxPTS + 1979) return;
131 if(self->RunTime>0) {
132 auto cur_timer = time(NULL);
133 auto used_time = difftime(cur_timer,self->StartTimer);
134 if(used_time>self->RunTime) {
135 self->NEval = *nrun;
136 *nrun = self->MaxPTS + 1979;
137 if(Verbose>10) cout << WarnColor << " Exit with Run out of Time: " << used_time << RESET << endl;
138 return;
139 }
140 }
141
142 if((*nrun-self->NEval) >= self->RunPTS) {
143 if(Verbose>10) {
144 if(self->YDim==2) {
145 char r0[64], r1[64], e0[32], e1[32];
146 quadmath_snprintf(r0, sizeof r0, "%.10QG", result[0]);
147 quadmath_snprintf(r1, sizeof r1, "%.10QG", result[1]);
148 quadmath_snprintf(e0, sizeof e0, "%.5QG", epsabs[0]);
149 quadmath_snprintf(e1, sizeof e1, "%.5QG", epsabs[1]);
150 cout << " N: " << (*nrun) << ", ";
151 if(self->ReIm==3 || self->ReIm==1) cout << "[" << r0 << ", " << e0 << "]";
152 if(self->ReIm==3 || self->ReIm==2) cout << "+I*[" << r1 << ", " << e1 << "]";
153 cout << endl;
154 } else {
155 for(int j=0; j<self->YDim; j++) {
156 char r[64], e[32];
157 quadmath_snprintf(r, sizeof r, "%.10QG", result[j]);
158 quadmath_snprintf(e, sizeof e, "%.5QG", epsabs[j]);
159 if(j==0) cout << " N: " << (*nrun) << ", ";
160 else {
161 cout << " ";
162 int ct = to_string(*nrun).length();
163 for(int k=0; k<ct; k++) cout << " ";
164 }
165 cout << "[" << r << ", " << e << "]";
166 cout << endl;
167 }
168 }
169 }
170 self->NEval = *nrun;
171 }
172
173 bool any_NAN_Inf = false;
174 for(int j=0; j<self->YDim; j++) {
175 if(isnanq(result[j]) || isnanq(epsabs[j]) || isinfq(result[j]) || isinfq(epsabs[j])) {
176 any_NAN_Inf = true;
177 break;
178 }
179 }
180 if(any_NAN_Inf) {
181 self->NEval = *nrun;
182 *nrun = self->MaxPTS + 1979;
183 if(self->LastState>0) self->LastState = -1;
184 if(Verbose>10) cout << ErrColor << " Exit with NaN, LastN=" << self->lastNRUN << RESET << endl;
185 return;
186 }
187
188 bool any_Big = false;
189 for(int j=0; j<self->YDim; j++) {
190 if(epsabs[j] > 1E30*self->EpsAbs) {
191 any_Big = true;
192 break;
193 }
194 }
195 if(any_Big) {
196 self->NEval = *nrun;
197 *nrun = self->MaxPTS + 1979;
198 if(self->LastState>0) self->LastState = -1;
199 if(Verbose>10) cout << WarnColor << " Exit with EpsAbs, LastN=" << self->lastNRUN << RESET << endl;
200 return;
201 }
202
203 bool all_Done = true;
204 for(int j=0; j<self->YDim; j++) {
205 if(epsabs[j] > 2*self->LastAbsErr[j] ) {
206 all_Done = false;
207 break;
208 }
209 }
210 if((self->LastState == 0) || all_Done) {
211 for(int j=0; j<self->YDim; j++) {
212 self->LastResult[j] = result[j];
213 self->LastAbsErr[j] = epsabs[j];
214 }
215 self->LastState = 1;
216 self->lastNRUN = *nrun;
217 self->lastnNAN = self->nNAN;
218 }
219
220 bool bExit = true;
221 for(int j=0; j<self->YDim; j++) {
222 if((epsabs[j] > self->EpsAbs+1E-50Q) && (epsabs[j] > fabsq(result[j])*self->EpsRel+1E-50Q)) {
223 bExit = false;
224 break;
225 }
226 }
227 if(bExit && (*nrun)>self->MinPTS) {
228 self->NEval = *nrun;
229 *nrun = self->MaxPTS + 1979;
230 return;
231 }
232
233 auto pid = getpid();
234 ostringstream fn;
235 fn << pid << ".int.done";
236 if(file_exists(fn.str().c_str())) {
237 self->NEval = *nrun;
238 *nrun = self->MaxPTS + 1979;
239 ostringstream cmd;
240 cmd << "rm " << fn.str();
241 auto rc = system(cmd.str().c_str());
242 if(Verbose>10) cout << " Exit: " << fn.str() << endl;
243 }
244 }
245
246 ex HCubature::Integrate(size_t tn) {
247 if(LastResult.size()!=YDim) LastResult.resize(YDim);
248 if(LastAbsErr.size()!=YDim) LastAbsErr.resize(YDim);
249 if(mpfr_buildopt_tls_p()<=0) throw Error("Integrate: mpfr_buildopt_tls_p()<=0.");
250 mpfr_free_cache();
251 auto pbit = mpfr::digits2bits(MPDigits);
252 if(mpfr::mpreal::get_default_prec()!=pbit) mpfr::mpreal::set_default_prec(pbit);
253 mpPi = mpfr::const_pi();
254 mpEuler = mpfr::const_euler();
255 mpiEpsilon = complex<mpREAL>(0,mpfr::machine_epsilon()*100);
256
257 unsigned int xdim = XDim;
258 unsigned int ydim = YDim;
259 qREAL result[ydim], estabs[ydim];
260
261 qREAL xmin[xdim], xmax[xdim];
262 for(int i=0; i<xdim; i++) {
263 xmin[i] = 0.0Q;
264 xmax[i] = 1.0Q;
265 }
266 LastState = 0;
267 NEval = 0;
268 nNAN = 0;
269
270 size_t _MinPTS_, _RunPTS_;
271 if(tn==0) {
272 _RunPTS_ = RunPTS;
273 MaxPTS = RunPTS * RunMAX;
274 _MinPTS_ = MinPTS>0 ? MinPTS : _RunPTS_/10;
275 } else {
276 MaxPTS = tn;
277 if(MaxPTS<10000) MaxPTS = 10000;
278 _RunPTS_ = MaxPTS/5;
279 _MinPTS_ = MinPTS>0 ? MinPTS : _RunPTS_/10;
280 }
281 StartTimer = time(NULL);
282
283 int nok = hcubature_v(ydim, Wrapper, this, xdim, xmin, xmax, _MinPTS_, _RunPTS_, MaxPTS, EpsAbs, EpsRel, result, estabs, tn==0 ? PrintHooker : NULL);
284
285 if(nok) {
286 qREAL abs_res = 0;
287 for(int j=0; j<ydim; j++) abs_res += result[j]*result[j];
288 abs_res = sqrtq(abs_res);
289 qREAL abs_est = 0;
290 for(int j=0; j<ydim; j++) abs_est += estabs[j]*estabs[j];
291 abs_est = sqrtq(abs_est);
292 qREAL flt128_eps = 10*FLT128_EPSILON;
293
294 if( (abs_res < flt128_eps) && (abs_est < flt128_eps) ) {
295 cout << ErrColor << "HCubature Failed with 0 result returned!" << RESET << endl;
296 return NaN;
297 }
298 }
299
300 if(LastState==-1 && use_last) {
301 for(int j=0; j<ydim; j++) {
302 result[j] = LastResult[j];
303 estabs[j] = LastAbsErr[j];
304 }
305 NEval = lastNRUN;
306 nNAN = lastnNAN;
307 }
308
309 ex FResult = 0;
310 bool any_NAN = false;
311 for(int j=0; j<ydim; j++) {
312 if(isnanq(result[j])) {
313 any_NAN = true;
314 break;
315 }
316 }
317 if(any_NAN) FResult = NaN;
318 else {
319 try{
320 if(ydim==2) {
321 FResult = VE(q2ex(result[0]), q2ex(estabs[0])) + VE(q2ex(result[1]), q2ex(estabs[1])) * I;
322 } else {
323 lst res;
324 for(int j=0; j<ydim; j++) res.append(VE(q2ex(result[j]), q2ex(estabs[j])));
325 FResult = res;
326 }
327 } catch(...) {
328 FResult = NaN;
329 }
330 }
331
332 // Check nNAN / NEval
333 if(nNAN * 1000 > NEval && NEval>0) {
334 cout << ErrColor << "NAN=" << nNAN << " v.s. RUN=" << NEval << RESET << endl;
335 }
336
337 return FResult;
338 }
339
340 int HCubature::XDQMP(qREAL const *x) {
341 unsigned int xdim = XDim;
342
343 if(xdim<=MPXDim) return 3;
344 qREAL xmin = 100;
345 for(int i=0; i<xdim; i++) {
346 if(x[i] < xmin) xmin = x[i];
347 }
348 if(xmin < MPXLimit) return 3;
349
350 if(FT!=NULL) {
351 qREAL ft = 1E50;
352 static FT_Type last_ft = NULL;
353 static qREAL ft0;
354 if(last_ft!=FT) {
355 qREAL x0[xdim];
356 for(int i=0; i<xdim; i++) x0[i]=0.521Q;
357 qREAL ft0 = fabsq(FT(x0, qParameter));
358 if(ft0<1E-50) ft0 = 1;
359 last_ft = FT;
360 }
361 ft = fabsq(FT(x, qParameter));
362 ft = ft/ft0;
363 if(ft<MPFLimit) return 3;
364 else if(ft<QFLimit) return 2;
365 }
366
367 if(xdim <= QXDim || xmin < QXLimit) return 2;
368
369 return 1;
370 }
371
372}
#define RESET
Definition BASIC.h:79
complex< mpREAL > mpCOMPLEX
Definition HCubature.cpp:20
complex< dREAL > dCOMPLEX
Definition HCubature.cpp:18
mpfr::mpreal mpREAL
Definition HCubature.cpp:19
__complex128 qCOMPLEX
Definition HCubature.cpp:16
long double dREAL
Definition HCubature.cpp:17
__float128 qREAL
Definition HCubature.cpp:15
const qCOMPLEX qiEpsilon
mpREAL mpEuler
Definition SD.h:28
mpCOMPLEX mpiEpsilon
mpREAL mpPi
SecDec header file.
class used to wrap error message
Definition BASIC.h:245
numerical integrator using HCubature
Definition SD.h:172
virtual ex Integrate(size_t n=0) override
static void DefaultPrintHooker(qREAL *, qREAL *, size_t *, void *)
PrintHookerType PrintHooker
Definition SD.h:180
static int Wrapper(unsigned int xdim, size_t npts, const qREAL *x, void *fdata, unsigned int ydim, qREAL *y)
Definition HCubature.cpp:34
qREAL(* FT_Type)(const qREAL xx[], const qREAL pl[])
Definition SD.h:143
const qREAL * qParameter
Definition SD.h:153
__float128 qREAL
Definition SD.h:128
long double dREAL
Definition SD.h:126
mpfr::mpreal mpREAL
Definition SD.h:130
ex q2ex(__float128 num)
__float128 to ex
Definition BASIC.cpp:868
const char * ErrColor
Definition BASIC.cpp:246
bool file_exists(string fn)
Definition BASIC.h:292
const char * WarnColor
Definition BASIC.cpp:247
int Verbose
Definition Init.cpp:145
const Symbol NaN