StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
DireMergingHooks.cc
1 // DireMergingHooks.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Stefan Prestel, Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for Dire merging classes.
7 
8 #include "Pythia8/PartonLevel.h"
9 #include "Pythia8/DireMergingHooks.h"
10 
11 namespace Pythia8 {
12 
13 //==========================================================================
14 
15 // The DireHardProcess class.
16 
17 //--------------------------------------------------------------------------
18 
19 // Declaration of hard process class
20 // This class holds information on the desired hard 2->2 process to be merged
21 // This class is a container class for History class use.
22 
23 // Initialisation on the process string
24 
25 void DireHardProcess::initOnProcess( string process,
26  ParticleData* particleData) {
27  state.init("(hard process)", particleData);
28  translateProcessString(process);
29 }
30 
31 //--------------------------------------------------------------------------
32 
33 // Function to translate a string specitying the core process into the
34 // internal notation
35 // Currently, the input string has to be in MadEvent notation
36 
37 void DireHardProcess::translateProcessString( string process){
38 
39  vector <int> incom;
40  vector <int> inter;
41  vector <int> outgo;
42  // Particle identifiers, ordered in such a way that e.g. the "u"
43  // in a mu is not mistaken for an u quark
44  int inParticleNumbers[] = {
45  // Leptons
46  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
47  // Jet container
48  2212,2212,0,0,0,0,
49  // Quarks
50  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6};
51  string inParticleNamesMG[] = {
52  // Leptons
53  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
54  // Jet container
55  "p~","p","l+","l-","vl~","vl",
56  // Quarks
57  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t"};
58 
59  // Declare intermediate particle identifiers
60  int interParticleNumbers[] = {
61  // Electroweak gauge bosons
62  22,23,-24,24,25,2400,
63  // All squarks
64  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
65  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
66  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006,
67  // Top quarks
68  -6,6,
69  // Dummy index as back-up
70  0};
71  // Declare names of intermediate particles
72  string interParticleNamesMG[] = {
73  // Electroweak gauge bosons
74  "a","z","w-","w+","h","W",
75  // All squarks
76  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
77  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2",
78  // Top quarks
79  "t~","t",
80  // Dummy index as back-up
81  "xx"};
82 
83  // Declare final state particle identifiers
84  int outParticleNumbers[] = {
85  // Leptons
86  -11,11,-12,12,-13,13,-14,14,-15,15,-16,16,
87  // Jet container and lepton containers
88  2212,2212,0,0,0,0,1200,1100,5000,
89  // Containers for inclusive handling for weak bosons and jets
90  10000022,10000023,10000024,10000025,10002212,
91  // All squarks
92  -1000001,1000001,-1000002,1000002,-1000003,1000003,-1000004,1000004,
93  -1000005,1000005,-1000006,1000006,-2000001,2000001,-2000002,2000002,
94  -2000003,2000003,-2000004,2000004,-2000005,2000005,-2000006,2000006,
95  // Quarks
96  -1,1,-2,2,-3,3,-4,4,-5,5,-6,6,
97  // SM uncoloured bosons
98  22,23,-24,24,25,2400,
99  // Neutralino in SUSY
100  1000022};
101  // Declare names of final state particles
102  string outParticleNamesMG[] = {
103  // Leptons
104  "e+","e-","ve~","ve","mu+","mu-","vm~","vm","ta+","ta-","vt~","vt",
105  // Jet container and lepton containers
106  "j~","j","l+","l-","vl~","vl","NEUTRINOS","LEPTONS","BQUARKS",
107  // Containers for inclusive handling for weak bosons and jets
108  "Ainc","Zinc","Winc", "Hinc", "Jinc",
109  // All squarks
110  "dl~","dl","ul~","ul","sl~","sl","cl~","cl","b1~","b1","t1~","t1",
111  "dr~","dr","ur~","ur","sr~","sr","cr~","cr","b2~","b2","t2~","t2",
112  // Quarks
113  "d~","d","u~","u","s~","s","c~","c","b~","b","t~","t",
114  // SM uncoloured bosons
115  "a","z","w-","w+","h","W",
116  // Neutralino in SUSY
117  "n1"};
118 
119  // Declare size of particle name arrays
120  int nIn = 30;
121  int nInt = 33;
122  int nOut = 69;
123 
124  // Start mapping user-defined particles onto particle ids.
125  string fullProc = process;
126 
127  // Find user-defined hard process content
128  // Count number of user particles
129  int nUserParticles = 0;
130  for(int n = fullProc.find("{", 0); n != int(string::npos);
131  n = fullProc.find("{", n)) {
132  nUserParticles++;
133  n++;
134  }
135  // Cut user-defined particles from remaining process
136  vector <string> userParticleStrings;
137  for(int i =0; i < nUserParticles;++i) {
138  int n = fullProc.find("{", 0);
139  userParticleStrings.push_back(fullProc.substr(0,n));
140  fullProc = fullProc.substr(n+1,fullProc.size());
141  }
142  // Cut remaining process string from rest
143  if (nUserParticles > 0)
144  userParticleStrings.push_back(
145  fullProc.substr( 0, fullProc.find("}",0) ) );
146  // Remove curly brackets and whitespace
147  for(int i =0; i < int(userParticleStrings.size());++i) {
148  while(userParticleStrings[i].find("{", 0) != string::npos)
149  userParticleStrings[i].erase(userParticleStrings[i].begin()
150  +userParticleStrings[i].find("{", 0));
151  while(userParticleStrings[i].find("}", 0) != string::npos)
152  userParticleStrings[i].erase(userParticleStrings[i].begin()
153  +userParticleStrings[i].find("}", 0));
154  while(userParticleStrings[i].find(" ", 0) != string::npos)
155  userParticleStrings[i].erase(userParticleStrings[i].begin()
156  +userParticleStrings[i].find(" ", 0));
157  }
158 
159  // Convert particle numbers in user particle to integers
160  vector<int>userParticleNumbers;
161  if ( int(userParticleStrings.size()) > 1) {
162  for( int i = 1; i < int(userParticleStrings.size()); ++i) {
163  userParticleNumbers.push_back(
164  atoi((char*)userParticleStrings[i].substr(
165  userParticleStrings[i].find(",",0)+1,
166  userParticleStrings[i].size()).c_str() ) );
167  }
168  }
169  // Save remaining process string
170  if (nUserParticles > 0)
171  userParticleStrings.push_back(
172  fullProc.substr(
173  fullProc.find("}",0)+1, fullProc.size() ) );
174  // Remove curly brackets and whitespace
175  for( int i = 0; i < int(userParticleStrings.size()); ++i) {
176  while(userParticleStrings[i].find("{", 0) != string::npos)
177  userParticleStrings[i].erase(userParticleStrings[i].begin()
178  +userParticleStrings[i].find("{", 0));
179  while(userParticleStrings[i].find("}", 0) != string::npos)
180  userParticleStrings[i].erase(userParticleStrings[i].begin()
181  +userParticleStrings[i].find("}", 0));
182  while(userParticleStrings[i].find(" ", 0) != string::npos)
183  userParticleStrings[i].erase(userParticleStrings[i].begin()
184  +userParticleStrings[i].find(" ", 0));
185  }
186 
187  // Start mapping residual process string onto particle IDs.
188  // Declare leftover process after user-defined particles have been converted
189  string residualProc;
190  if ( int(userParticleStrings.size()) > 1 )
191  residualProc = userParticleStrings.front() + userParticleStrings.back();
192  else
193  residualProc = fullProc;
194 
195  // Remove comma separation
196  while(residualProc.find(",", 0) != string::npos)
197  residualProc.erase(residualProc.begin()+residualProc.find(",",0));
198 
199  // Count number of resonances
200  int appearances = 0;
201  for(int n = residualProc.find("(", 0); n != int(string::npos);
202  n = residualProc.find("(", n)) {
203  appearances++;
204  n++;
205  }
206 
207  // Cut string in incoming, resonance+decay and outgoing pieces
208  vector <string> pieces;
209  for(int i =0; i < appearances;++i) {
210  int n = residualProc.find("(", 0);
211  pieces.push_back(residualProc.substr(0,n));
212  residualProc = residualProc.substr(n+1,residualProc.size());
213  }
214  // Cut last resonance from rest
215  if (appearances > 0) {
216  pieces.push_back( residualProc.substr(0,residualProc.find(")",0)) );
217  pieces.push_back( residualProc.substr(
218  residualProc.find(")",0)+1, residualProc.size()) );
219  }
220 
221  // If the string was not cut into pieces, i.e. no resonance was
222  // required, cut string using '>' as delimiter
223  if (pieces.empty() ){
224  appearances = 0;
225  for(int n = residualProc.find(">", 0); n != int(string::npos);
226  n = residualProc.find(">", n)) {
227  appearances++;
228  n++;
229  }
230 
231  // Cut string in incoming and outgoing pieces
232  for(int i =0; i < appearances;++i) {
233  int n = residualProc.find(">", 0);
234  pieces.push_back(residualProc.substr(0,n));
235  residualProc = residualProc.substr(n+1,residualProc.size());
236  }
237 
238  if (appearances == 1) pieces.push_back(residualProc);
239  if (appearances > 1) {
240  pieces.push_back( residualProc.substr(0,residualProc.find(">",0)) );
241  pieces.push_back( residualProc.substr(
242  residualProc.find(">",0)+1, residualProc.size()) );
243  }
244  }
245 
246  // Get incoming particles
247  for(int i=0; i < nIn; ++i) {
248  for(int n = pieces[0].find(inParticleNamesMG[i], 0);
249  n != int(string::npos);
250  n = pieces[0].find(inParticleNamesMG[i], n)) {
251  incom.push_back(inParticleNumbers[i]);
252  pieces[0].erase(pieces[0].begin()+n,
253  pieces[0].begin()+n+inParticleNamesMG[i].size());
254  n=0;
255  }
256  }
257 
258  // Check intermediate resonances and decay products
259  for(int i =1; i < int(pieces.size()); ++i){
260  // Seperate strings into intermediate and outgoing, if not already done
261  int k = pieces[i].find(">", 0);
262 
263  string intermediate = (pieces[i].find(">", 0) != string::npos) ?
264  pieces[i].substr(0,k) : "";
265  string outgoing = (pieces[i].find(">", 0) != string::npos) ?
266  pieces[i].substr(k+1,pieces[i].size()) : pieces[i];
267 
268  // Get intermediate particles
269  for(int j=0; j < nInt; ++j) {
270  for(int n = intermediate.find(interParticleNamesMG[j], 0);
271  n != int(string::npos);
272  n = intermediate.find(interParticleNamesMG[j], n)) {
273  inter.push_back(interParticleNumbers[j]);
274  intermediate.erase(intermediate.begin()+n,
275  intermediate.begin()+n+interParticleNamesMG[j].size());
276  n=0;
277  }
278  }
279 
280  // Get outgoing particles
281  for(int j=0; j < nOut; ++j) {
282  for(int n = outgoing.find(outParticleNamesMG[j], 0);
283  n != int(string::npos);
284  n = outgoing.find(outParticleNamesMG[j], n)) {
285  outgo.push_back(outParticleNumbers[j]);
286  outgoing.erase(outgoing.begin()+n,
287  outgoing.begin()+n+outParticleNamesMG[j].size());
288  n=0;
289  }
290  }
291 
292  // For arbitrary or non-existing intermediate, remember zero for each
293  // two outgoing particles, without bosons.
294  if (inter.empty()) {
295 
296  // For final state bosons, bookkeep the final state boson as
297  // intermediate as well.
298  int nBosons = 0;
299  for(int l=0; l < int(outgo.size()); ++l)
300  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
301  nBosons++;
302 
303  int nZeros = (outgo.size() - nBosons)/2;
304  for(int l=0; l < nZeros; ++l)
305  inter.push_back(0);
306  }
307 
308  // For final state bosons, bookkeep the final state boson as
309  // intermediate as well.
310  for(int l=0; l < int(outgo.size()); ++l)
311  if ( (abs(outgo[l]) > 20 && abs(outgo[l]) <= 25) || outgo[l] == 2400)
312  inter.push_back(outgo[l]);
313 
314  }
315 
316  // Now store incoming, intermediate and outgoing
317  // Set intermediate tags
318  for(int i=0; i < int(inter.size()); ++i)
319  hardIntermediate.push_back(inter[i]);
320 
321  // Set the incoming particle tags
322  if (incom.size() != 2)
323  cout << "Only two incoming particles allowed" << endl;
324  else {
325  hardIncoming1 = incom[0];
326  hardIncoming2 = incom[1];
327  }
328 
329  // Now store final particle identifiers
330  // Start with user-defined particles.
331  for( int i = 0; i < int(userParticleNumbers.size()); ++i)
332  if (userParticleNumbers[i] > 0) {
333  hardOutgoing2.push_back( userParticleNumbers[i]);
334  hardIntermediate.push_back(0);
335  // For non-existing intermediate, remember zero.
336  } else if (userParticleNumbers[i] < 0) {
337  hardOutgoing1.push_back( userParticleNumbers[i]);
338  // For non-existing intermediate, remember zero.
339  hardIntermediate.push_back(0);
340  }
341 
342  // Push back particles / antiparticles
343  for(int i=0; i < int(outgo.size()); ++i)
344  if (outgo[i] > 0
345  && outgo[i] != 2212
346  && outgo[i] != 5000
347  && outgo[i] != 1100
348  && outgo[i] != 1200
349  && outgo[i] != 2400
350  && outgo[i] != 1000022
351  && outgo[i] < 10000000)
352  hardOutgoing2.push_back( outgo[i]);
353  else if (outgo[i] < 0)
354  hardOutgoing1.push_back( outgo[i]);
355 
356  // Save final state W-boson container as particle
357  for(int i=0; i < int(outgo.size()); ++i)
358  if ( outgo[i] == 2400)
359  hardOutgoing2.push_back( outgo[i]);
360 
361  // Push back jets, distribute evenly among particles / antiparticles
362  // Push back majorana particles, distribute evenly
363  int iNow = 0;
364  for(int i=0; i < int(outgo.size()); ++i)
365  if ( (outgo[i] == 2212
366  || outgo[i] == 5000
367  || outgo[i] == 1200
368  || outgo[i] == 1000022
369  || outgo[i] > 10000000)
370  && iNow%2 == 0 ){
371  hardOutgoing2.push_back( outgo[i]);
372  iNow++;
373  } else if ( (outgo[i] == 2212
374  || outgo[i] == 5000
375  || outgo[i] == 1100
376  || outgo[i] == 1000022
377  || outgo[i] > 10000000)
378  && iNow%2 == 1 ){
379  hardOutgoing1.push_back( outgo[i]);
380  iNow++;
381  }
382 
383  // Done
384 }
385 
386 //--------------------------------------------------------------------------
387 
388 // Function to check if the candidates stored in Pos1 and Pos2, together with
389 // a proposed candidate iPos are allowed.
390 
391 bool DireHardProcess::allowCandidates(int iPos, vector<int> Pos1,
392  vector<int> Pos2, const Event& event){
393 
394  bool allowed = true;
395 
396  // Find colour-partner of new candidate
397  int type = (event[iPos].col() > 0) ? 1 : (event[iPos].acol() > 0) ? -1 : 0;
398 
399  if (type == 0) return true;
400 
401  if (type == 1){
402  int col = event[iPos].col();
403  int iPartner = 0;
404  for(int i=0; i < int(event.size()); ++i)
405  if ( i != iPos
406  && (( event[i].isFinal() && event[i].acol() == col)
407  ||( event[i].status() == -21 && event[i].col() == col) ))
408  iPartner = i;
409 
410  vector<int> partners;
411  for(int i=0; i < int(event.size()); ++i)
412  for(int j=0; j < int(Pos1.size()); ++j)
413  if ( Pos1[j] != 0 && i != Pos1[j] && event[Pos1[j]].colType() != 0
414  && (( event[i].isFinal() && event[i].col() == event[Pos1[j]].acol())
415  ||( event[i].status() == -21
416  && event[i].acol() == event[Pos1[j]].acol()) ))
417  partners.push_back(i);
418 
419  // Never allow equal initial partners!
420  if (event[iPartner].status() == -21){
421  for(int i=0; i < int(partners.size()); ++i)
422  if ( partners[i] == iPartner)
423  allowed = false;
424  }
425 
426  } else {
427  int col = event[iPos].acol();
428  int iPartner = 0;
429  for(int i=0; i < int(event.size()); ++i)
430  if ( i != iPos
431  && (( event[i].isFinal() && event[i].col() == col)
432  ||(!event[i].isFinal() && event[i].acol() == col) ))
433  iPartner = i;
434 
435  vector<int> partners;
436  for(int i=0; i < int(event.size()); ++i)
437  for(int j=0; j < int(Pos2.size()); ++j)
438  if ( Pos2[j] != 0 && i != Pos2[j] && event[Pos2[j]].colType() != 0
439  && (( event[i].isFinal() && event[i].acol() == event[Pos2[j]].col())
440  ||( event[i].status() == -21
441  && event[i].col() == event[Pos2[j]].col()) ))
442  partners.push_back(i);
443 
444  // Never allow equal initial partners!
445  if (event[iPartner].status() == -21){
446  for(int i=0; i < int(partners.size()); ++i){
447  if ( partners[i] == iPartner)
448  allowed = false;
449  }
450  }
451 
452  }
453 
454  return allowed;
455 
456 }
457 
458 //--------------------------------------------------------------------------
459 
460 // Function to identify the hard subprocess in the current event
461 
462 void DireHardProcess::storeCandidates( const Event& event, string process){
463 
464  // Store the reference event
465  state.clear();
466  state = event;
467 
468  // Local copy of intermediate bosons
469  vector<int> intermediates;
470  for(int i =0; i < int(hardIntermediate.size());++i)
471  intermediates.push_back( hardIntermediate[i]);
472 
473  // Local copy of outpoing partons
474  vector<int> outgoing1;
475  for(int i =0; i < int(hardOutgoing1.size());++i)
476  outgoing1.push_back( hardOutgoing1[i]);
477  vector<int> outgoing2;
478  for(int i =0; i < int(hardOutgoing2.size());++i)
479  outgoing2.push_back( hardOutgoing2[i]);
480 
481  // Clear positions of intermediate and outgoing particles
482  PosIntermediate.resize(0);
483  PosOutgoing1.resize(0);
484  PosOutgoing2.resize(0);
485  for(int i =0; i < int(hardIntermediate.size());++i)
486  PosIntermediate.push_back(0);
487  for(int i =0; i < int(hardOutgoing1.size());++i)
488  PosOutgoing1.push_back(0);
489  for(int i =0; i < int(hardOutgoing2.size());++i)
490  PosOutgoing2.push_back(0);
491 
492  // For QCD dijet or e+e- > jets hard process, do not store any candidates,
493  // as to not discriminate clusterings
494  if ( process.compare("pp>jj") == 0
495  || process.compare("e+e->jj") == 0
496  || process.compare("e+e->(z>jj)") == 0 ){
497  for(int i =0; i < int(hardOutgoing1.size());++i)
498  PosOutgoing1[i] = 0;
499  for(int i =0; i < int(hardOutgoing2.size());++i)
500  PosOutgoing2[i] = 0;
501  // Done
502  return;
503  }
504 
505  // For inclusive merging, do not store any candidates,
506  // as to not discriminate clusterings
507  bool isInclusive = true;
508  for(int i =0; i < int(hardOutgoing1.size());++i)
509  if (hardOutgoing1[i] < 10000000) isInclusive = false;
510  for(int i =0; i < int(hardOutgoing2.size());++i)
511  if (hardOutgoing2[i] < 10000000) isInclusive = false;
512  if ( isInclusive ){
513  for(int i =0; i < int(hardOutgoing1.size());++i)
514  PosOutgoing1[i] = 0;
515  for(int i =0; i < int(hardOutgoing2.size());++i)
516  PosOutgoing2[i] = 0;
517  // Done
518  return;
519  }
520 
521  // Initialise vector of particles that were already identified as
522  // hard process particles
523  vector<int> iPosChecked;
524 
525  // If the hard process is specified only by containers, then add all
526  // particles matching with the containers to the hard process.
527  bool hasOnlyContainers = true;
528  for(int i =0; i < int(hardOutgoing1.size());++i)
529  if ( hardOutgoing1[i] != 1100
530  && hardOutgoing1[i] != 1200
531  && hardOutgoing1[i] != 5000)
532  hasOnlyContainers = false;
533  for(int i =0; i < int(hardOutgoing2.size());++i)
534  if ( hardOutgoing2[i] != 1100
535  && hardOutgoing2[i] != 1200
536  && hardOutgoing2[i] != 5000)
537  hasOnlyContainers = false;
538 
539  if (hasOnlyContainers){
540 
541  PosOutgoing1.resize(0);
542  PosOutgoing2.resize(0);
543 
544  // Try to find all unmatched hard process leptons.
545  // Loop through event to find outgoing lepton
546  for(int i=0; i < int(event.size()); ++i){
547 
548  // Skip non-final particles
549  if ( !event[i].isFinal() ) continue;
550 
551  // Skip all particles that have already been identified
552  bool skip = false;
553  for(int k=0; k < int(iPosChecked.size()); ++k){
554  if (i == iPosChecked[k])
555  skip = true;
556  }
557  if (skip) continue;
558 
559  for(int j=0; j < int(outgoing2.size()); ++j){
560 
561  // If the particle matches an outgoing neutrino, save it
562  if ( outgoing2[j] == 1100
563  && ( event[i].idAbs() == 11
564  || event[i].idAbs() == 13
565  || event[i].idAbs() == 15) ){
566  PosOutgoing2.push_back(i);
567  iPosChecked.push_back(i);
568  }
569 
570  // If the particle matches an outgoing lepton, save it
571  if ( outgoing2[j] == 1200
572  && ( event[i].idAbs() == 12
573  || event[i].idAbs() == 14
574  || event[i].idAbs() == 16) ){
575  PosOutgoing2.push_back(i);
576  iPosChecked.push_back(i);
577  }
578 
579  // If the particle matches an outgoing b-quark, save it
580  if ( outgoing2[j] == 5000 && event[i].idAbs() == 5 ){
581  PosOutgoing2.push_back(i);
582  iPosChecked.push_back(i);
583  }
584 
585  }
586 
587  // Skip all particles that have already been identified
588  skip = false;
589  for(int k=0; k < int(iPosChecked.size()); ++k){
590  if (i == iPosChecked[k])
591  skip = true;
592  }
593  if (skip) continue;
594 
595  for(int j=0; j < int(outgoing1.size()); ++j){
596 
597  // If the particle matches an outgoing neutrino, save it
598  if ( outgoing1[j] == 1100
599  && ( event[i].idAbs() == 11
600  || event[i].idAbs() == 13
601  || event[i].idAbs() == 15) ){
602  PosOutgoing1.push_back(i);
603  iPosChecked.push_back(i);
604  }
605 
606  // If the particle matches an outgoing lepton, save it
607  if ( outgoing1[j] == 1200
608  && ( event[i].idAbs() == 12
609  || event[i].idAbs() == 14
610  || event[i].idAbs() == 16) ){
611  PosOutgoing1.push_back(i);
612  iPosChecked.push_back(i);
613  }
614 
615  // If the particle matches an outgoing b-quark, save it
616  if ( outgoing1[j] == 5000 && event[i].idAbs() == 5 ){
617  PosOutgoing1.push_back(i);
618  iPosChecked.push_back(i);
619  }
620 
621  }
622  }
623 
624  // Done
625  return;
626  }
627 
628  // Now begin finding candidates when not only containers are used.
629 
630  // First try to find final state bosons
631  for(int i=0; i < int(intermediates.size()); ++i){
632 
633  // Do nothing if the intermediate boson is absent
634  if (intermediates[i] == 0) continue;
635 
636  // Do nothing if this boson does not match any final state boson
637  bool matchesFinalBoson = false;
638  for(int j =0; j< int(outgoing1.size()); ++j){
639  if ( intermediates[i] == outgoing1[j] )
640  matchesFinalBoson = true;
641  }
642  for(int j =0; j< int(outgoing2.size()); ++j){
643  if ( intermediates[i] == outgoing2[j] )
644  matchesFinalBoson = true;
645  }
646  if (!matchesFinalBoson) continue;
647 
648  // Loop through event
649  for(int j=0; j < int(event.size()); ++j) {
650 
651  // Skip all particles that have already been identified
652  bool skip = false;
653  for(int m=0; m < int(iPosChecked.size()); ++m)
654  if (j == iPosChecked[m]) skip = true;
655  if (skip) continue;
656 
657  // If the particle has a requested intermediate id, check if
658  // if is a final state boson
659  if ( (event[j].id() == intermediates[i])
660  ||(event[j].idAbs() == 24 && intermediates[i] == 2400) ) {
661 
662  PosIntermediate[i] = j;
663  intermediates[i] = 0;
664  // Be careful only to replace one index at a time!
665  bool indexSet = false;
666 
667  for(int k=0; k < int(outgoing1.size()); ++k) {
668  if (event[j].id() == outgoing1[k] && !indexSet){
669  PosOutgoing1[k] = j;
670  outgoing1[k] = 99;
671  indexSet = true;
672  }
673  }
674 
675  for(int k=0; k < int(outgoing2.size()); ++k) {
676  if (event[j].id() == outgoing2[k] && !indexSet){
677  PosOutgoing2[k] = j;
678  outgoing2[k] = 99;
679  indexSet = true;
680  }
681  }
682 
683  // Check for W-boson container
684  for(int k=0; k < int(outgoing2.size()); ++k) {
685  if (event[j].idAbs() == 24 && outgoing2[k] == 2400 && !indexSet ){
686  PosOutgoing2[k] = j;
687  outgoing2[k] = 99;
688  indexSet = true;
689  }
690  }
691 
692  iPosChecked.push_back(j);
693 
694  }
695  }
696  }
697 
698  // Second try to find particles coupled to intermediate bosons
699  for(int i=0; i < int(intermediates.size()); ++i){
700 
701  // Do nothing if the intermediate boson is absent
702  if (intermediates[i] == 0) continue;
703 
704  // Loop through event
705  for(int j=0; j < int(event.size()); ++j) {
706  // If the particle has a requested intermediate id, check if
707  // daughters are hard process particles
708  if ( (event[j].id() == intermediates[i])
709  ||(event[j].idAbs() == 24 && intermediates[i] == 2400) ) {
710  // If this particle is a potential intermediate
711  PosIntermediate[i] = j;
712  intermediates[i] = 0;
713  // If id's of daughters are good, store position
714  int iPos1 = event[j].daughter1();
715  int iPos2 = event[j].daughter2();
716 
717  // Loop through daughters to check if these contain some hard
718  // outgoing particles
719  for( int k=iPos1; k <= iPos2; ++k){
720  int id = event[k].id();
721 
722  // Skip all particles that have already been identified
723  bool skip = false;
724  for(int m=0; m < int(iPosChecked.size()); ++m)
725  if (k == iPosChecked[m]) skip = true;
726  if (skip) continue;
727 
728  // Check if daughter is hard outgoing particle
729  for(int l=0; l < int(outgoing2.size()); ++l)
730  if ( outgoing2[l] != 99 ){
731  // Found particle id
732  if (id == outgoing2[l]
733  // Found jet
734  || (id > 0 && abs(id) < 10 && outgoing2[l] == 2212) ){
735  // Store position
736  PosOutgoing2[l] = k;
737  // Remove the matched particle from the list
738  outgoing2[l] = 99;
739  iPosChecked.push_back(k);
740  break;
741  }
742 
743  }
744 
745  // Check if daughter is hard outgoing antiparticle
746  for(int l=0; l < int(outgoing1.size()); ++l)
747  if ( outgoing1[l] != 99 ){
748  // Found particle id
749  if (id == outgoing1[l]
750  // Found jet
751  || (id < 0 && abs(id) < 10 && outgoing1[l] == 2212) ){
752  // Store position
753  PosOutgoing1[l] = k;
754  // Remove the matched particle from the list
755  outgoing1[l] = 99;
756  iPosChecked.push_back(k);
757  break;
758  }
759 
760  }
761 
762  } // End loop through daughters
763  } // End if ids match
764  } // End loop through event
765  } // End loop though requested intermediates
766 
767  // If all outgoing particles were found, done
768  bool done = true;
769  for(int i=0; i < int(outgoing1.size()); ++i)
770  if (outgoing1[i] != 99)
771  done = false;
772  for(int i=0; i < int(outgoing2.size()); ++i)
773  if (outgoing2[i] != 99)
774  done = false;
775  // Return
776  if (done) return;
777 
778  // Leptons not associated with resonance are allowed.
779  // Try to find all unmatched hard process leptons.
780  // Loop through event to find outgoing lepton
781  for(int i=0; i < int(event.size()); ++i){
782  // Skip non-final particles and final partons
783  if ( !event[i].isFinal() || event[i].colType() != 0)
784  continue;
785  // Skip all particles that have already been identified
786  bool skip = false;
787  for(int k=0; k < int(iPosChecked.size()); ++k){
788  if (i == iPosChecked[k])
789  skip = true;
790  }
791  if (skip) continue;
792 
793  // Check if any hard outgoing leptons remain
794  for(int j=0; j < int(outgoing2.size()); ++j){
795  // Do nothing if this particle has already be found,
796  // or if this particle is a jet or quark
797  if ( outgoing2[j] == 99
798  || outgoing2[j] == 2212
799  || abs(outgoing2[j]) < 10)
800  continue;
801 
802  // If the particle matches an outgoing lepton, save it
803  if ( event[i].id() == outgoing2[j] ){
804  PosOutgoing2[j] = i;
805  outgoing2[j] = 99;
806  iPosChecked.push_back(i);
807  }
808  }
809 
810  // Check if any hard outgoing antileptons remain
811  for(int j=0; j < int(outgoing1.size()); ++j){
812  // Do nothing if this particle has already be found,
813  // or if this particle is a jet or quark
814  if ( outgoing1[j] == 99
815  || outgoing1[j] == 2212
816  || abs(outgoing1[j]) < 10)
817  continue;
818 
819  // If the particle matches an outgoing lepton, save it
820  if (event[i].id() == outgoing1[j] ){
821  PosOutgoing1[j] = i;
822  outgoing1[j] = 99;
823  iPosChecked.push_back(i);
824  }
825  }
826  }
827 
828  multimap<int,int> out2copy;
829  for(int i=0; i < int(event.size()); ++i)
830  for(int j=0; j < int(outgoing2.size()); ++j)
831  // Do nothing if this particle has already be found,
832  // or if this particle is a jet.
833  if ( outgoing2[j] != 99
834  && outgoing2[j] != 2212
835  && ( abs(outgoing2[j]) < 10
836  || (abs(outgoing2[j]) > 1000000 && abs(outgoing2[j]) < 1000010)
837  || (abs(outgoing2[j]) > 2000000 && abs(outgoing2[j]) < 2000010)
838  || abs(outgoing2[j]) == 1000021 )
839  && event[i].isFinal()
840  && event[i].id() == outgoing2[j] ){
841  out2copy.insert(make_pair(j, i));
842  }
843 
844  multimap<int,int> out1copy;
845  for(int i=0; i < int(event.size()); ++i)
846  for(int j=0; j < int(outgoing1.size()); ++j)
847  // Do nothing if this particle has already be found,
848  // or if this particle is a jet.
849  if ( outgoing1[j] != 99
850  && outgoing1[j] != 2212
851  && ( abs(outgoing1[j]) < 10
852  || (abs(outgoing1[j]) > 1000000 && abs(outgoing1[j]) < 1000010)
853  || (abs(outgoing1[j]) > 2000000 && abs(outgoing1[j]) < 2000010)
854  || abs(outgoing1[j]) == 1000021 )
855  && event[i].isFinal()
856  && event[i].id() == outgoing1[j] ){
857  out1copy.insert(make_pair(j, i));
858  }
859 
860  if ( out1copy.size() > out2copy.size()){
861 
862  // In case the index of the multimap is filled twice, make sure not to
863  // arbitrarily overwrite set values.
864  vector<int> indexWasSet;
865  for ( multimap<int, int>::iterator it = out2copy.begin();
866  it != out2copy.end(); ++it ) {
867  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
868 
869  // Skip all particles that have already been identified
870  bool skip = false;
871  for(int k=0; k < int(iPosChecked.size()); ++k)
872  if (it->second == iPosChecked[k]) skip = true;
873  // Skip all indices that have already been identified
874  for(int k=0; k < int(indexWasSet.size()); ++k)
875  if (it->first == indexWasSet[k]) skip = true;
876  if (skip) continue;
877 
878  // Save parton
879  PosOutgoing2[it->first] = it->second;
880  // remove entry form lists
881  outgoing2[it->first] = 99;
882  iPosChecked.push_back(it->second);
883  indexWasSet.push_back(it->first);
884  }
885  }
886 
887  indexWasSet.resize(0);
888  for ( multimap<int, int>::iterator it = out1copy.begin();
889  it != out1copy.end(); ++it ) {
890  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
891 
892  // Skip all particles that have already been identified
893  bool skip = false;
894  for(int k=0; k < int(iPosChecked.size()); ++k)
895  if (it->second == iPosChecked[k]) skip = true;
896  // Skip all indices that have already been identified
897  for(int k=0; k < int(indexWasSet.size()); ++k)
898  if (it->first == indexWasSet[k]) skip = true;
899  if (skip) continue;
900 
901  // Save parton
902  PosOutgoing1[it->first] = it->second;
903  // remove entry form lists
904  outgoing1[it->first] = 99;
905  iPosChecked.push_back(it->second);
906  indexWasSet.push_back(it->first);
907  }
908  }
909 
910  } else {
911 
912  // In case the index of the multimap is filled twice, make sure not to
913  // arbitraryly overwrite set values.
914  vector<int> indexWasSet;
915  for ( multimap<int, int>::iterator it = out1copy.begin();
916  it != out1copy.end(); ++it ) {
917  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
918 
919  // Skip all particles that have already been identified
920  bool skip = false;
921  for(int k=0; k < int(iPosChecked.size()); ++k)
922  if (it->second == iPosChecked[k]) skip = true;
923  // Skip all indices that have already been identified
924  for(int k=0; k < int(indexWasSet.size()); ++k)
925  if (it->first == indexWasSet[k]) skip = true;
926  if (skip) continue;
927 
928  // Save parton
929  PosOutgoing1[it->first] = it->second;
930  // remove entry form lists
931  outgoing1[it->first] = 99;
932  iPosChecked.push_back(it->second);
933  indexWasSet.push_back(it->first);
934  }
935  }
936 
937  indexWasSet.resize(0);
938  for ( multimap<int, int>::iterator it = out2copy.begin();
939  it != out2copy.end(); ++it ) {
940  if ( allowCandidates(it->second, PosOutgoing1, PosOutgoing2, event) ){
941 
942  // Skip all particles that have already been identified
943  bool skip = false;
944  for(int k=0; k < int(iPosChecked.size()); ++k)
945  if (it->second == iPosChecked[k]) skip = true;
946  // Skip all indices that have already been identified
947  for(int k=0; k < int(indexWasSet.size()); ++k)
948  if (it->first == indexWasSet[k]) skip = true;
949  if (skip) continue;
950 
951  // Save parton
952  PosOutgoing2[it->first] = it->second;
953  // remove entry form lists
954  outgoing2[it->first] = 99;
955  iPosChecked.push_back(it->second);
956  indexWasSet.push_back(it->first);
957  }
958  }
959  }
960 
961  // It sometimes happens that MadEvent does not put a
962  // heavy coloured resonance into the LHE file, even if requested.
963  // This means that the decay products of this resonance need to be
964  // found separately.
965  // Loop through event to find hard process (anti)quarks
966  for(int i=0; i < int(event.size()); ++i){
967 
968  // Skip non-final particles and final partons
969  if ( !event[i].isFinal() || event[i].colType() == 0)
970  continue;
971 
972  // Skip all particles that have already been identified
973  bool skip = false;
974  for(int k=0; k < int(iPosChecked.size()); ++k){
975  if (i == iPosChecked[k])
976  skip = true;
977  }
978  if (skip) continue;
979 
980  // Check if any hard outgoing quarks remain
981  for(int j=0; j < int(outgoing2.size()); ++j){
982  // Do nothing if this particle has already be found,
983  // or if this particle is a jet, lepton container or lepton
984 
985  if ( outgoing2[j] == 99
986  || outgoing2[j] == 2212
987  || (abs(outgoing2[j]) > 10 && abs(outgoing2[j]) < 20)
988  || outgoing2[j] == 1100
989  || outgoing2[j] == 1200
990  || outgoing2[j] == 2400 )
991  continue;
992 
993  // If the particle matches an outgoing quark, save it
994  if (event[i].id() == outgoing2[j]){
995  // Save parton
996  PosOutgoing2[j] = i;
997  // remove entry form lists
998  outgoing2[j] = 99;
999  iPosChecked.push_back(i);
1000  break;
1001  }
1002  }
1003 
1004  // Check if any hard outgoing antiquarks remain
1005  for(int j=0; j < int(outgoing1.size()); ++j){
1006  // Do nothing if this particle has already be found,
1007  // or if this particle is a jet, lepton container or lepton
1008  if ( outgoing1[j] == 99
1009  || outgoing1[j] == 2212
1010  || (abs(outgoing1[j]) > 10 && abs(outgoing1[j]) < 20)
1011  || outgoing1[j] == 1100
1012  || outgoing1[j] == 1200
1013  || outgoing1[j] == 2400 )
1014  continue;
1015  // If the particle matches an outgoing antiquark, save it
1016  if (event[i].id() == outgoing1[j]){
1017  // Save parton
1018  PosOutgoing1[j] = i;
1019  // Remove parton from list
1020  outgoing1[j] = 99;
1021  iPosChecked.push_back(i);
1022  break;
1023  }
1024  }
1025  }
1026 
1027  // Done
1028 }
1029 
1030 //--------------------------------------------------------------------------
1031 
1032 // Function to check if the particle event[iPos] matches any of
1033 // the stored outgoing particles of the hard subprocess
1034 
1035 bool DireHardProcess::matchesAnyOutgoing(int iPos, const Event& event){
1036 
1037  // Match quantum numbers of any first outgoing candidate
1038  bool matchQN1 = false;
1039  // Match quantum numbers of any second outgoing candidate
1040  bool matchQN2 = false;
1041  // Match parton in the hard process,
1042  // or parton from decay of electroweak boson in hard process,
1043  // or parton from decay of electroweak boson from decay of top
1044  bool matchHP = false;
1045 
1046  // Check outgoing candidates
1047  for(int i=0; i < int(PosOutgoing1.size()); ++i)
1048  // Compare particle properties
1049  if ( event[iPos].id() == state[PosOutgoing1[i]].id()
1050  && event[iPos].colType() == state[PosOutgoing1[i]].colType()
1051  && event[iPos].chargeType() == state[PosOutgoing1[i]].chargeType()
1052  && ( ( event[iPos].col() > 0
1053  && event[iPos].col() == state[PosOutgoing1[i]].col())
1054  || ( event[iPos].acol() > 0
1055  && event[iPos].acol() == state[PosOutgoing1[i]].acol()))
1056  && event[iPos].charge() == state[PosOutgoing1[i]].charge() )
1057  matchQN1 = true;
1058 
1059  // Check outgoing candidates
1060  for(int i=0; i < int(PosOutgoing2.size()); ++i)
1061  // Compare particle properties
1062  if ( event[iPos].id() == state[PosOutgoing2[i]].id()
1063  && event[iPos].colType() == state[PosOutgoing2[i]].colType()
1064  && event[iPos].chargeType() == state[PosOutgoing2[i]].chargeType()
1065  && ( ( event[iPos].col() > 0
1066  && event[iPos].col() == state[PosOutgoing2[i]].col())
1067  || ( event[iPos].acol() > 0
1068  && event[iPos].acol() == state[PosOutgoing2[i]].acol()))
1069  && event[iPos].charge() == state[PosOutgoing2[i]].charge() )
1070  matchQN2 = true;
1071 
1072  // Check if maps to hard process:
1073  // Check that particle is in hard process
1074  if ( event[iPos].mother1()*event[iPos].mother2() == 12
1075  // Or particle has taken recoil from first splitting
1076  || ( event[iPos].status() == 44
1077  && event[event[iPos].mother1()].mother1()
1078  *event[event[iPos].mother1()].mother2() == 12 )
1079  || ( event[iPos].status() == 48
1080  && event[event[iPos].mother1()].mother1()
1081  *event[event[iPos].mother1()].mother2() == 12 )
1082  // Or particle has on-shell resonace as mother
1083  || ( event[iPos].status() == 23
1084  && event[event[iPos].mother1()].mother1()
1085  *event[event[iPos].mother1()].mother2() == 12 )
1086  // Or particle has on-shell resonace as mother,
1087  // which again has and on-shell resonance as mother
1088  || ( event[iPos].status() == 23
1089  && event[event[iPos].mother1()].status() == -22
1090  && event[event[event[iPos].mother1()].mother1()].status() == -22
1091  && event[event[event[iPos].mother1()].mother1()].mother1()
1092  *event[event[event[iPos].mother1()].mother1()].mother2() == 12 ) )
1093  matchHP = true;
1094 
1095  // Done
1096  return ( matchHP && (matchQN1 || matchQN2) );
1097 
1098 }
1099 
1100 
1101 //--------------------------------------------------------------------------
1102 
1103 // Function to check if instead of the particle event[iCandidate], another
1104 // particle could serve as part of the hard process. Assumes that iCandidate
1105 // is already stored as part of the hard process.
1106 
1107 bool DireHardProcess::findOtherCandidates(int iPos, const Event& event,
1108  bool doReplace){
1109 
1110  // Return value
1111  bool foundCopy = false;
1112 
1113  // Save stored candidates' properties.
1114  int id = event[iPos].id();
1115  int col = event[iPos].col();
1116  int acl = event[iPos].acol();
1117 
1118  // If the particle's mother is an identified intermediate resonance,
1119  // then do not attempt any replacement.
1120  int iMoth1 = event[iPos].mother1();
1121  int iMoth2 = event[iPos].mother2();
1122  if ( iMoth1 > 0 && iMoth2 == 0 ) {
1123  bool hasIdentifiedMother = false;
1124  for(int i=0; i < int(PosIntermediate.size()); ++i)
1125  // Compare particle properties
1126  if ( event[iMoth1].id() == state[PosIntermediate[i]].id()
1127  && event[iMoth1].colType() == state[PosIntermediate[i]].colType()
1128  && event[iMoth1].chargeType() == state[PosIntermediate[i]].chargeType()
1129  && event[iMoth1].col() == state[PosIntermediate[i]].col()
1130  && event[iMoth1].acol() == state[PosIntermediate[i]].acol()
1131  && event[iMoth1].charge() == state[PosIntermediate[i]].charge() )
1132  hasIdentifiedMother = true;
1133  if(hasIdentifiedMother && event[iMoth1].id() != id) return false;
1134  }
1135 
1136  // Find candidate amongst the already stored ME process candidates.
1137  vector<int> candidates1;
1138  vector<int> candidates2;
1139  // Check outgoing candidates
1140  for(int i=0; i < int(PosOutgoing1.size()); ++i)
1141  // Compare particle properties
1142  if ( id == state[PosOutgoing1[i]].id()
1143  && col == state[PosOutgoing1[i]].col()
1144  && acl == state[PosOutgoing1[i]].acol() )
1145  candidates1.push_back(i);
1146  // Check outgoing candidates
1147  for(int i=0; i < int(PosOutgoing2.size()); ++i)
1148  // Compare particle properties
1149  if ( id == state[PosOutgoing2[i]].id()
1150  && col == state[PosOutgoing2[i]].col()
1151  && acl == state[PosOutgoing2[i]].acol() )
1152  candidates2.push_back(i);
1153 
1154  // If more / less than one stored candidate for iPos has been found, exit.
1155  if ( candidates1.size() + candidates2.size() != 1 ) return false;
1156 
1157  // Now check for other allowed candidates.
1158  unordered_map<int,int> further1;
1159  for(int i=0; i < int(state.size()); ++i)
1160  for(int j=0; j < int(PosOutgoing1.size()); ++j)
1161  // Do nothing if this particle has already be found,
1162  // or if this particle is a jet, lepton container or lepton
1163  if ( state[i].isFinal()
1164  && i != PosOutgoing1[j]
1165  && state[PosOutgoing1[j]].id() == id
1166  && state[i].id() == id ){
1167  // Declare vector of already existing candiates.
1168  vector<int> newPosOutgoing1;
1169  for(int k=0; k < int(PosOutgoing1.size()); ++k)
1170  if ( k != j ) newPosOutgoing1.push_back( PosOutgoing1[k] );
1171  // If allowed, remember replacment parton.
1172  if ( allowCandidates(i, newPosOutgoing1, PosOutgoing2, state) )
1173  further1.insert(make_pair(j, i));
1174  }
1175 
1176  // Now check for other allowed candidates.
1177  unordered_map<int,int> further2;
1178  for(int i=0; i < int(state.size()); ++i)
1179  for(int j=0; j < int(PosOutgoing2.size()); ++j)
1180  // Do nothing if this particle has already be found,
1181  // or if this particle is a jet, lepton container or lepton
1182  if ( state[i].isFinal()
1183  && i != PosOutgoing2[j]
1184  && state[PosOutgoing2[j]].id() == id
1185  && state[i].id() == id ){
1186  // Declare vector of already existing candidates.
1187  vector<int> newPosOutgoing2;
1188  for(int k=0; k < int(PosOutgoing2.size()); ++k)
1189  if ( k != j ) newPosOutgoing2.push_back( PosOutgoing2[k] );
1190  // If allowed, remember replacment parton.
1191  if ( allowCandidates(i, PosOutgoing1, newPosOutgoing2, state) )
1192  further2.insert(make_pair(j, i));
1193  }
1194 
1195  // Remove all hard process particles that would be counted twice.
1196  unordered_map<int,int>::iterator it2 = further2.begin();
1197  while(it2 != further2.end()) {
1198  bool remove = false;
1199  for(int j=0; j < int(PosOutgoing2.size()); ++j)
1200  if (it2->second == PosOutgoing2[j] ) remove = true;
1201  if ( remove ) further2.erase(it2++);
1202  else ++it2;
1203  }
1204  unordered_map<int,int>::iterator it1 = further1.begin();
1205  while(it1 != further1.end()) {
1206  bool remove = false;
1207  for(int j=0; j < int(PosOutgoing1.size()); ++j)
1208  if (it1->second == PosOutgoing1[j] ) remove = true;
1209  if ( remove ) further1.erase(it1++);
1210  else ++it1;
1211  }
1212 
1213  // Decide of a replacment candidate has been found.
1214  foundCopy = (doReplace)
1215  ? exchangeCandidates(candidates1, candidates2, further1, further2)
1216  : (further1.size() + further2.size() > 0);
1217 
1218  // Done
1219  return foundCopy;
1220 
1221 }
1222 
1223 //--------------------------------------------------------------------------
1224 
1225 // Function to exchange hard process candidates.
1226 
1227 bool DireHardProcess::exchangeCandidates( vector<int> candidates1,
1228  vector<int> candidates2, unordered_map<int,int> further1,
1229  unordered_map<int,int> further2) {
1230 
1231  int nOld1 = candidates1.size();
1232  int nOld2 = candidates2.size();
1233  int nNew1 = further1.size();
1234  int nNew2 = further2.size();
1235  bool exchanged = false;
1236  // Replace, if one-to-one correspondence exists.
1237  if ( nOld1 == 1 && nOld2 == 0 && nNew1 == 1 && nNew2 == 0){
1238  PosOutgoing1[further1.begin()->first] = further1.begin()->second;
1239  exchanged = true;
1240  } else if ( nOld1 == 0 && nOld2 == 1 && nNew1 == 0 && nNew2 == 1){
1241  PosOutgoing2[further2.begin()->first] = further2.begin()->second;
1242  exchanged = true;
1243  // Else simply swap with the first candidate.
1244  } else if ( nNew1 > 1 && nNew2 == 0 ) {
1245  PosOutgoing1[further1.begin()->first] = further1.begin()->second;
1246  exchanged = true;
1247  } else if ( nNew1 == 0 && nNew2 > 0 ) {
1248  PosOutgoing2[further2.begin()->first] = further2.begin()->second;
1249  exchanged = true;
1250  }
1251 
1252  // Done
1253  return exchanged;
1254 
1255 }
1256 
1257 //==========================================================================
1258 
1259 // The DireMergingHooks class.
1260 
1261 //--------------------------------------------------------------------------
1262 
1263 // Initialise DireMergingHooks class
1264 
1265 void DireMergingHooks::init(){
1266 
1267  // Abuse init to store and restore state of MergingHooks.
1268  if (isInit) { store(); isInit = false; isStored = true; return;}
1269  if (isStored) { restore(); isInit = true; isStored = false; return;}
1270 
1271  isInit = isStored = false;
1272 
1273  // Get core process from user input. Return if no process was selected.
1274  processSave = settingsPtr->word("Merging:Process");
1275  if (processSave == "void") return;
1276 
1277  // Save pointers
1278  showers = 0;
1279 
1280  // Initialise AlphaS objects for reweighting
1281  double alphaSvalueFSR = settingsPtr->parm("TimeShower:alphaSvalue");
1282  int alphaSorderFSR = settingsPtr->mode("TimeShower:alphaSorder");
1283  int alphaSnfmax = settingsPtr->mode("StandardModel:alphaSnfmax");
1284  int alphaSuseCMWFSR= settingsPtr->flag("TimeShower:alphaSuseCMW");
1285  AlphaS_FSRSave.init(alphaSvalueFSR, alphaSorderFSR, alphaSnfmax,
1286  alphaSuseCMWFSR);
1287  double alphaSvalueISR = settingsPtr->parm("SpaceShower:alphaSvalue");
1288  int alphaSorderISR = settingsPtr->mode("SpaceShower:alphaSorder");
1289  int alphaSuseCMWISR= settingsPtr->flag("SpaceShower:alphaSuseCMW");
1290  AlphaS_ISRSave.init(alphaSvalueISR, alphaSorderISR, alphaSnfmax,
1291  alphaSuseCMWISR);
1292 
1293  // Initialise AlphaEM objects for reweighting
1294  int alphaEMFSRorder = settingsPtr->mode("TimeShower:alphaEMorder");
1295  AlphaEM_FSRSave.init(alphaEMFSRorder, settingsPtr);
1296  int alphaEMISRorder = settingsPtr->mode("SpaceShower:alphaEMorder");
1297  AlphaEM_ISRSave.init(alphaEMISRorder, settingsPtr);
1298 
1299  // Initialise merging switches
1300  doUserMergingSave = settingsPtr->flag("Merging:doUserMerging");
1301  // Initialise automated MadGraph kT merging
1302  doMGMergingSave = settingsPtr->flag("Merging:doMGMerging");
1303  // Initialise kT merging
1304  doKTMergingSave = settingsPtr->flag("Merging:doKTMerging");
1305  // Initialise evolution-pT merging
1306  doPTLundMergingSave = settingsPtr->flag("Merging:doPTLundMerging");
1307  // Initialise \Delta_R_{ij}, pT_i Q_{ij} merging
1308  doCutBasedMergingSave = settingsPtr->flag("Merging:doCutBasedMerging");
1309  // Initialise exact definition of kT
1310  ktTypeSave = settingsPtr->mode("Merging:ktType");
1311 
1312  // Initialise NL3 switches.
1313  doNL3TreeSave = settingsPtr->flag("Merging:doNL3Tree");
1314  doNL3LoopSave = settingsPtr->flag("Merging:doNL3Loop");
1315  doNL3SubtSave = settingsPtr->flag("Merging:doNL3Subt");
1316  bool doNL3 = doNL3TreeSave || doNL3LoopSave || doNL3SubtSave;
1317 
1318  // Initialise UNLOPS switches.
1319  doUNLOPSTreeSave = settingsPtr->flag("Merging:doUNLOPSTree");
1320  doUNLOPSLoopSave = settingsPtr->flag("Merging:doUNLOPSLoop");
1321  doUNLOPSSubtSave = settingsPtr->flag("Merging:doUNLOPSSubt");
1322  doUNLOPSSubtNLOSave = settingsPtr->flag("Merging:doUNLOPSSubtNLO");
1323  bool doUNLOPS = doUNLOPSTreeSave || doUNLOPSLoopSave
1324  || doUNLOPSSubtSave || doUNLOPSSubtNLOSave;
1325 
1326  // Initialise UMEPS switches
1327  doUMEPSTreeSave = settingsPtr->flag("Merging:doUMEPSTree");
1328  doUMEPSSubtSave = settingsPtr->flag("Merging:doUMEPSSubt");
1329  nReclusterSave = settingsPtr->mode("Merging:nRecluster");
1330  nQuarksMergeSave = settingsPtr->mode("Merging:nQuarksMerge");
1331  nRequestedSave = settingsPtr->mode("Merging:nRequested");
1332  bool doUMEPS = doUMEPSTreeSave || doUMEPSSubtSave;
1333 
1334  // Flag to only do phase space cut.
1335  doEstimateXSection = settingsPtr->flag("Merging:doXSectionEstimate");
1336 
1337  doMOPSSave = settingsPtr->flag("Dire:doMOPS");
1338  doMEMSave = settingsPtr->flag("Dire:doMEM");
1339 
1340  // Flag to check if merging weight should directly be included in the cross
1341  // section.
1342  includeWGTinXSECSave = settingsPtr->flag("Merging:includeWeightInXsection");
1343 
1344  // Flag to check if CKKW-L event veto should be applied.
1345  applyVeto = settingsPtr->flag("Merging:applyVeto");
1346 
1347  // Clear hard process
1348  hardProcess->clear();
1349 
1350  // Initialise input event.
1351  inputEvent.init("(hard process)", particleDataPtr);
1352 
1353  doRemoveDecayProducts = settingsPtr->flag("Merging:mayRemoveDecayProducts");
1354 
1355  // Initialise the hard process
1356  if ( doMGMergingSave )
1357  hardProcess->initOnLHEF(lheInputFile, particleDataPtr);
1358  else
1359  hardProcess->initOnProcess(processSave, particleDataPtr);
1360 
1361  // Parameters for reconstruction of evolution scales
1362  includeMassiveSave = settingsPtr->flag("Merging:includeMassive");
1363  enforceStrongOrderingSave = settingsPtr->flag
1364  ("Merging:enforceStrongOrdering");
1365  scaleSeparationFactorSave = settingsPtr->parm
1366  ("Merging:scaleSeparationFactor");
1367  orderInRapiditySave = settingsPtr->flag("Merging:orderInRapidity");
1368 
1369  // Parameters for choosing history probabilistically
1370  nonJoinedNormSave = settingsPtr->parm("Merging:nonJoinedNorm");
1371  fsrInRecNormSave = settingsPtr->parm("Merging:fsrInRecNorm");
1372  pickByFullPSave = settingsPtr->flag("Merging:pickByFullP");
1373  pickByPoPT2Save = settingsPtr->flag("Merging:pickByPoPT2");
1374  includeRedundantSave = settingsPtr->flag("Merging:includeRedundant");
1375 
1376  // Parameters for scale choices
1377  unorderedScalePrescipSave =
1378  settingsPtr->mode("Merging:unorderedScalePrescrip");
1379  unorderedASscalePrescipSave =
1380  settingsPtr->mode("Merging:unorderedASscalePrescrip");
1381  unorderedPDFscalePrescipSave =
1382  settingsPtr->mode("Merging:unorderedPDFscalePrescrip");
1383  incompleteScalePrescipSave =
1384  settingsPtr->mode("Merging:incompleteScalePrescrip");
1385 
1386  // Parameter for allowing swapping of one colour index while reclustering
1387  allowColourShufflingSave =
1388  settingsPtr->flag("Merging:allowColourShuffling");
1389 
1390  // Parameters to allow setting hard process scales to default (dynamical)
1391  // Pythia values.
1392  resetHardQRenSave = settingsPtr->flag("Merging:usePythiaQRenHard");
1393  resetHardQFacSave = settingsPtr->flag("Merging:usePythiaQFacHard");
1394 
1395  // Parameters for choosing history by sum(|pT|)
1396  pickBySumPTSave = settingsPtr->flag("Merging:pickBySumPT");
1397  herwigAcollFSRSave = settingsPtr->parm("Merging:aCollFSR");
1398  herwigAcollISRSave = settingsPtr->parm("Merging:aCollISR");
1399 
1400  // Information on the shower cut-off scale
1401  pT0ISRSave = settingsPtr->parm("SpaceShower:pT0Ref");
1402  pTcutSave = settingsPtr->parm("SpaceShower:pTmin");
1403  pTcutSave = max(pTcutSave,pT0ISRSave);
1404 
1405  // Initialise CKKWL weight
1406  weightCKKWLSave = {1.};
1407  weightFIRSTSave = {0.};
1408  nMinMPISave = 100;
1409  muMISave = -1.;
1410 
1411  // Initialise merging scale
1412  tmsValueSave = 0.;
1413  tmsListSave.resize(0);
1414 
1415  kFactor0jSave = settingsPtr->parm("Merging:kFactor0j");
1416  kFactor1jSave = settingsPtr->parm("Merging:kFactor1j");
1417  kFactor2jSave = settingsPtr->parm("Merging:kFactor2j");
1418 
1419  muFSave = settingsPtr->parm("Merging:muFac");
1420  muRSave = settingsPtr->parm("Merging:muRen");
1421  muFinMESave = settingsPtr->parm("Merging:muFacInME");
1422  muRinMESave = settingsPtr->parm("Merging:muRenInME");
1423 
1424  doWeakClusteringSave = settingsPtr->flag("Merging:allowWeakClustering");
1425  doSQCDClusteringSave = settingsPtr->flag("Merging:allowSQCDClustering");
1426  DparameterSave = settingsPtr->parm("Merging:Dparameter");
1427 
1428  // Save merging scale on maximal number of jets
1429  if ( doKTMergingSave || doUserMergingSave || doPTLundMergingSave
1430  || doUMEPS ) {
1431  // Read merging scale (defined in kT) from input parameter.
1432  tmsValueSave = settingsPtr->parm("Merging:TMS");
1433  nJetMaxSave = settingsPtr->mode("Merging:nJetMax");
1434  nJetMaxNLOSave = -1;
1435  } else if (doMGMergingSave) {
1436  // Read merging scale (defined in kT) from LHE file.
1437  tmsValueSave = hardProcess->tms;
1438  nJetMaxSave = settingsPtr->mode("Merging:nJetMax");
1439  nJetMaxNLOSave = -1;
1440  } else if (doCutBasedMergingSave) {
1441 
1442  // Save list of cuts defining the merging scale.
1443  nJetMaxSave = settingsPtr->mode("Merging:nJetMax");
1444  nJetMaxNLOSave = -1;
1445  // Write tms cut values to list of cut values,
1446  // ordered by DeltaR_{ij}, pT_{i}, Q_{ij}.
1447  tmsListSave.resize(0);
1448  double drms = settingsPtr->parm("Merging:dRijMS");
1449  double ptms = settingsPtr->parm("Merging:pTiMS");
1450  double qms = settingsPtr->parm("Merging:QijMS");
1451  tmsListSave.push_back(drms);
1452  tmsListSave.push_back(ptms);
1453  tmsListSave.push_back(qms);
1454 
1455  }
1456 
1457  // Read additional settingsPtr->for NLO merging methods.
1458  if ( doNL3 || doUNLOPS || doEstimateXSection ) {
1459  tmsValueSave = settingsPtr->parm("Merging:TMS");
1460  nJetMaxSave = settingsPtr->mode("Merging:nJetMax");
1461  nJetMaxNLOSave = settingsPtr->mode("Merging:nJetMaxNLO");
1462  }
1463 
1464  // Internal Pythia cross section should not include NLO merging weights.
1465  if ( doNL3 || doUNLOPS ) includeWGTinXSECSave = false;
1466 
1467  hasJetMaxLocal = false;
1468  nJetMaxLocal = nJetMaxSave;
1469  nJetMaxNLOLocal = nJetMaxNLOSave;
1470 
1471  // Check if external shower plugin should be used.
1472  useShowerPluginSave = settingsPtr->flag("Merging:useShowerPlugin");
1473 
1474  bool writeBanner = doKTMergingSave || doMGMergingSave
1475  || doUserMergingSave
1476  || doNL3 || doUNLOPS || doUMEPS
1477  || doPTLundMergingSave || doCutBasedMergingSave;
1478 
1479  isInit = true;
1480 
1481  if (!writeBanner) return;
1482 
1483  // Write banner.
1484  cout << "\n *------------------ MEPS Merging Initialization ---------------"
1485  << "---*";
1486  cout << "\n | "
1487  << " |\n";
1488  if ( doKTMergingSave || doMGMergingSave || doUserMergingSave
1489  || doPTLundMergingSave || doCutBasedMergingSave )
1490  cout << " | CKKW-L merge "
1491  << " |\n"
1492  << " |"<< setw(34) << processSave << " with up to"
1493  << setw(3) << nJetMaxSave << " additional jets |\n";
1494  else if ( doNL3 )
1495  cout << " | NL3 merge "
1496  << " |\n"
1497  << " |" << setw(31) << processSave << " with jets up to"
1498  << setw(3) << nJetMaxNLOSave << " correct to NLO |\n"
1499  << " | and up to" << setw(3) << nJetMaxSave
1500  << " additional jets included by CKKW-L merging at LO |\n";
1501  else if ( doUNLOPS )
1502  cout << " | UNLOPS merge "
1503  << " |\n"
1504  << " |" << setw(31) << processSave << " with jets up to"
1505  << setw(3)<< nJetMaxNLOSave << " correct to NLO |\n"
1506  << " | and up to" << setw(3) << nJetMaxSave
1507  << " additional jets included by UMEPS merging at LO |\n";
1508  else if ( doUMEPS )
1509  cout << " | UMEPS merge "
1510  << " |\n"
1511  << " |" << setw(34) << processSave << " with up to"
1512  << setw(3) << nJetMaxSave << " additional jets |\n";
1513 
1514  if ( doKTMergingSave )
1515  cout << " | Merging scale is defined in kT, with value ktMS = "
1516  << tmsValueSave << " GeV";
1517  else if ( doMGMergingSave )
1518  cout << " | Perform automanted MG/ME merging \n"
1519  << " | Merging scale is defined in kT, with value ktMS = "
1520  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1521  else if ( doUserMergingSave )
1522  cout << " | Merging scale is defined by the user, with value tMS = "
1523  << setw(6) << fixed << setprecision(1) << tmsValueSave << " |";
1524  else if ( doPTLundMergingSave )
1525  cout << " | Merging scale is defined by Lund pT, with value tMS = "
1526  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1527  else if ( doCutBasedMergingSave )
1528  cout << " | Merging scale is defined by combination of Delta R_{ij}, pT_i "
1529  << " |\n"
1530  << " | and Q_{ij} cut, with values "
1531  << " |\n"
1532  << " | Delta R_{ij,min} = "
1533  << setw(7) << scientific << setprecision(2) << tmsListSave[0]
1534  << " |\n"
1535  << " | pT_{i,min} = "
1536  << setw(6) << fixed << setprecision(1) << tmsListSave[1]
1537  << " GeV |\n"
1538  << " | Q_{ij,min} = "
1539  << setw(6) << fixed << setprecision(1) << tmsListSave[2]
1540  << " GeV |";
1541  else if ( doNL3TreeSave )
1542  cout << " | Generate tree-level O(alpha_s)-subtracted events "
1543  << " |\n"
1544  << " | Merging scale is defined by Lund pT, with value tMS = "
1545  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1546  else if ( doNL3LoopSave )
1547  cout << " | Generate virtual correction unit-weight events "
1548  << " |\n"
1549  << " | Merging scale is defined by Lund pT, with value tMS = "
1550  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1551  else if ( doNL3SubtSave )
1552  cout << " | Generate reclustered tree-level events "
1553  << " |\n"
1554  << " | Merging scale is defined by Lund pT, with value tMS = "
1555  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1556  else if ( doUNLOPSTreeSave )
1557  cout << " | Generate tree-level O(alpha_s)-subtracted events "
1558  << " |\n"
1559  << " | Merging scale is defined by Lund pT, with value tMS = "
1560  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1561  else if ( doUNLOPSLoopSave )
1562  cout << " | Generate virtual correction unit-weight events "
1563  << " |\n"
1564  << " | Merging scale is defined by Lund pT, with value tMS = "
1565  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1566  else if ( doUNLOPSSubtSave )
1567  cout << " | Generate reclustered tree-level events "
1568  << " |\n"
1569  << " | Merging scale is defined by Lund pT, with value tMS = "
1570  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1571  else if ( doUNLOPSSubtNLOSave )
1572  cout << " | Generate reclustered loop-level events "
1573  << " |\n"
1574  << " | Merging scale is defined by Lund pT, with value tMS = "
1575  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1576  else if ( doUMEPSTreeSave )
1577  cout << " | Generate tree-level events "
1578  << " |\n"
1579  << " | Merging scale is defined by Lund pT, with value tMS = "
1580  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1581  else if ( doUMEPSSubtSave )
1582  cout << " | Generate reclustered tree-level events "
1583  << " |\n"
1584  << " | Merging scale is defined by Lund pT, with value tMS = "
1585  << setw(6) << fixed << setprecision(1) << tmsValueSave << " GeV |";
1586 
1587  cout << "\n | "
1588  << " |";
1589  cout << "\n *-------------- END MEPS Merging Initialization ---------------"
1590  << "---*\n\n";
1591 
1592 }
1593 
1594 //--------------------------------------------------------------------------
1595 
1596 
1597 void DireMergingHooks::store() {
1598 
1599  hardProcessStore.hardIncoming1 = hardProcess->hardIncoming1;
1600  hardProcessStore.hardIncoming2 = hardProcess->hardIncoming2;
1601  hardProcessStore.hardOutgoing1 = hardProcess->hardOutgoing1;
1602  hardProcessStore.hardOutgoing2 = hardProcess->hardOutgoing2;
1603  hardProcessStore.hardIntermediate = hardProcess->hardIntermediate;
1604  hardProcessStore.state = hardProcess->state;
1605  hardProcessStore.PosOutgoing1 = hardProcess->PosOutgoing1;
1606  hardProcessStore.PosOutgoing2 = hardProcess->PosOutgoing2;
1607  hardProcessStore.PosIntermediate = hardProcess->PosIntermediate;
1608  hardProcessStore.tms = hardProcess->tms;
1609 
1610  nReclusterStore = nReclusterSave;
1611  nRequestedStore = nRequestedSave;
1612  pT0ISRStore = pT0ISRSave;
1613  pTcutStore = pTcutSave;
1614  inputEventStore = inputEvent;
1615  resonancesStore = resonances;
1616  muMIStore = muMISave;
1617  tmsValueStore = tmsValueSave;
1618  tmsValueNowStore = tmsValueNow;
1619  DparameterStore = DparameterSave;
1620  nJetMaxStore = nJetMaxSave;
1621  nJetMaxNLOStore = nJetMaxNLOSave;
1622  doOrderHistoriesStore = doOrderHistoriesSave;
1623  muFStore = muFSave;
1624  muRStore = muRSave;
1625  muFinMEStore = muFinMESave;
1626  muRinMEStore = muRinMESave;
1627  doIgnoreEmissionsStore = doIgnoreEmissionsSave;
1628  doIgnoreStepStore = doIgnoreStepSave;
1629  pTstore = pTsave;
1630  nMinMPIStore = nMinMPISave;
1631  nJetMaxLocalStore = nJetMaxLocal;
1632  nJetMaxNLOLocalStore = nJetMaxNLOLocal;
1633  hasJetMaxLocalStore = hasJetMaxLocal;
1634  nHardNowStore = nHardNowSave;
1635  nJetNowStore = nJetNowSave;
1636  tmsHardNowStore = tmsHardNowSave;
1637  tmsNowStore = tmsNowSave;
1638 
1639 }
1640 
1641 //--------------------------------------------------------------------------
1642 
1643 void DireMergingHooks::restore() {
1644 
1645  hardProcess->hardIncoming1 = hardProcessStore.hardIncoming1;
1646  hardProcess->hardIncoming2 = hardProcessStore.hardIncoming2;
1647  hardProcess->hardOutgoing1 = hardProcessStore.hardOutgoing1;
1648  hardProcess->hardOutgoing2 = hardProcessStore.hardOutgoing2;
1649  hardProcess->hardIntermediate = hardProcessStore.hardIntermediate;
1650  hardProcess->state = hardProcessStore.state;
1651  hardProcess->PosOutgoing1 = hardProcessStore.PosOutgoing1;
1652  hardProcess->PosOutgoing2 = hardProcessStore.PosOutgoing2;
1653  hardProcess->PosIntermediate = hardProcessStore.PosIntermediate;
1654  hardProcess->tms = hardProcessStore.tms;
1655 
1656  nReclusterSave = nReclusterStore;
1657  nRequestedSave = nRequestedStore;
1658  pT0ISRSave = pT0ISRStore;
1659  pTcutSave = pTcutStore;
1660  inputEvent = inputEventStore;
1661  resonances = resonancesStore;
1662  muMISave = muMIStore;
1663  tmsValueSave = tmsValueStore;
1664  tmsValueNow = tmsValueNowStore;
1665  DparameterSave = DparameterStore;
1666  nJetMaxSave = nJetMaxStore;
1667  nJetMaxNLOSave = nJetMaxNLOStore;
1668  doOrderHistoriesSave = doOrderHistoriesStore;
1669  muFSave = muFStore;
1670  muRSave = muRStore;
1671  muFinMESave = muFinMEStore;
1672  muRinMESave = muRinMEStore;
1673  doIgnoreEmissionsSave = doIgnoreEmissionsStore;
1674  doIgnoreStepSave = doIgnoreStepStore;
1675  pTsave = pTstore;
1676  nMinMPISave = nMinMPIStore;
1677  nJetMaxLocal = nJetMaxLocalStore;
1678  nJetMaxNLOLocal = nJetMaxNLOLocalStore;
1679  hasJetMaxLocal = hasJetMaxLocalStore;
1680  nHardNowSave = nHardNowStore;
1681  nJetNowSave = nJetNowStore;
1682  tmsHardNowSave = tmsHardNowStore;
1683  tmsNowSave = tmsNowStore;
1684 
1685 }
1686 
1687 //--------------------------------------------------------------------------
1688 
1689 // Function to check if emission should be rejected.
1690 
1691 bool DireMergingHooks::doVetoEmission( const Event& event) {
1692 
1693  // Do nothing in trial showers, or after first step.
1694  if ( doIgnoreEmissionsSave ) return false;
1695 
1696  // Do nothing in CKKW-L
1697  if ( doUserMerging() || doMGMerging() || doKTMerging()
1698  || doPTLundMerging() || doCutBasedMerging() )
1699  return false;
1700 
1701  if ( doMOPS() ) return false;
1702 
1703  // For NLO merging, count and veto emissions above the merging scale
1704  bool veto = false;
1705  // Get number of clustering steps
1706  int nSteps = getNumberOfClusteringSteps(event);
1707  // Get merging scale in current event
1708  double tnow = tmsNow( event);
1709 
1710  // Get maximal number of additional jets
1711  int nJetMax = nMaxJets();
1712  // Always remove emissions above the merging scale for
1713  // samples containing reclusterings!
1714  if ( nRecluster() > 0 ) nSteps = max(1, min(nJetMax-2, 1));
1715  // Check veto condition
1716  if ( nSteps - 1 < nJetMax && nSteps >= 1 && tnow > tms() && tms() > 0. )
1717  veto = true;
1718 
1719  // Do not veto if state already includes MPI.
1720  if ( infoPtr->nMPI() > 1 ) veto = false;
1721 
1722  // When performing NL3 merging of tree-level events, reset the
1723  // CKKWL weight.
1724  if ( veto && doNL3Tree() ) setWeightCKKWL({0.});
1725 
1726  // If the emission is allowed, do not check any further emissions
1727  if ( !veto ) doIgnoreEmissionsSave = true;
1728 
1729  // Done
1730  return veto;
1731 
1732 }
1733 
1734 //--------------------------------------------------------------------------
1735 
1736 // Function to check if emission should be rejected.
1737 
1738 bool DireMergingHooks::doVetoStep( const Event& process, const Event& event,
1739  bool doResonance ) {
1740 
1741  // Do nothing in trial showers, or after first step.
1742  if ( doIgnoreStepSave && !doResonance ) return false;
1743 
1744  // Do nothing in UMEPS or UNLOPS
1745  if ( doUMEPSTree() || doUMEPSSubt() || doUMEPSMerging() || doUNLOPSTree()
1746  || doUNLOPSLoop() || doUNLOPSSubt() || doUNLOPSSubtNLO()
1747  || doUNLOPSMerging() )
1748  return false;
1749 
1750  if ( doMOPS() ) return false;
1751 
1752  // Get number of clustering steps. If necessary, remove resonance
1753  // decay products first.
1754  int nSteps = 0;
1755  if ( getProcessString().find("inc") != string::npos )
1756  nSteps = getNumberOfClusteringSteps( bareEvent( process, false) );
1757  else nSteps = (doResonance) ? getNumberOfClusteringSteps(process)
1758  : getNumberOfClusteringSteps( bareEvent( process, false) );
1759 
1760  // Get maximal number of additional jets.
1761  int nJetMax = nMaxJets();
1762  // Get merging scale in current event.
1763  double tnow = tmsNow( event );
1764 
1765  // Do not print zero-weight events.
1766  // For non-resonant showers, simply check veto. If event should indeed be
1767  // vetoed, save the current pT and weights in case the veto needs to be
1768  // revoked.
1769  if ( !doResonance ) {
1770 
1771  // Store pT to check if veto needs to be revoked later.
1772  pTsave = infoPtr->pTnow();
1773  if ( nRecluster() == 1) nSteps--;
1774 
1776  //if (!applyVeto) {
1777  // setEventVetoInfo(nSteps, tnow);
1778  // return false;
1779  //}
1780 
1781  // Check merging veto condition.
1782  bool veto = false;
1783  if ( nSteps > nMaxJetsNLO() && nSteps < nJetMax && tnow > tms()
1784  && tms() > 0. ) {
1785  // Set weight to zero if event should be vetoed.
1786  weightCKKWL1Save = {0.};
1787  // Save weight before veto, in case veto needs to be revoked.
1788  weightCKKWL2Save = getWeightCKKWL();
1789  // Reset stored weights.
1790  if ( !includeWGTinXSEC() ) setWeightCKKWL({0.});
1791  if ( includeWGTinXSEC() ) infoPtr->weightContainerPtr->
1792  setWeightNominal(0.);
1793  veto = true;
1794  }
1795 
1796  // Store veto inputs to perform veto at a later stage.
1797  if (!applyVeto) {
1798  setEventVetoInfo(nSteps, tnow);
1799  return false;
1800  }
1801 
1802  // Done
1803  return veto;
1804 
1805  // For resonant showers, check if any previous veto should be revoked.
1806  // This means we treat showers off resonance decay products identical to
1807  // MPI: If a hard resonance emission has been produced, the event should
1808  // have been kept. Following this reasoning, it might be necessary to revoke
1809  // any previous veto.
1810  } else {
1811 
1812  // Initialise switch to revoke vetoing.
1813  bool revokeVeto = false;
1814 
1815  // Nothing to check if pTsave was not stored, i.e. no emission to
1816  // possibly veto was recorded.
1817  // Only allow revoking the veto for diboson processes, with resonant
1818  // electroweak bosons
1819  bool check = (nHardInLeptons() == 0)&& (nHardOutLeptons() == 2)
1820  && (nHardOutPartons() == 2);
1821 
1822  // For current purpose only!!!
1823  check = false;
1824 
1825  // For hadronic resonance decays at hadron colliders, do not veto
1826  // events with a hard emission of the resonance decay products,
1827  // since such states are not included in the matrix element
1828  if ( pTsave > 0. && check ) {
1829 
1830  // Check how many resonance decay systems are allowed
1831  int nResNow = nResInCurrent();
1832 
1833  // Find systems really containing only emission off a resonance
1834  // decay
1835  vector<int>goodSys;
1836  // Resonance decay systems are considered last, thus at the end of
1837  // the list
1838  int sysSize = partonSystemsPtr->sizeSys();
1839  for ( int i=0; i < nResNow; ++i ) {
1840  if ( partonSystemsPtr->sizeOut(sysSize - 1 - i) == 3 )
1841  goodSys.push_back(sysSize - 1 - i);
1842  }
1843 
1844  // Check the members of the resonance decay systems
1845  for ( int i=0; i < int(goodSys.size()); ++i ) {
1846 
1847  // Save the (three) members of the resonance decay system
1848  int iMem1 = partonSystemsPtr->getOut(goodSys[i],0);
1849  int iMem2 = partonSystemsPtr->getOut(goodSys[i],1);
1850  int iMem3 = partonSystemsPtr->getOut(goodSys[i],2);
1851 
1852  // Now find emitted gluon or gamma
1853  int iEmtGlue = ((event[iMem1].id() == 21) ? iMem1
1854  : ((event[iMem2].id() == 21) ? iMem2
1855  : ((event[iMem3].id() == 21) ? iMem3: 0)));
1856  int iEmtGamm = ((event[iMem1].id() == 22) ? iMem1
1857  : ((event[iMem2].id() == 22) ? iMem2
1858  : ((event[iMem3].id() == 22) ? iMem3: 0)));
1859  // Per system, only one emission
1860  int iEmt = (iEmtGlue != 0) ? iEmtGlue : iEmtGamm;
1861 
1862  int iRad = 0;
1863  int iRec = 0;
1864  if ( iEmt == iMem1 ) {
1865  iRad = (event[iMem2].mother1() != event[iMem2].mother2())
1866  ? iMem2 : iMem3;
1867  iRec = (event[iMem3].mother1() == event[iMem3].mother2())
1868  ? iMem3 : iMem2;
1869  } else if ( iEmt == iMem2 ) {
1870  iRad = (event[iMem1].mother1() != event[iMem1].mother2())
1871  ? iMem1 : iMem3;
1872  iRec = (event[iMem3].mother1() == event[iMem3].mother2())
1873  ? iMem3 : iMem1;
1874  } else {
1875  iRad = (event[iMem1].mother1() != event[iMem1].mother2())
1876  ? iMem1 : iMem2;
1877  iRec = (event[iMem2].mother1() == event[iMem2].mother2())
1878  ? iMem2 : iMem1;
1879  }
1880 
1881  double pTres = rhoPythia(event, iRad, iEmt, iRec, 1);
1882 
1883  // Revoke previous veto of last emission if a splitting of the
1884  // resonance produced a harder parton, i.e. we are inside the
1885  // PS region
1886  if ( pTres > pTsave ) {
1887  revokeVeto = true;
1888  // Do nothing (i.e. allow other first emission veto) for soft
1889  // splitting
1890  } else {
1891  revokeVeto = false;
1892  }
1893  // Done with one system
1894  }
1895  // Done with all systems
1896  }
1897 
1898  // Check veto condition
1899  bool veto = false;
1900  if ( revokeVeto && check ) {
1901  setWeightCKKWL(weightCKKWL2Save);
1902  } else if ( check ) {
1903  setWeightCKKWL(weightCKKWL1Save);
1904  if ( weightCKKWL1Save[0] == 0. ) veto = true;
1905  }
1906 
1907  // Check veto condition.
1908  if ( !check && nSteps > nMaxJetsNLO() && nSteps < nJetMax && tnow > tms()
1909  && tms() > 0.){
1910  // Set stored weights to zero.
1911  if ( !includeWGTinXSEC() ) setWeightCKKWL({0.});
1912  if ( includeWGTinXSEC() ) infoPtr->weightContainerPtr->
1913  setWeightNominal(0.);
1914  // Now allow veto.
1915  veto = true;
1916  }
1917 
1918  // If the emission is allowed, do not check any further emissions
1919  if ( !veto || !doIgnoreStepSave ) doIgnoreStepSave = true;
1920 
1921  // Done
1922  return veto;
1923 
1924  }
1925 
1926  // Done
1927  return false;
1928 
1929 }
1930 
1931 //--------------------------------------------------------------------------
1932 
1933 // Function to return the number of clustering steps for the current event
1934 
1935 int DireMergingHooks::getNumberOfClusteringSteps(const Event& event,
1936  bool resetJetMax ){
1937 
1938  // Count the number of final state partons
1939  int nFinalPartons = 0;
1940  for ( int i=0; i < event.size(); ++i)
1941  if ( event[i].isFinal()
1942  && isInHard( i, event)
1943  && (event[i].isQuark() || event[i].isGluon()) )
1944  nFinalPartons++;
1945 
1946  // Count the number of final state leptons
1947  int nFinalLeptons = 0;
1948  for( int i=0; i < event.size(); ++i)
1949  if ( event[i].isFinal() && isInHard( i, event) && event[i].isLepton())
1950  nFinalLeptons++;
1951 
1952  // Add neutralinos to number of leptons
1953  for( int i=0; i < event.size(); ++i)
1954  if ( event[i].isFinal() && isInHard( i, event)
1955  && event[i].idAbs() == 1000022)
1956  nFinalLeptons++;
1957 
1958  // Add sleptons to number of leptons
1959  for( int i=0; i < event.size(); ++i)
1960  if ( event[i].isFinal() && isInHard( i, event)
1961  && (event[i].idAbs() == 1000011
1962  || event[i].idAbs() == 2000011
1963  || event[i].idAbs() == 1000013
1964  || event[i].idAbs() == 2000013
1965  || event[i].idAbs() == 1000015
1966  || event[i].idAbs() == 2000015) )
1967  nFinalLeptons++;
1968 
1969  // Count the number of final state electroweak bosons
1970  int nFinalBosons = 0;
1971  for( int i=0; i < event.size(); ++i)
1972  if ( event[i].isFinal() && isInHard( i, event)
1973  && ( event[i].idAbs() == 22
1974  || event[i].idAbs() == 23
1975  || event[i].idAbs() == 24
1976  || event[i].idAbs() == 25 ) )
1977  nFinalBosons++;
1978 
1979  // Save sum of all final state particles
1980  int nFinal = nFinalPartons + nFinalLeptons
1981  + 2*(nFinalBosons - nHardOutBosons() );
1982 
1983  // Return the difference to the core process outgoing particles
1984  int nsteps = nFinal - nHardOutPartons() - nHardOutLeptons();
1985 
1986  nsteps = nFinalPartons + nFinalLeptons + nFinalBosons
1987  - (nHardOutPartons() + nHardOutLeptons() + nHardOutBosons());
1988 
1989  // For inclusive handling, the number of reclustering steps
1990  // can be different within a single sample.
1991  if ( getProcessString().find("inc") != string::npos ) {
1992 
1993  // Final particle counters
1994  int njInc = 0, naInc = 0, nzInc = 0, nwInc =0, nhInc = 0;
1995  for (int i=0; i < event.size(); ++i){
1996  if ( event[i].isFinal() && event[i].colType() != 0 ) njInc++;
1997  if ( getProcessString().find("Ainc") != string::npos
1998  && event[i].isFinal() && event[i].idAbs() == 22 ) naInc++;
1999  if ( getProcessString().find("Zinc") != string::npos
2000  && event[i].isFinal() && event[i].idAbs() == 23 ) nzInc++;
2001  if ( getProcessString().find("Winc") != string::npos
2002  && event[i].isFinal() && event[i].idAbs() == 24 ) nwInc++;
2003  if ( getProcessString().find("Hinc") != string::npos
2004  && event[i].isFinal() && event[i].idAbs() == 25 ) nhInc++;
2005  }
2006 
2007  // Set steps for QCD or QCD+QED events: Need at least two
2008  // massless particles at lowest multiplicity.
2009  if (nzInc == 0 && nwInc == 0 && nhInc == 0 && njInc+naInc > 1) {
2010  nsteps = naInc + njInc - 2;
2011  if (resetJetMax) {
2012  hasJetMaxLocal = true;
2013  nJetMaxLocal = nJetMaxSave - 2;
2014  nRequestedSave = nsteps;
2015  }
2016  }
2017 
2018  // Set steps for events containing heavy bosons. Need at least one
2019  // massive particle at lowest multiplicity.
2020  if ( nzInc > 0 || nwInc > 0 || nhInc > 0) {
2021  nsteps = njInc + naInc + nzInc + nwInc + nhInc - 1;
2022  if (resetJetMax) {
2023  hasJetMaxLocal = true;
2024  nJetMaxLocal = nJetMaxSave - 1;
2025  nRequestedSave = nsteps;
2026  }
2027  }
2028 
2029  } // dynamical handling of steps
2030 
2031  // Return the difference to the core process outgoing particles
2032  return nsteps;
2033 
2034 }
2035 
2036 //--------------------------------------------------------------------------
2037 
2038 // Function to set the correct starting scales of the shower.
2039 // Note: 2 -> 2 QCD systems can be produced by MPI. Hence, there is an
2040 // overlap between MPI and "hard" 2 -> 2 QCD systems which needs to be
2041 // removed by no-MPI probabilities. This means that for any "hard" 2 -> 2 QCD
2042 // system, multiparton interactions should start at the maximal scale
2043 // of multiple interactions. The same argument holds for any "hard" process
2044 // that overlaps with MPI.
2045 
2046 bool DireMergingHooks::setShowerStartingScales( bool isTrial,
2047  bool doMergeFirstEmm, double& pTscaleIn, const Event& event,
2048  double& pTmaxFSRIn, bool& limitPTmaxFSRIn,
2049  double& pTmaxISRIn, bool& limitPTmaxISRIn,
2050  double& pTmaxMPIIn, bool& limitPTmaxMPIIn ) {
2051 
2052  // Local copies of power/wimpy shower booleans and scales.
2053  bool limitPTmaxFSR = limitPTmaxFSRIn;
2054  bool limitPTmaxISR = limitPTmaxISRIn;
2055  bool limitPTmaxMPI = limitPTmaxMPIIn;
2056  double pTmaxFSR = pTmaxFSRIn;
2057  double pTmaxISR = pTmaxISRIn;
2058  double pTmaxMPI = pTmaxMPIIn;
2059  double pTscale = pTscaleIn;
2060 
2061  // Merging of EW+QCD showers with matrix elements: Ensure that
2062  // 1. any event with more than one final state particle will be showered
2063  // from the reconstructed transverse momentum of the last emission,
2064  // even if the factorisation scale is low.
2065  // 2. the shower starting scale for events with no emission is given by
2066  // the (user-defined) choice.
2067  bool isInclusive = ( getProcessString().find("inc") != string::npos );
2068 
2069  // Check if the process only contains two outgoing partons. If so, then
2070  // this process could also have been produced by MPI. Thus, the MPI starting
2071  // scale would need to be set accordingly to correctly attach a
2072  // "no-MPI-probability" to multi-jet events. ("Hard" MPI are included
2073  // by not restricting MPI when showering the lowest-multiplicity sample.)
2074  double pT2to2 = 0;
2075  int nFinalPartons = 0, nInitialPartons = 0, nFinalOther = 0;
2076  for ( int i = 0; i < event.size(); ++i ) {
2077  if ( (event[i].mother1() == 1 || event[i].mother1() == 2 )
2078  && (event[i].idAbs() < 6 || event[i].id() == 21) )
2079  nInitialPartons++;
2080  if (event[i].isFinal() && (event[i].idAbs() < 6 || event[i].id() == 21)) {
2081  nFinalPartons++;
2082  pT2to2 = event[i].pT();
2083  } else if ( event[i].isFinal() ) nFinalOther++;
2084  }
2085  bool is2to2QCD = ( nFinalPartons == 2 && nInitialPartons == 2
2086  && nFinalOther == 0 );
2087  bool hasMPIoverlap = is2to2QCD;
2088  bool is2to1 = ( nFinalPartons == 0 );
2089 
2090  double scale = event.scale();
2091 
2092  // SET THE STARTING SCALES FOR TRIAL SHOWERS.
2093  if ( isTrial ) {
2094 
2095  // Reset shower and MPI scales.
2096  pTmaxISR = pTmaxFSR = pTmaxMPI = scale;
2097 
2098  // Reset to minimal scale for wimpy showers. Keep scales for EW+QCD
2099  // merging.
2100  if ( limitPTmaxISR && !isInclusive ) pTmaxISR = min(scale,muF());
2101  if ( limitPTmaxFSR && !isInclusive ) pTmaxFSR = min(scale,muF());
2102  if ( limitPTmaxMPI && !isInclusive ) pTmaxMPI = min(scale,muF());
2103 
2104  // For EW+QCD merging, apply wimpy shower only to 2->1 processes.
2105  if ( limitPTmaxISR && isInclusive && is2to1 ) pTmaxISR = min(scale,muF());
2106  if ( limitPTmaxFSR && isInclusive && is2to1 ) pTmaxFSR = min(scale,muF());
2107  if ( limitPTmaxMPI && isInclusive && is2to1 ) pTmaxMPI = min(scale,muF());
2108 
2109  // For pure QCD set the PS starting scales to the pT of the dijet system.
2110  if (is2to2QCD) {
2111  pTmaxFSR = pT2to2;
2112  pTmaxISR = pT2to2;
2113  }
2114 
2115  // If necessary, set the MPI starting scale to the collider energy.
2116  if ( hasMPIoverlap ) pTmaxMPI = infoPtr->eCM();
2117 
2118  // Reset phase space limitation flags
2119  if ( pTscale < infoPtr->eCM() ) {
2120  limitPTmaxISR = limitPTmaxFSR = limitPTmaxMPI = true;
2121  // If necessary, set the MPI starting scale to the collider energy.
2122  if ( hasMPIoverlap ) limitPTmaxMPI = false;
2123  }
2124 
2125  }
2126 
2127  // SET THE STARTING SCALES FOR REGULAR SHOWERS.
2128  if ( doMergeFirstEmm ) {
2129 
2130  // Remember if this is a "regular" shower off a reclustered event.
2131  bool doRecluster = doUMEPSSubt() || doNL3Subt() || doUNLOPSSubt()
2132  || doUNLOPSSubtNLO();
2133 
2134  // Reset shower and MPI scales.
2135  pTmaxISR = pTmaxFSR = pTmaxMPI = scale;
2136 
2137  // Reset to minimal scale for wimpy showers. Keep scales for EW+QCD
2138  // merging.
2139  if ( limitPTmaxISR && !isInclusive ) pTmaxISR = min(scale,muF());
2140  if ( limitPTmaxFSR && !isInclusive ) pTmaxFSR = min(scale,muF());
2141  if ( limitPTmaxMPI && !isInclusive ) pTmaxMPI = min(scale,muF());
2142 
2143  // For EW+QCD merging, apply wimpy shower only to 2->1 processes.
2144  if ( limitPTmaxISR && isInclusive && is2to1 ) pTmaxISR = min(scale,muF());
2145  if ( limitPTmaxFSR && isInclusive && is2to1 ) pTmaxFSR = min(scale,muF());
2146  if ( limitPTmaxMPI && isInclusive && is2to1 ) pTmaxMPI = min(scale,muF());
2147 
2148  // For pure QCD set the PS starting scales to the pT of the dijet system.
2149  if (is2to2QCD) {
2150  pTmaxFSR = pT2to2;
2151  pTmaxISR = pT2to2;
2152  }
2153 
2154  // If necessary, set the MPI starting scale to the collider energy.
2155  if ( hasMPIoverlap && !doRecluster ) {
2156  pTmaxMPI = infoPtr->eCM();
2157  limitPTmaxMPI = false;
2158  }
2159 
2160  // For reclustered events, no-MPI-probability between "pTmaxMPI" and
2161  // "scale" already included in the event weight.
2162  if ( doRecluster ) {
2163  pTmaxMPI = muMI();
2164  limitPTmaxMPI = true;
2165  }
2166  }
2167 
2168  // Reset power/wimpy shower switches iand scales if necessary.
2169  limitPTmaxFSRIn = limitPTmaxFSR;
2170  limitPTmaxISRIn = limitPTmaxISR;
2171  limitPTmaxMPIIn = limitPTmaxMPI;
2172  pTmaxFSRIn = pTmaxFSR;
2173  pTmaxISRIn = pTmaxISR;
2174  pTmaxMPIIn = pTmaxMPI;
2175  pTscaleIn = pTscale;
2176 
2177  // Done
2178  return true;
2179 
2180 }
2181 
2182 //--------------------------------------------------------------------------
2183 
2184 // Function to return the value of the merging scale function in the current
2185 // event.
2186 
2187 double DireMergingHooks::tmsNow( const Event& event ) {
2188 
2189  // Get merging scale in current event.
2190  double tnow = 0.;
2191  //tnow = scalems(event, false);
2192  tnow = scalems(event);
2193  // Return merging scale value. Done
2194  return tnow;
2195 }
2196 
2197 //--------------------------------------------------------------------------
2198 
2199 // Function to check if the properties of the input particle should be
2200 // checked against the cut-based merging scale defintion.
2201 
2202 bool DireMergingHooks::checkAgainstCut( const Particle& particle){
2203 
2204  // Do not check uncoloured particles.
2205  if (particle.colType() == 0) return false;
2206  // By default, use u-, d-, c-, s- and b-quarks.
2207  if ( particle.idAbs() != 21 && particle.idAbs() > nQuarksMergeSave )
2208  return false;
2209  // Done
2210  return true;
2211 
2212 }
2213 
2214 //--------------------------------------------------------------------------
2215 
2216 // Find the minimal Lund pT between coloured partons in the input
2217 // event. If doPTLundMerging = true, this function will be used as a merging
2218 // scale definition.
2219 
2220 double DireMergingHooks::scalems( const Event& event){
2221 
2222  // Only check first emission.
2223  if (!isFirstEmission(event)) return 0.;
2224 
2225  // Find all electroweak decayed bosons in the state.
2226  vector<int> ewResonancePos;
2227  ewResonancePos.clear();
2228  for (int i=0; i < event.size(); ++i)
2229  if ( abs(event[i].status()) == 22
2230  && ( event[i].idAbs() == 22
2231  || event[i].idAbs() == 23
2232  || event[i].idAbs() == 24
2233  || event[i].idAbs() == 25
2234  || event[i].idAbs() == 6 ) )
2235  ewResonancePos.push_back(i);
2236 
2237  // Declare final parton vectors
2238  vector <int> FinalPartPos;
2239  FinalPartPos.clear();
2240  // Search inEvent record for final state partons.
2241  // Exclude decay products of ew resonance.
2242  for (int i=0; i < event.size(); ++i){
2243 
2244  if ( event[i].isFinal()
2245  && isInHard( i, event )
2246  && event[i].colType() != 0
2247  && checkAgainstCut(event[i]) ){
2248  bool isDecayProduct = false;
2249  for(int j=0; j < int(ewResonancePos.size()); ++j)
2250  if ( event[i].isAncestor( ewResonancePos[j]) )
2251  isDecayProduct = true;
2252  // Except for e+e- -> jets, do not check radiation in resonance decays.
2253  if ( !isDecayProduct
2254  || getProcessString().compare("e+e->jj") == 0
2255  || getProcessString().compare("e+e->(z>jj)") == 0 )
2256  FinalPartPos.push_back(i);
2257  }
2258 
2259  // Include photons into the tms definition for "weak+QCD merging".
2260  if ( getProcessString().find("Ainc") != string::npos
2261  && event[i].isFinal() && event[i].idAbs() == 22 )
2262  FinalPartPos.push_back(i);
2263  // Include Z-bosons into the tms definition for "weak+QCD merging".
2264  if ( getProcessString().find("Zinc") != string::npos
2265  && event[i].isFinal() && event[i].idAbs() == 23 )
2266  FinalPartPos.push_back(i);
2267  // Include W-bosons into the tms definition for "weak+QCD merging".
2268  if ( getProcessString().find("Winc") != string::npos
2269  && event[i].isFinal() && event[i].idAbs() == 24 )
2270  FinalPartPos.push_back(i);
2271  }
2272 
2273  // Get index of first incoming
2274  int in1 = 0;
2275  for (int i=0; i < event.size(); ++i)
2276  if (abs(event[i].status()) == 41 ){
2277  in1 = i;
2278  break;
2279  }
2280 
2281  // Get index of second incoming
2282  int in2 = 0;
2283  for (int i=0; i < event.size(); ++i)
2284  if (abs(event[i].status()) == 42 ){
2285  in2 = i;
2286  break;
2287  }
2288 
2289  // If no incoming of the cascade are found, try incoming
2290  if (in1 == 0 || in2 == 0){
2291  // Find current incoming partons
2292  for(int i=3; i < int(event.size()); ++i){
2293  if ( !isInHard( i, event ) ) continue;
2294  if (event[i].mother1() == 1) in1 = i;
2295  if (event[i].mother1() == 2) in2 = i;
2296  }
2297  }
2298 
2299  int nInitialPartons(0), nFinalOther(0);
2300  for ( int i = 0; i < event.size(); ++i ) {
2301  if ( (event[i].mother1() == 1 || event[i].mother1() == 2 )
2302  && (event[i].idAbs() < 6 || event[i].id() == 21) )
2303  nInitialPartons++;
2304  if (event[i].isFinal() && event[i].idAbs() >= 6 && event[i].id() != 21)
2305  nFinalOther++;
2306  }
2307  bool is2to2QCD = ( int(FinalPartPos.size()) == 2 && nInitialPartons == 2
2308  && nFinalOther == 0 );
2309 
2310  // For pure QCD set the cut to the pT of the dijet system.
2311  if (is2to2QCD) {
2312  double pt12 = min(event[FinalPartPos[0]].pT(),
2313  event[FinalPartPos[1]].pT());
2314  return pt12;
2315  }
2316 
2317  // No cut if only massive particles in final state.
2318  int nLight(0);
2319  for(int i=0; i < int(FinalPartPos.size()); ++i)
2320  if ( event[FinalPartPos[i]].idAbs() <= 5
2321  || event[FinalPartPos[i]].idAbs() == 21
2322  || event[FinalPartPos[i]].idAbs() == 22) nLight++;
2323  if (nLight == 0) return 0.;
2324 
2325 
2326  // Find minimal pythia pt in event
2327  double ptmin = event[0].e();
2328  for(int i=0; i < int(FinalPartPos.size()); ++i){
2329 
2330  double pt12 = ptmin;
2331 
2332  // Compute II separation of i-emission and first incoming as radiator
2333  if (event[in1].colType() != 0) {
2334  double temp = rhoPythia( event, in1, FinalPartPos[i], in2, 0);
2335  pt12 = min(pt12, temp);
2336  }
2337 
2338  // Compute II separation of i-emission and second incoming as radiator
2339  if ( event[in2].colType() != 0) {
2340  double temp = rhoPythia( event, in2, FinalPartPos[i], in1, 0);
2341  pt12 = min(pt12, temp);
2342  }
2343 
2344  // Compute all IF separations of i-emission and first incoming as radiator
2345  if ( event[in1].colType() != 0 ) {
2346  for(int j=0; j < int(FinalPartPos.size()); ++j) {
2347  // Allow both initial partons as recoiler
2348  if ( i != j ){
2349  // Check with first initial as recoiler
2350  double temp = rhoPythia(event,in1,FinalPartPos[i],FinalPartPos[j],0);
2351  pt12 = min(pt12, temp);
2352  }
2353  }
2354  }
2355 
2356  // Compute all IF separations of i-emission and second incoming as radiator
2357  if ( event[in2].colType() != 0 ) {
2358  for(int j=0; j < int(FinalPartPos.size()); ++j) {
2359  // Allow both initial partons as recoiler
2360  if ( i != j ){
2361  // Check with first initial as recoiler
2362  double temp = rhoPythia(event,in2,FinalPartPos[i],FinalPartPos[j],0);
2363  pt12 = min(pt12, temp);
2364  }
2365  }
2366  }
2367 
2368  // Compute all FF separations between final state partons.
2369  for(int j=0; j < int(FinalPartPos.size()); ++j) {
2370  for(int k=0; k < int(FinalPartPos.size()); ++k) {
2371  // Allow any parton as recoiler
2372  if ( (i != j) && (i != k) && (j != k) ){
2373  double temp = rhoPythia( event, FinalPartPos[i], FinalPartPos[j],
2374  FinalPartPos[k], 0);
2375  pt12 = min(pt12, temp);
2376  temp = rhoPythia( event, FinalPartPos[j], FinalPartPos[i],
2377  FinalPartPos[k], 0);
2378  pt12 = min(pt12, temp);
2379  }
2380  }
2381  }
2382 
2383  // Compute pythia FSR separation between two jets, with eith initial as
2384  // recoiler.
2385  if ( event[in1].colType() != 0 ) {
2386  for(int j=0; j < int(FinalPartPos.size()); ++j) {
2387  // Allow both initial partons as recoiler
2388  if ( i != j ){
2389  // Check with first initial as recoiler
2390  double temp = rhoPythia( event, FinalPartPos[i],FinalPartPos[j],
2391  in1, 0);
2392  pt12 = min(pt12, temp);
2393  }
2394  }
2395  }
2396 
2397  // Compute pythia FSR separation between two jets, with eith initial as
2398  // recoiler.
2399  if ( event[in2].colType() != 0) {
2400  for(int j=0; j < int(FinalPartPos.size()); ++j) {
2401  // Allow both initial partons as recoiler
2402  if ( i != j ){
2403  // Check with second initial as recoiler
2404  double temp = rhoPythia( event, FinalPartPos[i],FinalPartPos[j],
2405  in2, 0);
2406  pt12 = min(pt12, temp);
2407  }
2408  }
2409  }
2410 
2411  // Reset minimal y separation
2412  ptmin = min(ptmin,pt12);
2413  }
2414 
2415  return ptmin;
2416 
2417 }
2418 
2419 //--------------------------------------------------------------------------
2420 
2421 // Function to compute "pythia pT separation" from Particle input, as a helper
2422 // for rhoms(...).
2423 
2424 double DireMergingHooks::rhoPythia(const Event& event, int rad, int emt,
2425  int rec, int){
2426 
2427  // Use external shower for merging.
2428  // Ask showers for evolution variable.
2429  map<string,double> stateVars;
2430  double ptret = event[0].m();
2431  bool isFSR = showers->timesPtr->isTimelike(event, rad, emt, rec, "");
2432  if (isFSR) {
2433  vector<string> name = showers->timesPtr->getSplittingName
2434  (event, rad, emt, rec);
2435  for (int i=0; i < int(name.size()); ++i) {
2436  stateVars = showers->timesPtr->getStateVariables
2437  (event, rad, emt, rec, name[i]);
2438  double pttemp = ptret;
2439  if (stateVars.size() > 0 && stateVars.find("t") != stateVars.end())
2440  pttemp = sqrt(stateVars["t"]);
2441  ptret = min(ptret,pttemp);
2442  }
2443  } else {
2444  vector<string> name = showers->spacePtr->getSplittingName
2445  (event, rad, emt, rec);
2446  for (int i=0; i < int(name.size()); ++i) {
2447  stateVars = showers->spacePtr->getStateVariables
2448  (event, rad, emt, rec, name[i]);
2449  double pttemp = ptret;
2450  if (stateVars.size() > 0 && stateVars.find("t") != stateVars.end())
2451  pttemp = sqrt(stateVars["t"]);
2452  ptret = min(ptret,pttemp);
2453  }
2454  }
2455  return ptret;
2456 
2457 }
2458 
2459 //--------------------------------------------------------------------------
2460 
2461 // Function to find a colour (anticolour) index in the input event.
2462 // Helper for rhoms
2463 // IN int col : Colour tag to be investigated
2464 // int iExclude1 : Identifier of first particle to be excluded
2465 // from search
2466 // int iExclude2 : Identifier of second particle to be excluded
2467 // from search
2468 // Event event : event to be searched for colour tag
2469 // int type : Tag to define if col should be counted as
2470 // colour (type = 1) [->find anti-colour index
2471 // contracted with col]
2472 // anticolour (type = 2) [->find colour index
2473 // contracted with col]
2474 // OUT int : Position of particle in event record
2475 // contraced with col [0 if col is free tag]
2476 
2477 int DireMergingHooks::findColour(int col, int iExclude1, int iExclude2,
2478  const Event& event, int type, bool isHardIn){
2479 
2480  bool isHard = isHardIn;
2481  int index = 0;
2482 
2483  if (isHard){
2484  // Search event record for matching colour & anticolour
2485  for(int n = 0; n < event.size(); ++n) {
2486  if ( n != iExclude1 && n != iExclude2
2487  && event[n].colType() != 0
2488  &&( event[n].status() > 0 // Check outgoing
2489  || event[n].status() == -21) ) { // Check incoming
2490  if ( event[n].acol() == col ) {
2491  index = -n;
2492  break;
2493  }
2494  if ( event[n].col() == col ){
2495  index = n;
2496  break;
2497  }
2498  }
2499  }
2500  } else {
2501 
2502  // Search event record for matching colour & anticolour
2503  for(int n = 0; n < event.size(); ++n) {
2504  if ( n != iExclude1 && n != iExclude2
2505  && event[n].colType() != 0
2506  &&( event[n].status() == 43 // Check outgoing from ISR
2507  || event[n].status() == 51 // Check outgoing from FSR
2508  || event[n].status() == 52 // Check outgoing from FSR
2509  || event[n].status() == -41 // first initial
2510  || event[n].status() == -42) ) { // second initial
2511  if ( event[n].acol() == col ) {
2512  index = -n;
2513  break;
2514  }
2515  if ( event[n].col() == col ){
2516  index = n;
2517  break;
2518  }
2519  }
2520  }
2521  }
2522  // if no matching colour / anticolour has been found, return false
2523  if ( type == 1 && index < 0) return abs(index);
2524  if ( type == 2 && index > 0) return abs(index);
2525 
2526  return 0;
2527 }
2528 
2529 //==========================================================================
2530 
2531 } // end namespace Pythia8
Definition: AgUStep.h:26