115 lst lmom = ex_to<lst>(aio.
Internal);
116 lst emom = ex_to<lst>(aio.
External);
119 if(
Verbose > 1) cout <<
PRE <<
"\\--Reading ApartIBP" << flush;
126 if(IBPmethod==1) wdir = aio.
SaveDir +
"/FIRE";
127 else if(IBPmethod==2) wdir = aio.
SaveDir +
"/KIRA";
128 else if(IBPmethod==3) wdir = aio.
SaveDir +
"/UKIRA";
130 wdir = to_string(getpid());
131 if(IBPmethod==1) wdir = wdir +
"_FIRE";
132 else if(IBPmethod==2) wdir = wdir +
"_KIRA";
133 else if(IBPmethod==3) wdir = wdir +
"_UKIRA";
137 vector<IBP*> ibp_vec;
139 if(
Verbose > 1) cout <<
PRE <<
"\\--Reading AIR2F" << flush;
140 AIR2F_Get(aio.
SaveDir, air_vec, IntFs, ibp_vec, IBPmethod);
141 for(
auto ibp : ibp_vec) ibp->WorkingDir = wdir;
142 if(
Verbose > 1) cout <<
" @ " <<
now(
false) << endl;
148 if(
Verbose > 1) cout <<
PRE <<
"\\--Reading AP.gar" << flush;
150 if(
Verbose > 1) cout <<
" @ " <<
now(
false) << endl;
152 }
else rc = system((
"mkdir -p "+aio.
SaveDir).c_str());
156 int av_size = air_vec.size();
162 for(
int i=0; i<av_size; i++) {
163 for(
auto cv : ex_to<lst>(air_vec[i])) vset.insert(cv.op(1));
165 exvector vvec(vset.begin(), vset.end());
169 for(
int i=0; i<vvec.size(); i++) v2api[vvec[i]] = i;
170 for(
int i=0; i<av_size; i++) {
172 lst cvs = ex_to<lst>(air_vec[i]);
173 for(
auto & cv : cvs) av_item.append(lst{cv.op(0).subs(
iEpsilon==0,
nopat), v2api[cv.op(1)]});
174 air_vec[i] = av_item;
178 auto ap_vec =
GiNaC_Parallel(vvec.size(), [&vvec,lmom,emom,aio] (
int idx) {
179 auto air = vvec[idx];
180 air = Apart(air,lmom,emom,aio.smap);
181 air = air.subs(ApartIR(1,w)==aio.apart1);
182 air = collect_lst(air, ApartIR(w1,w2), o_flintf);
188 for(
auto cvs : ap_vec)
for(
auto cv : cvs)
if(is_a<matrix>(cv.op(1).op(0))) ap_set.insert(cv.op(1));
189 exvector ap_ir_vec(ap_set.begin(), ap_set.end());
196 ap_vec =
GiNaC_Parallel(ap_vec.size(), [&aio,&ap_vec,&ap_rules] (
int idx) {
197 auto const & cvs = ap_vec[idx];
200 for(auto const & cv : cvs) {
201 auto fi = ap_rules.find(cv.op(1));
202 if(fi==ap_rules.end()) res += cv.op(0) * cv.op(1);
203 else res += cv.op(0) * fi->second;
206 for(auto cv : cvs) res += cv.op(0) * ApartIRC(cv.op(1));
211 int vn = ap_vec.size();
212 for(
int idx=0; idx<vn; idx++) {
213 lst cvs = ex_to<lst>(ap_vec[idx]);
216 for(
auto const & cv : cvs) {
217 auto fi = ap_rules.find(cv.op(1));
218 if(fi==ap_rules.end()) res += cv.op(0) * cv.op(1);
219 else res += cv.op(0) * fi->second;
222 for(
auto cv : cvs) res += cv.op(0) *
ApartIRC(cv.op(1));
232 lst cvs = ex_to<lst>(air_vec[idx]);
234 for(
auto const & cv : cvs) {
235 int idx = ex_to<numeric>(cv.op(1)).to_int();
236 res += cv.op(0) * ap_vec[idx];
243 if(aio.SaveDir !=
"") {
244 garWrite(air_vec,aio.SaveDir+
"/AP.gar");
245 garRead(air_vec,aio.SaveDir+
"/AP.gar");
254 auto ret =
GiNaC_Parallel(air_vec.size(), [&air_vec](
int idx)->ex {
255 auto air = air_vec[idx];
257 find(air, ApartIR(w1,w2), airs);
259 for(auto item : airs) ret.append(item);
263 for(
auto airs : ret) for(auto air : ex_to<lst>(airs))
intg.insert(air);
264 AIR = exvector(
intg.begin(),
intg.end());
267 for(
auto sp : aio.CSP)
SP_map.erase(
sp);
273 repls.append(w*kv.first == w*kv.second);
274 repls.append(kv.first == kv.second);
278 for(
auto li : lmom) {
279 if(is_a<Vector>(li)) loops.append(ex_to<Vector>(li).name);
280 else loops.append(li);
282 for(
auto li : emom) {
283 if(is_a<Vector>(li)) exts.append(ex_to<Vector>(li).name);
284 else exts.append(li);
287 if(Verbose>0) cout <<
PRE <<
"\\--Prepare " <<
WHITE <<
"IBP" <<
RESET <<
" reduction @ " <<
now(
false) << flush;
290 std::map<ex, IBP*, ex_is_less> p2IBP;
292 int ntot = AIR.size();
293 for(
int i=0; i<ntot; i++) {
294 if(Verbose>0 && (((i+1)%1000)==0 || i+1==ntot)) {
295 cout <<
"\r \r" << flush;
296 cout <<
PRE <<
"\\--Prepare " <<
WHITE <<
"IBP" <<
RESET <<
" reduction [" << (i+1) <<
"/" << ntot <<
"] @ " <<
now(
false) << flush;
298 auto const & ir = AIR[i];
299 auto mat = ex_to<matrix>(ir.op(0));
300 auto vars = ex_to<lst>(ir.op(1));
302 int nrow = mat.rows();
304 for(
int c=0; c<mat.cols(); c++) {
306 for(
int r=0; r<nrow-2; r++) pc += mat(r,c) * vars.op(r);
309 ex nc = ex(0)-mat(nrow-1,c);
313 if(ncn==-1) den_tot++;
314 pns.append(lst{ ncn, pc, nc });
316 bool pn_sector =
false;
317 if(aio.pn_sector>0 && den_tot>=aio.pn_sector) pn_sector =
true;
319 for(
int i=0; i<pns.nops(); i++) pns[i] = lst{ pns.op(i).op(1), pns.op(i).op(2) };
323 for(
int i=0; i<pns.nops(); i++) pns[i] = lst{ pns.op(i).op(1), pns.op(i).op(2) };
326 int nCut = aio.Cut.nops();
329 cuts = cuts.subs(SP_map,nopat);
330 if(aio.CutFirst)
for(
auto cut : cuts) pns.prepend(lst{
SP2sp(cut), 1 });
331 else for(
auto cut : cuts) pns.append(lst{
SP2sp(cut), 1 });
335 for(
auto item : pns) {
336 props.append(item.op(0));
337 ns.append(item.op(1));
343 for(
int i=0; i<ns.nops(); i++) nss.append(ns.op(i)>0 ? 1 : 0);
344 key = lst{props,nss};
347 auto kv = p2IBP.find(key);
348 if(kv==p2IBP.end()) {
350 if(IBPmethod==0) ibp =
new IBP();
351 else if(IBPmethod==1) ibp =
new FIRE();
352 else if(IBPmethod==2) ibp =
new KIRA();
353 else if(IBPmethod==3) ibp =
new UKIRA();
359 p2IBP.insert(make_pair(key,ibp));
360 ibp->Propagator = props;
361 ibp->Internal = loops;
362 ibp->External = exts;
363 ibp->Replacement = repls;
364 if(aio.ISP.nops()>0)
for(
auto item : aio.ISP) ibp->ISP.append(
SP2sp(item));
365 if(aio.DSP.nops()>0) {
366 for(
auto item : aio.DSP) {
367 lst
sp = ex_to<lst>(item);
368 if(is_a<Vector>(
sp.op(0)))
sp[0] = (ex_to<Vector>(
sp.op(0)).name);
369 if(is_a<Vector>(
sp.op(1))) sp[1] = (ex_to<Vector>(
sp.op(1)).name);
375 for(
auto const & item : ns) {
376 if(item>0) sector.append(1);
377 else sector.append(0);
379 ibp->SECTOR = sector;
381 ibp->WorkingDir = wdir;
382 ibp->ProblemNumber =
pn;
385 if(aio.CutFirst)
for(
int i=0; i<nCut; i++) ibp->Cut.append(i+1);
386 else for(
int i=0; i<nCut; i++) ibp->Cut.append(nCut-i);
388 ibp_vec.push_back(ibp);
389 ibp->Integral.append(ns);
390 AIR2F[AIR[i]] = F(ibp->ProblemNumber, ns);
392 IBP* ibp = kv->second;
393 ibp->Integral.append(ns);
394 AIR2F[AIR[i]] = F(ibp->ProblemNumber, ns);
397 if(Verbose>0) cout << endl;
399 if(Verbose>0) cout <<
PRE <<
"\\--Total Ints/Pros: " <<
WHITE << ntot <<
"/" << ibp_vec.size() <<
RESET <<
" @ " <<
now(
false) << endl;
404 auto int_fr =
FindRules(ibp_vec,
false, aio.UF);
405 IntFs = int_fr.second;
408 air_vec =
GiNaC_Parallel(air_vec.size(), [&air_vec,&AIR2F,&int_fr] (
int idx) {
409 auto air = air_vec[idx];
410 air = air.subs(AIR2F,nopat);
411 air = air.subs(int_fr.first,nopat);
412 air = collect_ex(air, F(w1,w2));
415 if(aio.SaveDir !=
"") AIR2F_Save(aio.SaveDir, air_vec, IntFs, ibp_vec);
420 MapFunction _F2ex([&ibp_vec,aio](
const ex &e, MapFunction &self)->ex {
421 if(!e.has(F(w1,w2)))
return e;
422 else if(e.match(F(w1,w2))) {
423 int pn = ex_to<numeric>(e.op(0)).to_int();
424 auto pso = ex_to<lst>(ibp_vec[
pn-1]->Propagator);
425 auto nso = ex_to<lst>(e.op(1));
427 for(
int i=0; i<pso.nops(); i++) {
428 if(!aio.keep0F && nso.op(i).is_zero())
continue;
429 ps.append(pso.op(i));
430 ns.append(nso.op(i));
433 }
else return e.map(self);
437 air_vec =
GiNaC_Parallel(air_vec.size(), [&air_vec,&_F2ex](
int idx)->ex {
438 auto res = air_vec[idx];
441 for(
auto fp : ibp_vec) delete fp;
442 if(aio.SaveDir ==
"") rc = system((
"rm -rf "+wdir).c_str());
447 if(aio.SaveDir !=
"" &&
file_exists(aio.SaveDir+
"/MIs.gar")) {
451 vector<IBP*> ibp_vec_re;
453 map<int,lst> pn_ints_map;
454 for(
auto item : IntFs) {
455 int pn = ex_to<numeric>(item.op(0)).to_int();
456 pn_ints_map[
pn].append(item.op(1));
460 for(
auto pi : pn_ints_map) {
461 auto ibp = ibp_vec[pi.first-1];
462 ibp->Integral = pi.second;
463 nints += ibp->Integral.nops();
464 ibp_vec_re.push_back(ibp);
467 if(Verbose>0) cout <<
PRE <<
"\\--Refined Ints/Pros: " <<
WHITE << nints <<
"/" << ibp_vec_re.size() <<
RESET <<
" @ " <<
now(
false) << endl;
472 auto pRes =
GiNaC_Parallel(ibp_vec_re.size(), [&ibp_vec_re](
int idx)->ex {
473 ibp_vec_re[idx]->Export();
474 auto ret = lst{ ibp_vec_re[idx]->IsAlwaysZero ? 1 : 0, ibp_vec_re[idx]->Rules };
477 for(
int i=0; i<ibp_vec_re.size(); i++) {
478 ibp_vec_re[i]->IsAlwaysZero = (pRes[i].op(0)==1 ? true :
false);
479 ibp_vec_re[i]->Rules = ex_to<lst>(pRes[i].op(1));
482 int nproc = aio.NIBP;
483 if(nproc<1) nproc = 8;
485 if(nproc<1) nproc = 1;
486 size_t nibp = ibp_vec_re.size();
490 #pragma omp parallel for num_threads(nproc) schedule(dynamic, 1)
491 for(
int pi=0; pi<nibp; pi++) {
495 cout <<
"\r \r" << flush;
496 cout <<
PRE <<
"\\--" <<
WHITE <<
"FIRE" <<
RESET <<
" Reduction [" << (++cproc) <<
"/" << nibp <<
"] " << flush;
499 ibp_vec_re[pi]->Run();
501 if(Verbose>1 && nibp>0) cout <<
"@" <<
now(
false) << endl;
507 ibp_vec_re[idx]->Run();
511 for(
int pi=0; pi<nibp; pi++) {
512 if(Verbose>1) cout <<
"\r \r" <<
PRE <<
"\\--" <<
WHITE <<
"FIRE" <<
RESET <<
" Reduction [" << (++cproc) <<
"/" << nibp <<
"] " << flush;
513 ibp_vec_re[pi]->Run();
515 if(Verbose>1 && nibp>0) cout <<
"@" <<
now(
false) << endl;
519 if(ibp_vec_re.size()>100) {
520 auto ret =
GiNaC_Parallel(ibp_vec_re.size(), [&ibp_vec_re,wdir](
int idx)->ex {
521 ibp_vec_re[idx]->Import();
522 return ibp_vec_re[idx]->TO();
524 for(
int i=0; i<ibp_vec_re.size(); i++) ibp_vec_re[i]->FROM(ret[i]);
527 for(
auto item : ibp_vec_re) {
528 if(Verbose>1) cout <<
"\r \r" <<
PRE <<
"\\--" <<
WHITE <<
"FIRE" <<
RESET <<
" Import [" << (++cproc) <<
"/" << ibp_vec_re.size() <<
"] " << flush;
531 if(Verbose>1 && ibp_vec_re.size()>0) cout <<
"@" <<
now(
false) << endl;
535 if(aio.SaveDir ==
"") rc = system((
"rm -rf "+wdir).c_str());
536 }
else if(IBPmethod==2 || IBPmethod==3) {
537 for(
auto ibp : ibp_vec_re) ibp->Reduce();
538 if(aio.SaveDir ==
"") rc = system((
"rm -rf "+wdir).c_str());
542 auto fr =
FindRules(ibp_vec_re,
true, aio.UF);
543 exmap miRules = fr.first;
545 if(aio.SaveDir !=
"") rc = system((
"mkdir -p "+aio.SaveDir+
"/Rules").c_str());
546 auto rules_vec =
GiNaC_Parallel(ibp_vec_re.size(), [&ibp_vec_re,&miRules,&aio](
int idx)->ex {
547 lst rules = ex_to<lst>(ibp_vec_re[idx]->Rules);
549 for(auto ri : rules) res.append(lst {
551 collect_ex(ri.op(1).subs(miRules,nopat),F(w1,w2),o_flint)
553 for(
auto mi : ibp_vec_re[idx]->MIntegral) {
554 auto fi = miRules.find(mi);
555 if(fi!=miRules.end()) res.append(lst{ mi, fi->second });
557 auto pn = ibp_vec_re[idx]->ProblemNumber;
558 if(aio.SaveDir !=
"") {
559 garWrite(aio.SaveDir+
"/Rules/"+to_string(
pn)+
".gar", res);
563 if(aio.SaveDir !=
"") {
564 garWrite(aio.SaveDir+
"/MIs.gar", _F2ex(fr.second));
566 for(
auto rs : rules_vec) {
567 for(
auto ri : rs) if(ri.op(0)!=ri.op(1)) ibpRules[ri.op(0)] = ri.op(1);
576 GiNaC_Parallel(air_vec.size(), [&air_vec,&ibpRules,&_F2ex,&aio](
int idx)->ex {
577 ex res = air_vec[idx];
579 if(aio.SaveDir !=
"") {
581 find(res, F(w1,w2), fs);
583 for(auto fi : fs) pns.insert(fi.op(0));
585 auto rs = ex_to<lst>(garRead(aio.SaveDir+
"/Rules/"+ex2str(pn)+
".gar"));
586 for(auto ri : rs) if(ri.op(0)!=ri.op(1)) rules[ri.op(0)] = ri.op(1);
588 }
else rules = ibpRules;
589 res = res.subs(rules,nopat);
590 if(aio.pat.nops()>0) {
596 if(aio.cv!=
nullptr) {
597 auto _cv = aio.cv(c,v);
607 for(
auto fp : ibp_vec) delete fp;
609 if(aio.SaveDir !=
"")
garWrite(air_vec, aio.SaveDir+
"/ApartIBP.gar");