sherpa is hosted by Hepforge, IPPP Durham
close Warning: Can't synchronize with repository "(default)" (/hepforge/svn/sherpa does not appear to be a Subversion repository.). Look in the Trac log for more information.

Ticket #317: OpenLoopsReplace_Interface.C

File OpenLoopsReplace_Interface.C, 31.6 KB (added by Frank Siegert, 10 years ago)
Line 
1#include "PHASIC++/Process/Process_Base.H"
2#include "PHASIC++/Process/ME_Generator_Base.H"
3#include <dirent.h>
4
5
6#include "PHASIC++/Process/Tree_ME2_Base.H"
7#include "PHASIC++/Process/Virtual_ME2_Base.H"
8
9namespace MODEL {
10  class Model_Base;
11}
12
13namespace OpenLoopsReplace {
14
15typedef void (*Amp2Func)(double* moms, double* M2L0, double* M2L1, double* IRL1,
16                         double* M2L2, double* IRL2);
17
18typedef void (*PermutationFunc)(int* permutation);
19
20
21
22
23  class OpenLoopsReplace_Particle {
24  public:
25    std::string m_name, m_faname;
26    size_t m_order;
27    OpenLoopsReplace_Particle() : m_name(""), m_faname(""), m_order(0) {}
28    OpenLoopsReplace_Particle(std::string name, std::string faname, size_t order) :
29      m_name(name), m_faname(faname), m_order(order) {}
30  };
31
32
33  class OpenLoopsReplace_Interface: public PHASIC::ME_Generator_Base {
34
35    void InitializeParticles();
36
37    static std::string MatchOptions(std::vector<std::string> options,
38                                    int oew, int oqcd, int nloop);
39    static int SelectInfo(const dirent *entry);
40    static bool Order(const std::pair<size_t, ATOOLS::Flavour> &a,
41                      const std::pair<size_t, ATOOLS::Flavour> &b);
42
43  public :
44    OpenLoopsReplace_Interface() : ME_Generator_Base("OpenLoopsReplace") {}
45    ~OpenLoopsReplace_Interface() {}
46
47    bool Initialize(const std::string &path,const std::string &file,
48                    MODEL::Model_Base *const model,
49                    BEAM::Beam_Spectra_Handler *const beam,
50                    PDF::ISR_Handler *const isr);
51
52    static void SetParameter(const std::string & key, double value);
53    static void SetParameter(const std::string & key, int value);
54    static void SetParameter(const std::string & key, std::string value);
55    static double GetDoubleParameter(const std::string & key);
56    static int GetIntParameter(const std::string & key);
57    static void FlushParameters();
58
59    static std::string GetProcessPermutation(const ATOOLS::Flavour_Vector& flavs_orig,
60                                             std::vector<int>& permutation);
61    static std::pair<std::string, std::string> ScanFiles(std::string& process,
62                                                         int oew, int oqcd, int nloop);
63    static ATOOLS::Flavour_Vector MapFlavours(const ATOOLS::Flavour_Vector& orig);
64
65    PHASIC::Process_Base *InitializeProcess(const PHASIC::Process_Info &pi, bool add)
66    { return NULL; }
67    int  PerformTests() { return 1; }
68    bool NewLibraries() { return false; }
69    void SetClusterDefinitions(PDF::Cluster_Definitions_Base *const defs) {}
70    ATOOLS::Cluster_Amplitude *ClusterConfiguration
71    (PHASIC::Process_Base *const proc,const size_t &mode) { return NULL; }
72
73    static std::string s_olprefix;
74    static std::vector<std::string> s_allowed_libs;
75    static bool s_generate_list;
76    static std::set<std::string> s_shoppinglist;
77    static std::map<int, OpenLoopsReplace_Particle> s_particles;
78  };
79
80
81  class OpenLoopsReplace_Born: public PHASIC::Tree_ME2_Base {
82
83    Amp2Func m_amp2;
84    PermutationFunc m_permutationfunc;
85    std::vector<int> m_permutation;
86    static OpenLoopsReplace_Interface* s_interface;
87
88    size_t m_oqcd, m_oew;
89    double m_symfac;
90
91  public:
92
93    OpenLoopsReplace_Born(const PHASIC::Process_Info& pi,
94                   const ATOOLS::Flavour_Vector& flavs,
95                   Amp2Func amp2,
96                   PermutationFunc permutationfunc,
97                   std::vector<int> permutation,
98                   std::string functag);
99
100    ~OpenLoopsReplace_Born();
101
102    double Calc(const ATOOLS::Vec4D_Vector& momenta);
103
104    inline static void SetInterface(OpenLoopsReplace_Interface* interface)
105    {
106      s_interface=interface;
107    }
108  };
109
110
111  class OpenLoopsReplace_Virtual : public PHASIC::Virtual_ME2_Base {
112
113    Amp2Func m_amp2;
114    PermutationFunc m_permutationfunc;
115    std::vector<int> m_permutation;
116    static OpenLoopsReplace_Interface* s_interface;
117    int m_oew, m_oqcd;
118    int m_write_points;
119    std::ofstream m_points_file;
120
121    bool     m_analyse;
122    std::map<std::string,ATOOLS::Histogram *> m_histograms;
123
124  public:
125
126    OpenLoopsReplace_Virtual(const PHASIC::Process_Info& pi,
127                      const ATOOLS::Flavour_Vector& flavs,
128                      Amp2Func amp2,
129                      PermutationFunc permutationfunc,
130                      std::vector<int> permutation,
131                      std::string functag);
132
133    ~OpenLoopsReplace_Virtual();
134 
135    inline bool SetColours(const ATOOLS::Vec4D_Vector& momenta) {
136      return true;
137    }
138
139    inline double Eps_Scheme_Factor(const ATOOLS::Vec4D_Vector& mom) {
140      return 4.*M_PI;
141    }
142 
143    void Calc(const ATOOLS::Vec4D_Vector& momenta);
144
145    inline static void SetInterface(OpenLoopsReplace_Interface* interface)
146    {
147      s_interface=interface;
148    }
149
150  };
151
152}
153
154
155
156#include "ATOOLS/Org/CXXFLAGS_PACKAGES.H"
157#include "MODEL/Main/Model_Base.H"
158#include "PHASIC++/Main/Phase_Space_Handler.H"
159#include "ATOOLS/Org/Data_Reader.H"
160#include "ATOOLS/Org/Message.H"
161#include "ATOOLS/Org/MyStrStream.H"
162#include "ATOOLS/Org/Library_Loader.H"
163#include "ATOOLS/Org/Run_Parameter.H"
164#include <algorithm>
165#include <sys/stat.h>
166
167using namespace PHASIC;
168using namespace MODEL;
169using namespace ATOOLS;
170using namespace std;
171
172
173extern "C" {
174
175  void openloops_welcome_(char* str, int* len_str);
176
177  void loop_parameters_write_();
178
179  void ol_getparameter_double_c_(const char* key, double* val, int* err);
180  void ol_getparameter_int_c_(const char* key, int* val, int* err);
181  void ol_setparameter_double_c_(const char* key, double* val, int* err);
182  void ol_setparameter_int_c_(const char* key, int* val, int* err);
183  void ol_setparameter_string_c_(const char* key, const char* val, int* err);
184  void ol_parameters_flush_();
185
186}
187
188
189namespace OpenLoopsReplace {
190
191  std::map<int, OpenLoopsReplace_Particle> OpenLoopsReplace_Interface::s_particles;
192  std::string OpenLoopsReplace_Interface::s_olprefix;
193  std::vector<std::string> OpenLoopsReplace_Interface::s_allowed_libs;
194  bool OpenLoopsReplace_Interface::s_generate_list;
195  set<string> OpenLoopsReplace_Interface::s_shoppinglist;
196
197  bool OpenLoopsReplace_Interface::Initialize(const string &path,const string &file,
198                                       MODEL::Model_Base *const model,
199                                       BEAM::Beam_Spectra_Handler *const beam,
200                                       PDF::ISR_Handler *const isr)
201  {
202    InitializeParticles();
203
204    // find OL installation prefix with several overwrite options
205    struct stat st;
206    Data_Reader reader(" ",";","#","=");
207    s_olprefix = rpa->gen.Variable("SHERPA_CPP_PATH")+"/Process/OpenLoopsReplace";
208    if(stat(s_olprefix.c_str(),&st) != 0) s_olprefix = OPENLOOPS_PREFIX;
209    s_olprefix = reader.GetValue<string>("OL_PREFIX", s_olprefix);
210    msg_Info()<<"Initialising OpenLoopsReplace generator from "<<s_olprefix<<endl;
211
212    // load library dynamically
213    s_loader->AddPath(s_olprefix+"/lib");
214    s_loader->AddPath(s_olprefix+"/proclib");
215    if (!s_loader->LoadLibrary("openloops")) THROW(fatal_error, "Failed to load libopenloops.");
216
217    // set particle masses/widths
218    int tmparr[] = {kf_e, kf_mu, kf_tau, kf_u, kf_d, kf_s, kf_c, kf_b, kf_t, kf_Wplus, kf_Z, kf_h0};
219    vector<int> pdgids (tmparr, tmparr + sizeof(tmparr) / sizeof(tmparr[0]) );
220    int dummy;
221    for (size_t i=0; i<pdgids.size(); ++i) {
222      if (Flavour(pdgids[i]).Mass()>0.0) SetParameter("mass("+ToString(pdgids[i])+")", Flavour(pdgids[i]).Mass());
223      if (Flavour(pdgids[i]).Width()>0.0) SetParameter("width("+ToString(pdgids[i])+")", Flavour(pdgids[i]).Width());
224    }
225
226    // set remaining OL parameters specified by user
227    vector<string> parameters;
228    reader.VectorFromFile(parameters,"OL_PARAMETERS");
229    for (size_t i=1; i<parameters.size(); i=i+2) SetParameter(parameters[i-1], parameters[i]);
230    ol_parameters_flush_();
231
232    reader.VectorFromFile(s_allowed_libs, "OL_ALLOWED_LIBS");
233    s_generate_list=reader.GetValue<size_t>("OL_GENERATE_LIST", false);
234    if (s_allowed_libs.size()) PRINT_VAR(s_allowed_libs);
235
236    int lenws=1200;
237    char welcomestr[lenws];
238    openloops_welcome_(welcomestr, &lenws);
239    msg_Info()<<std::string(welcomestr,lenws)<<std::endl;
240
241    MyStrStream cite;
242    cite<<"The OpenLoopsReplace library~\\cite{Cascioli:2011va} of virtual"<<endl
243        <<"matrix elements has been used. "<<endl;
244    if (GetIntParameter("redlib1")==1 || GetIntParameter("redlib1")==7 ||
245        GetIntParameter("redlib2")==1 || GetIntParameter("redlib2")==7) {
246      cite<<"It is partly based on the tensor integral reduction described "<<endl
247          <<"in~\\cite{Denner:2002ii,Denner:2005nn,Denner:2010tr}."<<endl;
248    }
249    if (GetIntParameter("redlib1")==5 || GetIntParameter("redlib2")==5) {
250      cite<<"It is partly based on the integrand reduction described "<<endl
251          <<"in~\\cite{Ossola:2007ax,vanHameren:2010cp}."<<endl;
252    }
253    if (GetIntParameter("redlib1")==6 || GetIntParameter("redlib2")==6) {
254      cite<<"It is partly based on the integrand reduction described "<<endl
255          <<"in~\\cite{Mastrolia:2010nb,vanHameren:2010cp}."<<endl;
256    }
257    if (GetIntParameter("redlib1")==8 || GetIntParameter("redlib2")==8) {
258      cite<<"It is partly based on the integrand reduction Ninja."<<endl;
259    }
260    rpa->gen.AddCitation(1,cite.str());
261
262    OpenLoopsReplace_Virtual::SetInterface(this);
263    OpenLoopsReplace_Born::SetInterface(this);
264    return true;
265  }
266
267  void OpenLoopsReplace_Interface::InitializeParticles()
268  {
269    s_particles.clear();
270    s_particles[kf_nue] = OpenLoopsReplace_Particle("ne", "F[1,{1}]", 0);
271    s_particles[-kf_nue] = OpenLoopsReplace_Particle("nex", "-F[1,{1}]", 1);
272    s_particles[kf_numu] = OpenLoopsReplace_Particle("nm", "F[1,{2}]", 2);
273    s_particles[-kf_numu] = OpenLoopsReplace_Particle("nmx", "-F[1,{2}]", 3);
274    s_particles[kf_nutau] = OpenLoopsReplace_Particle("nl", "F[1,{3}]", 4);
275    s_particles[-kf_nutau] = OpenLoopsReplace_Particle("nlx", "-F[1,{3}]", 5);
276    s_particles[kf_e] = OpenLoopsReplace_Particle("e", "F[2,{1}]", 6);
277    s_particles[-kf_e] = OpenLoopsReplace_Particle("ex", "-F[2,{1}]", 7);
278    s_particles[kf_mu] = OpenLoopsReplace_Particle("m", "F[2,{2}]", 8);
279    s_particles[-kf_mu] = OpenLoopsReplace_Particle("mx", "-F[2,{2}]", 9);
280    s_particles[kf_tau] = OpenLoopsReplace_Particle("l", "F[2,{3}]", 10);
281    s_particles[-kf_tau] = OpenLoopsReplace_Particle("lx", "-F[2,{3}]", 11);
282    s_particles[kf_u] = OpenLoopsReplace_Particle("u", "F[3,{1}]", 12);
283    s_particles[-kf_u] = OpenLoopsReplace_Particle("ux", "-F[3,{1}]", 13);
284    s_particles[kf_c] = OpenLoopsReplace_Particle("c", "F[3,{2}]", 14);
285    s_particles[-kf_c] = OpenLoopsReplace_Particle("cx", "-F[3,{2}]", 15);
286    s_particles[kf_t] = OpenLoopsReplace_Particle("t", "F[3,{3}]", 16);
287    s_particles[-kf_t] = OpenLoopsReplace_Particle("tx", "-F[3,{3}]", 17);
288    s_particles[kf_d] = OpenLoopsReplace_Particle("d", "F[4,{1}]", 18);
289    s_particles[-kf_d] = OpenLoopsReplace_Particle("dx", "-F[4,{1}]", 19);
290    s_particles[kf_s] = OpenLoopsReplace_Particle("s", "F[4,{2}]", 20);
291    s_particles[-kf_s] = OpenLoopsReplace_Particle("sx", "-F[4,{2}]", 21);
292    s_particles[kf_b] = OpenLoopsReplace_Particle("b", "F[4,{3}]", 22);
293    s_particles[-kf_b] = OpenLoopsReplace_Particle("bx", "-F[4,{3}]", 23);
294    s_particles[kf_h0] = OpenLoopsReplace_Particle("h", "S[1]", 24);
295    s_particles[kf_photon] = OpenLoopsReplace_Particle("a", "V[1]", 25);
296    s_particles[kf_Z] = OpenLoopsReplace_Particle("z", "V[2]", 26);
297    s_particles[-kf_Wplus] = OpenLoopsReplace_Particle("w", "V[3]", 27);
298    s_particles[kf_Wplus] = OpenLoopsReplace_Particle("wx", "-V[3]", 28);
299    s_particles[kf_gluon] = OpenLoopsReplace_Particle("g", "V[5]", 29);
300  }
301
302  std::string OpenLoopsReplace_Interface::MatchOptions(vector<string> options, int oew, int oqcd, int nloop) {
303    for (size_t i=2; i<options.size(); ++i) {
304      string option=options[i].substr(0, options[i].find("="));
305      string value=options[i].substr(options[i].find("=")+1);
306
307      if (option=="EW" && value!=ToString(oew)+",0") return "0";
308      if (option=="QCD" && value!=ToString(oqcd)+","+ToString(nloop)) return "0";
309      if (option=="CKMORDER") {
310        int ckmorder=ToType<int>(value);
311        if (ckmorder<3) {
312          if (s_model->ComplexMatrixElement("CKM", 0,2)!=Complex(0.0,0.0) ||
313              s_model->ComplexMatrixElement("CKM", 2,0)!=Complex(0.0,0.0)) {
314            return "0";
315          }
316        }
317        if (ckmorder<2) {
318          if (s_model->ComplexMatrixElement("CKM", 1,2)!=Complex(0.0,0.0) ||
319              s_model->ComplexMatrixElement("CKM", 2,1)!=Complex(0.0,0.0)) {
320            return "0";
321          }
322        }
323        if (ckmorder<1) {
324          if (s_model->ComplexMatrixElement("CKM", 0,1)!=Complex(0.0,0.0) ||
325              s_model->ComplexMatrixElement("CKM", 1,0)!=Complex(0.0,0.0)) {
326            return "0";
327          }
328        }
329      }
330      const string nfs("nf");
331      double nfsv=GetIntParameter(nfs);
332      if (option=="nf" && ToType<int>(value)!=nfsv) return "0";
333      if (option=="MD" && (double)GetDoubleParameter("mass(1)")>0.0) return "0";
334      if (option=="MU" && (double)GetDoubleParameter("mass(2)")>0.0) return "0";
335      if (option=="MS" && (double)GetDoubleParameter("mass(3)")>0.0) return "0";
336      if (option=="MC" && (double)GetDoubleParameter("mass(4)")>0.0) return "0";
337      if (option=="MB" && (double)GetDoubleParameter("mass(5)")>0.0) return "0";
338      if (option=="MT" && (double)GetDoubleParameter("mass(6)")>0.0) return "0";
339      if (option=="ME" && (double)GetDoubleParameter("mass(11)")>0.0) return "0";
340      if (option=="MM" && (double)GetDoubleParameter("mass(13)")>0.0) return "0";
341      if (option=="MT" && (double)GetDoubleParameter("mass(15)")>0.0) return "0";
342
343      if (option=="map") return value;
344    }
345    return "1";
346  }
347
348
349  int OpenLoopsReplace_Interface::SelectInfo(const dirent *entry)
350  {
351    string fname(entry->d_name);
352    if (fname.find(".info")!=string::npos) {
353      return true;
354    }
355    else return false;
356  }
357
358  pair<string, string> OpenLoopsReplace_Interface::ScanFiles(string& process, int oew, int oqcd, int nloop)
359  {
360    struct dirent **entries;
361    string procdatapath=s_olprefix+"/proclib";
362    int n(scandir(procdatapath.c_str(),&entries,&SelectInfo,alphasort));
363    if (n<0) THROW(fatal_error, "OpenLoopsReplace process dir "+procdatapath+" not found.");
364    vector<string> files;
365    for (int ifile=0; ifile<n; ++ifile) {
366      files.push_back(string(entries[ifile]->d_name));
367      free(entries[ifile]);
368    }
369    free(entries);
370
371    for (int ifile=0; ifile<files.size(); ++ifile) {
372      Data_Reader reader(" ",";","#","");
373      reader.SetAddCommandLine(false);
374      reader.SetInputFile(procdatapath+"/"+files[ifile]);
375      reader.SetMatrixType(mtc::transposed);
376      vector<vector<string> > content;
377      reader.MatrixFromFile(content);
378      for (size_t i=0; i<content.size(); ++i) {
379
380        bool autoload=true;
381        if (content[i].size()>0 && content[i][0]=="options") {
382          for (size_t j=0; j<content[i].size(); ++j) {
383            if (content[i][j]=="autoload=0") {
384              autoload=false;
385            }
386          }
387        }
388
389        if (content[i].size()>2 && content[i][1]==process) {
390          string match=MatchOptions(content[i], oew, oqcd, nloop);
391          if (match=="0") {
392            PRINT_INFO("Ignoring process with incompatible options.");
393            continue;
394          }
395          else if (match!="1") {
396            PRINT_INFO("Mapping "<<process<<" to "<<match<<".");
397            process=match;
398            return ScanFiles(process, oew, oqcd, nloop);
399          }
400          string grouptag=content[i][0];
401          string process_subid=content[i][2];
402          if (s_allowed_libs.size()>0 || autoload==false) {
403            bool allowed=false;
404            for (size_t i=0; i<s_allowed_libs.size(); ++i) {
405              if (grouptag==s_allowed_libs[i]) allowed=true;
406            }
407            if (!allowed) continue;
408          }
409          return make_pair(grouptag, process_subid);
410        }
411      }
412    }
413    PRINT_INFO("Didn't find info file matching process "<<process);
414    return make_pair("", "0");
415  }
416
417
418  bool OpenLoopsReplace_Interface::Order(const pair<size_t, Flavour> &a,const pair<size_t, Flavour> &b)
419  {
420    if (s_particles.find(a.second.HepEvt())==s_particles.end() ||
421        s_particles.find(b.second.HepEvt())==s_particles.end()) {
422      THROW(fatal_error, "Unknown particle.");
423    }
424    return s_particles[a.second.HepEvt()].m_order<s_particles[b.second.HepEvt()].m_order;
425  }
426
427
428  string OpenLoopsReplace_Interface::GetProcessPermutation(const Flavour_Vector& flavs_orig,
429                                                    vector<int>& permutation) {
430    vector<pair<size_t, Flavour> > flavs_ol(flavs_orig.size());
431    for (size_t i=0; i<2; ++i) {
432      flavs_ol[i]=make_pair(i,flavs_orig[i]);
433    }
434    for (size_t i=2; i<flavs_orig.size(); ++i) {
435      flavs_ol[i]=make_pair(i,flavs_orig[i].Bar());
436    }
437
438    sort(flavs_ol.begin(), flavs_ol.end(), Order);
439
440    permutation.clear();
441    permutation.resize(flavs_ol.size());
442    for (size_t i=0; i<flavs_ol.size(); ++i) {
443      for (size_t j=0; j<flavs_ol.size(); ++j) {
444        if (i==flavs_ol[j].first) {
445          permutation[i]=int(j+1); // +1 for fortran openloops
446          break;
447        }
448      }
449    }
450
451    string process;
452    for (size_t i=0; i<flavs_ol.size(); ++i) {
453      process += s_particles[flavs_ol[i].second.HepEvt()].m_name;
454    }
455    return process;
456  }
457
458  bool SortByFirstDec(pair<size_t, size_t> p1, pair<size_t, size_t> p2) {
459    return p1.first>p2.first;
460  }
461
462  Flavour_Vector OpenLoopsReplace_Interface::MapFlavours(const Flavour_Vector& orig)
463  {
464    // for (size_t i=2; i<orig.size(); ++i) {
465    //   if (false && orig[i].Width()!=0.0) {
466    //     THROW(fatal_error, "Non-zero width of final state particle.");
467    //   }
468    // }
469
470    /* Concept:
471      For each family i=0,...,2:
472      (1) Given a final state, determine the four (anti)lepton/neutrino
473          multiplicities in the given process:
474          a_nubar, a_nu, a_lbar, a_l
475
476      (2) Compute the discriminant N[i] as
477          N[i] = Ngen - (i+1) + Ngen*(a_nubar + a_nu*Nmax + a_lbar*Nmax^2 + a_l*Nmax^3)
478          where Nmax should be chosen such that a_...<=Nmax.
479          In practice one can safely set Nmax=10 and it will work for any
480          process with <= 20 final-state leptons.
481          It is also convenient to set Ngen=10, although i runs only from 1 to 3.
482
483      (3) Reassign the lepton generations with a permutation
484          p1 -> 1, p2 -> 2, p3 -> 3  such that  N[p1] > N[p2] > N[p3] */
485
486    multiset<int> hepevt;
487    for (size_t i=0; i<orig.size(); ++i) { hepevt.insert(orig[i].HepEvt()); }
488
489    size_t Ngen(10), Nmax(10);
490    vector<pair<size_t, size_t> > N(3);
491    for (size_t i=0; i<3; ++i) {
492      int nu_gen=10+2*(i+1);
493      int l_gen=9+2*(i+1);
494
495      size_t a_nu=hepevt.count(nu_gen);
496      size_t a_nubar=hepevt.count(-nu_gen);
497      size_t a_l=hepevt.count(l_gen);
498      size_t a_lbar=hepevt.count(-l_gen);
499
500      N[i]=make_pair(Ngen-(i+1) + Ngen*
501                     (a_nubar+a_nu*Nmax+a_lbar*Nmax*Nmax+a_l*Nmax*Nmax*Nmax),
502                     i);
503    }
504
505    sort(N.begin(), N.end(), SortByFirstDec);
506
507    Flavour_Vector ret(orig);
508    for (size_t i=0; i<3; ++i) {
509      int nu_gen=10+2*(N[i].second+1);
510      int nu_gen_new=10+2*(i+1);
511      int l_gen=9+2*(N[i].second+1);
512      int l_gen_new=9+2*(i+1);
513
514      for (size_t j=0; j<orig.size(); ++j) {
515        if (orig[j].Kfcode()==nu_gen) {
516          ret[j]=Flavour(nu_gen_new, orig[j].IsAnti());
517        }
518        if (orig[j].Kfcode()==l_gen) {
519          ret[j]=Flavour(l_gen_new, orig[j].IsAnti());
520        }
521      }
522    }
523    return ret;
524  }
525
526  double OpenLoopsReplace_Interface::GetDoubleParameter(const std::string & key) {
527    int err(0);
528    double value;
529    ol_getparameter_double_c_(key.c_str(), &value, &err);
530    return value;
531  }
532  int OpenLoopsReplace_Interface::GetIntParameter(const std::string & key) {
533    int err(0);
534    int value;
535    ol_getparameter_int_c_(key.c_str(), &value, &err);
536    return value;
537  }
538  template <class ValueType>
539  void HandleParameterStatus(int err, const std::string & key, ValueType value) {
540    if (err==0) {
541      msg_Debugging()<<"Setting OpenLoopsReplace parameter: "<<key<<" = "<<value<<endl;
542    }
543    else if (err==1) {
544      THROW(fatal_error, "Unknown OpenLoopsReplace parameter: "+key+" = "+ToString(value));
545    }
546    else if (err==2) {
547      THROW(fatal_error, "Error setting OpenLoopsReplace parameter: "+key+" = "+ToString(value));
548    }
549  }
550  void OpenLoopsReplace_Interface::SetParameter(const std::string & key, double value) {
551    int err(0);
552    ol_setparameter_double_c_(key.c_str(), &value, &err);
553    HandleParameterStatus(err, key, value);
554  }
555  void OpenLoopsReplace_Interface::SetParameter(const std::string & key, int value) {
556    int err(0);
557    ol_setparameter_int_c_(key.c_str(), &value, &err);
558    HandleParameterStatus(err, key, value);
559  }
560  void OpenLoopsReplace_Interface::SetParameter(const std::string & key, std::string value) {
561    int err(0);
562    ol_setparameter_string_c_(key.c_str(), value.c_str(), &err);
563    HandleParameterStatus(err, key, value);
564  }
565  void OpenLoopsReplace_Interface::FlushParameters() {
566    ol_parameters_flush_();
567  }
568
569
570}
571
572using namespace OpenLoopsReplace;
573
574DECLARE_GETTER(OpenLoopsReplace_Interface,"OpenLoopsReplace",ME_Generator_Base,ME_Generator_Key);
575
576ME_Generator_Base *ATOOLS::Getter<ME_Generator_Base,ME_Generator_Key,
577                                  OpenLoopsReplace_Interface>::
578operator()(const ME_Generator_Key &key) const
579{
580  return new OpenLoopsReplace::OpenLoopsReplace_Interface();
581}
582
583void ATOOLS::Getter<ME_Generator_Base,ME_Generator_Key,OpenLoopsReplace_Interface>::
584PrintInfo(ostream &str,const size_t width) const
585{ 
586  str<<"Interface to the OpenLoopsReplace loop ME generator"; 
587}
588
589
590
591
592#include "ATOOLS/Org/CXXFLAGS.H"
593#include "ATOOLS/Org/Message.H"
594#include "ATOOLS/Org/Library_Loader.H"
595
596using namespace PHASIC;
597using namespace MODEL;
598using namespace ATOOLS;
599using namespace std;
600
601namespace OpenLoopsReplace {
602
603OpenLoopsReplace_Interface* OpenLoopsReplace_Born::s_interface=NULL;
604
605OpenLoopsReplace_Born::OpenLoopsReplace_Born(const Process_Info& pi,
606                               const Flavour_Vector& flavs,
607                               Amp2Func amp2,
608                               PermutationFunc permutationfunc,
609                               std::vector<int> permutation,
610                               std::string functag) :
611  Tree_ME2_Base(pi, flavs),
612  m_amp2(amp2), m_permutationfunc(permutationfunc),
613  m_permutation(permutation)
614{
615  m_symfac=pi.m_fi.FSSymmetryFactor();
616  m_symfac*=pi.m_ii.ISSymmetryFactor();
617  m_oew=pi.m_oew;
618  m_oqcd=pi.m_oqcd;
619}
620
621OpenLoopsReplace_Born::~OpenLoopsReplace_Born()
622{
623}
624
625double OpenLoopsReplace_Born::Calc(const Vec4D_Vector& momenta)
626{
627  Vec4D_Vector m_moms(momenta);
628
629  s_interface->SetParameter("alpha", AlphaQED());
630  s_interface->SetParameter("alphas", AlphaQCD());
631  s_interface->FlushParameters();
632
633  double M2L0;
634  std::vector<double> M2L1(3), M2L2(5), IRL1(3), IRL2(5);
635
636  m_permutationfunc(&m_permutation[0]);
637  m_amp2(&m_moms[0][0], &M2L0, &M2L1[0], &IRL1[0], &M2L2[0], &IRL2[0]);
638
639  if (IsZero(M2L1[1]) && IsZero(M2L1[2]) &&
640      IsZero(IRL1[1]) && IsZero(IRL1[2]) &&
641      IsZero(M2L2[1]) && IsZero(M2L2[2]) && IsZero(M2L2[3]) && IsZero(M2L2[4]) &&
642      IsZero(IRL2[1]) && IsZero(IRL2[2]) && IsZero(IRL2[3]) && IsZero(IRL2[4])) {
643    // OL returns ME2 including 1/symfac, but Calc is supposed to return it
644    // without 1/symfac, thus multiplying with symfac here
645    if (IsZero(M2L0)) return m_symfac*M2L2[0];
646    else return m_symfac*M2L0;
647  }
648  else {
649    PRINT_INFO("Poles non-zero. Returning 0.");
650    return 0.0;
651  }
652}
653
654}
655
656using namespace OpenLoopsReplace;
657
658DECLARE_TREEME2_GETTER(OpenLoopsReplace_Born,"OpenLoopsReplace_Born")
659Tree_ME2_Base *ATOOLS::Getter<Tree_ME2_Base,Process_Info,OpenLoopsReplace_Born>::
660operator()(const Process_Info &pi) const
661{
662  DEBUG_FUNC(pi);
663  if (pi.m_loopgenerator!="OpenLoopsReplace") return NULL;
664  if (pi.m_fi.m_nloewtype!=nlo_type::lo) return NULL;
665  if (pi.m_fi.m_nloqcdtype!=nlo_type::lo &&
666      pi.m_fi.m_nloqcdtype!=nlo_type::born &&
667      pi.m_fi.m_nloqcdtype!=nlo_type::real) return NULL;
668  if (MODEL::s_model->Name()!="SM") return NULL;
669
670  Flavour_Vector flavs=pi.ExtractFlavours();
671  Flavour_Vector map_flavs=OpenLoopsReplace_Interface::MapFlavours(flavs);
672  msg_Tracking()<<endl<<flavs<<" --> "<<map_flavs<<endl;
673
674  vector<int> permutation;
675  string process=OpenLoopsReplace_Interface::GetProcessPermutation(map_flavs, permutation);
676  pair<string, string> groupsub=OpenLoopsReplace_Interface::ScanFiles(process, pi.m_oew, pi.m_oqcd, 0);
677  string grouptag=groupsub.first;
678  string subid=groupsub.second;
679  if (grouptag!="") {
680    // symbols in fortran are always defined as lower case
681    string lc_functag(grouptag+"_"+process+"_"+subid+"_");
682    for (size_t i(0);i<lc_functag.length();++i)
683      lc_functag[i]=tolower(lc_functag[i]);
684    vector<string> suffixes;
685    suffixes.push_back("1sL"); // deprecated
686    suffixes.push_back("ls");
687    suffixes.push_back("lst");
688    suffixes.push_back("lps");
689    suffixes.push_back("lpst");
690    void *ampfunc, *permfunc;
691    for (size_t i=0; i<suffixes.size(); ++i) {
692      string libraryfile="openloops_"+grouptag+"_"+suffixes[i];
693      ampfunc=s_loader->GetLibraryFunction(libraryfile,"vamp2_"+lc_functag);
694      permfunc=s_loader->GetLibraryFunction(libraryfile,"set_permutation_"+lc_functag);
695      if (ampfunc!=NULL && permfunc!=NULL) break;
696    }
697    if (ampfunc==NULL || permfunc==NULL) {
698      PRINT_INFO("Didn't find functions");
699      return NULL;
700    }
701
702    msg_Info()<<endl;
703    PRINT_INFO("Initialising OpenLoopsReplace Born for "<<flavs<<": "<<lc_functag);
704    return new OpenLoopsReplace_Born(pi, flavs, (Amp2Func) ampfunc,
705                              (PermutationFunc) permfunc, permutation, lc_functag);
706  }
707  else {
708    return NULL;
709  }
710}
711
712
713#include "MODEL/Main/Model_Base.H"
714#include "ATOOLS/Org/Run_Parameter.H"
715#include "ATOOLS/Org/Exception.H"
716#include "ATOOLS/Org/MyStrStream.H"
717#include "ATOOLS/Org/Data_Reader.H"
718#include "ATOOLS/Org/Library_Loader.H"
719#include "ATOOLS/Math/Poincare.H"
720
721
722using namespace PHASIC;
723using namespace ATOOLS;
724using namespace std;
725
726namespace OpenLoopsReplace {
727
728OpenLoopsReplace_Interface* OpenLoopsReplace_Virtual::s_interface=NULL;
729
730OpenLoopsReplace_Virtual::OpenLoopsReplace_Virtual(const Process_Info& pi,
731                                     const Flavour_Vector& flavs,
732                                     Amp2Func amp2,
733                                     PermutationFunc permutationfunc,
734                                     std::vector<int> permutation,
735                                     std::string functag) :
736  Virtual_ME2_Base(pi, flavs),
737  m_amp2(amp2), m_permutationfunc(permutationfunc),
738  m_permutation(permutation), m_analyse(true)
739{
740  m_oew=pi.m_oew;
741  m_oqcd=pi.m_oqcd;
742}
743
744OpenLoopsReplace_Virtual::~OpenLoopsReplace_Virtual()
745{
746}
747
748
749void OpenLoopsReplace_Virtual::Calc(const Vec4D_Vector& momenta) {
750  Vec4D_Vector m_moms(momenta);
751
752  s_interface->SetParameter("alpha", AlphaQED());
753  s_interface->SetParameter("alphas", AlphaQCD());
754  s_interface->SetParameter("mu", sqrt(m_mur2));
755  s_interface->FlushParameters();
756 
757  double M2L0;
758  vector<double> M2L1(3), M2L2(5), IRL1(3), IRL2(5);
759
760  MyTiming* timing;
761  if (msg_LevelIsDebugging()) {
762    timing = new MyTiming();
763    timing->Start();
764  }
765  m_permutationfunc(&m_permutation[0]);
766  m_amp2(&m_moms[0][0], &M2L0, &M2L1[0], &IRL1[0], &M2L2[0], &IRL2[0]);
767  if (msg_LevelIsDebugging()) {
768    timing->Stop();
769    PRINT_INFO(momenta[2][0]<<" "<<m_flavs<<" user="<<timing->UserTime()
770               <<" real="<<timing->RealTime()<<" sys="<<timing->SystemTime());
771  }
772
773  double B(M2L0), V_finite(M2L1[0]), V_eps(M2L1[1]), V_eps2(M2L1[2]);
774
775  // factor which by Sherpa convention has to be divided out at this stage
776  double factor=B*AlphaQCD()/2.0/M_PI;
777
778  m_born=B;
779  m_res.Finite()=(V_finite/factor);
780  m_res.IR()=(V_eps/factor);
781  m_res.IR2()=(V_eps2/factor);
782}
783
784}
785
786
787using namespace OpenLoopsReplace;
788
789void dummyamp2func(double* moms, double* M2L0, double* M2L1, double* IRL1, double* M2L2, double* IRL2)
790{ THROW(normal_exit, "Shopping list generated."); }
791void dummypermfunc(int* permutation)
792{ THROW(normal_exit, "Shopping list generated."); }
793
794DECLARE_VIRTUALME2_GETTER(OpenLoopsReplace_Virtual,"OpenLoopsReplace_Virtual")
795Virtual_ME2_Base *ATOOLS::Getter<Virtual_ME2_Base,Process_Info,OpenLoopsReplace_Virtual>::
796operator()(const Process_Info &pi) const
797{
798  DEBUG_FUNC(pi);
799  if (pi.m_loopgenerator!="OpenLoopsReplace") return NULL;
800  if (pi.m_fi.m_nloewtype!=nlo_type::lo) return NULL;
801  if (pi.m_fi.m_nloqcdtype!=nlo_type::loop) return NULL;
802  if (MODEL::s_model->Name()!="SM") return NULL;
803
804  Flavour_Vector flavs=pi.ExtractFlavours();
805  Flavour_Vector map_flavs=OpenLoopsReplace_Interface::MapFlavours(flavs);
806  msg_Tracking()<<endl<<flavs<<" --> "<<map_flavs<<endl;
807
808  vector<int> permutation;
809  string process=OpenLoopsReplace_Interface::GetProcessPermutation(map_flavs, permutation);
810  pair<string, string> groupsub=OpenLoopsReplace_Interface::ScanFiles(process, pi.m_oew, pi.m_oqcd-1, 1);
811  string grouptag=groupsub.first;
812  string subid=groupsub.second;
813  if (grouptag!="") {
814    // symbols in fortran are always defined as lower case
815    string lc_functag(grouptag+"_"+process+"_"+subid+"_");
816    for (size_t i(0);i<lc_functag.length();++i)
817      lc_functag[i]=tolower(lc_functag[i]);
818    vector<string> suffixes;
819    suffixes.push_back("1tL"); // deprecated
820    suffixes.push_back("1L"); // deprecated
821    suffixes.push_back("1ptL"); // deprecated
822    suffixes.push_back("0L"); // deprecated
823    suffixes.push_back("l");
824    suffixes.push_back("lt");
825    suffixes.push_back("lpt");
826    suffixes.push_back("ls");
827    suffixes.push_back("lp");
828    suffixes.push_back("lst");
829    suffixes.push_back("lps");
830    suffixes.push_back("lpst");
831    void *ampfunc, *permfunc;
832    for (size_t i=0; i<suffixes.size(); ++i) {
833      string libraryfile="openloops_"+grouptag+"_"+suffixes[i];
834      ampfunc=s_loader->GetLibraryFunction(libraryfile,"vamp2_"+lc_functag);
835      permfunc=s_loader->GetLibraryFunction(libraryfile,"set_permutation_"+lc_functag);
836      if (ampfunc!=NULL && permfunc!=NULL) break;
837    }
838    if (ampfunc==NULL || permfunc==NULL) {
839      PRINT_INFO("Didn't find functions");
840      return NULL;
841    }
842
843    msg_Info()<<endl;
844    PRINT_INFO("Initialising OpenLoopsReplace Virtual for "<<flavs<<": "<<lc_functag);
845    return new OpenLoopsReplace_Virtual(pi, flavs, (Amp2Func) ampfunc,
846                                 (PermutationFunc) permfunc, permutation, lc_functag);
847  }
848  else {
849    if (OpenLoopsReplace_Interface::s_generate_list) {
850      if (OpenLoopsReplace_Interface::s_shoppinglist.find(process)==OpenLoopsReplace_Interface::s_shoppinglist.end()) {
851        ofstream list("OL_list.m", ios::app);
852        list<<"(* "<<process<<" *)"<<endl;
853        list<<"SubProcess["<<OpenLoopsReplace_Interface::s_shoppinglist.size()+1<<"] = {\n"
854            <<" FeynArtsProcess -> {"
855            <<OpenLoopsReplace_Interface::s_particles[map_flavs[0].HepEvt()].m_faname<<", "
856            <<OpenLoopsReplace_Interface::s_particles[map_flavs[1].HepEvt()].m_faname<<"} -> {";
857        for (size_t i=2; i<map_flavs.size()-1; ++i) {
858          list<<OpenLoopsReplace_Interface::s_particles[map_flavs[i].HepEvt()].m_faname<<", ";
859        }
860        list<<OpenLoopsReplace_Interface::s_particles[map_flavs[map_flavs.size()-1].HepEvt()].m_faname<<"},\n"
861            <<" SelectCoupling -> (Exponent[#, gQCD] == "<<pi.m_oqcd-1<<"+2*#2 &),\n"
862            <<" SortExternal -> True,\n"
863            <<" InsertFieldsOptions -> {Restrictions -> {ExcludeParticles -> {S[2|3], SV}, NoQuarkMixing}}";
864        list<<"\n};\n"<<endl;
865        list.close();
866        PRINT_INFO("Generated list entry for "<<process);
867        OpenLoopsReplace_Interface::s_shoppinglist.insert(process);
868      }
869      return new OpenLoopsReplace_Virtual(pi, flavs, dummyamp2func,
870                                   dummypermfunc, permutation, "dummy");
871    }
872  }
873
874  return NULL;
875}