Ticket #317: OpenLoopsReplace_Interface.C
File OpenLoopsReplace_Interface.C, 31.6 KB (added by , 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 | |
9 | namespace MODEL { |
10 | class Model_Base; |
11 | } |
12 | |
13 | namespace OpenLoopsReplace { |
14 | |
15 | typedef void (*Amp2Func)(double* moms, double* M2L0, double* M2L1, double* IRL1, |
16 | double* M2L2, double* IRL2); |
17 | |
18 | typedef 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 | |
167 | using namespace PHASIC; |
168 | using namespace MODEL; |
169 | using namespace ATOOLS; |
170 | using namespace std; |
171 | |
172 | |
173 | extern "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 | |
189 | namespace 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 | |
572 | using namespace OpenLoopsReplace; |
573 | |
574 | DECLARE_GETTER(OpenLoopsReplace_Interface,"OpenLoopsReplace",ME_Generator_Base,ME_Generator_Key); |
575 | |
576 | ME_Generator_Base *ATOOLS::Getter<ME_Generator_Base,ME_Generator_Key, |
577 | OpenLoopsReplace_Interface>:: |
578 | operator()(const ME_Generator_Key &key) const |
579 | { |
580 | return new OpenLoopsReplace::OpenLoopsReplace_Interface(); |
581 | } |
582 | |
583 | void ATOOLS::Getter<ME_Generator_Base,ME_Generator_Key,OpenLoopsReplace_Interface>:: |
584 | PrintInfo(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 | |
596 | using namespace PHASIC; |
597 | using namespace MODEL; |
598 | using namespace ATOOLS; |
599 | using namespace std; |
600 | |
601 | namespace OpenLoopsReplace { |
602 | |
603 | OpenLoopsReplace_Interface* OpenLoopsReplace_Born::s_interface=NULL; |
604 | |
605 | OpenLoopsReplace_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 | |
621 | OpenLoopsReplace_Born::~OpenLoopsReplace_Born() |
622 | { |
623 | } |
624 | |
625 | double 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 | |
656 | using namespace OpenLoopsReplace; |
657 | |
658 | DECLARE_TREEME2_GETTER(OpenLoopsReplace_Born,"OpenLoopsReplace_Born") |
659 | Tree_ME2_Base *ATOOLS::Getter<Tree_ME2_Base,Process_Info,OpenLoopsReplace_Born>:: |
660 | operator()(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 | |
722 | using namespace PHASIC; |
723 | using namespace ATOOLS; |
724 | using namespace std; |
725 | |
726 | namespace OpenLoopsReplace { |
727 | |
728 | OpenLoopsReplace_Interface* OpenLoopsReplace_Virtual::s_interface=NULL; |
729 | |
730 | OpenLoopsReplace_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 | |
744 | OpenLoopsReplace_Virtual::~OpenLoopsReplace_Virtual() |
745 | { |
746 | } |
747 | |
748 | |
749 | void 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 | |
787 | using namespace OpenLoopsReplace; |
788 | |
789 | void dummyamp2func(double* moms, double* M2L0, double* M2L1, double* IRL1, double* M2L2, double* IRL2) |
790 | { THROW(normal_exit, "Shopping list generated."); } |
791 | void dummypermfunc(int* permutation) |
792 | { THROW(normal_exit, "Shopping list generated."); } |
793 | |
794 | DECLARE_VIRTUALME2_GETTER(OpenLoopsReplace_Virtual,"OpenLoopsReplace_Virtual") |
795 | Virtual_ME2_Base *ATOOLS::Getter<Virtual_ME2_Base,Process_Info,OpenLoopsReplace_Virtual>:: |
796 | operator()(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 | } |