StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MergingHooks.cc
1 // MergingHooks.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2012 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // This file is written by Stefan Prestel.
7 // Function definitions (not found in the header) for the HardProcess and
8 // MergingHooks classes.
9 
10 #include "MergingHooks.h"
11 
12 namespace Pythia8 {
13 
14 //==========================================================================
15 
16 // The HardProcess class.
17 
18 //--------------------------------------------------------------------------
19 
20 // Declaration of hard process class
21 // This class holds information on the desired hard 2->2 process to be merged
22 // This class is a container class for History class use.
23 
24 // Initialisation on the process string
25 
26 void HardProcess::initOnProcess( string process, ParticleData* particleData) {
27  state.init("(hard process)", particleData);
28  translateProcessString(process);
29 }
30 
31 //--------------------------------------------------------------------------
32 
33 // Initialisation on the path to LHE file
34 
35 void HardProcess::initOnLHEF( string LHEfile, ParticleData* particleData) {
36  state.init("(hard process)", particleData);
37  translateLHEFString(LHEfile);
38 }
39 
40 //--------------------------------------------------------------------------
41 
42 // Function to access the LHE file and read relevant information.
43 // The merging scale will be read from the +1 jet sample, called
44 // LHEpath_1.lhe
45 // while the hard process will be read from
46 // LHEpath_0.lhe
47 // Currently, only read from MadEvent- or Sherpa-generated LHE files
48 // is automatic, else the user is asked to supply the necessary
49 // information.
50 
51 void HardProcess::translateLHEFString( string LHEpath){
52 
53  // Open path to LHEF and extract merging scale
54  ifstream infile;
55  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
56 
57  // Check with ME generator has been used
58  int iLine =0;
59  int nLinesMax = 200;
60  string lineGenerator;
61  while( iLine < nLinesMax
62  && lineGenerator.find("SHERPA", 0) == string::npos
63  && lineGenerator.find("MadGraph", 0) == string::npos){
64  iLine++;
65  lineGenerator = " ";
66  getline(infile,lineGenerator);
67  }
68  infile.close();
69 
70  vector <int> incom;
71  vector <int> inter;
72  vector <int> outgo;
73  // Particle identifiers, ordered in such a way that e.g. the "u"
74  // in a mu is not mistaken for an u quark
75  int inParticleNumbers[] = {
76  // Leptons
77  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
78  // Jet container
79  2212,2212,0,0,0,0,
80  // Quarks
81  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6};
82 
83  string inParticleNamesSH[] = {
84  // Leptons
85  "-11","11","-12","12","-13","13","-14","14","-15","15","-16","16",
86  // Jet container
87  "-93","93","-90","90","-91","91",
88  // Quarks
89  "-1","1","-2","2","-3","3","-4","4","-5","5","-6","6"};
90  string inParticleNamesMG[] = {
91  // Leptons
92  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
93  // Jet container
94  "p~","p","l+","l-","vl~","vl",
95  // Quarks
96  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t"};
97 
98  // Declare intermediate particle identifiers
99  int interParticleNumbers[] = {
100  // Electroweak gauge bosons
101  22,23,-24,24,
102  // Top quarks
103  -6,6,
104  // Dummy index as back-up
105  0,
106  // All squarks
107  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
108  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
109  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
110  // Declare names of intermediate particles
111  string interParticleNamesMG[] = {
112  // Electroweak gauge bosons
113  "a","z","w-","w+",
114  // Top quarks
115  "t~","t",
116  // Dummy index as back-up
117  "xx",
118  // All squarks
119  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
120  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
121 
122  // Declare final state particle identifiers
123  int outParticleNumbers[] = {
124  // Leptons
125  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
126  // Jet container
127  2212,2212,0,0,0,0,
128  // Quarks
129  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6,
130  // Neutralino in SUSY
131  1000022,
132  // All squarks
133  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
134  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
135  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
136  // Declare names of final state particles
137  string outParticleNamesMG[] = {
138  // Leptons
139  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
140  // Jet container
141  "j~","j","l+","l-","vl~","vl",
142  // Quarks
143  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t",
144  // Neutralino in SUSY
145  "n1",
146  // All squarks
147  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
148  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
149 
150  string outParticleNamesSH[] = {
151  // Leptons
152  "-11","11","-12","12","-13","13","-14","14","-15","15","-16","16",
153  // Jet container
154  "-93","93","-90","90","-91","91",
155  // Quarks
156  "-1","1","-2","2","-3","3","-4","4","-5","5","-6","6",
157  // Neutralino in SUSY
158  "1000022",
159  // All squarks
160  "-1000001","1000001","-1000002","1000002","-1000003","1000003",
161  "-1000004","1000004",
162  "-1000005","1000005","-1000006","1000006","-2000001","2000001",
163  "-2000002","2000002",
164  "-2000003","2000003","-2000004","2000004","-2000005","2000005",
165  "-2000006","2000006"};
166 
167  // Declare size of particle name arrays
168  int nIn = 30;
169  int nInt = 31;
170  int nOut = 55;
171 
172  // Save type of the generator, in order to be able to extract
173  // the tms definition
174  meGenType = (lineGenerator.find("MadGraph", 0) != string::npos) ? -1
175  : (lineGenerator.find("SHERPA", 0) != string::npos) ? -2 : 0;
176 
177  if(meGenType == -2){
178  // Now read merging scale
179  // Open path to LHEF and extract merging scale
180  infile.open( (char*)( LHEpath +"_1.lhe").c_str());
181  string lineTMS;
182  while(lineTMS.find("NJetFinder ", 0) == string::npos){
183  lineTMS = " ";
184  getline(infile,lineTMS);
185  }
186  infile.close();
187  lineTMS = lineTMS.substr(0,lineTMS.find(" 0.0 ",0));
188  lineTMS = lineTMS.substr(lineTMS.find(" ", 0)+3,lineTMS.size());
189  // Remove whitespaces
190  while(lineTMS.find(" ", 0) != string::npos)
191  lineTMS.erase(lineTMS.begin()+lineTMS.find(" ",0));
192  // Replace d with e
193  if( lineTMS.find("d", 0) != string::npos)
194  lineTMS.replace(lineTMS.find("d", 0),1,1,'e');
195  tms = atof((char*)lineTMS.c_str());
196 
197  // Now read hard process
198  // Open path to LHEF and extract hard process
199  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
200  string line;
201  while(line.find("Process", 0) == string::npos){
202  line = " ";
203  getline(infile,line);
204  }
205  infile.close();
206  line = line.substr(line.find(" ",0),line.size());
207 
208  // Cut string into incoming and outgoing pieces
209  vector <string> pieces;
210  pieces.push_back( line.substr(0,line.find("->", 0)) );
211  // Do not count additional final jets
212  int end = (line.find("{", 0) != string::npos) ? line.find("{", 0)-2
213  : line.size();
214  pieces.push_back( line.substr(line.find("->", 0)+2, end) );
215 
216  // Get incoming particles
217  for(int i=0; i < nIn; ++i) {
218  for(int n = pieces[0].find(inParticleNamesSH[i], 0);
219  n != int(string::npos);
220  n = pieces[0].find(inParticleNamesSH[i], n)) {
221  incom.push_back(inParticleNumbers[i]);
222  pieces[0].erase(pieces[0].begin()+n,
223  pieces[0].begin()+n+inParticleNamesSH[i].size());
224  n=0;
225  }
226  }
227  // Get intermediate particles
228  // If intermediates are still empty, fill intermediate with default value
229  inter.push_back(0);
230  // Get final particles
231  for(int i=0; i < nOut; ++i) {
232  for(int n = pieces[1].find(outParticleNamesSH[i], 0);
233  n != int(string::npos);
234  n = pieces[1].find(outParticleNamesSH[i], n)) {
235  outgo.push_back(outParticleNumbers[i]);
236  pieces[1].erase(pieces[1].begin()+n,
237  pieces[1].begin()+n+outParticleNamesSH[i].size());
238  n=0;
239  }
240  }
241 
242  } else if(meGenType == -1){
243  // Now read merging scale
244  // Open path to LHEF and extract merging scale
245  infile.open( (char*)( LHEpath +"_1.lhe").c_str());
246  string lineTMS;
247  while(lineTMS.find("ktdurham", 0) == string::npos){
248  lineTMS = " ";
249  getline(infile,lineTMS);
250  }
251  lineTMS = lineTMS.substr(0,lineTMS.find("=",0));
252  infile.close();
253  // Remove whitespaces
254  while(lineTMS.find(" ", 0) != string::npos)
255  lineTMS.erase(lineTMS.begin()+lineTMS.find(" ",0));
256  // Replace d with e
257  if( lineTMS.find("d", 0) != string::npos)
258  lineTMS.replace(lineTMS.find("d", 0),1,1,'e');
259  tms = atof((char*)lineTMS.c_str());
260 
261  // Now read hard process
262  // Open path to LHEF and extract hard process
263  infile.open( (char*)( LHEpath +"_0.lhe").c_str());
264  string line;
265  while(line.find("@1", 0) == string::npos){
266  line = " ";
267  getline(infile,line);
268  }
269  infile.close();
270  line = line.substr(0,line.find("@",0));
271 
272  // Count number of resonances
273  int appearances = 0;
274  for(int n = line.find("(", 0); n != int(string::npos);
275  n = line.find("(", n)) {
276  appearances++;
277  n++;
278  }
279 
280  // Cut string in incoming, resonance+decay and outgoing pieces
281  vector <string> pieces;
282  for(int i =0; i < appearances;++i) {
283  int n = line.find("(", 0);
284  pieces.push_back(line.substr(0,n));
285  line = line.substr(n+1,line.size());
286  }
287  // Cut last resonance from rest
288  if(appearances > 0) {
289  pieces.push_back( line.substr(0,line.find(")",0)) );
290  pieces.push_back( line.substr(line.find(")",0)+1,line.size()) );
291  }
292 
293  // If the string was not cut into pieces, i.e. no resonance was
294  // required, cut string using '>' as delimiter
295  if(pieces.empty() ){
296  appearances = 0;
297  for(int n = line.find(">", 0); n != int(string::npos);
298  n = line.find(">", n)) {
299  appearances++;
300  n++;
301  }
302 
303  // Cut string in incoming and outgoing pieces
304  for(int i =0; i < appearances;++i) {
305  int n = line.find(">", 0);
306  pieces.push_back(line.substr(0,n));
307  line = line.substr(n+1,line.size());
308  }
309 
310  if(appearances == 1) pieces.push_back(line);
311  if(appearances > 1) {
312  pieces.push_back( line.substr(0,line.find(">",0)) );
313  pieces.push_back( line.substr(line.find(">",0)+1,line.size()) );
314  }
315  }
316 
317  // Get incoming particles
318  for(int i=0; i < nIn; ++i) {
319  for(int n = pieces[0].find(inParticleNamesMG[i], 0);
320  n != int(string::npos);
321  n = pieces[0].find(inParticleNamesMG[i], n)) {
322  incom.push_back(inParticleNumbers[i]);
323  pieces[0].erase(pieces[0].begin()+n,
324  pieces[0].begin()+n+inParticleNamesMG[i].size());
325  n=0;
326  }
327  }
328 
329  // Check intermediate resonances and decay products
330  for(int i =1; i < int(pieces.size()); ++i){
331  // Seperate strings into intermediate and outgoing, if not already done
332  int k = pieces[i].find(">", 0);
333 
334  string intermediate = (pieces[i].find(">", 0) != string::npos) ?
335  pieces[i].substr(0,k) : "";
336  string outgoing = (pieces[i].find(">", 0) != string::npos) ?
337  pieces[i].substr(k+1,pieces[i].size()) : pieces[i];
338 
339  // Get intermediate particles
340  for(int j=0; j < nInt; ++j) {
341  for(int n = intermediate.find(interParticleNamesMG[j], 0);
342  n != int(string::npos);
343  n = intermediate.find(interParticleNamesMG[j], n)) {
344  inter.push_back(interParticleNumbers[j]);
345  intermediate.erase(intermediate.begin()+n,
346  intermediate.begin()+n+interParticleNamesMG[j].size());
347  n=0;
348  }
349  }
350 
351  // Get outgoing particles
352  for(int j=0; j < nOut; ++j) {
353  for(int n = outgoing.find(outParticleNamesMG[j], 0);
354  n != int(string::npos);
355  n = outgoing.find(outParticleNamesMG[j], n)) {
356  outgo.push_back(outParticleNumbers[j]);
357  outgoing.erase(outgoing.begin()+n,
358  outgoing.begin()+n+outParticleNamesMG[j].size());
359  n=0;
360  }
361  }
362 
363  // For arbitrary or non-existing intermediate, remember zero for each
364  // two outgoing particles
365  if(inter.empty()) {
366  int nZeros = outgo.size()/2;
367  for(int l=0; l < nZeros; ++l)
368  inter.push_back(0);
369  }
370 
371  }
372 
373  } else {
374 
375  cout << "Reading of tms and hard process information from LHEF currently"
376  << " only automated for MadEvent- or SHERPA-produced LHEF" << endl;
377  int tempInt = 0;
378  cout << "Use default process pp -> e+ve + jets? (0:no / 1:yes): ";
379  cin >> tempInt;
380  cout << endl;
381 
382  if(tempInt == 0){
383  tempInt = 0;
384  double tempDouble = 0.0;
385  cout << "Please specify merging scale (kT Durham, in GeV): ";
386  cin >> tempDouble;
387  tms = tempDouble;
388  meGenType = -1;
389  cout << endl;
390  cout << "Please specify first incoming particle ";
391  cout << "(p+/p- = 2212, e- = 11, e+ = -11): ";
392  cin >> tempInt;
393  incom.push_back(tempInt);
394  tempInt = 0;
395  cout << endl;
396  cout << "Please specify second incoming particle ";
397  cout << "(p+/p- = 2212, e- = 11, e+ = -11): ";
398  cin >> tempInt;
399  incom.push_back(tempInt);
400  tempInt = 0;
401  cout << endl;
402  cout << "Please specify intermediate particle, if any ";
403  cout << "(0 for none, else PDG code): ";
404  cin >> tempInt;
405  inter.push_back(tempInt);
406  cout << endl;
407  do {
408  tempInt = 0;
409  cout << "Please specify outgoing particle ";
410  cout << "(jet=2212, else PDG code, exit with 99): ";
411  cin >> tempInt;
412  if(tempInt != 99) outgo.push_back(tempInt);
413  } while(tempInt != 99);
414  cout << endl;
415  } else {
416  cout << "LHE file not produced by SHERPA or MG/ME - ";
417  cout << "Using default process and tms" << endl;
418  incom.push_back(2212);
419  incom.push_back(2212);
420  inter.push_back(24);
421  outgo.push_back(-11);
422  outgo.push_back(12);
423  tms = 10.;
424  meGenType = -1;
425  }
426  }
427 
428  // Now store incoming, intermediate and outgoing
429  // Set intermediate tags
430  for(int i=0; i < int(inter.size()); ++i)
431  hardIntermediate.push_back(inter[i]);
432 
433  // Set the incoming particle tags
434  if(incom.size() != 2)
435  cout << "Only two incoming particles allowed" << endl;
436  else {
437  hardIncoming1 = incom[0];
438  hardIncoming2 = incom[1];
439  }
440 
441  // Set final particle identifiers
442  if(outgo.size()%2 == 1) {
443  cout << "Only even number of outgoing particles allowed" << endl;
444  for(int i=0; i < int(outgo.size()); ++i)
445  cout << outgo[i] << endl;
446  } else {
447 
448  // Push back particles / antiparticles
449  for(int i=0; i < int(outgo.size()); ++i)
450  if(outgo[i] > 0
451  && outgo[i] != 2212
452  && outgo[i] != 1000022)
453  hardOutgoing2.push_back( outgo[i]);
454  else if (outgo[i] < 0)
455  hardOutgoing1.push_back( outgo[i]);
456 
457  // Push back jets, distribute evenly amongst particles / antiparticles
458  // Push back majorana particles, distribute evenly
459  int iNow = 0;
460  for(int i=0; i < int(outgo.size()); ++i)
461  if( (outgo[i] == 2212
462  || outgo[i] == 1000022)
463  && iNow%2 == 0 ){
464  hardOutgoing2.push_back( outgo[i]);
465  iNow++;
466  } else if( (outgo[i] == 2212
467  || outgo[i] == 1000022)
468  && iNow%2 == 1 ){
469  hardOutgoing1.push_back( outgo[i]);
470  iNow++;
471  }
472  }
473 
474  // Done
475 }
476 
477 //--------------------------------------------------------------------------
478 
479 // Function to translate a string specitying the core process into the
480 // internal notation
481 // Currently, the input string has to be in MadEvent notation
482 
483 void HardProcess::translateProcessString( string process){
484 
485  vector <int> incom;
486  vector <int> inter;
487  vector <int> outgo;
488  // Particle identifiers, ordered in such a way that e.g. the "u"
489  // in a mu is not mistaken for an u quark
490  int inParticleNumbers[] = {
491  // Leptons
492  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
493  // Jet container
494  2212,2212,0,0,0,0,
495  // Quarks
496  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6};
497  string inParticleNamesMG[] = {
498  // Leptons
499  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
500  // Jet container
501  "p~","p","l+","l-","vl~","vl",
502  // Quarks
503  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t"};
504 
505  // Declare intermediate particle identifiers
506  int interParticleNumbers[] = {
507  // Electroweak gauge bosons
508  22,23,-24,24,
509  // Top quarks
510  -6,6,
511  // Dummy index as back-up
512  0,
513  // All squarks
514  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
515  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
516  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
517  // Declare names of intermediate particles
518  string interParticleNamesMG[] = {
519  // Electroweak gauge bosons
520  "a","z","w-","w+",
521  // Top quarks
522  "t~","t",
523  // Dummy index as back-up
524  "xx",
525  // All squarks
526  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
527  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
528 
529  // Declare final state particle identifiers
530  int outParticleNumbers[] = {
531  // Leptons
532  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
533  // Jet container
534  2212,2212,0,0,0,0,
535  // Quarks
536  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6,
537  // Neutralino in SUSY
538  1000022,
539  // All squarks
540  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
541  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
542  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006};
543  // Declare names of final state particles
544  string outParticleNamesMG[] = {
545  // Leptons
546  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
547  // Jet container
548  "j~","j","l+","l-","vl~","vl",
549  // Quarks
550  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t",
551  // Neutralino in SUSY
552  "n1",
553  // All squarks
554  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
555  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2"};
556 
557  // Declare size of particle name arrays
558  int nIn = 30;
559  int nInt = 31;
560  int nOut = 55;
561 
562  string line = process;
563 
564  // Count number of resonances
565  int appearances = 0;
566  for(int n = line.find("(", 0); n != int(string::npos);
567  n = line.find("(", n)) {
568  appearances++;
569  n++;
570  }
571 
572  // Cut string in incoming, resonance+decay and outgoing pieces
573  vector <string> pieces;
574  for(int i =0; i < appearances;++i) {
575  int n = line.find("(", 0);
576  pieces.push_back(line.substr(0,n));
577  line = line.substr(n+1,line.size());
578  }
579  // Cut last resonance from rest
580  if(appearances > 0) {
581  pieces.push_back( line.substr(0,line.find(")",0)) );
582  pieces.push_back( line.substr(line.find(")",0)+1,line.size()) );
583  }
584 
585  // If the string was not cut into pieces, i.e. no resonance was
586  // required, cut string using '>' as delimiter
587  if(pieces.empty() ){
588  appearances = 0;
589  for(int n = line.find(">", 0); n != int(string::npos);
590  n = line.find(">", n)) {
591  appearances++;
592  n++;
593  }
594 
595  // Cut string in incoming and outgoing pieces
596  for(int i =0; i < appearances;++i) {
597  int n = line.find(">", 0);
598  pieces.push_back(line.substr(0,n));
599  line = line.substr(n+1,line.size());
600  }
601 
602  if(appearances == 1) pieces.push_back(line);
603  if(appearances > 1) {
604  pieces.push_back( line.substr(0,line.find(">",0)) );
605  pieces.push_back( line.substr(line.find(">",0)+1,line.size()) );
606  }
607  }
608 
609  // Get incoming particles
610  for(int i=0; i < nIn; ++i) {
611  for(int n = pieces[0].find(inParticleNamesMG[i], 0);
612  n != int(string::npos);
613  n = pieces[0].find(inParticleNamesMG[i], n)) {
614  incom.push_back(inParticleNumbers[i]);
615  pieces[0].erase(pieces[0].begin()+n,
616  pieces[0].begin()+n+inParticleNamesMG[i].size());
617  n=0;
618  }
619  }
620 
621  // Check intermediate resonances and decay products
622  for(int i =1; i < int(pieces.size()); ++i){
623  // Seperate strings into intermediate and outgoing, if not already done
624  int k = pieces[i].find(">", 0);
625 
626  string intermediate = (pieces[i].find(">", 0) != string::npos) ?
627  pieces[i].substr(0,k) : "";
628  string outgoing = (pieces[i].find(">", 0) != string::npos) ?
629  pieces[i].substr(k+1,pieces[i].size()) : pieces[i];
630 
631  // Get intermediate particles
632  for(int j=0; j < nInt; ++j) {
633  for(int n = intermediate.find(interParticleNamesMG[j], 0);
634  n != int(string::npos);
635  n = intermediate.find(interParticleNamesMG[j], n)) {
636  inter.push_back(interParticleNumbers[j]);
637  intermediate.erase(intermediate.begin()+n,
638  intermediate.begin()+n+interParticleNamesMG[j].size());
639  n=0;
640  }
641  }
642 
643  // Get outgoing particles
644  for(int j=0; j < nOut; ++j) {
645  for(int n = outgoing.find(outParticleNamesMG[j], 0);
646  n != int(string::npos);
647  n = outgoing.find(outParticleNamesMG[j], n)) {
648  outgo.push_back(outParticleNumbers[j]);
649  outgoing.erase(outgoing.begin()+n,
650  outgoing.begin()+n+outParticleNamesMG[j].size());
651  n=0;
652  }
653  }
654 
655  // For arbitrary or non-existing intermediate, remember zero for each
656  // two outgoing particles
657  if(inter.empty()) {
658  int nZeros = outgo.size()/2;
659  for(int l=0; l < nZeros; ++l)
660  inter.push_back(0);
661  }
662 
663  }
664 
665  // Now store incoming, intermediate and outgoing
666  // Set intermediate tags
667  for(int i=0; i < int(inter.size()); ++i)
668  hardIntermediate.push_back(inter[i]);
669 
670  // Set the incoming particle tags
671  if(incom.size() != 2)
672  cout << "Only two incoming particles allowed" << endl;
673  else {
674  hardIncoming1 = incom[0];
675  hardIncoming2 = incom[1];
676  }
677 
678  // Set final particle identifiers
679  if(outgo.size()%2 == 1) {
680  cout << "Only even number of outgoing particles allowed" << endl;
681  for(int i=0; i < int(outgo.size()); ++i)
682  cout << outgo[i] << endl;
683  } else {
684 
685  // Push back particles / antiparticles
686  for(int i=0; i < int(outgo.size()); ++i)
687  if(outgo[i] > 0
688  && outgo[i] != 2212
689  && outgo[i] != 1000022)
690  hardOutgoing2.push_back( outgo[i]);
691  else if (outgo[i] < 0)
692  hardOutgoing1.push_back( outgo[i]);
693 
694  // Push back jets, distribute evenly among particles / antiparticles
695  // Push back majorana particles, distribute evenly
696  int iNow = 0;
697  for(int i=0; i < int(outgo.size()); ++i)
698  if( (outgo[i] == 2212
699  || outgo[i] == 1000022)
700  && iNow%2 == 0 ){
701  hardOutgoing2.push_back( outgo[i]);
702  iNow++;
703  } else if( (outgo[i] == 2212
704  || outgo[i] == 1000022)
705  && iNow%2 == 1 ){
706  hardOutgoing1.push_back( outgo[i]);
707  iNow++;
708  }
709  }
710 
711  // Done
712 }
713 
714 //--------------------------------------------------------------------------
715 
716 // Function to identify the hard subprocess in the current event
717 
718 void HardProcess::storeCandidates( const Event& event){
719 
720  // Store the reference event
721  state.clear();
722  state = event;
723 
724  // Local copy of intermediate bosons
725  vector<int> intermediates;
726  for(int i =0; i < int(hardIntermediate.size());++i)
727  intermediates.push_back( hardIntermediate[i]);
728 
729  // Local copy of outpoing partons
730  vector<int> outgoing1;
731  for(int i =0; i < int(hardOutgoing1.size());++i)
732  outgoing1.push_back( hardOutgoing1[i]);
733  vector<int> outgoing2;
734  for(int i =0; i < int(hardOutgoing2.size());++i)
735  outgoing2.push_back( hardOutgoing2[i]);
736 
737  // Clear positions of intermediate and outgoing particles
738  PosIntermediate.resize(0);
739  PosOutgoing1.resize(0);
740  PosOutgoing2.resize(0);
741  for(int i =0; i < int(hardIntermediate.size());++i)
742  PosIntermediate.push_back(0);
743  for(int i =0; i < int(hardOutgoing1.size());++i)
744  PosOutgoing1.push_back(0);
745  for(int i =0; i < int(hardOutgoing2.size());++i)
746  PosOutgoing2.push_back(0);
747 
748  // If the hard process only consists of jets, and no intermediate
749  // particle is required, then no candidates need to be fixed, since
750  // all clusterings to the 2 -> 2 process should be allowed.
751  // Check if hard process contains only jets
752  bool hasOnlyJets = true;
753  for(int i =0; i < int(hardOutgoing1.size());++i)
754  if(hardOutgoing1[i] != 2212)
755  hasOnlyJets = false;
756  for(int i =0; i < int(hardOutgoing2.size());++i)
757  if(hardOutgoing2[i] != 2212)
758  hasOnlyJets = false;
759 
760  // If the hard process contains only of non-specified jets,
761  // do not store any candidates, as to not discrimintate
762  // clusterings
763  if(hasOnlyJets){
764  for(int i =0; i < int(hardOutgoing1.size());++i)
765  PosOutgoing1[i] = 0;
766  for(int i =0; i < int(hardOutgoing2.size());++i)
767  PosOutgoing2[i] = 0;
768  // Done
769  return;
770  }
771 
772  // Initialise vector of particles that were already identified as
773  // hard process particles
774  vector<int> iPosChecked;
775 
776  // First try to find particles coupled to intermediate bosons
777  for(int i=0; i < int(intermediates.size()); ++i){
778 
779  // Do nothing if the intermediate boson is absent
780  if(intermediates[i] == 0) continue;
781 
782  // Loop through event
783  for(int j=0; j < int(event.size()); ++j) {
784  // If the particle has a requested intermediate id, check if
785  // daughters are hard process particles
786  if(event[j].id() == intermediates[i]) {
787  // If this particle is a potential intermediate
788  PosIntermediate[i] = j;
789  intermediates[i] = 0;
790  // If id's of daughters are good, store position
791  int iPos1 = event[j].daughter1();
792  int iPos2 = event[j].daughter2();
793 
794  // Loop through daughters to check if these contain some hard
795  // outgoing particles
796  for( int k=iPos1; k <= iPos2; ++k){
797  int id = event[k].id();
798 
799  // Check if daughter is hard outgoing particle
800  for(int l=0; l < int(outgoing2.size()); ++l)
801  if( outgoing2[l] != 99 ){
802  // Found particle id
803  if(id == outgoing2[l]
804  // Found jet
805  || (id > 0 && abs(id) < 10 && outgoing2[l] == 2212) ){
806  // Store position
807  PosOutgoing2[l] = k;
808  // Remove the matched particle from the list
809  outgoing2[l] = 99;
810  iPosChecked.push_back(k);
811  break;
812  }
813  }
814 
815  // Check if daughter is hard outgoing antiparticle
816  for(int l=0; l < int(outgoing1.size()); ++l)
817  if( outgoing1[l] != 99 ){
818  // Found particle id
819  if(id == outgoing1[l]
820  // Found jet
821  || (id < 0 && abs(id) < 10 && outgoing1[l] == 2212) ){
822  // Store position
823  PosOutgoing1[l] = k;
824  // Remove the matched particle from the list
825  outgoing1[l] = 99;
826  iPosChecked.push_back(k);
827  break;
828  }
829  }
830 
831  } // End loop through daughters
832  } // End if ids match
833  } // End loop through event
834  } // End loop though requested intermediates
835 
836  // If all outgoing particles were found, done
837  bool done = true;
838  for(int i=0; i < int(outgoing1.size()); ++i)
839  if(outgoing1[i] != 99)
840  done = false;
841  for(int i=0; i < int(outgoing2.size()); ++i)
842  if(outgoing2[i] != 99)
843  done = false;
844  // Return
845  if(done) return;
846 
847  // Leptons not associated with resonance are allowed.
848  // Try to find all unmatched hard process leptons.
849  // Loop through event to find outgoing lepton
850  for(int i=0; i < int(event.size()); ++i){
851  // Skip non-final particles and final partons
852  if( !event[i].isFinal() || event[i].colType() != 0)
853  continue;
854  // Skip all particles that have already been identified
855  bool skip = false;
856  for(int k=0; k < int(iPosChecked.size()); ++k){
857  if(i == iPosChecked[k])
858  skip = true;
859  }
860  if(skip) continue;
861 
862  // Check if any hard outgoing leptons remain
863  for(int j=0; j < int(outgoing2.size()); ++j){
864  // Do nothing if this particle has already be found,
865  // or if this particle is a jet or quark
866  if( outgoing2[j] == 99
867  || outgoing2[j] == 2212
868  || abs(outgoing2[j]) < 10)
869  continue;
870 
871  // If the particle matches an outgoing lepton, save it
872  if(event[i].id() == outgoing2[j]){
873  PosOutgoing2[j] = i;
874  outgoing2[j] = 99;
875  iPosChecked.push_back(i);
876  }
877  }
878 
879  // Check if any hard outgoing antileptons remain
880  for(int j=0; j < int(outgoing1.size()); ++j){
881  // Do nothing if this particle has already be found,
882  // or if this particle is a jet or quark
883  if( outgoing1[j] == 99
884  || outgoing1[j] == 2212
885  || abs(outgoing1[j]) < 10)
886  continue;
887 
888  // If the particle matches an outgoing lepton, save it
889  if(event[i].id() == outgoing1[j]){
890  PosOutgoing1[j] = i;
891  outgoing1[j] = 99;
892  iPosChecked.push_back(i);
893  }
894  }
895  }
896 
897  // It sometimes happens that MadEvent does not put a
898  // heavy coloured resonance into the LHE file, even if requested.
899  // This means that the decay products of this resonance need to be
900  // found separately.
901  // Loop through event to find hard process (anti)quarks
902  for(int i=0; i < int(event.size()); ++i){
903 
904  // Skip non-final particles and final partons
905  if( !event[i].isFinal() || event[i].colType() == 0)
906  continue;
907 
908  // Skip all particles that have already been identified
909  bool skip = false;
910  for(int k=0; k < int(iPosChecked.size()); ++k){
911  if(i == iPosChecked[k])
912  skip = true;
913  }
914  if(skip) continue;
915 
916  // Check if any hard outgoing leptons remain
917  for(int j=0; j < int(outgoing2.size()); ++j){
918  // Do nothing if this particle has already be found,
919  // or if this particle is a jet or quark
920  if( outgoing2[j] == 99
921  || outgoing2[j] == 2212
922  || abs(outgoing2[j]) > 10)
923  continue;
924  // If the particle matches an outgoing quarks, save it
925  if(event[i].id() == outgoing2[j]){
926  // Save parton
927  PosOutgoing2[j] = i;
928  // remove entry form lists
929  outgoing2[j] = 99;
930  iPosChecked.push_back(i);
931  }
932  }
933 
934  // Check if any hard outgoing antiquarks remain
935  for(int j=0; j < int(outgoing1.size()); ++j){
936  // Do nothing if this particle has already be found,
937  // or if this particle is a jet or quark
938  if( outgoing1[j] == 99
939  || outgoing1[j] == 2212
940  || abs(outgoing1[j]) > 10)
941  continue;
942  // If the particle matches an outgoing lepton, save it
943  if(event[i].id() == outgoing1[j]){
944  // Save parton
945  PosOutgoing1[j] = i;
946  // Remove parton from list
947  outgoing1[j] = 99;
948  iPosChecked.push_back(i);
949  }
950  }
951  }
952 
953  // Done
954 }
955 
956 //--------------------------------------------------------------------------
957 
958 // Function to check if the particle event[iPos] matches any of
959 // the stored outgoing particles of the hard subprocess
960 
961 bool HardProcess::matchesAnyOutgoing(int iPos, const Event& event){
962 
963  // Match quantum numbers of any first outgoing candidate
964  bool matchQN1 = false;
965  // Match quantum numbers of any second outgoing candidate
966  bool matchQN2 = false;
967  // Match parton in the hard process,
968  // or parton from decay of electroweak boson in hard process,
969  // or parton from decay of electroweak boson from decay of top
970  bool matchHP = false;
971 
972  // Check outgoing candidates
973  for(int i=0; i < int(PosOutgoing1.size()); ++i)
974  // Compare particle properties
975  if( event[iPos].id() == state[PosOutgoing1[i]].id()
976  && event[iPos].colType() == state[PosOutgoing1[i]].colType()
977  && event[iPos].chargeType() == state[PosOutgoing1[i]].chargeType()
978  && event[iPos].col() == state[PosOutgoing1[i]].col()
979  && event[iPos].acol() == state[PosOutgoing1[i]].acol()
980  && event[iPos].charge() == state[PosOutgoing1[i]].charge() )
981  matchQN1 = true;
982 
983  // Check outgoing candidates
984  for(int i=0; i < int(PosOutgoing2.size()); ++i)
985  // Compare particle properties
986  if( event[iPos].id() == state[PosOutgoing2[i]].id()
987  && event[iPos].colType() == state[PosOutgoing2[i]].colType()
988  && event[iPos].chargeType() == state[PosOutgoing2[i]].chargeType()
989  && event[iPos].col() == state[PosOutgoing2[i]].col()
990  && event[iPos].acol() == state[PosOutgoing2[i]].acol()
991  && event[iPos].charge() == state[PosOutgoing2[i]].charge() )
992  matchQN2 = true;
993 
994  // Check if maps to hard process:
995  // Check that particle is in hard process
996  if( event[iPos].mother1()*event[iPos].mother2() == 12
997  // Or particle has taken recoil from first splitting
998  || ( event[iPos].status() == 44
999  && event[event[iPos].mother1()].mother1()
1000  *event[event[iPos].mother1()].mother2() == 12 )
1001  // Or particle has on-shell resonace as mother
1002  || ( event[iPos].status() == 23
1003  && event[event[iPos].mother1()].mother1()
1004  *event[event[iPos].mother1()].mother2() == 12 )
1005  // Or particle has on-shell resonace as mother,
1006  // which again has and on-shell resonance as mother
1007  || ( event[iPos].status() == 23
1008  && event[event[iPos].mother1()].status() == -22
1009  && event[event[event[iPos].mother1()].mother1()].status() == -22
1010  && event[event[event[iPos].mother1()].mother1()].mother1()
1011  *event[event[event[iPos].mother1()].mother1()].mother2() == 12 ) )
1012  matchHP = true;
1013 
1014  // Done
1015  return matchHP && ( matchQN1 || matchQN2 );
1016 
1017 }
1018 
1019 
1020 //--------------------------------------------------------------------------
1021 
1022 // Function to return the type of the ME generator
1023 
1024 int HardProcess::MEgenType(){ return meGenType;}
1025 
1026 //--------------------------------------------------------------------------
1027 
1028 // Function to get the number of coloured final state partons in the
1029 // hard process
1030 
1031 int HardProcess::nQuarksOut(){
1032  int nFin =0;
1033  for(int i =0; i< int(hardOutgoing1.size()); ++i){
1034  if(hardOutgoing1[i] == 2212 || abs(hardOutgoing1[i]) < 10) nFin++;
1035  if(hardOutgoing2[i] == 2212 || abs(hardOutgoing2[i]) < 10) nFin++;
1036  }
1037  return nFin;
1038 }
1039 
1040 //--------------------------------------------------------------------------
1041 
1042 // Function to get the number of uncoloured final state particles in the
1043 // hard process
1044 
1045 int HardProcess::nLeptonOut(){
1046  int nFin =0;
1047  for(int i =0; i< int(hardOutgoing1.size()); ++i){
1048  if(abs(hardOutgoing1[i]) > 10 && abs(hardOutgoing1[i]) < 20) nFin++;
1049  if(abs(hardOutgoing2[i]) > 10 && abs(hardOutgoing2[i]) < 20) nFin++;
1050  // Bookkeep MSSM neutralinos as leptons
1051  if(abs(hardOutgoing1[i]) == 1000022) nFin++;
1052  if(abs(hardOutgoing2[i]) == 1000022) nFin++;
1053  }
1054  return nFin;
1055 }
1056 
1057 //--------------------------------------------------------------------------
1058 
1059 // Function to get the number of coloured initial state partons in the
1060 // hard process
1061 
1062 int HardProcess::nQuarksIn(){
1063  int nIn =0;
1064  if(hardIncoming1 == 2212 || abs(hardIncoming1) < 10) nIn++;
1065  if(hardIncoming2 == 2212 || abs(hardIncoming2) < 10) nIn++;
1066  return nIn;
1067 }
1068 
1069 //--------------------------------------------------------------------------
1070 
1071 // Function to get the number of uncoloured initial state particles in the
1072 // hard process
1073 
1074 int HardProcess::nLeptonIn(){
1075  int nIn =0;
1076  if(abs(hardIncoming1) > 10 && abs(hardIncoming1) < 20) nIn++;
1077  if(abs(hardIncoming2) > 10 && abs(hardIncoming2) < 20) nIn++;
1078  return nIn;
1079 }
1080 
1081 //--------------------------------------------------------------------------
1082 
1083 // Function to report if a resonace decay was found in the
1084 // 2->2 hard sub-process in the current state
1085 
1086 int HardProcess::hasResInCurrent(){
1087  for(int i =0; i< int(PosIntermediate.size()); ++i)
1088  if(PosIntermediate[i] == 0) return 0;
1089  return 1;
1090 }
1091 
1092 //--------------------------------------------------------------------------
1093 
1094 // Function to report the number of resonace decays in the 2->2 sub-process
1095 // of the current state
1096 
1097 int HardProcess::nResInCurrent(){
1098  int nRes = 0;
1099  for(int i =0; i< int(PosIntermediate.size()); ++i){
1100  if(PosIntermediate[i] != 0) nRes++;
1101  }
1102  return nRes;
1103 }
1104 
1105 //--------------------------------------------------------------------------
1106 
1107 // Function to report if a resonace decay was found in the
1108 // 2->2 hard core process
1109 
1110 bool HardProcess::hasResInProc(){
1111  for(int i =0; i< int(hardIntermediate.size()); ++i)
1112  if(hardIntermediate[i] == 0) return false;
1113  return true;
1114 }
1115 
1116 //--------------------------------------------------------------------------
1117 
1118 // Function to print the hard process (for debug)
1119 
1120 void HardProcess::list() const {
1121  cout << " Hard Process: ";
1122  cout << " \t " << hardIncoming1 << " + " << hardIncoming2;
1123  cout << " \t -----> \t ";
1124  for(int i =0; i < int(hardIntermediate.size());++i)
1125  cout << hardIntermediate[i] << " ";
1126  cout << " \t -----> \t ";
1127  for(int i =0; i < int(hardOutgoing1.size());++i) {
1128  cout << hardOutgoing1[i] << " ";
1129  cout << hardOutgoing2[i] << " ";
1130  }
1131  cout << endl;
1132 }
1133 
1134 //--------------------------------------------------------------------------
1135 
1136 // Function to list the hard process candiates in the matrix element state
1137 // (for debug)
1138 
1139 void HardProcess::listCandidates() const {
1140  cout << " Hard Process candidates: ";
1141  cout << " \t " << hardIncoming1 << " + " << hardIncoming2;
1142  cout << " \t -----> \t ";
1143  for(int i =0; i < int(PosIntermediate.size());++i)
1144  cout << PosIntermediate[i] << " ";
1145  cout << " \t -----> \t ";
1146  for(int i =0; i < int(PosOutgoing1.size());++i) {
1147  cout << PosOutgoing1[i] << " ";
1148  cout << PosOutgoing2[i] << " ";
1149  }
1150  cout << endl;
1151 }
1152 
1153 //--------------------------------------------------------------------------
1154 
1155 // Function to clear hard process information
1156 
1157 void HardProcess::clear() {
1158 
1159  // Clear flavour of the first incoming particle
1160  hardIncoming1 = hardIncoming2 = 0;
1161  // Clear outgoing particles
1162  hardOutgoing1.resize(0);
1163  hardOutgoing2.resize(0);
1164  // Clear intermediate bosons in the hard 2->2
1165  hardIntermediate.resize(0);
1166 
1167  // Clear reference event
1168  state.clear();
1169 
1170  // Clear potential positions of outgoing particles in reference event
1171  PosOutgoing1.resize(0);
1172  PosOutgoing2.resize(0);
1173  // Clear potential positions of intermediate bosons in reference event
1174  PosIntermediate.resize(0);
1175 
1176  // Clear merging scale read from LHE file
1177  tms = 0.;
1178  // Clear type of ME generator
1179  meGenType = 0;
1180 
1181 
1182 }
1183 
1184 //==========================================================================
1185 
1186 // The MergingHooks class.
1187 
1188 //--------------------------------------------------------------------------
1189 
1190 // Initialise MergingHooks class
1191 
1192 void MergingHooks::init( Settings& settings, Info* infoPtrIn,
1193  ParticleData* particleDataPtrIn, ostream& os){
1194 
1195  // Save pointers
1196  infoPtr = infoPtrIn;
1197  particleDataPtr = particleDataPtrIn;
1198 
1199  // Initialise AlphaS objects for reweighting
1200  double alphaSvalueFSR = settings.parm("TimeShower:alphaSvalue");
1201  int alphaSorderFSR = settings.mode("TimeShower:alphaSorder");
1202  AlphaS_FSRSave.init(alphaSvalueFSR,alphaSorderFSR);
1203  double alphaSvalueISR = settings.parm("SpaceShower:alphaSvalue");
1204  int alphaSorderISR = settings.mode("SpaceShower:alphaSorder");
1205  AlphaS_ISRSave.init(alphaSvalueISR,alphaSorderISR);
1206 
1207  // Initialise merging switches
1208  doUserMergingSave = settings.flag("Merging:doUserMerging");
1209 
1210  // Initialise automated MadGraph kT merging
1211  doMGMergingSave = settings.flag("Merging:doMGMerging");
1212 
1213  // Initialise kT merging
1214  doKTMergingSave = settings.flag("Merging:doKTMerging");
1215 
1216  // Initialise exact definition of kT
1217  ktTypeSave = settings.mode("Merging:ktType");
1218 
1219  // Get core process from user input
1220  processSave = settings.word("Merging:Process");
1221 
1222  // Clear hard process
1223  hardProcess.clear();
1224 
1225  // Initialise the hard process
1226  if(doUserMergingSave || doKTMergingSave)
1227  hardProcess.initOnProcess(processSave, particleDataPtr);
1228  else
1229  hardProcess.initOnLHEF(lheInputFile, particleDataPtr);
1230 
1231  // Parameters for reconstruction of evolution scales
1232  includeMassiveSave = settings.flag("Merging:includeMassive");
1233  enforceStrongOrderingSave = settings.flag("Merging:enforceStrongOrdering");
1234  scaleSeparationFactorSave = settings.parm("Merging:scaleSeparationFactor");
1235  orderInRapiditySave = settings.flag("Merging:orderInRapidity");
1236 
1237  // Parameters for choosing history probabilistically
1238  nonJoinedNormSave = settings.parm("Merging:nonJoinedNorm");
1239  fsrInRecNormSave = settings.parm("Merging:fsrInRecNorm");
1240  pickByFullPSave = settings.flag("Merging:pickByFullP");
1241  pickByPoPT2Save = settings.flag("Merging:pickByPoPT2");
1242  includeRedundantSave = settings.flag("Merging:includeRedundant");
1243 
1244  // Parameters for scale choices
1245  unorderedScalePrescipSave =
1246  settings.mode("Merging:unorderedScalePrescrip");
1247  unorderedASscalePrescipSave =
1248  settings.mode("Merging:unorderedASscalePrescrip");
1249  incompleteScalePrescipSave =
1250  settings.mode("Merging:incompleteScalePrescrip");
1251 
1252  // Parameter for allowing swapping of one colour index while reclustering
1253  allowColourShufflingSave =
1254  settings.flag("Merging:allowColourShuffling");
1255 
1256  // Parameters for choosing history by sum(|pT|)
1257  pickBySumPTSave = settings.flag("Merging:pickBySumPT");
1258  herwigAcollFSRSave = settings.parm("Merging:aCollFSR");
1259  herwigAcollISRSave = settings.parm("Merging:aCollISR");
1260 
1261  // Information on the shower cut-off scale
1262  pT0ISRSave = settings.parm("SpaceShower:pT0Ref");
1263  pTcutSave = settings.parm("SpaceShower:pTmin");
1264  pTcutSave = max(pTcutSave,pT0ISRSave);
1265 
1266  // Initialise CKKWL weight
1267  weightSave = 1.;
1268 
1269  // Save merging scale on maximal number of jets
1270  // (Note: Not used at the moment)
1271  if(doKTMergingSave) {
1272  tmsValueSave = settings.parm("Merging:TMS");
1273  nJetMaxSave = settings.mode("Merging:nJetMax");
1274  } else if (doMGMergingSave) {
1275  tmsValueSave = hardProcess.tms;
1276  nJetMaxSave = settings.mode("Merging:nJetMax");
1277  } else {
1278  tmsValueSave = settings.parm("Merging:TMS");
1279  nJetMaxSave = settings.mode("Merging:nJetMax");
1280  }
1281 
1282  // Write banner
1283  os << "\n"
1284  << " *---------- MEPS Merging Initialization -----------------------*"
1285  << "\n"
1286  << " | We merge " << processSave << " with up to " << nJetMaxSave
1287  << " additional jets \n";
1288  if(doKTMergingSave)
1289  os << " | Merging scale is defined in kT with the value ktMS = "
1290  << tmsValueSave << " GeV";
1291  else if(doMGMergingSave)
1292  os << " | Perform automanted MG/ME merging \n"
1293  << " | Merging scale is defined in kT with the value ktMS = "
1294  << tmsValueSave << " GeV";
1295  else
1296  os << " | Merging scale is defined by the user, with the value tMS = "
1297  << tmsValueSave;
1298  os << "\n *---------- END MEPS Merging Initialization -------------------*"
1299  << "\n\n";
1300 
1301 }
1302 
1303 //--------------------------------------------------------------------------
1304 
1305 // Function to return the number of clustering steps for the current event
1306 
1307 int MergingHooks::getNumberOfClusteringSteps(const Event& event){
1308 
1309  // Count the number of final state partons
1310  int nFinalPartons = 0;
1311  for( int i=0; i < event.size(); ++i)
1312  if( event[i].isFinal() && event[i].isParton())
1313  nFinalPartons++;
1314 
1315  // Add tops to number of partons
1316  for( int i=0; i < event.size(); ++i)
1317  if( event[i].isFinal() && event[i].idAbs() == 6)
1318  nFinalPartons++;
1319 
1320  // Count the number of final state leptons
1321  int nFinalLeptons = 0;
1322  for( int i=0; i < event.size(); ++i)
1323  if( event[i].isFinal() && event[i].isLepton())
1324  nFinalLeptons++;
1325 
1326  // Add neutralinos to number of leptons
1327  for( int i=0; i < event.size(); ++i)
1328  if( event[i].isFinal()
1329  && event[i].idAbs() == 1000022)
1330  nFinalLeptons++;
1331 
1332  // Count the number of final state electroweak bosons
1333  int nFinalBosons = 0;
1334  for( int i=0; i < event.size(); ++i)
1335  if( event[i].isFinal()
1336  && ( event[i].idAbs() == 24
1337  || event[i].idAbs() == 23 ) )
1338  nFinalBosons++;
1339 
1340  // Save sum of all final state particles
1341  int nFinal = nFinalPartons + nFinalLeptons + 2*nFinalBosons;
1342 
1343  // Return the difference to the core process outgoing particles
1344  return (nFinal - nHardOutPartons() - nHardOutLeptons());
1345 
1346 }
1347 
1348 //--------------------------------------------------------------------------
1349 
1350 double MergingHooks::kTms(const Event& event) {
1351 
1352  // Cut only on QCD partons!
1353  // Count particle types
1354  int nFinalColoured = 0;
1355  int nFinalNow =0;
1356  for( int i=0; i < event.size(); ++i) {
1357  if(event[i].isFinal()){
1358  if(event[i].id() != 23 && abs(event[i].id()) != 24)
1359  nFinalNow++;
1360  if( event[i].colType() != 0)
1361  nFinalColoured++;
1362  }
1363  }
1364 
1365  // Use MergingHooks in-built functions to get information on the hard
1366  // process
1367  int nLeptons = nHardOutLeptons();
1368  int nQuarks = nHardOutPartons();
1369  int nResNow = nResInCurrent();
1370 
1371  // Check if photons, electrons etc. have been produced. If so, do not veto
1372  if(nFinalNow - ( (nLeptons+nQuarks)/2 - nResNow)*2 != nFinalColoured){
1373  // Sometimes, Pythia detaches the decay products even though no
1374  // resonance was put into the LHE file, to catch this, add another
1375  // if statement
1376  if(nFinalNow != nFinalColoured) return 0.;
1377  }
1378 
1379  // Check that one parton has been produced. If not (e.g. in MPI), do not veto
1380  int nMPI = infoPtr->nMPI();
1381  if(nMPI > 1) return 0.;
1382 
1383  // Declare kT algorithm parameters
1384  double Dparam = 0.4;
1385  // Declare final parton vector
1386  vector <int> FinalPartPos;
1387  FinalPartPos.clear();
1388  // Search event record for final state partons
1389  for (int i=0; i < event.size(); ++i)
1390  if(event[i].isFinal() && event[i].colType() != 0)
1391  FinalPartPos.push_back(i);
1392 
1393  // Find minimal Durham kT in event, using own function: Check
1394  // definition of separation
1395  int type = (event[3].colType() == 0
1396  && event[4].colType() == 0) ? -1 : ktTypeSave;
1397  // Find minimal kT
1398  double ktmin = event[0].e();
1399  for(int i=0; i < int(FinalPartPos.size()); ++i){
1400  double kt12 = ktmin;
1401  // Compute separation to the beam axis for hadronic collisions
1402  if(type == 1 || type == 2) {
1403  double temp = event[FinalPartPos[i]].pT();
1404  kt12 = min(kt12, temp);
1405  }
1406  // Compute separation to other final state jets
1407  for(int j=i+1; j < int(FinalPartPos.size()); ++j) {
1408  double temp = kTdurham( event[FinalPartPos[i]], event[FinalPartPos[j]],
1409  type, Dparam);
1410  kt12 = min(kt12, temp);
1411  }
1412  // Keep the minimal Durham separation
1413  ktmin = min(ktmin,kt12);
1414  }
1415 
1416  // Return minimal Durham kT
1417  return ktmin;
1418 
1419 }
1420 
1421 //--------------------------------------------------------------------------
1422 
1423 // Function to compute durham y separation from Particle input
1424 
1425 double MergingHooks::kTdurham(const Particle& RadAfterBranch,
1426  const Particle& EmtAfterBranch, int Type, double D ){
1427 
1428  // Declare return variable
1429  double ktdur;
1430  // Save 4-momenta of final state particles
1431  Vec4 jet1 = RadAfterBranch.p();
1432  Vec4 jet2 = EmtAfterBranch.p();
1433 
1434  if( Type == -1) {
1435  // Get angle between jets for e+e- collisions, make sure that
1436  // -1 <= cos(theta) <= 1
1437  double costh;
1438  if (jet1.pAbs()*jet2.pAbs() <=0.) costh = 1.;
1439  else {
1440  costh = costheta(jet1,jet2);
1441  }
1442  // Calculate kt durham separation between jets for e+e- collisions
1443  ktdur = 2.0*min( pow(jet1.e(),2) , (pow(jet2.e(),2)) )*(1.0 - costh);
1444  } else if( Type == 1 ){
1445  // Get delta_y for hadronic collisions:
1446  // Get mT of first jet
1447  double mT1sq = jet1.m2Calc() + jet1.pT2();
1448  double mT1 = 0.;
1449  if(mT1sq < 0) mT1 = - sqrt(-mT1sq);
1450  else mT1 = sqrt(mT1sq);
1451  // Get mT of second jet
1452  double mT2sq = jet2.m2Calc() + jet2.pT2();
1453  double mT2 = 0.;
1454  if(mT2sq < 0) mT2 = - sqrt(-mT2sq);
1455  else mT2 = sqrt(mT2sq);
1456  // Get rapidity of first jet
1457  double y1 = log( ( jet1.e() + abs(jet1.pz()) ) / mT1 );
1458  if(jet1.pz() < 0) y1 *= -1.;
1459  // Get rapidity of second jet
1460  double y2 = log( ( jet2.e() + abs(jet2.pz()) ) / mT2 );
1461  if(jet2.pz() < 0) y2 *= -1.;
1462  // Get delta_phi for hadronic collisions
1463  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
1464  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
1465  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
1466  double dPhi = acos( cosdPhi );
1467  // Calculate kT durham like fastjet,
1468  // but with rapidity instead of pseudo-rapidity
1469  ktdur = min( pow(pt1,2),pow(pt2,2) )
1470  * ( pow(y1-y2,2) + pow(dPhi,2) ) / pow(D,2);
1471  } else if( Type == 2 ){
1472  // Get delta_eta for hadronic collisions
1473  double eta1 = 0.5*log( (jet1.e() + jet1.pz()) / (jet1.e() - jet1.pz()) );
1474  double eta2 = 0.5*log( (jet2.e() + jet2.pz()) / (jet2.e() - jet2.pz()) );
1475  // Get delta_phi and cos(Delta_phi) for hadronic collisions
1476  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
1477  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
1478  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
1479  double dPhi = acos( cosdPhi );
1480  // Calculate kT durham like fastjet
1481  ktdur = min( pow(pt1,2),pow(pt2,2) )
1482  * ( pow(eta1-eta2,2) + pow(dPhi,2) ) / pow(D,2);
1483  } else if( Type == 3 ){
1484  // Get cosh(Delta_eta) for hadronic collisions
1485  double eta1 = 0.5*log( (jet1.e() + jet1.pz()) / (jet1.e() - jet1.pz()) );
1486  double eta2 = 0.5*log( (jet2.e() + jet2.pz()) / (jet2.e() - jet2.pz()) );
1487  double coshdEta = cosh( eta1 - eta2 );
1488  // Get delta_phi and cos(Delta_phi) for hadronic collisions
1489  double pt1 = sqrt( pow(jet1.px(),2) + pow(jet1.py(),2) );
1490  double pt2 = sqrt( pow(jet2.px(),2) + pow(jet2.py(),2) );
1491  double cosdPhi = ( jet1.px()*jet2.px() + jet1.py()*jet2.py() ) / (pt1*pt2);
1492  // Calculate kT durham separation "SHERPA-like"
1493  ktdur = 2.0*min( pow(pt1,2),pow(pt2,2) )
1494  * ( coshdEta - cosdPhi ) / pow(D,2);
1495  } else {
1496  ktdur = 0.0;
1497  }
1498  // Return kT
1499  return sqrt(ktdur);
1500 }
1501 
1502 //--------------------------------------------------------------------------
1503 
1504 // Function to set the path to the LHE file, so that more automated merging
1505 // can be used
1506 
1507 void MergingHooks::setLHEInputFile( string lheFile){
1508  // Remove "_1.lhe" suffix from LHE file name.
1509  // This is done so that the HarsProcess class can access both the +0 and +1
1510  // LHE files to find both the merging scale and the core process string
1511  // Store.
1512  lheInputFile = lheFile.substr(0,lheFile.size()-6);
1513 }
1514 
1515 //==========================================================================
1516 
1517 } // end namespace Pythia8
Definition: AgUStep.h:26