Line data Source code
1 : // History.cc is a part of the PYTHIA event generator.
2 : // Copyright (C) 2015 Torbjorn Sjostrand.
3 : // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 : // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 :
6 : // This file is written by Stefan Prestel.
7 : // Function definitions (not found in the header) for the
8 : // Clustering and History classes.
9 :
10 : #include "Pythia8/History.h"
11 :
12 : namespace Pythia8 {
13 :
14 : //==========================================================================
15 :
16 : // The Clustering class.
17 :
18 : //--------------------------------------------------------------------------
19 :
20 : // Declaration of Clustering class
21 : // This class holds information about one radiator, recoiler,
22 : // emitted system.
23 : // This class is a container class for History class use.
24 :
25 : // print for debug
26 : void Clustering::list() const {
27 0 : cout << " emt " << emitted
28 0 : << " rad " << emittor
29 0 : << " rec " << recoiler
30 0 : << " partner " << partner
31 0 : << " pTscale " << pTscale << endl;
32 0 : }
33 :
34 : //==========================================================================
35 :
36 : // The History class.
37 :
38 : // A History object represents an event in a given step in the CKKW-L
39 : // clustering procedure. It defines a tree-like recursive structure,
40 : // where the root node represents the state with n jets as given by
41 : // the matrix element generator, and is characterized by the member
42 : // variable mother being null. The leaves on the tree corresponds to a
43 : // fully clustered paths where the original n-jets has been clustered
44 : // down to the Born-level state. Also states which cannot be clustered
45 : // down to the Born-level are possible - these will be called
46 : // incomplete. The leaves are characterized by the vector of children
47 : // being empty.
48 :
49 : //--------------------------------------------------------------------------
50 :
51 : // Number of trial emission to use for calculating the average number of
52 : // emissions
53 : const int History::NTRIAL = 1;
54 :
55 : //--------------------------------------------------------------------------
56 :
57 : // Declaration of History class
58 : // The only constructor. Default arguments are used when creating
59 : // the initial history node. The \a depth is the maximum number of
60 : // clusterings requested. \a scalein is the scale at which the \a
61 : // statein was clustered (should be set to the merging scale for the
62 : // initial history node. \a beamAIn and beamBIn are needed to
63 : // calcutate PDF ratios, \a particleDataIn to have access to the
64 : // correct masses of particles. If \a isOrdered is true, the previous
65 : // clusterings has been ordered. \a is the PDF ratio for this
66 : // clustering (=1 for FSR clusterings). \a probin is the accumulated
67 : // probabilities for the previous clusterings, and \ mothin is the
68 : // previous history node (null for the initial node).
69 :
70 0 : History::History( int depth,
71 : double scalein,
72 : Event statein,
73 : Clustering c,
74 : MergingHooks* mergingHooksPtrIn,
75 : BeamParticle beamAIn,
76 : BeamParticle beamBIn,
77 : ParticleData* particleDataPtrIn,
78 : Info* infoPtrIn,
79 : bool isOrdered = true,
80 : bool isStronglyOrdered = true,
81 : bool isAllowed = true,
82 : bool isNextInInput = true,
83 : double probin = 1.0,
84 : History * mothin = 0)
85 0 : : state(statein),
86 0 : mother(mothin),
87 0 : sumpath(0.0),
88 0 : sumGoodBranches(0.0),
89 0 : sumBadBranches(0.0),
90 0 : foundOrderedPath(false),
91 0 : foundStronglyOrderedPath(false),
92 0 : foundAllowedPath(false),
93 0 : foundCompletePath(false),
94 0 : scale(scalein),
95 0 : nextInInput(isNextInInput),
96 0 : prob(probin),
97 0 : clusterIn(c),
98 0 : iReclusteredOld(0),
99 0 : doInclude(true),
100 0 : mergingHooksPtr(mergingHooksPtrIn),
101 0 : beamA(beamAIn),
102 0 : beamB(beamBIn),
103 0 : particleDataPtr(particleDataPtrIn),
104 0 : infoPtr(infoPtrIn)
105 0 : {
106 :
107 : // Initialise beam particles
108 0 : setupBeams();
109 :
110 : // Update probability with PDF ratio
111 0 : if (mother && mergingHooksPtr->includeRedundant()) prob *= pdfForSudakov();
112 :
113 : // Minimal scalar sum of pT used in Herwig to choose history
114 : // Keep track of scalar PT
115 0 : if (mother) {
116 0 : double acoll = (mother->state[clusterIn.emittor].isFinal())
117 0 : ? mergingHooksPtr->herwigAcollFSR()
118 0 : : mergingHooksPtr->herwigAcollISR();
119 0 : sumScalarPT = mother->sumScalarPT + acoll*scale;
120 0 : } else
121 0 : sumScalarPT = 0.0;
122 :
123 : // Remember reclustered radiator in lower multiplicity state
124 0 : if ( mother ) iReclusteredOld = mother->iReclusteredNew;
125 :
126 : // Check if more steps should be taken.
127 : int nFinalP = 0;
128 : int nFinalW = 0;
129 0 : for ( int i = 0; i < int(state.size()); ++i )
130 0 : if ( state[i].isFinal() ) {
131 0 : if ( state[i].colType() != 0 )
132 0 : nFinalP++;
133 0 : if ( state[i].idAbs() == 24 )
134 0 : nFinalW++;
135 : }
136 0 : if ( mergingHooksPtr->doWClustering()
137 0 : && nFinalP == 2 && nFinalW == 0 ) depth = 0;
138 :
139 : // If this is not the fully clustered state, try to find possible
140 : // QCD clusterings.
141 0 : vector<Clustering> clusterings;
142 0 : if ( depth > 0 ) clusterings = getAllQCDClusterings();
143 :
144 : // If necessary, try to find possible EW clusterings.
145 0 : vector<Clustering> clusteringsEW;
146 0 : if ( depth > 0 && mergingHooksPtr->doWClustering() )
147 0 : clusteringsEW = getAllEWClusterings();
148 0 : if ( !clusteringsEW.empty() ) {
149 0 : clusterings.insert( clusterings.end(), clusteringsEW.begin(),
150 0 : clusteringsEW.end() );
151 0 : }
152 :
153 : // If necessary, try to find possible SQCD clusterings.
154 0 : vector<Clustering> clusteringsSQCD;
155 0 : if ( depth > 0 && mergingHooksPtr->doSQCDClustering() )
156 0 : clusteringsSQCD = getAllSQCDClusterings();
157 0 : if ( !clusteringsSQCD.empty() )
158 0 : clusterings.insert( clusterings.end(), clusteringsSQCD.begin(),
159 0 : clusteringsSQCD.end() );
160 :
161 : // If no clusterings were found, the recursion is done and we
162 : // register this node.
163 0 : if ( clusterings.empty() ) {
164 : // Multiply with hard process matrix element.
165 0 : prob *= hardProcessME(state);
166 0 : registerPath( *this, isOrdered, isStronglyOrdered, isAllowed, depth == 0 );
167 0 : return;
168 : }
169 :
170 : // Now we sort the possible clusterings so that we try the
171 : // smallest scale first.
172 0 : multimap<double, Clustering *> sorted;
173 0 : for ( int i = 0, N = clusterings.size(); i < N; ++i ) {
174 0 : sorted.insert(make_pair(clusterings[i].pT(), &clusterings[i]));
175 : }
176 :
177 0 : for ( multimap<double, Clustering *>::iterator it = sorted.begin();
178 0 : it != sorted.end(); ++it ) {
179 :
180 : // If this path is not strongly ordered and we already have found an
181 : // ordered path, then we don't need to continue along this path.
182 0 : bool stronglyOrdered = isStronglyOrdered;
183 0 : if ( mergingHooksPtr->enforceStrongOrdering()
184 0 : && ( !stronglyOrdered
185 0 : || ( mother && ( it->first <
186 0 : mergingHooksPtr->scaleSeparationFactor()*scale ) ))) {
187 0 : if ( onlyStronglyOrderedPaths() ) continue;
188 : stronglyOrdered = false;
189 0 : }
190 :
191 : // Check if reclustering follows ordered sequence.
192 0 : bool ordered = isOrdered;
193 0 : if ( mergingHooksPtr->orderInRapidity()
194 0 : && mergingHooksPtr->orderHistories() ) {
195 : // Get new z value
196 0 : double z = getCurrentZ((*it->second).emittor,
197 0 : (*it->second).recoiler,(*it->second).emitted);
198 : // Get z value of splitting that produced this state
199 0 : double zOld = (!mother) ? 0. : mother->getCurrentZ(clusterIn.emittor,
200 0 : clusterIn.recoiler,clusterIn.emitted);
201 : // If this path is not ordered in pT and y, and we already have found
202 : // an ordered path, then we don't need to continue along this path.
203 0 : if ( !ordered || ( mother && (it->first < scale
204 0 : || it->first < pow(1. - z,2) / (z * (1. - zOld ))*scale ))) {
205 0 : if ( onlyOrderedPaths() ) continue;
206 : ordered = false;
207 0 : }
208 :
209 0 : } else if ( mergingHooksPtr->orderHistories() ) {
210 : // If this path is not ordered in pT and we already have found an
211 : // ordered path, then we don't need to continue along this path, unless
212 : // we have not yet found an allowed path.
213 0 : if ( !ordered || ( mother && (it->first < scale) ) ) {
214 0 : if ( onlyOrderedPaths() && onlyAllowedPaths() ) continue;
215 : ordered = false;
216 0 : }
217 : }
218 :
219 : // Check if reclustered state should be disallowed.
220 0 : bool doCut = mergingHooksPtr->canCutOnRecState()
221 0 : || mergingHooksPtr->allowCutOnRecState();
222 0 : bool allowed = isAllowed;
223 0 : if ( doCut
224 0 : && mergingHooksPtr->doCutOnRecState(cluster(*it->second)) ) {
225 0 : if ( onlyAllowedPaths() ) continue;
226 : allowed = false;
227 0 : }
228 :
229 : // Perform the clustering and recurse and construct the next
230 : // history node.
231 0 : children.push_back(new History(depth - 1,it->first,cluster(*it->second),
232 0 : *it->second, mergingHooksPtr, beamA, beamB, particleDataPtr,
233 0 : infoPtr, ordered, stronglyOrdered, allowed, true,
234 0 : prob*getProb(*it->second), this ));
235 0 : }
236 0 : }
237 :
238 : //--------------------------------------------------------------------------
239 :
240 : // Function to project all possible paths onto only the desired paths.
241 :
242 : bool History::projectOntoDesiredHistories() {
243 : // At the moment, only trim histories.
244 0 : return trimHistories();
245 : }
246 :
247 : //--------------------------------------------------------------------------
248 :
249 : // In the initial history node, select one of the paths according to
250 : // the probabilities. This function should be called for the initial
251 : // history node.
252 : // IN trialShower* : Previously initialised trialShower object,
253 : // to perform trial showering and as
254 : // repository of pointers to initialise alphaS
255 : // PartonSystems* : PartonSystems object needed to initialise
256 : // shower objects
257 : // OUT double : (Sukadov) , (alpha_S ratios) , (PDF ratios)
258 :
259 : double History::weightTREE(PartonLevel* trial, AlphaStrong * asFSR,
260 : AlphaStrong * asISR, double RN) {
261 :
262 0 : if ( mergingHooksPtr->canCutOnRecState() && !foundAllowedPath ) {
263 0 : string message="Warning in History::weightTREE: No allowed history";
264 0 : message+=" found. Using disallowed history.";
265 0 : infoPtr->errorMsg(message);
266 0 : }
267 0 : if ( mergingHooksPtr->orderHistories() && !foundOrderedPath ) {
268 0 : string message="Warning in History::weightTREE: No ordered history";
269 0 : message+=" found. Using unordered history.";
270 0 : infoPtr->errorMsg(message);
271 0 : }
272 0 : if ( mergingHooksPtr->canCutOnRecState()
273 0 : && mergingHooksPtr->orderHistories()
274 0 : && !foundAllowedPath && !foundOrderedPath ) {
275 0 : string message="Warning in History::weightTREE: No allowed or ordered";
276 0 : message+=" history found.";
277 0 : infoPtr->errorMsg(message);
278 0 : }
279 :
280 : // Read alpha_S in ME calculation and maximal scale (eCM)
281 0 : double asME = infoPtr->alphaS();
282 0 : double maxScale = (foundCompletePath) ? infoPtr->eCM()
283 0 : : mergingHooksPtr->muFinME();
284 : // Select a path of clusterings
285 0 : History * selected = select(RN);
286 : // Set scales in the states to the scales pythia would have set
287 0 : selected->setScalesInHistory();
288 :
289 : // Get weight.
290 : double sudakov = 1.;
291 0 : double asWeight = 1.;
292 0 : double pdfWeight = 1.;
293 :
294 : // Do trial shower, calculation of alpha_S ratios, PDF ratios
295 0 : sudakov = selected->weightTree( trial, asME, maxScale,
296 0 : selected->clusterIn.pT(), asFSR, asISR, asWeight,
297 : pdfWeight );
298 :
299 : // MPI no-emission probability
300 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI();
301 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
302 : maxScale );
303 :
304 : // Set hard process renormalisation scale to default Pythia value.
305 0 : bool resetScales = mergingHooksPtr->resetHardQRen();
306 : // For pure QCD dijet events, evaluate the coupling of the hard process at
307 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
308 : // arbitrary scale.
309 0 : if ( resetScales
310 0 : && mergingHooksPtr->getProcessString().compare("pp>jj") == 0) {
311 : // Reset to a running coupling. Here we choose FSR for simplicity.
312 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
313 0 : double runningCoupling = (*asFSR).alphaS(newQ2Ren) / asME;
314 0 : asWeight *= pow2(runningCoupling);
315 0 : }
316 :
317 : // For prompt photon events, evaluate the coupling of the hard process at
318 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
319 : // arbitrary scale.
320 0 : if ( resetScales
321 0 : && mergingHooksPtr->getProcessString().compare("pp>aj") == 0) {
322 : // Reset to a running coupling. In prompt photon always ISR.
323 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
324 : double runningCoupling =
325 0 : (*asISR).alphaS( newQ2Ren + pow(mergingHooksPtr->pT0ISR(),2) ) / asME;
326 0 : asWeight *= runningCoupling;
327 0 : }
328 :
329 : // Done
330 0 : return (sudakov*asWeight*pdfWeight*mpiwt);
331 :
332 0 : }
333 :
334 : //--------------------------------------------------------------------------
335 :
336 : // Function to return weight of virtual correction and subtractive events
337 : // for NL3 merging
338 :
339 : double History::weightLOOP(PartonLevel* trial, double RN ) {
340 :
341 0 : if ( mergingHooksPtr->canCutOnRecState() && !foundAllowedPath ) {
342 0 : string message="Warning in History::weightLOOP: No allowed history";
343 0 : message+=" found. Using disallowed history.";
344 0 : infoPtr->errorMsg(message);
345 0 : }
346 :
347 : // Select a path of clusterings
348 0 : History * selected = select(RN);
349 : // Set scales in the states to the scales pythia would have set
350 0 : selected->setScalesInHistory();
351 :
352 : // So far, no reweighting
353 : double wt = 1.;
354 :
355 : // Only reweighting with MPI no-emission probability
356 0 : double maxScale = (foundCompletePath) ? infoPtr->eCM()
357 0 : : mergingHooksPtr->muFinME();
358 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI();
359 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
360 : maxScale );
361 : wt = mpiwt;
362 : // Done
363 0 : return wt;
364 0 : }
365 :
366 : //--------------------------------------------------------------------------
367 :
368 : // Function to calculate O(\alpha_s)-term of CKKWL-weight for NLO merging
369 :
370 : double History::weightFIRST(PartonLevel* trial, AlphaStrong* asFSR,
371 : AlphaStrong* asISR, double RN, Rndm* rndmPtr ) {
372 :
373 : // Read alpha_S in ME calculation and maximal scale (eCM)
374 0 : double asME = infoPtr->alphaS();
375 0 : double muR = mergingHooksPtr->muRinME();
376 0 : double maxScale = (foundCompletePath)
377 0 : ? infoPtr->eCM()
378 0 : : mergingHooksPtr->muFinME();
379 :
380 : // Pick path of clusterings
381 0 : History * selected = select(RN);
382 : // Set scales in the states to the scales pythia would have set
383 0 : selected->setScalesInHistory();
384 :
385 0 : double nSteps = mergingHooksPtr->getNumberOfClusteringSteps(state);
386 :
387 : // Get the lowest order k-factor and add first two terms in expansion
388 0 : double kFactor = asME * mergingHooksPtr->k1Factor(nSteps);
389 :
390 : // If using Bbar, which includes a tree-level part, subtract an
391 : // additional one, i.e. the O(\as^0) contribution as well
392 0 : double wt = 1. + kFactor;
393 :
394 : // Calculate sum of O(alpha) terms
395 0 : wt += selected->weightFirst(trial,asME, muR, maxScale, asFSR, asISR,
396 : rndmPtr );
397 :
398 : // Get starting scale for trial showers.
399 0 : double startingScale = (selected->mother) ? state.scale() : infoPtr->eCM();
400 :
401 : // Count emissions: New variant
402 : // Generate true average, not only one-point
403 : bool fixpdf = true;
404 : bool fixas = true;
405 : double nWeight1 = 0.;
406 0 : for(int i=0; i < NTRIAL; ++i) {
407 : // Get number of emissions
408 0 : vector<double> unresolvedEmissionTerm = countEmissions( trial,
409 0 : startingScale, mergingHooksPtr->tms(), 2, asME, asFSR, asISR, 3,
410 : fixpdf, fixas );
411 0 : nWeight1 += unresolvedEmissionTerm[1];
412 0 : }
413 :
414 0 : wt += nWeight1/double(NTRIAL);
415 :
416 : // Done
417 0 : return wt;
418 :
419 : }
420 :
421 : //--------------------------------------------------------------------------
422 :
423 : double History::weight_UMEPS_TREE(PartonLevel* trial, AlphaStrong * asFSR,
424 : AlphaStrong * asISR, double RN) {
425 : // No difference to CKKW-L. Recycle CKKW-L function.
426 0 : return weightTREE( trial, asFSR, asISR, RN);
427 : }
428 :
429 : //--------------------------------------------------------------------------
430 :
431 : // Function to return weight of virtual correction events for NLO merging
432 :
433 : double History::weight_UMEPS_SUBT(PartonLevel* trial, AlphaStrong * asFSR,
434 : AlphaStrong * asISR, double RN ) {
435 :
436 : // Read alpha_S in ME calculation and maximal scale (eCM)
437 0 : double asME = infoPtr->alphaS();
438 0 : double maxScale = (foundCompletePath) ? infoPtr->eCM()
439 0 : : mergingHooksPtr->muFinME();
440 : // Select a path of clusterings
441 0 : History * selected = select(RN);
442 : // Set scales in the states to the scales pythia would have set
443 0 : selected->setScalesInHistory();
444 :
445 : // Get weight.
446 : double sudakov = 1.;
447 0 : double asWeight = 1.;
448 0 : double pdfWeight = 1.;
449 :
450 : // Do trial shower, calculation of alpha_S ratios, PDF ratios
451 0 : sudakov = selected->weightTree(trial, asME, maxScale,
452 0 : selected->clusterIn.pT(), asFSR,asISR, asWeight, pdfWeight);
453 :
454 : // MPI no-emission probability.
455 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI()+1;
456 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
457 : maxScale );
458 :
459 : // Set hard process renormalisation scale to default Pythia value.
460 0 : bool resetScales = mergingHooksPtr->resetHardQRen();
461 : // For pure QCD dijet events, evaluate the coupling of the hard process at
462 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
463 : // arbitrary scale.
464 0 : if ( resetScales
465 0 : && mergingHooksPtr->getProcessString().compare("pp>jj") == 0) {
466 : // Reset to a running coupling. Here we choose FSR for simplicity.
467 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
468 0 : double runningCoupling = (*asFSR).alphaS(newQ2Ren) / asME;
469 0 : asWeight *= pow(runningCoupling,2);
470 0 : }
471 :
472 : // For prompt photon events, evaluate the coupling of the hard process at
473 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
474 : // arbitrary scale.
475 0 : if ( resetScales
476 0 : && mergingHooksPtr->getProcessString().compare("pp>aj") == 0) {
477 : // Reset to a running coupling. In prompt photon always ISR.
478 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
479 : double runningCoupling =
480 0 : (*asISR).alphaS( newQ2Ren + pow(mergingHooksPtr->pT0ISR(),2) ) / asME;
481 0 : asWeight *= runningCoupling;
482 0 : }
483 :
484 : // Done
485 0 : return (sudakov*asWeight*pdfWeight*mpiwt);
486 :
487 0 : }
488 :
489 : //--------------------------------------------------------------------------
490 :
491 : double History::weight_UNLOPS_TREE(PartonLevel* trial, AlphaStrong * asFSR,
492 : AlphaStrong * asISR, double RN) {
493 :
494 : // Read alpha_S in ME calculation and maximal scale (eCM)
495 0 : double asME = infoPtr->alphaS();
496 0 : double maxScale = (foundCompletePath) ? infoPtr->eCM()
497 0 : : mergingHooksPtr->muFinME();
498 : // Select a path of clusterings
499 0 : History * selected = select(RN);
500 : // Set scales in the states to the scales pythia would have set
501 0 : selected->setScalesInHistory();
502 :
503 : // Get weight.
504 0 : double asWeight = 1.;
505 0 : double pdfWeight = 1.;
506 :
507 : // Do trial shower, calculation of alpha_S ratios, PDF ratios
508 0 : double wt = selected->weightTree(trial, asME, maxScale,
509 0 : selected->clusterIn.pT(), asFSR, asISR, asWeight, pdfWeight);
510 : // MPI no-emission probability.
511 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI();
512 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
513 : maxScale );
514 :
515 : // Set hard process renormalisation scale to default Pythia value.
516 0 : bool resetScales = mergingHooksPtr->resetHardQRen();
517 : // For pure QCD dijet events, evaluate the coupling of the hard process at
518 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
519 : // arbitrary scale.
520 0 : if ( resetScales
521 0 : && mergingHooksPtr->getProcessString().compare("pp>jj") == 0) {
522 : // Reset to a running coupling. Here we choose FSR for simplicity.
523 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
524 0 : double runningCoupling = (*asFSR).alphaS(newQ2Ren) / asME;
525 0 : asWeight *= pow(runningCoupling,2);
526 0 : }
527 :
528 : // For prompt photon events, evaluate the coupling of the hard process at
529 : // a more reasonable pT, rather than evaluation \alpha_s at a fixed
530 : // arbitrary scale.
531 0 : if ( resetScales
532 0 : && mergingHooksPtr->getProcessString().compare("pp>aj") == 0) {
533 : // Reset to a running coupling. In prompt photon always ISR.
534 0 : double newQ2Ren = pow2( selected->hardRenScale(selected->state) );
535 : double runningCoupling =
536 0 : (*asISR).alphaS( newQ2Ren + pow(mergingHooksPtr->pT0ISR(),2) ) / asME;
537 0 : asWeight *= runningCoupling;
538 0 : }
539 :
540 : // Done
541 0 : return (wt*asWeight*pdfWeight*mpiwt);
542 :
543 0 : }
544 :
545 : //--------------------------------------------------------------------------
546 :
547 : double History::weight_UNLOPS_LOOP(PartonLevel* trial, double RN ) {
548 : // No difference to default NL3
549 0 : return weightLOOP(trial, RN );
550 : }
551 :
552 : //--------------------------------------------------------------------------
553 :
554 : double History::weight_UNLOPS_SUBT(PartonLevel* trial, AlphaStrong * asFSR,
555 : AlphaStrong * asISR, double RN ) {
556 :
557 : // Select a path of clusterings
558 0 : History * selected = select(RN);
559 : // Set scales in the states to the scales pythia would have set
560 0 : selected->setScalesInHistory();
561 : // So far, no reweighting
562 : double wt = 1.;
563 :
564 : // Read alpha_S in ME calculation and maximal scale (eCM)
565 0 : double asME = infoPtr->alphaS();
566 0 : double maxScale = (foundCompletePath)
567 0 : ? infoPtr->eCM()
568 0 : : mergingHooksPtr->muFinME();
569 :
570 : // Only allow two clusterings if all intermediate states above the
571 : // merging scale.
572 0 : double nSteps = mergingHooksPtr->getNumberOfClusteringSteps(state);
573 0 : if ( nSteps == 2 && mergingHooksPtr->nRecluster() == 2
574 0 : && ( !foundCompletePath
575 0 : || !selected->allIntermediateAboveRhoMS( mergingHooksPtr->tms() )) ) {
576 0 : return 0.;
577 : }
578 :
579 : // Get weights: alpha_S ratios and PDF ratios
580 0 : double asWeight = 1.;
581 0 : double pdfWeight = 1.;
582 : // Do trial shower, calculation of alpha_S ratios, PDF ratios
583 0 : double sudakov = selected->weightTree(trial, asME, maxScale,
584 0 : selected->clusterIn.pT(), asFSR, asISR,
585 : asWeight, pdfWeight);
586 : // MPI no-emission probability.
587 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI()+1;
588 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
589 : maxScale );
590 :
591 : // Set weight
592 0 : wt = ( mergingHooksPtr->nRecluster() == 2 ) ? 1.
593 0 : : asWeight*pdfWeight*sudakov*mpiwt;
594 :
595 : // Done
596 : return wt;
597 :
598 0 : }
599 :
600 : //--------------------------------------------------------------------------
601 :
602 : double History::weight_UNLOPS_SUBTNLO(PartonLevel* trial, double RN ) {
603 :
604 : // Select a path of clusterings
605 0 : History * selected = select(RN);
606 : // Set scales in the states to the scales pythia would have set
607 0 : selected->setScalesInHistory();
608 : // So far, no reweighting
609 : double wt = 1.;
610 : // Only reweighting with MPI no-emission probability
611 0 : double maxScale = (foundCompletePath) ? infoPtr->eCM()
612 0 : : mergingHooksPtr->muFinME();
613 0 : int njetsMaxMPI = mergingHooksPtr->nMinMPI()+1;
614 0 : double mpiwt = selected->weightTreeEmissions( trial, -1, 0, njetsMaxMPI,
615 : maxScale );
616 : wt = mpiwt;
617 : // Done
618 0 : return wt;
619 :
620 : }
621 :
622 : //--------------------------------------------------------------------------
623 :
624 : // Function to calculate O(\alpha_s)-term of CKKWL-weight for NLO merging
625 :
626 : double History::weight_UNLOPS_CORRECTION( int order, PartonLevel* trial,
627 : AlphaStrong* asFSR, AlphaStrong* asISR,
628 : double RN, Rndm* rndmPtr ) {
629 :
630 : // Already done if no correction should be calculated
631 0 : if ( order < 0 ) return 0.;
632 :
633 : // Read alpha_S in ME calculation and maximal scale (eCM)
634 0 : double asME = infoPtr->alphaS();
635 0 : double muR = mergingHooksPtr->muRinME();
636 0 : double maxScale = (foundCompletePath)
637 0 : ? infoPtr->eCM()
638 0 : : mergingHooksPtr->muFinME();
639 :
640 : // Pick path of clusterings
641 0 : History * selected = select(RN);
642 : // Set scales in the states to the scales pythia would have set
643 0 : selected->setScalesInHistory();
644 :
645 0 : double nSteps = mergingHooksPtr->getNumberOfClusteringSteps(state);
646 :
647 : // Get the lowest order k-factor and add first two terms in expansion
648 0 : double kFactor = asME * mergingHooksPtr->k1Factor(nSteps);
649 :
650 : // If using Bbar, which includes a tree-level part, subtract an
651 : // additional one, i.e. the O(\as^0) contribution as well
652 : double wt = 1.;
653 :
654 : // If only O(\alpha_s^0)-term is to be calculated, done already.
655 0 : if ( order == 0 ) return wt;
656 :
657 : // Start by adding the O(\alpha_s^1)-term of the k-factor.
658 0 : wt += kFactor;
659 :
660 : // Calculate sum of O(\alpha_s^1)-terms of the ckkw-l weight WITHOUT
661 : // the O(\alpha_s^1)-term of the last no-emission probability.
662 : bool fixpdf = true;
663 : bool fixas = true;
664 : // Get first term in expansion of alpha_s ratios.
665 0 : double wA = selected->weightFirstALPHAS( asME, muR, asFSR, asISR );
666 : // Add logarithm from \alpha_s expansion to weight.
667 0 : wt += (fixas) ? wA : 0.;
668 : // Generate true average, not only one-point.
669 : double nWeight = 0.;
670 0 : for ( int i=0; i < NTRIAL; ++i ) {
671 : // Get average number of emissions.
672 0 : double wE = selected->weightFirstEmissions(trial,asME, maxScale,
673 : asFSR, asISR, fixpdf, fixas );
674 : // Add average number of emissions off reconstructed states to weight.
675 0 : nWeight += wE;
676 : // Get first term in expansion of PDF ratios.
677 0 : double pscale = selected->clusterIn.pT();
678 0 : double wP = selected->weightFirstPDFs(asME, maxScale, pscale, rndmPtr);
679 : // Add integral of DGLAP shifted PDF ratios from \alpha_s expansion to wt.
680 0 : nWeight += (fixpdf) ? wP : 0.;
681 : }
682 0 : wt += nWeight/double(NTRIAL);
683 :
684 : // If O(\alpha_s^1)-term + O(\alpha_s^1)-term is to be calculated, done.
685 0 : if ( order == 1 ) return wt;
686 :
687 : // So far, no calculation of O(\alpha_s^2)-term
688 0 : return 0.;
689 :
690 0 : }
691 :
692 : //--------------------------------------------------------------------------
693 :
694 : // Function to set the state with complete scales for evolution.
695 :
696 : void History::getStartingConditions( const double RN, Event& outState ) {
697 :
698 : // Select the history
699 0 : History * selected = select(RN);
700 :
701 : // Set scales in the states to the scales pythia would have set
702 0 : selected->setScalesInHistory();
703 :
704 : // Copy the output state
705 0 : outState = state;
706 :
707 : // Set the scale of the lowest order process
708 0 : if (!selected->mother) {
709 : int nFinal = 0;
710 0 : for(int i=0; i < int(outState.size()); ++i)
711 0 : if (outState[i].isFinal()) nFinal++;
712 0 : if (nFinal <=2)
713 0 : outState.scale(mergingHooksPtr->muF());
714 :
715 : // Save information on last splitting, to allow the next
716 : // emission in the shower to have smaller rapidity with
717 : // respect to the last ME splitting
718 : // For hard process, use dummy values
719 0 : if (mergingHooksPtr->getNumberOfClusteringSteps(state) == 0) {
720 0 : infoPtr->zNowISR(0.5);
721 0 : infoPtr->pT2NowISR(pow(state[0].e(),2));
722 0 : infoPtr->hasHistory(true);
723 : // For incomplete process, try to use real values
724 0 : } else {
725 0 : infoPtr->zNowISR(selected->zISR());
726 0 : infoPtr->pT2NowISR(pow(selected->pTISR(),2));
727 0 : infoPtr->hasHistory(true);
728 : }
729 :
730 0 : } else {
731 :
732 : // Save information on last splitting, to allow the next
733 : // emission in the shower to have smaller rapidity with
734 : // respect to the last ME splitting
735 0 : infoPtr->zNowISR(selected->zISR());
736 0 : infoPtr->pT2NowISR(pow(selected->pTISR(),2));
737 0 : infoPtr->hasHistory(true);
738 :
739 : }
740 :
741 : // Save MPI starting scale
742 0 : if (mergingHooksPtr->getNumberOfClusteringSteps(state) == 0)
743 0 : mergingHooksPtr->muMI(infoPtr->eCM());
744 : else
745 0 : mergingHooksPtr->muMI(outState.scale());
746 :
747 0 : }
748 :
749 : //--------------------------------------------------------------------------
750 :
751 : // Function to print the history that would be chosen from the number RN.
752 :
753 : void History::printHistory( const double RN ) {
754 0 : History * selected = select(RN);
755 0 : selected->printStates();
756 : // Done
757 0 : }
758 :
759 : //--------------------------------------------------------------------------
760 :
761 : // Function to print the states in a history, starting from the hard process.
762 :
763 : void History::printStates() {
764 0 : if ( !mother ) {
765 : state.list();
766 : return;
767 : }
768 : // Print.
769 0 : state.list();
770 : // Recurse
771 0 : mother->printStates();
772 : // Done
773 0 : return;
774 0 : }
775 :
776 : //--------------------------------------------------------------------------
777 :
778 : // Function to set the state with complete scales for evolution.
779 :
780 : bool History::getClusteredEvent( const double RN, int nSteps,
781 : Event& outState) {
782 :
783 : // Select history
784 0 : History * selected = select(RN);
785 : // Set scales in the states to the scales pythia would have set
786 : // (Only needed if not done before in calculation of weights or
787 : // setting of starting conditions)
788 0 : selected->setScalesInHistory();
789 : // If the history does not allow for nSteps clusterings (e.g. because the
790 : // history is incomplete), return false
791 0 : if (nSteps > selected->nClusterings()) return false;
792 : // Return event with nSteps-1 additional partons (i.e. recluster the last
793 : // splitting) and copy the output state
794 0 : outState = selected->clusteredState(nSteps-1);
795 : // Done.
796 0 : return true;
797 :
798 0 : }
799 :
800 : //--------------------------------------------------------------------------
801 :
802 : bool History::getFirstClusteredEventAboveTMS( const double RN, int nDesired,
803 : Event& process, int& nPerformed, bool doUpdate ) {
804 :
805 : // Do reclustering (looping) steps. Remember process scale.
806 0 : int nTried = nDesired - 1;
807 : // Get number of clustering steps.
808 0 : int nSteps = select(RN)->nClusterings();
809 : // Set scales in the states to the scales pythia would have set.
810 0 : select(RN)->setScalesInHistory();
811 :
812 : // Recluster until reclustered event is above the merging scale.
813 0 : Event dummy = Event();
814 0 : do {
815 : // Initialise temporary output of reclustering.
816 0 : dummy.clear();
817 0 : dummy.init( "(hard process-modified)", particleDataPtr );
818 0 : dummy.clear();
819 : // Recluster once more.
820 0 : nTried++;
821 : // If reclustered event does not exist, exit.
822 0 : if ( !getClusteredEvent( RN, nSteps-nTried+1, dummy ) ) return false;
823 0 : if ( nTried >= nSteps ) break;
824 :
825 : // Continue loop if reclustered event has unresolved partons.
826 0 : } while ( mergingHooksPtr->getNumberOfClusteringSteps(dummy) > 0
827 0 : && mergingHooksPtr->rhoms( dummy, false) < mergingHooksPtr->tms() );
828 :
829 : // Update the hard process.
830 0 : if ( doUpdate ) process = dummy;
831 :
832 : // Failed to produce output state.
833 0 : if ( nTried > nSteps ) return false;
834 :
835 0 : nPerformed = nTried;
836 0 : if ( doUpdate ) {
837 : // Update to the actual number of steps.
838 0 : mergingHooksPtr->nReclusterSave = nPerformed;
839 : // Save MPI starting scale
840 0 : if (mergingHooksPtr->getNumberOfClusteringSteps(state) == 0)
841 0 : mergingHooksPtr->muMI(infoPtr->eCM());
842 : else
843 0 : mergingHooksPtr->muMI(state.scale());
844 : }
845 :
846 : // Done
847 0 : return true;
848 :
849 0 : }
850 :
851 : //--------------------------------------------------------------------------
852 :
853 : // Calculate and return pdf ratio.
854 :
855 : double History::getPDFratio( int side, bool forSudakov, bool useHardPDFs,
856 : int flavNum, double xNum, double muNum,
857 : int flavDen, double xDen, double muDen) {
858 :
859 : // Do nothing for e+e- beams
860 0 : if ( abs(flavNum) > 10 && flavNum != 21 ) return 1.0;
861 0 : if ( abs(flavDen) > 10 && flavDen != 21 ) return 1.0;
862 :
863 : // Now calculate PDF ratio if necessary
864 : double pdfRatio = 1.0;
865 :
866 : // Get mother and daughter pdfs
867 : double pdfNum = 0.0;
868 : double pdfDen = 0.0;
869 :
870 : // Use hard process PDFs (i.e. PDFs NOT used in ISR, FSR or MPI).
871 0 : if ( useHardPDFs ) {
872 0 : if (side == 1) {
873 0 : if (forSudakov)
874 0 : pdfNum = mother->beamA.xfHard( flavNum, xNum, muNum*muNum);
875 : else
876 0 : pdfNum = beamA.xfHard( flavNum, xNum, muNum*muNum);
877 0 : if (forSudakov)
878 0 : pdfDen = max(1e-10, beamA.xfHard( flavDen, xDen, muDen*muDen));
879 : else
880 0 : pdfDen = max(1e-10, beamA.xfHard( flavDen, xDen, muDen*muDen));
881 : } else {
882 0 : if (forSudakov)
883 0 : pdfNum = mother->beamB.xfHard( flavNum, xNum, muNum*muNum);
884 : else
885 0 : pdfNum = beamB.xfHard( flavNum, xNum, muNum*muNum);
886 :
887 0 : if (forSudakov)
888 0 : pdfDen = max(1e-10,beamB.xfHard( flavDen, xDen, muDen*muDen));
889 : else
890 0 : pdfDen = max(1e-10,beamB.xfHard( flavDen, xDen, muDen*muDen));
891 : }
892 :
893 : // Use rescaled PDFs in the presence of multiparton interactions
894 : } else {
895 0 : if (side == 1) {
896 0 : if (forSudakov)
897 0 : pdfNum = mother->beamA.xfISR(0, flavNum, xNum, muNum*muNum);
898 : else
899 0 : pdfNum = beamA.xfISR(0, flavNum, xNum, muNum*muNum);
900 0 : if (forSudakov)
901 0 : pdfDen = max(1e-10, beamA.xfISR(0, flavDen, xDen, muDen*muDen));
902 : else
903 0 : pdfDen = max(1e-10, beamA.xfISR(0, flavDen, xDen, muDen*muDen));
904 :
905 : } else {
906 0 : if (forSudakov)
907 0 : pdfNum = mother->beamB.xfISR(0, flavNum, xNum, muNum*muNum);
908 : else
909 0 : pdfNum = beamB.xfISR(0, flavNum, xNum, muNum*muNum);
910 :
911 0 : if (forSudakov)
912 0 : pdfDen = max(1e-10,beamB.xfISR(0, flavDen, xDen, muDen*muDen));
913 : else
914 0 : pdfDen = max(1e-10,beamB.xfISR(0, flavDen, xDen, muDen*muDen));
915 : }
916 : }
917 :
918 : // Return ratio of pdfs
919 0 : if ( pdfNum > 1e-15 && pdfDen > 1e-10 ) {
920 0 : pdfRatio *= pdfNum / pdfDen;
921 0 : } else if ( pdfNum < pdfDen ) {
922 : pdfRatio = 0.;
923 0 : } else if ( pdfNum > pdfDen ) {
924 : pdfRatio = 1.;
925 0 : }
926 :
927 : // Done
928 : return pdfRatio;
929 :
930 0 : }
931 :
932 : //--------------------------------------------------------------------------
933 :
934 : /*--------------- METHODS USED FOR ONLY ONE PATH OF HISTORY NODES ------- */
935 :
936 : // Function to set all scales in the sequence of states. This is a
937 : // wrapper routine for setScales and setEventScales methods
938 :
939 : void History::setScalesInHistory() {
940 : // Find correct links from n+1 to n states (mother --> child), as
941 : // needed for enforcing ordered scale sequences
942 0 : vector<int> ident;
943 0 : findPath(ident);
944 : // Set production scales in the states to the scales pythia would
945 : // have set and enforce ordering
946 0 : setScales(ident,true);
947 : // Set the overall event scales to the scale of the last branching
948 0 : setEventScales();
949 0 : }
950 :
951 : //--------------------------------------------------------------------------
952 :
953 : // Function to find the index (in the mother histories) of the
954 : // child history, thus providing a way access the path from both
955 : // initial history (mother == 0) and final history (all children == 0)
956 : // IN vector<int> : The index of each child in the children vector
957 : // of the current history node will be saved in
958 : // this vector
959 : // NO OUTPUT
960 :
961 : void History::findPath(vector<int>& out) {
962 :
963 : // If the initial and final nodes are identical, return
964 0 : if (!mother && int(children.size()) < 1) return;
965 : // Find the child by checking the children vector for the perfomed
966 : // clustering
967 0 : int iChild=-1;
968 0 : if ( mother ) {
969 0 : int size = int(mother->children.size());
970 : // Loop through children and identify child chosen
971 0 : for ( int i=0; i < size; ++i) {
972 0 : if ( mother->children[i]->scale == scale
973 0 : && mother->children[i]->prob == prob
974 0 : && equalClustering(mother->children[i]->clusterIn,clusterIn)) {
975 0 : iChild = i;
976 0 : break;
977 : }
978 : }
979 : // Save the index of the child in the children vector and recurse
980 0 : if (iChild >-1)
981 0 : out.push_back(iChild);
982 0 : mother->findPath(out);
983 0 : }
984 0 : }
985 :
986 : //--------------------------------------------------------------------------
987 :
988 : // Functions to set the parton production scales and enforce
989 : // ordering on the scales of the respective clusterings stored in
990 : // the History node:
991 : // Method will start from lowest multiplicity state and move to
992 : // higher states, setting the production scales the shower would
993 : // have used.
994 : // When arriving at the highest multiplicity, the method will switch
995 : // and go back in direction of lower states to check and enforce
996 : // ordering for unordered histories.
997 : // IN vector<int> : Vector of positions of the chosen child
998 : // in the mother history to allow to move
999 : // in direction initial->final along path
1000 : // bool : True: Move in direction low->high
1001 : // multiplicity and set production scales
1002 : // False: Move in direction high->low
1003 : // multiplicity and check and enforce
1004 : // ordering
1005 : // NO OUTPUT
1006 :
1007 : void History::setScales( vector<int> index, bool forward) {
1008 :
1009 : // First, set the scales of the hard process to the kinematial
1010 : // limit (=s)
1011 0 : if ( children.empty() && forward ) {
1012 : // New "incomplete" configurations showered from mu
1013 0 : if (!mother) {
1014 0 : double scaleNew = 1.;
1015 :
1016 0 : if (mergingHooksPtr->incompleteScalePrescip()==0) {
1017 0 : scaleNew = mergingHooksPtr->muF();
1018 0 : } else if (mergingHooksPtr->incompleteScalePrescip()==1) {
1019 0 : Vec4 pOut;
1020 0 : pOut.p(0.,0.,0.,0.);
1021 0 : for(int i=0; i<int(state.size()); ++i)
1022 0 : if (state[i].isFinal())
1023 0 : pOut += state[i].p();
1024 0 : scaleNew = pOut.mCalc();
1025 0 : } else if (mergingHooksPtr->incompleteScalePrescip()==2) {
1026 0 : scaleNew = state[0].e();
1027 0 : }
1028 :
1029 0 : scaleNew = max( mergingHooksPtr->pTcut(), scaleNew);
1030 :
1031 0 : state.scale(scaleNew);
1032 0 : for(int i=3; i < int(state.size());++i)
1033 0 : if (state[i].colType() != 0)
1034 0 : state[i].scale(scaleNew);
1035 0 : } else {
1036 : // 2->2 with non-parton particles showered from eCM
1037 0 : state.scale( state[0].e() );
1038 : // Count final partons
1039 0 : bool isLEP = ( state[3].isLepton() && state[4].isLepton() );
1040 : int nFinal = 0;
1041 : int nFinalPartons = 0;
1042 : int nFinalPhotons = 0;
1043 0 : for ( int i=0; i < int(state.size()); ++i ) {
1044 0 : if ( state[i].isFinal() ) {
1045 0 : nFinal++;
1046 0 : if ( state[i].colType() != 0 ) nFinalPartons++;
1047 0 : if ( state[i].id() == 22 ) nFinalPhotons++;
1048 : }
1049 : }
1050 0 : bool isQCD = ( nFinal == 2 && nFinal == nFinalPartons );
1051 0 : bool isPPh = ( nFinal == 2 && nFinalPartons == 1 && nFinalPhotons == 1);
1052 : // If 2->2, purely partonic, set event scale to kinematic pT
1053 0 : if ( !isLEP && ( isQCD || isPPh ) )
1054 0 : state.scale( hardFacScale(state) );
1055 :
1056 : }
1057 : }
1058 : // Set all particle production scales, starting from lowest
1059 : // multiplicity (final) state
1060 0 : if (mother && forward) {
1061 : // When choosing splitting scale, beware of unordered splittings:
1062 : double scaleNew = 1.;
1063 0 : if (mergingHooksPtr->unorderedScalePrescip() == 0) {
1064 : // Use larger scale as common splitting scale for mother and child
1065 0 : scaleNew = max( mergingHooksPtr->pTcut(), max(scale,mother->scale));
1066 0 : } else if (mergingHooksPtr->unorderedScalePrescip() == 1) {
1067 : // Use smaller scale as common splitting scale for mother and child
1068 0 : if (scale < mother->scale)
1069 0 : scaleNew *= max( mergingHooksPtr->pTcut(), min(scale,mother->scale));
1070 : else
1071 0 : scaleNew *= max( mergingHooksPtr->pTcut(), max(scale,mother->scale));
1072 : }
1073 :
1074 : // Rescale the mother state partons to the clustering scales
1075 : // that have been found along the path
1076 0 : mother->state[clusterIn.emitted].scale(scaleNew);
1077 0 : mother->state[clusterIn.emittor].scale(scaleNew);
1078 0 : mother->state[clusterIn.recoiler].scale(scaleNew);
1079 :
1080 : // Find unchanged copies of partons in higher multiplicity states
1081 : // and rescale those
1082 0 : mother->scaleCopies(clusterIn.emitted, mother->state, scaleNew);
1083 0 : mother->scaleCopies(clusterIn.emittor, mother->state, scaleNew);
1084 0 : mother->scaleCopies(clusterIn.recoiler, mother->state, scaleNew);
1085 :
1086 : // Recurse
1087 0 : mother->setScales(index,true);
1088 0 : }
1089 :
1090 : // Now, check and correct ordering from the highest multiplicity
1091 : // state backwards to all the clustered states
1092 0 : if (!mother || !forward) {
1093 : // Get index of child along the path
1094 : int iChild = -1;
1095 0 : if ( int(index.size()) > 0 ) {
1096 0 : iChild = index.back();
1097 0 : index.pop_back();
1098 0 : }
1099 :
1100 : // Check that the reclustered scale is above the shower cut
1101 0 : if (mother) {
1102 0 : scale = max(mergingHooksPtr->pTcut(), scale);
1103 0 : }
1104 : // If this is NOT the 2->2 process, check and enforce ordering
1105 0 : if (iChild != -1 && !children.empty()) {
1106 :
1107 0 : if (scale > children[iChild]->scale ) {
1108 0 : if (mergingHooksPtr->unorderedScalePrescip() == 0) {
1109 : // Use larger scale as common splitting scale for mother and child
1110 0 : double scaleNew = max( mergingHooksPtr->pTcut(),
1111 0 : max(scale,children[iChild]->scale));
1112 : // Enforce ordering in particle production scales
1113 0 : for( int i = 0; i < int(children[iChild]->state.size()); ++i)
1114 0 : if (children[iChild]->state[i].scale() == children[iChild]->scale)
1115 0 : children[iChild]->state[i].scale(scaleNew);
1116 : // Enforce ordering in saved clustering scale
1117 0 : children[iChild]->scale = scaleNew;
1118 :
1119 0 : } else if ( mergingHooksPtr->unorderedScalePrescip() == 1) {
1120 : // Use smaller scale as common splitting scale for mother & child
1121 0 : double scaleNew = max(mergingHooksPtr->pTcut(),
1122 0 : min(scale,children[iChild]->scale));
1123 : // Enforce ordering in particle production scales
1124 0 : for( int i = 0; i < int(state.size()); ++i)
1125 0 : if (state[i].scale() == scale)
1126 0 : state[i].scale(scaleNew);
1127 : // Enforce ordering in saved clustering scale
1128 0 : scale = scaleNew;
1129 0 : }
1130 : // Just set the overall event scale to the minimal scale
1131 : } else {
1132 0 : double scalemin = state[0].e();
1133 0 : for( int i = 0; i < int(state.size()); ++i)
1134 0 : if (state[i].colType() != 0)
1135 0 : scalemin = max(mergingHooksPtr->pTcut(),
1136 0 : min(scalemin,state[i].scale()));
1137 0 : state.scale(scalemin);
1138 0 : scale = max(mergingHooksPtr->pTcut(), scale);
1139 0 : }
1140 : //Recurse
1141 0 : children[iChild]->setScales(index, false);
1142 0 : }
1143 0 : }
1144 :
1145 0 : }
1146 :
1147 : //--------------------------------------------------------------------------
1148 :
1149 : // Function to find a particle in all higher multiplicity events
1150 : // along the history path and set its production scale to the input
1151 : // scale
1152 : // IN int iPart : Parton in refEvent to be checked / rescaled
1153 : // Event& refEvent : Reference event for iPart
1154 : // double scale : Scale to be set as production scale for
1155 : // unchanged copies of iPart in subsequent steps
1156 :
1157 : void History::scaleCopies(int iPart, const Event& refEvent, double rho) {
1158 :
1159 : // Check if any parton recently rescaled is found unchanged:
1160 : // Same charge, colours in mother->state
1161 0 : if ( mother ) {
1162 0 : for( int i=0; i < mother->state.size(); ++i) {
1163 0 : if ( ( mother->state[i].id() == refEvent[iPart].id()
1164 0 : && mother->state[i].colType() == refEvent[iPart].colType()
1165 0 : && mother->state[i].chargeType() == refEvent[iPart].chargeType()
1166 0 : && mother->state[i].col() == refEvent[iPart].col()
1167 0 : && mother->state[i].acol() == refEvent[iPart].acol() )
1168 : ) {
1169 : // Rescale the unchanged parton
1170 0 : mother->state[i].scale(rho);
1171 : // Recurse
1172 0 : if (mother->mother)
1173 0 : mother->scaleCopies( iPart, refEvent, rho );
1174 : } // end if found unchanged parton case
1175 : } // end loop over particle entries in event
1176 0 : }
1177 0 : }
1178 :
1179 : //--------------------------------------------------------------------------
1180 :
1181 : // Functions to set the OVERALL EVENT SCALES [=state.scale()] to
1182 : // the scale of the last clustering
1183 : // NO INPUT
1184 : // NO OUTPUT
1185 :
1186 : void History::setEventScales() {
1187 : // Set the event scale to the scale of the last clustering,
1188 : // except for the very lowest multiplicity state
1189 0 : if (mother) {
1190 0 : mother->state.scale(scale);
1191 : // Recurse
1192 0 : mother->setEventScales();
1193 0 : }
1194 0 : }
1195 :
1196 : //--------------------------------------------------------------------------
1197 :
1198 : // Functions to return the z value of the last ISR splitting
1199 : // NO INPUT
1200 : // OUTPUT double : z value of last ISR splitting in history
1201 :
1202 : double History::zISR() {
1203 :
1204 : // Do nothing for ME level state
1205 0 : if (!mother) return 0.0;
1206 : // Skip FSR splitting
1207 0 : if (mother->state[clusterIn.emittor].isFinal()) return mother->zISR();
1208 : // Calculate z
1209 0 : int rad = clusterIn.emittor;
1210 0 : int rec = clusterIn.recoiler;
1211 0 : int emt = clusterIn.emitted;
1212 0 : double z = (mother->state[rad].p() + mother->state[rec].p()
1213 0 : - mother->state[emt].p()).m2Calc()
1214 0 : / (mother->state[rad].p() + mother->state[rec].p()).m2Calc();
1215 : // Recurse
1216 0 : double znew = mother->zISR();
1217 : // Update z
1218 0 : if (znew > 0.) z = znew;
1219 :
1220 : return z;
1221 0 : }
1222 :
1223 : //--------------------------------------------------------------------------
1224 :
1225 : // Functions to return the z value of the last FSR splitting
1226 : // NO INPUT
1227 : // OUTPUT double : z value of last FSR splitting in history
1228 :
1229 : double History::zFSR() {
1230 :
1231 : // Do nothing for ME level state
1232 0 : if (!mother) return 0.0;
1233 : // Skip ISR splitting
1234 0 : if (!mother->state[clusterIn.emittor].isFinal()) return mother->zFSR();
1235 : // Calculate z
1236 0 : int rad = clusterIn.emittor;
1237 0 : int rec = clusterIn.recoiler;
1238 0 : int emt = clusterIn.emitted;
1239 : // Construct 2->3 variables for FSR
1240 0 : Vec4 sum = mother->state[rad].p() + mother->state[rec].p()
1241 0 : + mother->state[emt].p();
1242 0 : double m2Dip = sum.m2Calc();
1243 0 : double x1 = 2. * (sum * mother->state[rad].p()) / m2Dip;
1244 0 : double x3 = 2. * (sum * mother->state[emt].p()) / m2Dip;
1245 : // Calculate z of splitting for FSR
1246 0 : double z = x1/(x1+x3);
1247 : // Recurse
1248 0 : double znew = mother->zFSR();
1249 : // Update z
1250 0 : if (znew > 0.) z = znew;
1251 :
1252 : return z;
1253 0 : }
1254 :
1255 : //--------------------------------------------------------------------------
1256 :
1257 : // Functions to return the pT scale of the last FSR splitting
1258 : // NO INPUT
1259 : // OUTPUT double : pT scale of last FSR splitting in history
1260 :
1261 : double History::pTISR() {
1262 : // Do nothing for ME level state
1263 0 : if (!mother) return 0.0;
1264 : // Skip FSR splitting
1265 0 : if (mother->state[clusterIn.emittor].isFinal()) return mother->pTISR();
1266 0 : double pT = mother->state.scale();
1267 : // Recurse
1268 0 : double pTnew = mother->pTISR();
1269 : // Update pT
1270 0 : if (pTnew > 0.) pT = pTnew;
1271 :
1272 : return pT;
1273 0 : }
1274 :
1275 : //--------------------------------------------------------------------------
1276 :
1277 : // Functions to return the pT scale of the last FSR splitting
1278 : // NO INPUT
1279 : // OUTPUT double : pT scale of last FSR splitting in history
1280 :
1281 : double History::pTFSR() {
1282 :
1283 : // Do nothing for ME level state
1284 0 : if (!mother) return 0.0;
1285 : // Skip ISR splitting
1286 0 : if (!mother->state[clusterIn.emittor].isFinal()) return mother->pTFSR();
1287 0 : double pT = mother->state.scale();
1288 : // Recurse
1289 0 : double pTnew = mother->pTFSR();
1290 : // Update pT
1291 0 : if (pTnew > 0.) pT = pTnew;
1292 : return pT;
1293 0 : }
1294 :
1295 : //--------------------------------------------------------------------------
1296 :
1297 : // Function to return the depth of the history (i.e. the number of
1298 : // reclustered splittings)
1299 : // NO INPUT
1300 : // OUTPUT int : Depth of history
1301 :
1302 : int History::nClusterings() {
1303 0 : if (!mother) return 0;
1304 0 : int w = mother->nClusterings();
1305 0 : w += 1;
1306 : return w;
1307 0 : }
1308 :
1309 : //--------------------------------------------------------------------------
1310 :
1311 : // Functions to return the event after nSteps splittings of the 2->2 process
1312 : // Example: nSteps = 1 -> return event with one additional parton
1313 : // INPUT int : Number of splittings in the event,
1314 : // as counted from core 2->2 process
1315 : // OUTPUT Event : event with nSteps additional partons
1316 :
1317 : Event History::clusteredState(int nSteps) {
1318 :
1319 : // Save state
1320 0 : Event outState = state;
1321 : // As long as there are steps to do, recursively save state
1322 0 : if (mother && nSteps > 0)
1323 0 : outState = mother->clusteredState(nSteps - 1);
1324 : // Done
1325 : return outState;
1326 :
1327 0 : }
1328 :
1329 : //--------------------------------------------------------------------------
1330 :
1331 : // Function to choose a path from all paths in the tree
1332 : // according to their splitting probabilities
1333 : // IN double : Random number
1334 : // OUT History* : Leaf of history path chosen
1335 :
1336 : History * History::select(double rnd) {
1337 :
1338 : // No need to choose if no paths have been constructed.
1339 0 : if ( goodBranches.empty() && badBranches.empty() ) return this;
1340 :
1341 : // Choose amongst paths allowed by projections.
1342 : double sum = 0.;
1343 0 : map<double, History*> selectFrom;
1344 0 : if ( !goodBranches.empty() ) {
1345 0 : selectFrom = goodBranches;
1346 0 : sum = sumGoodBranches;
1347 0 : } else {
1348 0 : selectFrom = badBranches;
1349 0 : sum = sumBadBranches;
1350 : }
1351 :
1352 0 : if (mergingHooksPtr->pickBySumPT()) {
1353 : // Find index of history with minimal sum of scalar pT
1354 : int nFinal = 0;
1355 0 : for (int i=0; i < state.size(); ++i)
1356 0 : if (state[i].isFinal())
1357 0 : nFinal++;
1358 0 : double iMin = 0.;
1359 0 : double sumMin = (nFinal-2)*state[0].e();
1360 0 : for ( map<double, History*>::iterator it = selectFrom.begin();
1361 0 : it != selectFrom.end(); ++it ) {
1362 :
1363 0 : if (it->second->sumScalarPT < sumMin) {
1364 0 : sumMin = it->second->sumScalarPT;
1365 0 : iMin = it->first;
1366 0 : }
1367 : }
1368 : // Choose history with smallest sum of scalar pT
1369 0 : return selectFrom.lower_bound(iMin)->second;
1370 0 : } else {
1371 : // Choose history according to probability, be careful about upper bound
1372 0 : if ( rnd != 1. ) {
1373 0 : return selectFrom.upper_bound(sum*rnd)->second;
1374 : } else {
1375 0 : return selectFrom.lower_bound(sum*rnd)->second;
1376 : }
1377 : }
1378 : // Done
1379 0 : }
1380 :
1381 : //--------------------------------------------------------------------------
1382 :
1383 : // Function to project paths onto desired paths.
1384 :
1385 : bool History::trimHistories() {
1386 : // Do nothing if no paths have been constructed.
1387 0 : if ( paths.empty() ) return false;
1388 : // Loop through all constructed paths. Check all removal conditions.
1389 0 : for ( map<double, History*>::iterator it = paths.begin();
1390 0 : it != paths.end(); ++it ) {
1391 : // Check if history is allowed.
1392 0 : if ( it->second->keep() && !it->second->keepHistory() )
1393 0 : it->second->remove();
1394 : }
1395 : // Project onto desired / undesired branches.
1396 : double sumold, sumnew, sumprob, mismatch;
1397 : sumold = sumnew = sumprob = mismatch = 0.;
1398 : // Loop through all constructed paths and store allowed paths.
1399 : // Skip undesired paths.
1400 0 : for ( map<double, History*>::iterator it = paths.begin();
1401 0 : it != paths.end(); ++it ) {
1402 : // Update index
1403 0 : sumnew = it->first;
1404 0 : if ( it->second->keep() ) {
1405 : // Fill branches with allowed paths.
1406 0 : goodBranches.insert( make_pair( sumnew - mismatch, it->second) );
1407 : // Add probability of this path.
1408 0 : sumGoodBranches = sumnew - mismatch;
1409 0 : } else {
1410 : // Update mismatch in probabilities resulting from not including this
1411 : // path
1412 : double mismatchOld = mismatch;
1413 0 : mismatch += sumnew - sumold;
1414 : // Fill branches with allowed paths.
1415 0 : badBranches.insert( make_pair( mismatchOld + sumnew - sumold,
1416 0 : it->second ) );
1417 : // Add probability of this path.
1418 0 : sumBadBranches = mismatchOld + sumnew - sumold;
1419 : }
1420 : // remember index of this path in order to caclulate probability of
1421 : // subsequent path.
1422 0 : sumold = it->first;
1423 : }
1424 : // Done
1425 0 : return !goodBranches.empty();
1426 0 : }
1427 :
1428 : //--------------------------------------------------------------------------
1429 :
1430 : // Function implementing checks on a paths, deciding if the path is valid.
1431 :
1432 : bool History::keepHistory() {
1433 : bool keepPath = true;
1434 : // Tag unordered paths for removal.
1435 0 : if ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
1436 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 ) {
1437 : // Tag unordered paths for removal. Include scale of hard 2->2 process
1438 : // into the ordering definition.
1439 0 : double maxScale = hardFacScale(state);
1440 0 : keepPath = isOrderedPath( maxScale );
1441 0 : }
1442 :
1443 : //Done
1444 0 : return keepPath;
1445 0 : }
1446 :
1447 : //--------------------------------------------------------------------------
1448 :
1449 : // Function to check if a path is ordered in evolution pT.
1450 :
1451 : bool History::isOrderedPath( double maxscale ) {
1452 0 : double newscale = clusterIn.pT();
1453 0 : if ( !mother ) return true;
1454 0 : bool ordered = mother->isOrderedPath(newscale);
1455 0 : if ( !ordered || maxscale < newscale) return false;
1456 0 : return ordered;
1457 0 : }
1458 :
1459 : //--------------------------------------------------------------------------
1460 :
1461 : // Function to check if all reconstucted states in a path pass the merging
1462 : // scale cut.
1463 :
1464 : bool History::allIntermediateAboveRhoMS( double rhoms, bool good ) {
1465 : // If one state below the merging scale has already been found, no need to
1466 : // check further.
1467 0 : if ( !good ) return false;
1468 : // Check merging scale for states with more than 0 jets
1469 : int nFinal = 0;
1470 0 : for ( int i = 0; i < state.size(); ++i )
1471 0 : if ( state[i].isFinal() && state[i].colType() != 0 )
1472 0 : nFinal++;
1473 0 : double rhoNew = (nFinal > 0 ) ? mergingHooksPtr->rhoms( state, false )
1474 0 : : state[0].e();
1475 : // Assume state from ME generator passes merging scale cut.
1476 0 : if ( !mother ) return good;
1477 : // Recurse.
1478 0 : return good && mother->allIntermediateAboveRhoMS( rhoms, (rhoNew > rhoms) );
1479 0 : }
1480 :
1481 : //--------------------------------------------------------------------------
1482 :
1483 : // Function to check if any ordered paths were found (and kept).
1484 :
1485 : bool History::foundAnyOrderedPaths() {
1486 : //Do nothing if no paths were found
1487 0 : if ( paths.empty() ) return false;
1488 0 : double maxscale = infoPtr->eCM();
1489 : // Loop through paths. Divide probability into ordered and unordered pieces.
1490 0 : for ( map<double, History*>::iterator it = paths.begin();
1491 0 : it != paths.end(); ++it )
1492 0 : if ( it->second->isOrderedPath(maxscale) )
1493 0 : return true;
1494 : // Done
1495 0 : return false;
1496 0 : }
1497 :
1498 : //--------------------------------------------------------------------------
1499 :
1500 : // For a full path, find the weight calculated from the ratio of
1501 : // couplings, the no-emission probabilities, and possible PDF
1502 : // ratios. This function should only be called for the last history
1503 : // node of a full path.
1504 : // IN TimeShower : Already initialised shower object to be used as
1505 : // trial shower
1506 : // double : alpha_s value used in ME calculation
1507 : // double : Maximal mass scale of the problem (e.g. E_CM)
1508 : // AlphaStrong: Initialised shower alpha_s object for FSR
1509 : // alpha_s ratio calculation
1510 : // AlphaStrong: Initialised shower alpha_s object for ISR
1511 : // alpha_s ratio calculation (can be different from previous)
1512 :
1513 : double History::weightTree(PartonLevel* trial, double as0, double maxscale,
1514 : double pdfScale, AlphaStrong * asFSR, AlphaStrong * asISR,
1515 : double& asWeight, double& pdfWeight) {
1516 :
1517 : // Use correct scale
1518 0 : double newScale = scale;
1519 :
1520 : // For ME state, just multiply by PDF ratios
1521 0 : if ( !mother ) {
1522 :
1523 0 : int sideRad = (state[3].pz() > 0) ? 1 :-1;
1524 0 : int sideRec = (state[4].pz() > 0) ? 1 :-1;
1525 : // Calculate PDF first leg
1526 0 : if (state[3].colType() != 0) {
1527 : // Find x value and flavour
1528 0 : double x = 2.*state[3].e() / state[0].e();
1529 0 : int flav = state[3].id();
1530 :
1531 : // Find numerator/denominator scale
1532 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1533 0 : double scaleDen = mergingHooksPtr->muFinME();
1534 : // For initial parton, multiply by PDF ratio
1535 0 : double ratio = getPDFratio(sideRad, false, false, flav, x, scaleNum,
1536 : flav, x, scaleDen);
1537 0 : pdfWeight *= ratio;
1538 0 : }
1539 :
1540 : // Calculate PDF ratio for second leg
1541 0 : if (state[4].colType() != 0) {
1542 : // Find x value and flavour
1543 0 : double x = 2.*state[4].e() / state[0].e();
1544 0 : int flav = state[4].id();
1545 : // Find numerator/denominator scale
1546 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1547 0 : double scaleDen = mergingHooksPtr->muFinME();
1548 : // For initial parton, multiply with PDF ratio
1549 0 : double ratio = getPDFratio(sideRec, false, false, flav, x, scaleNum,
1550 : flav, x, scaleDen);
1551 0 : pdfWeight *= ratio;
1552 0 : }
1553 :
1554 : return 1.0;
1555 : }
1556 :
1557 : // Remember new PDF scale n case true sclae should be used for un-ordered
1558 : // splittings.
1559 : double newPDFscale = newScale;
1560 0 : if (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1561 0 : newPDFscale = clusterIn.pT();
1562 :
1563 : // Recurse
1564 0 : double w = mother->weightTree(trial, as0, newScale, newPDFscale,
1565 : asFSR, asISR, asWeight, pdfWeight);
1566 :
1567 : // Do nothing for empty state
1568 0 : if (state.size() < 3) return 1.0;
1569 : // If up to now, trial shower was not successful, return zero
1570 0 : if ( w < 1e-12 ) return 0.0;
1571 : // Do trial shower on current state, return zero if not successful
1572 0 : w *= doTrialShower(trial, 1, maxscale);
1573 0 : if ( w < 1e-12 ) return 0.0;
1574 :
1575 : // Calculate alpha_s ratio for current state
1576 0 : if ( asFSR && asISR ) {
1577 0 : double asScale = pow2( newScale );
1578 0 : if (mergingHooksPtr->unorderedASscalePrescip() == 1)
1579 0 : asScale = pow2( clusterIn.pT() );
1580 0 : bool FSR = mother->state[clusterIn.emittor].isFinal();
1581 0 : double alphaSinPS = (FSR) ? (*asFSR).alphaS(asScale)
1582 0 : : (*asISR).alphaS(asScale
1583 0 : + pow2(mergingHooksPtr->pT0ISR()) );
1584 0 : asWeight *= alphaSinPS / as0;
1585 0 : }
1586 :
1587 : // Calculate pdf ratios: Get both sides of event
1588 : int inP = 3;
1589 : int inM = 4;
1590 0 : int sideP = (mother->state[inP].pz() > 0) ? 1 :-1;
1591 0 : int sideM = (mother->state[inM].pz() > 0) ? 1 :-1;
1592 :
1593 0 : if ( mother->state[inP].colType() != 0 ) {
1594 : // Find x value and flavour
1595 0 : double x = getCurrentX(sideP);
1596 0 : int flav = getCurrentFlav(sideP);
1597 : // Find numerator scale
1598 0 : double scaleNum = (children.empty())
1599 0 : ? hardFacScale(state)
1600 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1601 : ? pdfScale : maxscale );
1602 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1603 0 : ? clusterIn.pT() : newScale;
1604 : // Multiply PDF ratio
1605 0 : double ratio = getPDFratio(sideP, false, false, flav, x, scaleNum,
1606 : flav, x, scaleDen);
1607 0 : pdfWeight *= ratio;
1608 0 : }
1609 :
1610 0 : if ( mother->state[inM].colType() != 0 ) {
1611 : // Find x value and flavour
1612 0 : double x = getCurrentX(sideM);
1613 0 : int flav = getCurrentFlav(sideM);
1614 : // Find numerator scale
1615 0 : double scaleNum = (children.empty())
1616 0 : ? hardFacScale(state)
1617 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1618 : ? pdfScale : maxscale );
1619 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1620 0 : ? clusterIn.pT() : newScale;
1621 : // Multiply PDF ratio
1622 0 : double ratio = getPDFratio(sideM, false, false, flav, x, scaleNum,
1623 : flav, x, scaleDen);
1624 0 : pdfWeight *= ratio;
1625 0 : }
1626 :
1627 : // Done
1628 : return w;
1629 0 : }
1630 :
1631 : //--------------------------------------------------------------------------
1632 :
1633 : // Function to return the \alpha_s-ratio part of the CKKWL weight of a path.
1634 :
1635 : double History::weightTreeALPHAS( double as0, AlphaStrong * asFSR,
1636 : AlphaStrong * asISR ) {
1637 :
1638 : // For ME state, do nothing.
1639 0 : if ( !mother ) return 1.;
1640 : // Recurse
1641 0 : double w = mother->weightTreeALPHAS( as0, asFSR, asISR );
1642 : // Do nothing for empty state
1643 0 : if (state.size() < 3) return w;
1644 :
1645 : // Calculate alpha_s ratio for current state
1646 0 : if ( asFSR && asISR ) {
1647 0 : double asScale = pow2( scale );
1648 0 : if (mergingHooksPtr->unorderedASscalePrescip() == 1)
1649 0 : asScale = pow2( clusterIn.pT() );
1650 0 : bool FSR = mother->state[clusterIn.emittor].isFinal();
1651 0 : double alphaSinPS = (FSR)
1652 0 : ? (*asFSR).alphaS(asScale)
1653 0 : : (*asISR).alphaS(asScale + pow2(mergingHooksPtr->pT0ISR()) );
1654 0 : w *= alphaSinPS / as0;
1655 0 : }
1656 :
1657 : // Done
1658 0 : return w;
1659 0 : }
1660 :
1661 : //--------------------------------------------------------------------------
1662 :
1663 : // Function to return the PDF-ratio part of the CKKWL weight of a path.
1664 :
1665 : double History::weightTreePDFs( double maxscale, double pdfScale ) {
1666 :
1667 : // Use correct scale
1668 0 : double newScale = scale;
1669 :
1670 : // For ME state, just multiply by PDF ratios
1671 0 : if ( !mother ) {
1672 :
1673 : double wt = 1.;
1674 0 : int sideRad = (state[3].pz() > 0) ? 1 :-1;
1675 0 : int sideRec = (state[4].pz() > 0) ? 1 :-1;
1676 :
1677 : // Calculate PDF first leg
1678 0 : if (state[3].colType() != 0) {
1679 : // Find x value and flavour
1680 0 : double x = 2.*state[3].e() / state[0].e();
1681 0 : int flav = state[3].id();
1682 : // Find numerator/denominator scale
1683 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1684 0 : double scaleDen = mergingHooksPtr->muFinME();
1685 : // For initial parton, multiply by PDF ratio
1686 0 : wt *= getPDFratio(sideRad, false, false, flav, x, scaleNum, flav, x,
1687 : scaleDen);
1688 0 : }
1689 :
1690 : // Calculate PDF ratio for second leg
1691 0 : if (state[4].colType() != 0) {
1692 : // Find x value and flavour
1693 0 : double x = 2.*state[4].e() / state[0].e();
1694 0 : int flav = state[4].id();
1695 : // Find numerator/denominator scale
1696 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1697 0 : double scaleDen = mergingHooksPtr->muFinME();
1698 : // For initial parton, multiply with PDF ratio
1699 0 : wt *= getPDFratio(sideRec, false, false, flav, x, scaleNum, flav, x,
1700 : scaleDen);
1701 0 : }
1702 :
1703 : return wt;
1704 : }
1705 :
1706 : // Remember new PDF scale n case true sclae should be used for un-ordered
1707 : // splittings.
1708 : double newPDFscale = newScale;
1709 0 : if ( mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1710 0 : newPDFscale = clusterIn.pT();
1711 :
1712 : // Recurse
1713 0 : double w = mother->weightTreePDFs( newScale, newPDFscale );
1714 :
1715 : // Do nothing for empty state
1716 0 : if (state.size() < 3) return w;
1717 :
1718 : // Calculate pdf ratios: Get both sides of event
1719 : int inP = 3;
1720 : int inM = 4;
1721 0 : int sideP = (mother->state[inP].pz() > 0) ? 1 :-1;
1722 0 : int sideM = (mother->state[inM].pz() > 0) ? 1 :-1;
1723 :
1724 0 : if ( mother->state[inP].colType() != 0 ) {
1725 : // Find x value and flavour
1726 0 : double x = getCurrentX(sideP);
1727 0 : int flav = getCurrentFlav(sideP);
1728 : // Find numerator scale
1729 0 : double scaleNum = (children.empty())
1730 0 : ? hardFacScale(state)
1731 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1732 : ? pdfScale : maxscale );
1733 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1734 0 : ? clusterIn.pT() : newScale;
1735 : // Multiply PDF ratio
1736 0 : double ratio = getPDFratio(sideP, false, false, flav, x, scaleNum,
1737 : flav, x, scaleDen);
1738 0 : w *= ratio;
1739 0 : }
1740 :
1741 0 : if ( mother->state[inM].colType() != 0 ) {
1742 : // Find x value and flavour
1743 0 : double x = getCurrentX(sideM);
1744 0 : int flav = getCurrentFlav(sideM);
1745 : // Find numerator scale
1746 0 : double scaleNum = (children.empty())
1747 0 : ? hardFacScale(state)
1748 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1749 : ? pdfScale : maxscale );
1750 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1751 0 : ? clusterIn.pT() : newScale;
1752 : // Multiply PDF ratio
1753 0 : double ratio = getPDFratio(sideM, false, false, flav, x, scaleNum,
1754 : flav, x, scaleDen);
1755 0 : w *= ratio;
1756 0 : }
1757 :
1758 : // Done
1759 : return w;
1760 0 : }
1761 :
1762 : //--------------------------------------------------------------------------
1763 :
1764 : // Function to return the no-emission probability part of the CKKWL weight.
1765 :
1766 : double History::weightTreeEmissions( PartonLevel* trial, int type,
1767 : int njetMin, int njetMax, double maxscale ) {
1768 :
1769 : // Use correct scale
1770 0 : double newScale = scale;
1771 : // For ME state, just multiply by PDF ratios
1772 0 : if ( !mother ) return 1.0;
1773 : // Recurse
1774 0 : double w = mother->weightTreeEmissions(trial,type,njetMin,njetMax,newScale);
1775 : // Do nothing for empty state
1776 0 : if (state.size() < 3) return 1.0;
1777 : // If up to now, trial shower was not successful, return zero
1778 0 : if ( w < 1e-12 ) return 0.0;
1779 : // If this node has too many jets, no not calculate no-emission probability.
1780 0 : int njetNow = mergingHooksPtr->getNumberOfClusteringSteps( state) ;
1781 0 : if (njetNow >= njetMax) return 1.0;
1782 :
1783 0 : if (njetNow < njetMin ) w *= 1.0;
1784 : // Do trial shower on current state, return zero if not successful
1785 0 : else w *= doTrialShower(trial, type, maxscale);
1786 :
1787 0 : if ( w < 1e-12 ) return 0.0;
1788 : // Done
1789 0 : return w;
1790 :
1791 0 : }
1792 :
1793 : //--------------------------------------------------------------------------
1794 :
1795 : // Function to generate the O(\alpha_s)-term of the CKKWL-weight.
1796 :
1797 : double History::weightFirst(PartonLevel* trial, double as0, double muR,
1798 : double maxscale, AlphaStrong * asFSR, AlphaStrong * asISR, Rndm* rndmPtr ) {
1799 :
1800 : // Use correct scale
1801 0 : double newScale = scale;
1802 :
1803 0 : if ( !mother ) {
1804 :
1805 : double weight = 0.;
1806 :
1807 : // Calculate PDF first leg
1808 0 : if (state[3].colType() != 0) {
1809 : // Find x value and flavour
1810 0 : double x = 2.*state[3].e() / state[0].e();
1811 0 : int flav = state[3].id();
1812 : // Find numerator/denominator scale
1813 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1814 0 : double scaleDen = mergingHooksPtr->muFinME();
1815 : // Monte Carlo integrand.
1816 0 : double intPDF4 = monteCarloPDFratios(flav, x, scaleNum, scaleDen,
1817 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1818 0 : weight += intPDF4;
1819 0 : }
1820 :
1821 : // Calculate PDF ratio for second leg
1822 0 : if (state[4].colType() != 0) {
1823 : // Find x value and flavour
1824 0 : double x = 2.*state[4].e() / state[0].e();
1825 0 : int flav = state[4].id();
1826 : // Find numerator/denominator scale
1827 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1828 0 : double scaleDen = mergingHooksPtr->muFinME();
1829 : // Monte Carlo integrand.
1830 0 : double intPDF4 = monteCarloPDFratios(flav, x, scaleNum, scaleDen,
1831 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1832 0 : weight += intPDF4;
1833 0 : }
1834 :
1835 : return weight;
1836 : }
1837 :
1838 : // Recurse
1839 0 : double w = mother->weightFirst(trial, as0, muR, newScale, asFSR, asISR,
1840 : rndmPtr );
1841 :
1842 : // Do nothing for empty state
1843 0 : if (state.size() < 3) return 0.0;
1844 :
1845 : // Find right scale
1846 : double b = 1.;
1847 0 : double asScale2 = newScale*newScale;
1848 0 : int showerType = (mother->state[clusterIn.emittor].isFinal() ) ? 1 : -1;
1849 0 : if (showerType == -1) {
1850 0 : asScale2 += pow(mergingHooksPtr->pT0ISR(),2);
1851 : b = 1.;
1852 0 : }
1853 : // Find summand beta_0 / 2 * ln(muR^2/t_i) due to as expansion.
1854 : double NF = 4.;
1855 : double BETA0 = 11. - 2./3.* NF;
1856 : // For fixed \alpha_s in matrix element
1857 0 : w += as0 / (2.*M_PI) * 0.5 * BETA0 * log( (muR*muR) / (b*asScale2) );
1858 :
1859 : // Count emissions: New variant
1860 : // Generate true average, not only one-point.
1861 : bool fixpdf = true;
1862 : bool fixas = true;
1863 : double nWeight1 = 0.;
1864 : double nWeight2 = 0.;
1865 :
1866 0 : for(int i=0; i < NTRIAL; ++i) {
1867 : // Get number of emissions
1868 0 : vector<double> unresolvedEmissionTerm = countEmissions(trial, maxscale,
1869 : newScale, 2, as0, asFSR, asISR, 3, fixpdf, fixas);
1870 0 : nWeight1 += unresolvedEmissionTerm[1];
1871 0 : }
1872 0 : w += nWeight1/double(NTRIAL) + nWeight2/double(NTRIAL);
1873 :
1874 : // Calculate pdf ratios: Get both sides of event
1875 : int inP = 3;
1876 : int inM = 4;
1877 0 : int sideP = (mother->state[inP].pz() > 0) ? 1 :-1;
1878 0 : int sideM = (mother->state[inM].pz() > 0) ? 1 :-1;
1879 :
1880 0 : if ( mother->state[inP].colType() != 0 ) {
1881 : // Find x value and flavour
1882 0 : double x = getCurrentX(sideP);
1883 0 : int flav = getCurrentFlav(sideP);
1884 : // Find numerator scale
1885 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1886 : // Monte Carlo integrand.
1887 0 : double intPDF4 = monteCarloPDFratios(flav, x, scaleNum, newScale,
1888 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1889 0 : w += intPDF4;
1890 :
1891 0 : }
1892 :
1893 0 : if ( mother->state[inM].colType() != 0 ) {
1894 : // Find x value and flavour
1895 0 : double x = getCurrentX(sideM);
1896 0 : int flav = getCurrentFlav(sideM);
1897 : // Find numerator scale
1898 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1899 : // Monte Carlo integrand.
1900 0 : double intPDF4 = monteCarloPDFratios(flav, x, scaleNum, newScale,
1901 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1902 0 : w += intPDF4;
1903 :
1904 0 : }
1905 :
1906 : // Done
1907 : return w;
1908 :
1909 0 : }
1910 :
1911 : //--------------------------------------------------------------------------
1912 :
1913 : // Function to generate the O(\alpha_s)-term of the \alpha_s-ratios
1914 : // appearing in the CKKWL-weight.
1915 :
1916 : double History::weightFirstALPHAS( double as0, double muR,
1917 : AlphaStrong * asFSR, AlphaStrong * asISR ) {
1918 :
1919 : // Use correct scale
1920 0 : double newScale = scale;
1921 : // Done
1922 0 : if ( !mother ) return 0.;
1923 : // Recurse
1924 0 : double w = mother->weightFirstALPHAS( as0, muR, asFSR, asISR );
1925 : // Find right scale
1926 0 : int showerType = (mother->state[clusterIn.emittor].isFinal() ) ? 1 : -1;
1927 : double b = 1.;
1928 0 : double asScale = pow2( newScale );
1929 0 : if ( mergingHooksPtr->unorderedASscalePrescip() == 1 )
1930 0 : asScale = pow2( clusterIn.pT() );
1931 0 : if (showerType == -1) {
1932 0 : asScale += pow2( mergingHooksPtr->pT0ISR() );
1933 : b = 1.;
1934 0 : }
1935 : // Find summand beta_0 / 2 * ln(muR^2/t_i) due to as expansion.
1936 : double NF = 4.;
1937 : double BETA0 = 11. - 2./3.* NF;
1938 : // For fixed \alpha_s in matrix element
1939 0 : w += as0 / (2.*M_PI) * 0.5 * BETA0 * log( (muR*muR) / (b*asScale) );
1940 : // Done
1941 : return w;
1942 :
1943 0 : }
1944 :
1945 : //--------------------------------------------------------------------------
1946 :
1947 : // Function to generate the O(\alpha_s)-term of the PDF-ratios
1948 : // appearing in the CKKWL-weight.
1949 :
1950 : double History::weightFirstPDFs( double as0, double maxscale, double pdfScale,
1951 : Rndm* rndmPtr ) {
1952 :
1953 : // Use correct scale
1954 0 : double newScale = scale;
1955 :
1956 0 : if ( !mother ) {
1957 :
1958 : double wt = 0.;
1959 :
1960 : // Calculate PDF first leg
1961 0 : if (state[3].colType() != 0) {
1962 : // Find x value and flavour
1963 0 : double x = 2.*state[3].e() / state[0].e();
1964 0 : int flav = state[3].id();
1965 : // Find numerator/denominator scale
1966 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1967 0 : double scaleDen = mergingHooksPtr->muFinME();
1968 : // Monte Carlo integrand.
1969 0 : wt += monteCarloPDFratios(flav, x, scaleNum, scaleDen,
1970 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1971 0 : }
1972 : // Calculate PDF ratio for second leg
1973 0 : if (state[4].colType() != 0) {
1974 : // Find x value and flavour
1975 0 : double x = 2.*state[4].e() / state[0].e();
1976 0 : int flav = state[4].id();
1977 : // Find numerator/denominator scale
1978 0 : double scaleNum = (children.empty()) ? hardFacScale(state) : maxscale;
1979 0 : double scaleDen = mergingHooksPtr->muFinME();
1980 : // Monte Carlo integrand.
1981 0 : wt += monteCarloPDFratios(flav, x, scaleNum, scaleDen,
1982 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
1983 0 : }
1984 :
1985 : // Done
1986 : return wt;
1987 : }
1988 :
1989 : // Remember new PDF scale n case true sclae should be used for un-ordered
1990 : // splittings.
1991 : double newPDFscale = newScale;
1992 0 : if (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
1993 0 : newPDFscale = clusterIn.pT();
1994 :
1995 : // Recurse
1996 0 : double w = mother->weightFirstPDFs( as0, newScale, newPDFscale, rndmPtr);
1997 :
1998 : // Calculate pdf ratios: Get both sides of event
1999 : int inP = 3;
2000 : int inM = 4;
2001 0 : int sideP = (mother->state[inP].pz() > 0) ? 1 :-1;
2002 0 : int sideM = (mother->state[inM].pz() > 0) ? 1 :-1;
2003 :
2004 0 : if ( mother->state[inP].colType() != 0 ) {
2005 : // Find x value and flavour
2006 0 : double x = getCurrentX(sideP);
2007 0 : int flav = getCurrentFlav(sideP);
2008 : // Find numerator / denominator scales
2009 0 : double scaleNum = (children.empty())
2010 0 : ? hardFacScale(state)
2011 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
2012 : ? pdfScale : maxscale );
2013 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
2014 0 : ? clusterIn.pT() : newScale;
2015 : // Monte Carlo integrand.
2016 0 : w += monteCarloPDFratios(flav, x, scaleNum, scaleDen,
2017 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
2018 0 : }
2019 :
2020 0 : if ( mother->state[inM].colType() != 0 ) {
2021 : // Find x value and flavour
2022 0 : double x = getCurrentX(sideM);
2023 0 : int flav = getCurrentFlav(sideM);
2024 : // Find numerator / denominator scales
2025 0 : double scaleNum = (children.empty())
2026 0 : ? hardFacScale(state)
2027 0 : : ( (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
2028 : ? pdfScale : maxscale );
2029 0 : double scaleDen = (mergingHooksPtr->unorderedPDFscalePrescip() == 1)
2030 0 : ? clusterIn.pT() : newScale;
2031 : // Monte Carlo integrand.
2032 0 : w += monteCarloPDFratios(flav, x, scaleNum, scaleDen,
2033 0 : mergingHooksPtr->muFinME(), as0, rndmPtr);
2034 0 : }
2035 :
2036 : // Done
2037 : return w;
2038 :
2039 0 : }
2040 :
2041 :
2042 : //--------------------------------------------------------------------------
2043 :
2044 : // Function to generate the O(\alpha_s)-term of the no-emission
2045 : // probabilities appearing in the CKKWL-weight.
2046 :
2047 : double History::weightFirstEmissions(PartonLevel* trial, double as0,
2048 : double maxscale, AlphaStrong * asFSR, AlphaStrong * asISR,
2049 : bool fixpdf, bool fixas ) {
2050 :
2051 : // Use correct scale
2052 0 : double newScale = scale;
2053 0 : if ( !mother ) return 0.0;
2054 : // Recurse
2055 0 : double w = mother->weightFirstEmissions(trial, as0, newScale, asFSR, asISR,
2056 0 : fixpdf, fixas );
2057 : // Do nothing for empty state
2058 0 : if (state.size() < 3) return 0.0;
2059 : // Generate true average.
2060 : double nWeight1 = 0.;
2061 : double nWeight2 = 0.;
2062 0 : for(int i=0; i < NTRIAL; ++i) {
2063 : // Get number of emissions
2064 0 : vector<double> unresolvedEmissionTerm = countEmissions(trial, maxscale,
2065 : newScale, 2, as0, asFSR, asISR, 3, fixpdf, fixas);
2066 0 : nWeight1 += unresolvedEmissionTerm[1];
2067 0 : }
2068 :
2069 0 : w += nWeight1/double(NTRIAL) + nWeight2/double(NTRIAL);
2070 :
2071 : // Done
2072 : return w;
2073 :
2074 0 : }
2075 :
2076 : //--------------------------------------------------------------------------
2077 :
2078 : // Function to return the factorisation scale of the hard process in Pythia.
2079 :
2080 : double History::hardFacScale(const Event& event) {
2081 : // Declare output scale.
2082 : double hardscale = 0.;
2083 : // If scale should not be reset, done.
2084 0 : if ( !mergingHooksPtr->resetHardQFac() ) return mergingHooksPtr->muF();
2085 : // For pure QCD dijet events, calculate the hadronic cross section
2086 : // of the hard process at the pT of the dijet system, rather than at fixed
2087 : // arbitrary scale.
2088 0 : if ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
2089 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 ) {
2090 : // Find the mT in the hard sub-process.
2091 0 : vector <double> mT;
2092 0 : for ( int i=0; i < event.size(); ++i)
2093 0 : if ( event[i].isFinal() && event[i].colType() != 0 )
2094 0 : mT.push_back( abs(event[i].mT2()) );
2095 0 : if ( int(mT.size()) != 2 )
2096 0 : hardscale = infoPtr->QFac();
2097 : else
2098 0 : hardscale = sqrt( min( mT[0], mT[1] ) );
2099 0 : } else {
2100 0 : hardscale = mergingHooksPtr->muF();
2101 : }
2102 : // Done
2103 0 : return hardscale;
2104 0 : }
2105 :
2106 : //--------------------------------------------------------------------------
2107 :
2108 : // Function to return the factorisation scale of the hard process in Pythia.
2109 :
2110 : double History::hardRenScale(const Event& event) {
2111 : // Declare output scale.
2112 : double hardscale = 0.;
2113 : // If scale should not be reset, done.
2114 0 : if ( !mergingHooksPtr->resetHardQRen() ) return mergingHooksPtr->muR();
2115 : // For pure QCD dijet events, calculate the hadronic cross section
2116 : // of the hard process at the pT of the dijet system, rather than at fixed
2117 : // arbitrary scale.
2118 0 : if ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
2119 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 ) {
2120 : // Find the mT in the hard sub-process.
2121 0 : vector <double> mT;
2122 0 : for ( int i=0; i < event.size(); ++i)
2123 0 : if ( event[i].isFinal()
2124 0 : && ( event[i].colType() != 0 || event[i].id() == 22 ) )
2125 0 : mT.push_back( abs(event[i].mT()) );
2126 0 : if ( int(mT.size()) != 2 )
2127 0 : hardscale = infoPtr->QRen();
2128 : else
2129 0 : hardscale = sqrt( mT[0]*mT[1] );
2130 0 : } else {
2131 0 : hardscale = mergingHooksPtr->muR();
2132 : }
2133 : // Done
2134 0 : return hardscale;
2135 0 : }
2136 :
2137 : //--------------------------------------------------------------------------
2138 :
2139 : // Perform a trial shower using the \a pythia object between
2140 : // maxscale down to this scale and return the corresponding Sudakov
2141 : // form factor.
2142 : // IN trialShower : Shower object used as trial shower
2143 : // double : Maximum scale for trial shower branching
2144 : // OUT 0.0 : trial shower emission outside allowed pT range
2145 : // 1.0 : trial shower successful (any emission was below
2146 : // the minimal scale )
2147 :
2148 : double History::doTrialShower( PartonLevel* trial, int type,
2149 : double maxscaleIn, double minscaleIn ) {
2150 :
2151 : // Copy state to local process
2152 0 : Event process = state;
2153 : // Set starting scale.
2154 0 : double startingScale = maxscaleIn;
2155 : // Careful when setting shower starting scale for pure QCD and prompt
2156 : // photon case.
2157 0 : if ( mergingHooksPtr->getNumberOfClusteringSteps(process) == 0
2158 0 : && ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
2159 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 ) )
2160 0 : startingScale = min( startingScale, hardFacScale(process) );
2161 :
2162 : // Set output.
2163 : bool doVeto = false;
2164 :
2165 0 : while ( true ) {
2166 :
2167 : // Reset trialShower object
2168 0 : trial->resetTrial();
2169 : // Construct event to be showered
2170 0 : Event event = Event();
2171 0 : event.init("(hard process-modified)", particleDataPtr);
2172 0 : event.clear();
2173 :
2174 : // Reset process scale so that shower starting scale is correctly set.
2175 0 : process.scale(startingScale);
2176 : doVeto = false;
2177 :
2178 : // Get pT before reclustering
2179 0 : double minScale = (minscaleIn > 0.) ? minscaleIn : scale;
2180 :
2181 : // If the maximal scale and the minimal scale coincide (as would
2182 : // be the case for the corrected scales of unordered histories),
2183 : // do not generate Sudakov
2184 0 : if (minScale >= startingScale) break;
2185 :
2186 : // Find z and pT values at which the current state was formed, to
2187 : // ensure that the showers can order the next emission correctly in
2188 : // rapidity, if required.
2189 : // NOT CORRECTLY SET FOR HIGHEST MULTIPLICITY STATE!
2190 0 : double z = ( mergingHooksPtr->getNumberOfClusteringSteps(state) == 0
2191 0 : || !mother )
2192 : ? 0.5
2193 0 : : mother->getCurrentZ(clusterIn.emittor,clusterIn.recoiler,
2194 0 : clusterIn.emitted);
2195 : // Store z and pT values at which the current state was formed
2196 0 : infoPtr->zNowISR(z);
2197 0 : infoPtr->pT2NowISR(pow(startingScale,2));
2198 0 : infoPtr->hasHistory(true);
2199 :
2200 : // Perform trial shower emission
2201 0 : trial->next(process,event);
2202 : // Get trial shower pT.
2203 0 : double pTtrial = trial->pTLastInShower();
2204 0 : int typeTrial = trial->typeLastInShower();
2205 :
2206 : // Clear parton systems.
2207 0 : trial->resetTrial();
2208 :
2209 : // Get veto (merging) scale value
2210 0 : double vetoScale = (mother) ? 0. : mergingHooksPtr->tms();
2211 : // Get merging scale in current event
2212 0 : double tnow = mergingHooksPtr->tmsNow( event );
2213 :
2214 : // Done if evolution scale has fallen below minimum
2215 0 : if ( pTtrial < minScale ) break;
2216 : // Reset starting scale.
2217 0 : startingScale = pTtrial;
2218 :
2219 : // Continue if this state is below the veto scale
2220 0 : if ( tnow < vetoScale && vetoScale > 0. ) continue;
2221 :
2222 : // Retry if the trial emission was not allowed.
2223 0 : if ( mergingHooksPtr->canVetoTrialEmission()
2224 0 : && mergingHooksPtr->doVetoTrialEmission( process, event) ) continue;
2225 :
2226 : // Only consider allowed emissions for veto:
2227 : // Only allow MPI for MPI no-emission probability.
2228 0 : if ( type == -1 && typeTrial != 1 ) continue;
2229 : // Only allow ISR or FSR for radiative no-emission probability.
2230 0 : if ( type == 1 && !(typeTrial == 2 || typeTrial >= 3) ) continue;
2231 :
2232 : // Veto event if trial pT was above the next nodal scale.
2233 0 : if ( pTtrial > minScale ) doVeto = true;
2234 :
2235 : //// For last no-emission probability, veto event if the trial state
2236 : //// is above the merging scale, i.e. in the matrix element region.
2237 : //if ( !mother && tnow > vetoScale && vetoScale > 0. ) doVeto = true;
2238 :
2239 : // For 2 -> 2 pure QCD state, do not allow multiparton interactions
2240 : // above the kinematical pT of the 2 -> 2 state.
2241 0 : if ( type == -1
2242 0 : && typeTrial == 1
2243 0 : && mergingHooksPtr->getNumberOfClusteringSteps(process) == 0
2244 0 : && ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
2245 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 )
2246 0 : && pTtrial > hardFacScale(process) )
2247 0 : return 0.0;
2248 :
2249 : // If pT of trial emission was in suitable range (trial shower
2250 : // successful), return false
2251 0 : if ( pTtrial < minScale ) doVeto = false;
2252 :
2253 : // Done
2254 0 : break;
2255 :
2256 0 : }
2257 :
2258 : // Done
2259 0 : return ( (doVeto) ? 0. : 1. );
2260 0 : }
2261 :
2262 : //--------------------------------------------------------------------------
2263 :
2264 : // Assume we have a vector of i elements containing indices into
2265 : // another vector with N elements. Update the indices so that all
2266 : // unique combinations (starting from 0,1,2,3, ...) are
2267 : // covered. Return false when all combinations have been ehausted.
2268 :
2269 : bool History::updateind(vector<int> & ind, int i, int N) {
2270 0 : if ( i < 0 ) return false;
2271 0 : if ( ++ind[i] < N ) return true;
2272 0 : if ( !updateind(ind, i - 1, N - 1) ) return false;
2273 0 : ind[i] = ind[i - 1] + 1;
2274 0 : return true;
2275 0 : }
2276 :
2277 : //--------------------------------------------------------------------------
2278 :
2279 : // Return the expansion of the no-emission probability up to the Nth
2280 : // term. Optionally calculate the the terms using fixed alphaS
2281 : // and/or PDF ratios.
2282 :
2283 : vector<double>
2284 : History::countEmissions(PartonLevel* trial, double maxscale,
2285 : double minscale, int showerType, double as0,
2286 : AlphaStrong * asFSR, AlphaStrong * asISR, int N = 1,
2287 : bool fixpdf = true, bool fixas = true) {
2288 :
2289 0 : if ( N < 0 ) return vector<double>();
2290 0 : vector<double> result(N+1);
2291 0 : result[0] = 1.0;
2292 0 : if ( N < 1 ) return result;
2293 :
2294 : // Copy state to local process
2295 0 : Event process = state;
2296 :
2297 0 : double startingScale = maxscale;
2298 : // Careful when setting shower starting scale for pure QCD and prompt
2299 : // photon case.
2300 0 : if ( mergingHooksPtr->getNumberOfClusteringSteps(process) == 0
2301 0 : && ( mergingHooksPtr->getProcessString().compare("pp>jj") == 0
2302 0 : || mergingHooksPtr->getProcessString().compare("pp>aj") == 0 ) )
2303 0 : startingScale = min( startingScale, hardFacScale(process) );
2304 :
2305 0 : vector<double> wts;
2306 :
2307 0 : while ( true ) {
2308 : // Reset trialShower object
2309 0 : trial->resetTrial();
2310 : // Construct event to be showered
2311 0 : Event event = Event();
2312 0 : event.init("(hard process-modified)", particleDataPtr);
2313 0 : event.clear();
2314 :
2315 : // Reset process scale
2316 0 : process.scale(startingScale);
2317 :
2318 : // If the maximal scale and the minimal scale coincide (as would
2319 : // be the case for the corrected scales of unordered histories),
2320 : // do not generate Sudakov
2321 0 : if (minscale >= startingScale) return result;
2322 :
2323 : // Find z and pT values at which the current state was formed, to
2324 : // ensure that the showers can order the next emission correctly in
2325 : // rapidity, if required
2326 0 : if ( mother ) {
2327 0 : double z = ( mergingHooksPtr->getNumberOfClusteringSteps(state) == 0)
2328 : ? 0.5
2329 0 : : mother->getCurrentZ(clusterIn.emittor,clusterIn.recoiler,
2330 0 : clusterIn.emitted);
2331 : // Store z and pT values at which the current state was formed
2332 0 : infoPtr->zNowISR(z);
2333 0 : infoPtr->pT2NowISR(pow(startingScale,2));
2334 0 : infoPtr->hasHistory(true);
2335 0 : }
2336 :
2337 : // Perform trial shower emission
2338 0 : trial->next(process,event);
2339 :
2340 : // Get trial shower pT
2341 0 : double pTtrial = trial->pTLastInShower();
2342 0 : int typeTrial = trial->typeLastInShower();
2343 :
2344 : // Clear parton systems.
2345 0 : trial->resetTrial();
2346 :
2347 : // Get veto (merging) scale value
2348 0 : double vetoScale = (mother) ? 0. : mergingHooksPtr->tms();
2349 : // Get merging scale in current event
2350 0 : double tnow = mergingHooksPtr->tmsNow( event );
2351 :
2352 : // Save scale of current state.
2353 0 : startingScale = pTtrial;
2354 : // If the scale of the current state is below the minimal scale, exit.
2355 0 : if ( pTtrial < minscale ) break;
2356 : // If this state is below the merging scale, do not count emission.
2357 0 : if ( tnow < vetoScale && vetoScale > 0. ) continue;
2358 : // Retry if the trial emission was not allowed.
2359 0 : if ( mergingHooksPtr->canVetoTrialEmission()
2360 0 : && mergingHooksPtr->doVetoTrialEmission( process, event) ) continue;
2361 :
2362 : // Check if a new emission should be generated, either because
2363 : // the latest emission was not of the desired kind or if the
2364 : // emission was above the minimal scale
2365 : double alphaSinPS = as0;
2366 : double pdfs = 1.0;
2367 : // Initial state splittings.
2368 0 : if ( (showerType == -1 || showerType == 2) && typeTrial == 2 ) {
2369 : // Get weight to translate to alpha_s at fixed renormalisation scale.
2370 0 : if ( fixas ) alphaSinPS = (*asISR).alphaS(pTtrial*pTtrial);
2371 : // Get weight to translate to PDFs at fixed factorisation scale.
2372 0 : if ( fixpdf )
2373 0 : pdfs = pdfFactor( event, typeTrial, pTtrial,
2374 0 : mergingHooksPtr->muFinME() );
2375 : // Final state splittings.
2376 0 : } else if ( (showerType == 1 || showerType == 2) && typeTrial >= 3 ) {
2377 : // Get weight to translate to alpha_s at fixed renormalisation scale.
2378 0 : if ( fixas ) alphaSinPS = (*asFSR).alphaS(pTtrial*pTtrial);
2379 : // Get weight to translate to PDFs at fixed factorisation scale. Needed
2380 : // for final state splittings with initial state recoiler.
2381 0 : if ( fixpdf )
2382 0 : pdfs = pdfFactor( event, typeTrial, pTtrial,
2383 0 : mergingHooksPtr->muFinME() );
2384 : }
2385 :
2386 : // Save weight correcting to emission generated with fixed scales.
2387 0 : if ( typeTrial == 2 || typeTrial >= 3 )
2388 0 : wts.push_back(as0/alphaSinPS*pdfs);
2389 :
2390 0 : }
2391 :
2392 0 : for ( int n = 1; n <= min(N, int(wts.size())); ++n ) {
2393 0 : vector<int> ind(N);
2394 0 : for ( int i = 0; i < N; ++i ) ind[i] = i;
2395 0 : do {
2396 : double x = 1.0;
2397 0 : for ( int j = 0; j < n; ++j ) x *= wts[ind[j]];
2398 0 : result[n] += x;
2399 0 : } while ( updateind(ind, n - 1, wts.size()) );
2400 0 : if ( n%2 ) result[n] *= -1.0;
2401 0 : }
2402 :
2403 : // Done
2404 0 : return result;
2405 0 : }
2406 :
2407 : //--------------------------------------------------------------------------
2408 :
2409 : // Function to integrate PDF ratios between two scales over x and t,
2410 : // where the PDFs are always evaluated at the lower t-integration limit
2411 :
2412 : double History::monteCarloPDFratios(int flav, double x, double maxScale,
2413 : double minScale, double pdfScale, double asME, Rndm* rndmPtr) {
2414 :
2415 : // Perform numerical integration for PDF ratios
2416 : // Prefactor is as/2PI
2417 0 : double factor = asME / (2.*M_PI);
2418 : // Scale integration just produces a multiplicative logarithm
2419 0 : factor *= log(maxScale/minScale);
2420 :
2421 : // For identical scales, done
2422 0 : if (factor == 0.) return 0.;
2423 :
2424 : // Declare constants
2425 : double CF = 4./3.;
2426 : double CA = 3.;
2427 : double NF = 4.;
2428 : double TR = 1./2.;
2429 :
2430 : double integral = 0.;
2431 0 : double RN = rndmPtr->flat();
2432 :
2433 0 : if (flav == 21) {
2434 0 : double zTrial = pow(x,RN);
2435 0 : integral = -log(x) * zTrial *
2436 0 : integrand(flav, x, pdfScale, zTrial);
2437 0 : integral += 1./6.*(11.*CA - 4.*NF*TR)
2438 0 : + 2.*CA*log(1.-x);
2439 0 : } else {
2440 0 : double zTrial = x + RN*(1. - x);
2441 0 : integral = (1.-x) *
2442 0 : integrand(flav, x, pdfScale, zTrial);
2443 0 : integral += 3./2.*CF
2444 0 : + 2.*CF*log(1.-x);
2445 : }
2446 :
2447 : // Done
2448 0 : return (factor*integral);
2449 0 : }
2450 :
2451 : /*--------------- METHODS USED FOR CONTRUCTION OF ALL HISTORIES --------- */
2452 :
2453 : // Check if a ordered (and complete) path has been found in the
2454 : // initial node, in which case we will no longer be interested in
2455 : // any unordered paths.
2456 :
2457 : bool History::onlyOrderedPaths() {
2458 0 : if ( !mother || foundOrderedPath ) return foundOrderedPath;
2459 0 : return foundOrderedPath = mother->onlyOrderedPaths();
2460 0 : }
2461 :
2462 : //--------------------------------------------------------------------------
2463 :
2464 : // Check if a STRONGLY ordered (and complete) path has been found in the
2465 : // initial node, in which case we will no longer be interested in
2466 : // any unordered paths.
2467 :
2468 : bool History::onlyStronglyOrderedPaths() {
2469 0 : if ( !mother || foundStronglyOrderedPath ) return foundStronglyOrderedPath;
2470 0 : return foundStronglyOrderedPath = mother->onlyStronglyOrderedPaths();
2471 0 : }
2472 :
2473 : //--------------------------------------------------------------------------
2474 :
2475 : // Check if an allowed (according to user-criterion) path has been found in
2476 : // the initial node, in which case we will no longer be interested in
2477 : // any forbidden paths.
2478 :
2479 : bool History::onlyAllowedPaths() {
2480 0 : if ( !mother || foundAllowedPath ) return foundAllowedPath;
2481 0 : return foundAllowedPath = mother->onlyAllowedPaths();
2482 0 : }
2483 :
2484 : //--------------------------------------------------------------------------
2485 :
2486 : // When a full path has been found, register it with the initial
2487 : // history node.
2488 : // IN History : History to be registered as path
2489 : // bool : Specifying if clusterings so far were ordered
2490 : // bool : Specifying if path is complete down to 2->2 process
2491 : // OUT true if History object forms a plausible path (eg prob>0 ...)
2492 :
2493 : bool History::registerPath(History & l, bool isOrdered,
2494 : bool isStronglyOrdered, bool isAllowed, bool isComplete) {
2495 :
2496 : // We are not interested in improbable paths.
2497 0 : if ( l.prob <= 0.0)
2498 0 : return false;
2499 : // We only register paths in the initial node.
2500 0 : if ( mother ) return mother->registerPath(l, isOrdered,
2501 0 : isStronglyOrdered, isAllowed, isComplete);
2502 :
2503 : // Again, we are not interested in improbable paths.
2504 0 : if ( sumpath == sumpath + l.prob )
2505 0 : return false;
2506 0 : if ( mergingHooksPtr->canCutOnRecState()
2507 0 : && foundAllowedPath && !isAllowed )
2508 0 : return false;
2509 0 : if ( mergingHooksPtr->enforceStrongOrdering()
2510 0 : && foundStronglyOrderedPath && !isStronglyOrdered )
2511 0 : return false;
2512 0 : if ( mergingHooksPtr->orderHistories()
2513 0 : && foundOrderedPath && !isOrdered ) {
2514 : // Prefer complete or allowed paths to ordered paths.
2515 0 : if ( (!foundCompletePath && isComplete)
2516 0 : || (!foundAllowedPath && isAllowed) ) ;
2517 0 : else return false;
2518 : }
2519 :
2520 0 : if ( foundCompletePath && !isComplete )
2521 0 : return false;
2522 0 : if ( !mergingHooksPtr->canCutOnRecState()
2523 0 : && !mergingHooksPtr->allowCutOnRecState() )
2524 0 : foundAllowedPath = true;
2525 :
2526 0 : if ( mergingHooksPtr->canCutOnRecState() && isAllowed && isComplete) {
2527 0 : if ( !foundAllowedPath || !foundCompletePath ) {
2528 : // If this is the first complete, allowed path, discard the
2529 : // old, disallowed or incomplete ones.
2530 0 : paths.clear();
2531 0 : sumpath = 0.0;
2532 0 : }
2533 0 : foundAllowedPath = true;
2534 :
2535 0 : }
2536 :
2537 0 : if ( mergingHooksPtr->enforceStrongOrdering() && isStronglyOrdered
2538 0 : && isComplete ) {
2539 0 : if ( !foundStronglyOrderedPath || !foundCompletePath ) {
2540 : // If this is the first complete, ordered path, discard the
2541 : // old, non-ordered or incomplete ones.
2542 0 : paths.clear();
2543 0 : sumpath = 0.0;
2544 0 : }
2545 0 : foundStronglyOrderedPath = true;
2546 0 : foundCompletePath = true;
2547 :
2548 0 : }
2549 :
2550 0 : if ( mergingHooksPtr->orderHistories() && isOrdered && isComplete ) {
2551 0 : if ( !foundOrderedPath || !foundCompletePath ) {
2552 : // If this is the first complete, ordered path, discard the
2553 : // old, non-ordered or incomplete ones.
2554 0 : paths.clear();
2555 0 : sumpath = 0.0;
2556 0 : }
2557 0 : foundOrderedPath = true;
2558 0 : foundCompletePath = true;
2559 :
2560 0 : }
2561 :
2562 0 : if ( isComplete ) {
2563 0 : if ( !foundCompletePath ) {
2564 : // If this is the first complete path, discard the old,
2565 : // incomplete ones.
2566 0 : paths.clear();
2567 0 : sumpath = 0.0;
2568 0 : }
2569 0 : foundCompletePath = true;
2570 0 : }
2571 :
2572 : // Remember, if this path is ordered, even if no ordering is required
2573 0 : if ( isOrdered ) {
2574 0 : foundOrderedPath = true;
2575 0 : }
2576 :
2577 : // Index path by probability
2578 0 : sumpath += l.prob;
2579 0 : paths[sumpath] = &l;
2580 :
2581 0 : return true;
2582 0 : }
2583 :
2584 : //--------------------------------------------------------------------------
2585 :
2586 : // For the history-defining state (and if necessary interfering
2587 : // states), find all possible clusterings.
2588 : // NO INPUT
2589 : // OUT vector of all (rad,rec,emt) systems
2590 :
2591 : vector<Clustering> History::getAllQCDClusterings() {
2592 0 : vector<Clustering> ret;
2593 : // Initialise vectors to keep track of position of partons in the
2594 : // history-defining state
2595 0 : vector <int> PosFinalPartn;
2596 0 : vector <int> PosInitPartn;
2597 0 : vector <int> PosFinalGluon;
2598 0 : vector <int> PosFinalQuark;
2599 0 : vector <int> PosFinalAntiq;
2600 0 : vector <int> PosInitGluon;
2601 0 : vector <int> PosInitQuark;
2602 0 : vector <int> PosInitAntiq;
2603 :
2604 : // Search event record for final state particles and store these in
2605 : // quark, anti-quark and gluon vectors
2606 0 : for ( int i=0; i < state.size(); ++i )
2607 0 : if ( state[i].isFinal() && state[i].colType() !=0 ) {
2608 : // Store final partons
2609 0 : if ( state[i].id() == 21 ) PosFinalGluon.push_back(i);
2610 0 : else if ( state[i].idAbs() < 10 && state[i].id() > 0)
2611 0 : PosFinalQuark.push_back(i);
2612 0 : else if ( state[i].idAbs() < 10 && state[i].id() < 0)
2613 0 : PosFinalAntiq.push_back(i);
2614 0 : } else if (state[i].status() == -21 && state[i].colType() != 0 ) {
2615 : // Store initial partons
2616 0 : if ( state[i].id() == 21 ) PosInitGluon.push_back(i);
2617 0 : else if ( state[i].idAbs() < 10 && state[i].id() > 0)
2618 0 : PosInitQuark.push_back(i);
2619 0 : else if ( state[i].idAbs() < 10 && state[i].id() < 0)
2620 0 : PosInitAntiq.push_back(i);
2621 : }
2622 :
2623 : // Get all clusterings for input state
2624 0 : vector<Clustering> systems;
2625 0 : systems = getQCDClusterings(state);
2626 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2627 0 : systems.resize(0);
2628 :
2629 : // If valid clusterings were found, return
2630 0 : if ( !ret.empty() ) return ret;
2631 : // If no clusterings have been found until now, try to find
2632 : // clusterings of diagrams that interfere with the current one
2633 : // (i.e. change the colours of the current event slightly and run
2634 : // search again)
2635 0 : else if ( ret.empty()
2636 0 : && mergingHooksPtr->allowColourShuffling() ) {
2637 0 : Event NewState = Event(state);
2638 : // Start with changing final state quark colour
2639 0 : for(int i = 0; i < int(PosFinalQuark.size()); ++i) {
2640 : // Never change the hard process candidates
2641 0 : if ( mergingHooksPtr->hardProcess.matchesAnyOutgoing(PosFinalQuark[i],
2642 : NewState) )
2643 : continue;
2644 0 : int col = NewState[PosFinalQuark[i]].col();
2645 0 : for(int j = 0; j < int(PosInitAntiq.size()); ++j) {
2646 : // Now swap colours
2647 0 : int acl = NewState[PosInitAntiq[j]].acol();
2648 0 : if ( col == acl ) continue;
2649 0 : NewState[PosFinalQuark[i]].col(acl);
2650 0 : NewState[PosInitAntiq[j]].acol(col);
2651 0 : systems = getQCDClusterings(NewState);
2652 0 : if (!systems.empty()) {
2653 0 : state = NewState;
2654 0 : NewState.clear();
2655 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2656 0 : systems.resize(0);
2657 0 : return ret;
2658 : }
2659 0 : }
2660 0 : }
2661 : // Now change final state antiquark anticolour
2662 0 : for(int i = 0; i < int(PosFinalAntiq.size()); ++i) {
2663 : // Never change the hard process candidates
2664 0 : if ( mergingHooksPtr->hardProcess.matchesAnyOutgoing(PosFinalAntiq[i],
2665 : NewState) )
2666 : continue;
2667 0 : int acl = NewState[PosFinalAntiq[i]].acol();
2668 0 : for(int j = 0; j < int(PosInitQuark.size()); ++j) {
2669 : // Now swap colours
2670 0 : int col = NewState[PosInitQuark[j]].col();
2671 0 : if ( col == acl ) continue;
2672 0 : NewState[PosFinalAntiq[i]].acol(col);
2673 0 : NewState[PosInitQuark[j]].col(acl);
2674 0 : systems = getQCDClusterings(NewState);
2675 0 : if (!systems.empty()) {
2676 0 : state = NewState;
2677 0 : NewState.clear();
2678 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2679 0 : systems.resize(0);
2680 0 : return ret;
2681 : }
2682 0 : }
2683 0 : }
2684 :
2685 0 : if ( !ret.empty() ) {
2686 0 : string message="Warning in History::getAllQCDClusterings: Changed";
2687 0 : message+=" colour structure to allow at least one clustering.";
2688 0 : infoPtr->errorMsg(message);
2689 0 : }
2690 :
2691 0 : }
2692 :
2693 : // Done
2694 0 : return ret;
2695 0 : }
2696 :
2697 : //--------------------------------------------------------------------------
2698 :
2699 : // For one given state, find all possible clusterings.
2700 : // IN Event : state to be investigated
2701 : // OUT vector of all (rad,rec,emt) systems in the state
2702 :
2703 : vector<Clustering> History::getQCDClusterings( const Event& event) {
2704 0 : vector<Clustering> ret;
2705 :
2706 : // Initialise vectors to keep track of position of partons in the
2707 : // input event
2708 0 : vector <int> PosFinalPartn;
2709 0 : vector <int> PosInitPartn;
2710 :
2711 0 : vector <int> PosFinalGluon;
2712 0 : vector <int> PosFinalQuark;
2713 0 : vector <int> PosFinalAntiq;
2714 0 : vector <int> PosInitGluon;
2715 0 : vector <int> PosInitQuark;
2716 0 : vector <int> PosInitAntiq;
2717 :
2718 : // Search event record for final state particles and store these in
2719 : // quark, anti-quark and gluon vectors
2720 0 : for (int i=0; i < event.size(); ++i)
2721 0 : if ( event[i].isFinal() && event[i].colType() !=0 ) {
2722 : // Store final partons
2723 0 : PosFinalPartn.push_back(i);
2724 0 : if ( event[i].id() == 21 ) PosFinalGluon.push_back(i);
2725 0 : else if ( event[i].idAbs() < 10 && event[i].id() > 0)
2726 0 : PosFinalQuark.push_back(i);
2727 0 : else if ( event[i].idAbs() < 10 && event[i].id() < 0)
2728 0 : PosFinalAntiq.push_back(i);
2729 0 : } else if ( event[i].status() == -21 && event[i].colType() != 0 ) {
2730 : // Store initial partons
2731 0 : PosInitPartn.push_back(i);
2732 0 : if ( event[i].id() == 21 ) PosInitGluon.push_back(i);
2733 0 : else if ( event[i].idAbs() < 10 && event[i].id() > 0)
2734 0 : PosInitQuark.push_back(i);
2735 0 : else if ( event[i].idAbs() < 10 && event[i].id() < 0)
2736 0 : PosInitAntiq.push_back(i);
2737 : }
2738 :
2739 0 : int nFiGluon = int(PosFinalGluon.size());
2740 0 : int nFiQuark = int(PosFinalQuark.size());
2741 0 : int nFiAntiq = int(PosFinalAntiq.size());
2742 0 : int nInGluon = int(PosInitGluon.size());
2743 0 : int nInQuark = int(PosInitQuark.size());
2744 0 : int nInAntiq = int(PosInitAntiq.size());
2745 :
2746 0 : vector<Clustering> systems;
2747 :
2748 : // Find rad + emt + rec systems:
2749 : // (1) Start from gluon and find all (rad,rec,emt=gluon) triples
2750 0 : for (int i = 0; i < nFiGluon; ++i) {
2751 0 : int EmtGluon = PosFinalGluon[i];
2752 0 : systems = findQCDTriple( EmtGluon, 2, event, PosFinalPartn, PosInitPartn);
2753 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2754 0 : systems.resize(0);
2755 : }
2756 :
2757 : // For more than one quark-antiquark pair in final state, check for
2758 : // g -> qqbar splittings
2759 : bool check_g2qq = true;
2760 0 : if ( ( ( nInQuark + nInAntiq == 0 )
2761 0 : && (nInGluon == 0)
2762 0 : && (nFiQuark == 1) && (nFiAntiq == 1) )
2763 0 : || ( ( nFiQuark + nFiAntiq == 0)
2764 0 : && (nInQuark == 1) && (nInAntiq == 1) ) )
2765 0 : check_g2qq = false;
2766 :
2767 0 : if ( check_g2qq ) {
2768 :
2769 : // (2) Start from quark and find all (rad,rec,emt=quark) triples
2770 : // ( when g -> q qbar occured )
2771 0 : for( int i=0; i < nFiQuark; ++i) {
2772 0 : int EmtQuark = PosFinalQuark[i];
2773 0 : systems = findQCDTriple( EmtQuark,1,event, PosFinalPartn, PosInitPartn);
2774 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2775 0 : systems.resize(0);
2776 : }
2777 :
2778 : // (3) Start from anti-quark and find all (rad,rec,emt=anti-quark)
2779 : // triples ( when g -> q qbar occured )
2780 0 : for( int i=0; i < nFiAntiq; ++i) {
2781 0 : int EmtAntiq = PosFinalAntiq[i];
2782 0 : systems = findQCDTriple( EmtAntiq,1,event, PosFinalPartn, PosInitPartn);
2783 0 : ret.insert(ret.end(), systems.begin(), systems.end());
2784 0 : systems.resize(0);
2785 : }
2786 0 : }
2787 :
2788 : return ret;
2789 0 : }
2790 :
2791 : //--------------------------------------------------------------------------
2792 :
2793 : // Function to construct (rad,rec,emt) triples from the event
2794 : // IN int : Position of Emitted in event record for which
2795 : // dipoles should be constructed
2796 : // int : Colour topogy to be tested
2797 : // 1= g -> qqbar, causing 2 -> 2 dipole splitting
2798 : // 2= q(bar) -> q(bar) g && g -> gg,
2799 : // causing a 2 -> 3 dipole splitting
2800 : // Event : event record to be checked for ptential partners
2801 : // OUT vector of all allowed radiator+recoiler+emitted triples
2802 :
2803 : vector<Clustering> History::findQCDTriple (int EmtTagIn, int colTopIn,
2804 : const Event& event,
2805 : vector<int> PosFinalPartn,
2806 : vector <int> PosInitPartn ) {
2807 :
2808 : // Copy input parton tag
2809 : int EmtTag = EmtTagIn;
2810 : // Copy input colour topology tag
2811 : // (1: g --> qqbar splitting present, 2:rest)
2812 : int colTop = colTopIn;
2813 :
2814 : // Initialise FinalSize
2815 0 : int FinalSize = int(PosFinalPartn.size());
2816 0 : int InitSize = int(PosInitPartn.size());
2817 0 : int Size = InitSize + FinalSize;
2818 :
2819 0 : vector<Clustering> clus;
2820 :
2821 : // Search final partons to find partons colour-connected to
2822 : // event[EmtTag], choose radiator, then choose recoiler
2823 0 : for ( int a = 0; a < Size; ++a ) {
2824 0 : int i = (a < FinalSize)? a : (a - FinalSize) ;
2825 0 : int iRad = (a < FinalSize)? PosFinalPartn[i] : PosInitPartn[i];
2826 :
2827 0 : if ( event[iRad].col() == event[EmtTag].col()
2828 0 : && event[iRad].acol() == event[EmtTag].acol() )
2829 0 : continue;
2830 :
2831 0 : if (iRad != EmtTag ) {
2832 0 : int pTdef = event[iRad].isFinal() ? 1 : -1;
2833 0 : int sign = (a < FinalSize)? 1 : -1 ;
2834 :
2835 : // First colour topology: g --> qqbar. Here, emt & rad should
2836 : // have same flavour (causes problems for gamma->qqbar).
2837 0 : if (colTop == 1) {
2838 :
2839 0 : if ( event[iRad].id() == -sign*event[EmtTag].id() ) {
2840 : int col = -1;
2841 : int acl = -1;
2842 0 : if (event[iRad].id() < 0) {
2843 0 : col = event[EmtTag].acol();
2844 0 : acl = event[iRad].acol();
2845 0 : } else {
2846 0 : col = event[EmtTag].col();
2847 0 : acl = event[iRad].col();
2848 : }
2849 : // Recoiler
2850 : int iRec = 0;
2851 : // Colour partner
2852 : int iPartner = 0;
2853 :
2854 0 : if (col > 0) {
2855 : // Find recoiler by colour
2856 0 : iRec = FindCol(col,iRad,EmtTag,event,1,true);
2857 : // In initial state splitting has final state colour partner,
2858 : // Save both partner and recoiler
2859 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
2860 : // Save colour recoiler
2861 : iPartner = iRec;
2862 : // Reset kinematic recoiler to initial state parton
2863 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
2864 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
2865 : // For final state splittings, colour partner and recoiler are
2866 : // identical
2867 0 : } else {
2868 : iPartner = iRec;
2869 : }
2870 0 : if ( iRec != 0 && iPartner != 0
2871 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
2872 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
2873 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
2874 0 : continue;
2875 : }
2876 :
2877 : // Reset partner
2878 : iPartner = 0;
2879 : // Find recoiler by colour
2880 0 : iRec = FindCol(col,iRad,EmtTag,event,2,true);
2881 : // In initial state splitting has final state colour partner,
2882 : // Save both partner and recoiler
2883 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
2884 : // Save colour recoiler
2885 : iPartner = iRec;
2886 : // Reset kinematic recoiler to initial state parton
2887 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
2888 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
2889 : // For final state splittings, colour partner and recoiler are
2890 : // identical
2891 0 : } else {
2892 : iPartner = iRec;
2893 : }
2894 0 : if ( iRec != 0 && iPartner != 0
2895 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
2896 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
2897 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
2898 0 : continue;
2899 : }
2900 : }
2901 :
2902 :
2903 0 : if (acl > 0) {
2904 :
2905 : // Reset partner
2906 : iPartner = 0;
2907 : // Find recoiler by colour
2908 0 : iRec = FindCol(acl,iRad,EmtTag,event,1,true);
2909 : // In initial state splitting has final state colour partner,
2910 : // Save both partner and recoiler
2911 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
2912 : // Save colour recoiler
2913 : iPartner = iRec;
2914 : // Reset kinematic recoiler to initial state parton
2915 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
2916 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
2917 : // For final state splittings, colour partner and recoiler are
2918 : // identical
2919 0 : } else {
2920 : iPartner = iRec;
2921 : }
2922 0 : if ( iRec != 0 && iPartner != 0
2923 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
2924 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
2925 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
2926 0 : continue;
2927 : }
2928 :
2929 : // Reset partner
2930 : iPartner = 0;
2931 : // Find recoiler by colour
2932 0 : iRec = FindCol(acl,iRad,EmtTag,event,2,true);
2933 : // In initial state splitting has final state colour partner,
2934 : // Save both partner and recoiler
2935 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
2936 : // Save colour recoiler
2937 : iPartner = iRec;
2938 : // Reset kinematic recoiler to initial state parton
2939 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
2940 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
2941 : // For final state splittings, colour partner and recoiler are
2942 : // identical
2943 0 : } else {
2944 : iPartner = iRec;
2945 : }
2946 0 : if ( iRec != 0 && iPartner != 0
2947 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
2948 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
2949 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
2950 0 : continue;
2951 : }
2952 : }
2953 : // Initial gluon splitting
2954 0 : } else if ( event[iRad].id() == 21
2955 0 : &&( event[iRad].col() == event[EmtTag].col()
2956 0 : || event[iRad].acol() == event[EmtTag].acol() )) {
2957 : // For an initial state radiator, always set recoiler
2958 : // to the other initial state parton (recoil is taken
2959 : // by full remaining system, so this is just a
2960 : // labelling for such a process)
2961 : int RecInit = 0;
2962 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
2963 0 : if (PosInitPartn[l] != iRad) RecInit = PosInitPartn[l];
2964 :
2965 : // Find the colour connected partner
2966 : // Find colour index of radiator before splitting
2967 0 : int col = getRadBeforeCol(iRad, EmtTag, event);
2968 0 : int acl = getRadBeforeAcol(iRad, EmtTag, event);
2969 :
2970 : // Find the correct partner: If a colour line has split,
2971 : // the partner is connected to the radiator before the splitting
2972 : // by a colour line (same reasoning for anticolour). The colour
2973 : // that split is the colour appearing twice in the
2974 : // radiator + emitted pair.
2975 : // Thus, if we remove a colour index with the clustering,
2976 : // we should look for a colour partner, else look for
2977 : // an anticolour partner
2978 0 : int colRemove = (event[iRad].col() == event[EmtTag].col())
2979 0 : ? event[iRad].col() : 0;
2980 :
2981 : int iPartner = 0;
2982 0 : if (colRemove > 0 && col > 0)
2983 0 : iPartner = FindCol(col,iRad,EmtTag,event,1,true)
2984 0 : + FindCol(col,iRad,EmtTag,event,2,true);
2985 0 : else if (colRemove > 0 && acl > 0)
2986 0 : iPartner = FindCol(acl,iRad,EmtTag,event,1,true)
2987 0 : + FindCol(acl,iRad,EmtTag,event,2,true);
2988 :
2989 0 : if ( allowedClustering( iRad, EmtTag, RecInit, iPartner, event ) ) {
2990 0 : clus.push_back( Clustering(EmtTag, iRad, RecInit, iPartner,
2991 0 : pTLund(event[iRad],event[EmtTag],event[RecInit], pTdef) ));
2992 0 : continue;
2993 : }
2994 0 : }
2995 :
2996 : // Second colour topology: Gluon emission
2997 :
2998 : } else {
2999 0 : if ( (event[iRad].col() == event[EmtTag].acol())
3000 0 : || (event[iRad].acol() == event[EmtTag].col())
3001 0 : || (event[iRad].col() == event[EmtTag].col())
3002 0 : || (event[iRad].acol() == event[EmtTag].acol()) ) {
3003 : // For the rest, choose recoiler to have a common colour
3004 : // tag with radiator, while not being the "Emitted"
3005 :
3006 : int col = -1;
3007 : int acl = -1;
3008 :
3009 0 : if (event[iRad].isFinal() ) {
3010 :
3011 0 : if ( event[iRad].id() < 0) {
3012 0 : acl = event[EmtTag].acol();
3013 0 : col = event[iRad].col();
3014 0 : } else if ( event[iRad].id() > 0 && event[iRad].id() < 10) {
3015 0 : col = event[EmtTag].col();
3016 0 : acl = event[iRad].acol();
3017 0 : } else {
3018 0 : col = event[iRad].col();
3019 0 : acl = event[iRad].acol();
3020 : }
3021 :
3022 : int iRec = 0;
3023 0 : if (col > 0) {
3024 0 : iRec = FindCol(col,iRad,EmtTag,event,1,true);
3025 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3026 0 : if (iRec != 0
3027 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3028 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3029 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3030 0 : continue;
3031 : }
3032 :
3033 0 : iRec = FindCol(col,iRad,EmtTag,event,2,true);
3034 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3035 0 : if (iRec != 0
3036 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3037 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3038 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3039 0 : continue;
3040 : }
3041 : }
3042 :
3043 :
3044 0 : if (acl > 0) {
3045 0 : iRec = FindCol(acl,iRad,EmtTag,event,1,true);
3046 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3047 0 : if (iRec != 0
3048 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3049 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3050 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3051 0 : continue;
3052 : }
3053 :
3054 0 : iRec = FindCol(acl,iRad,EmtTag,event,2,true);
3055 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3056 0 : if (iRec != 0
3057 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3058 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3059 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3060 0 : continue;
3061 : }
3062 : }
3063 :
3064 0 : } else {
3065 :
3066 : // For an initial state radiator, always set recoiler
3067 : // to the other initial state parton (recoil is taken
3068 :
3069 : // by full remaining system, so this is just a
3070 : // labelling for such a process)
3071 : int RecInit = 0;
3072 : int iPartner = 0;
3073 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3074 0 : if (PosInitPartn[l] != iRad) RecInit = PosInitPartn[l];
3075 :
3076 : // Find the colour connected partner
3077 : // Find colour index of radiator before splitting
3078 0 : col = getRadBeforeCol(iRad, EmtTag, event);
3079 0 : acl = getRadBeforeAcol(iRad, EmtTag, event);
3080 :
3081 : // Find the correct partner: If a colour line has split,
3082 : // the partner is connected to the radiator before the splitting
3083 : // by a colour line (same reasoning for anticolour). The colour
3084 : // that split is the colour appearing twice in the
3085 : // radiator + emitted pair.
3086 : // Thus, if we remove a colour index with the clustering,
3087 : // we should look for a colour partner, else look for
3088 : // an anticolour partner
3089 0 : int colRemove = (event[iRad].col() == event[EmtTag].col())
3090 0 : ? event[iRad].col() : 0;
3091 0 : iPartner = (colRemove > 0)
3092 0 : ? FindCol(col,iRad,EmtTag,event,1,true)
3093 0 : + FindCol(col,iRad,EmtTag,event,2,true)
3094 0 : : FindCol(acl,iRad,EmtTag,event,1,true)
3095 0 : + FindCol(acl,iRad,EmtTag,event,2,true);
3096 :
3097 0 : if ( allowedClustering( iRad, EmtTag, RecInit, iPartner, event)) {
3098 0 : clus.push_back( Clustering(EmtTag, iRad, RecInit, iPartner,
3099 0 : pTLund(event[iRad],event[EmtTag],event[RecInit], pTdef)));
3100 :
3101 0 : continue;
3102 : }
3103 0 : }
3104 0 : }
3105 : }
3106 0 : }
3107 0 : }
3108 :
3109 : // Done
3110 : return clus;
3111 0 : }
3112 :
3113 : //--------------------------------------------------------------------------
3114 :
3115 : // For the history-defining state (and if necessary interfering
3116 : // states), find all possible clusterings.
3117 : // NO INPUT
3118 : // OUT vector of all (rad,rec,emt) systems
3119 :
3120 : vector<Clustering> History::getAllEWClusterings() {
3121 0 : vector<Clustering> ret;
3122 :
3123 : // Get all clusterings for input state
3124 0 : vector<Clustering> systems;
3125 0 : systems = getEWClusterings(state);
3126 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3127 : // Done
3128 : return ret;
3129 0 : }
3130 :
3131 : //--------------------------------------------------------------------------
3132 :
3133 : // For one given state, find all possible clusterings.
3134 : // IN Event : state to be investigated
3135 : // OUT vector of all (rad,rec,emt) systems in the state
3136 :
3137 : vector<Clustering> History::getEWClusterings( const Event& event) {
3138 0 : vector<Clustering> ret;
3139 :
3140 : // Initialise vectors to keep track of position of partons in the
3141 : // input event
3142 0 : vector <int> PosFinalPartn;
3143 0 : vector <int> PosInitPartn;
3144 0 : vector <int> PosFinalW;
3145 :
3146 : // Search event record for final state particles and store these in
3147 : // quark, anti-quark and gluon vectors
3148 0 : for ( int i=0; i < event.size(); ++i )
3149 0 : if ( event[i].isFinal() && abs(event[i].colType()) == 1 ) {
3150 : // Store final partons
3151 0 : PosFinalPartn.push_back(i);
3152 0 : } else if ( event[i].status() == -21 && abs(event[i].colType()) == 1 ) {
3153 : // Store initial partons
3154 0 : PosInitPartn.push_back(i);
3155 : }
3156 : // Search event record for final W
3157 0 : for ( int i=0; i < event.size(); ++i )
3158 0 : if ( event[i].isFinal() && event[i].idAbs() == 24 )
3159 0 : PosFinalW.push_back( i );
3160 :
3161 0 : vector<Clustering> systems;
3162 : // Find rad + emt + rec systems:
3163 : // (1) Start from W boson and find all (rad,rec,emt=W) triples
3164 0 : for ( int i = 0; i < int(PosFinalW.size()); ++i ) {
3165 0 : int EmtW = PosFinalW[i];
3166 0 : systems = findEWTriple( EmtW, event, PosFinalPartn);
3167 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3168 0 : systems.resize(0);
3169 : }
3170 :
3171 : return ret;
3172 0 : }
3173 :
3174 : //--------------------------------------------------------------------------
3175 :
3176 : // Function to construct (rad,rec,emt) triples from the event
3177 : // IN int : Position of Emitted in event record for which
3178 : // dipoles should be constructed
3179 : // int : Colour topogy to be tested
3180 : // 1= g -> qqbar, causing 2 -> 2 dipole splitting
3181 : // 2= q(bar) -> q(bar) g && g -> gg,
3182 : // causing a 2 -> 3 dipole splitting
3183 : // Event : event record to be checked for ptential partners
3184 : // OUT vector of all allowed radiator+recoiler+emitted triples
3185 :
3186 : vector<Clustering> History::findEWTriple ( int EmtTagIn, const Event& event,
3187 : vector<int> PosFinalPartn ) {
3188 : // Copy input parton tag
3189 : int EmtTag = EmtTagIn;
3190 : // Copy input colour topology tag
3191 : // (1: g --> qqbar splitting present, 2:rest)
3192 :
3193 : // Initialise FinalSize
3194 0 : int FinalSize = int(PosFinalPartn.size());
3195 :
3196 0 : vector<Clustering> clus;
3197 :
3198 : // Search final partons to find partons colour-connected to
3199 : // event[EmtTag], choose radiator, then choose recoiler
3200 0 : for ( int a = 0; a < FinalSize; ++a ) {
3201 :
3202 0 : int iRad = PosFinalPartn[a];
3203 0 : if (iRad != EmtTag ) {
3204 : int pTdef = 1;
3205 : // Find recoiler by flavour.
3206 0 : int flavRad = event[iRad].id();
3207 0 : int flavEmt = event[EmtTag].id();
3208 :
3209 : // Loop through final partons and try to find matching flavours.
3210 0 : for ( int i = 0; i < FinalSize; ++i ) {
3211 0 : int iRec = PosFinalPartn[i];
3212 0 : if ( i != a && flavEmt > 0
3213 0 : && event[iRec].id() == -flavRad - 1 )
3214 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3215 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ) );
3216 : }
3217 0 : }
3218 : }
3219 :
3220 : // Done
3221 : return clus;
3222 0 : }
3223 :
3224 : //--------------------------------------------------------------------------
3225 :
3226 : // For the history-defining state (and if necessary interfering
3227 : // states), find all possible clusterings.
3228 : // NO INPUT
3229 : // OUT vector of all (rad,rec,emt) systems
3230 :
3231 : vector<Clustering> History::getAllSQCDClusterings() {
3232 0 : vector<Clustering> ret;
3233 :
3234 : // Get all clusterings for input state
3235 0 : vector<Clustering> systems;
3236 0 : systems = getSQCDClusterings(state);
3237 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3238 : // Done
3239 : return ret;
3240 0 : }
3241 :
3242 : //--------------------------------------------------------------------------
3243 :
3244 : // For one given state, find all possible clusterings.
3245 : // IN Event : state to be investigated
3246 : // OUT vector of all (rad,rec,emt) systems in the state
3247 :
3248 : vector<Clustering> History::getSQCDClusterings( const Event& event) {
3249 0 : vector<Clustering> ret;
3250 :
3251 : // Initialise vectors to keep track of position of partons in the
3252 : // input event
3253 0 : vector <int> PosFinalPartn;
3254 0 : vector <int> PosInitPartn;
3255 :
3256 0 : vector <int> PosFinalGluon;
3257 0 : vector <int> PosFinalQuark;
3258 0 : vector <int> PosFinalAntiq;
3259 0 : vector <int> PosInitGluon;
3260 0 : vector <int> PosInitQuark;
3261 0 : vector <int> PosInitAntiq;
3262 :
3263 : // Search event record for final state particles and store these in
3264 : // quark, anti-quark and gluon vectors
3265 0 : for (int i=0; i < event.size(); ++i)
3266 0 : if ( event[i].isFinal() && event[i].colType() !=0 ) {
3267 : // Store final partons
3268 0 : PosFinalPartn.push_back(i);
3269 0 : if ( event[i].id() == 21 || event[i].id() == 1000021)
3270 0 : PosFinalGluon.push_back(i);
3271 0 : else if ( (event[i].idAbs() < 10 && event[i].id() > 0)
3272 0 : || (event[i].idAbs() < 1000010 && event[i].idAbs() > 1000000
3273 0 : && event[i].id() > 0)
3274 0 : || (event[i].idAbs() < 2000010 && event[i].idAbs() > 2000000
3275 0 : && event[i].id() > 0))
3276 0 : PosFinalQuark.push_back(i);
3277 0 : else if ( (event[i].idAbs() < 10 && event[i].id() < 0)
3278 0 : || (event[i].idAbs() < 1000010 && event[i].idAbs() > 1000000
3279 0 : && event[i].id() < 0)
3280 0 : || (event[i].idAbs() < 2000010 && event[i].idAbs() > 2000000
3281 0 : && event[i].id() < 0))
3282 0 : PosFinalAntiq.push_back(i);
3283 0 : } else if ( event[i].status() == -21 && event[i].colType() != 0 ) {
3284 : // Store initial partons
3285 0 : PosInitPartn.push_back(i);
3286 0 : if ( event[i].id() == 21 || event[i].id() == 1000021)
3287 0 : PosInitGluon.push_back(i);
3288 0 : else if ( (event[i].idAbs() < 10 && event[i].id() > 0)
3289 0 : || (event[i].idAbs() < 1000010 && event[i].idAbs() > 1000000
3290 0 : && event[i].id() > 0)
3291 0 : || (event[i].idAbs() < 2000010 && event[i].idAbs() > 2000000
3292 0 : && event[i].id() > 0))
3293 0 : PosInitQuark.push_back(i);
3294 0 : else if ( (event[i].idAbs() < 10 && event[i].id() < 0)
3295 0 : || (event[i].idAbs() < 1000010 && event[i].idAbs() > 1000000
3296 0 : && event[i].id() < 0)
3297 0 : || (event[i].idAbs() < 2000010 && event[i].idAbs() > 2000000
3298 0 : && event[i].id() < 0))
3299 0 : PosInitAntiq.push_back(i);
3300 : }
3301 :
3302 0 : int nFiGluon = int(PosFinalGluon.size());
3303 0 : int nFiQuark = int(PosFinalQuark.size());
3304 0 : int nFiAntiq = int(PosFinalAntiq.size());
3305 0 : int nInGluon = int(PosInitGluon.size());
3306 0 : int nInQuark = int(PosInitQuark.size());
3307 0 : int nInAntiq = int(PosInitAntiq.size());
3308 0 : vector<Clustering> systems;
3309 :
3310 : // Find rad + emt + rec systems:
3311 : // (1) Start from gluon and find all (rad,rec,emt=gluon) triples
3312 0 : for (int i = 0; i < nFiGluon; ++i) {
3313 0 : int EmtGluon = PosFinalGluon[i];
3314 0 : systems = findSQCDTriple( EmtGluon, 2, event, PosFinalPartn, PosInitPartn);
3315 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3316 0 : systems.resize(0);
3317 : }
3318 :
3319 : // For more than one quark-antiquark pair in final state, check for
3320 : // g -> qqbar splittings
3321 : bool check_g2qq = true;
3322 0 : if ( ( ( nInQuark + nInAntiq == 0 )
3323 0 : && (nInGluon == 0)
3324 0 : && (nFiQuark == 1) && (nFiAntiq == 1) )
3325 0 : || ( ( nFiQuark + nFiAntiq == 0)
3326 0 : && (nInQuark == 1) && (nInAntiq == 1) ) )
3327 0 : check_g2qq = false;
3328 :
3329 0 : if ( check_g2qq ) {
3330 :
3331 : // (2) Start from quark and find all (rad,rec,emt=quark) triples
3332 : // ( when g -> q qbar occured )
3333 0 : for( int i=0; i < nFiQuark; ++i) {
3334 0 : int EmtQuark = PosFinalQuark[i];
3335 0 : systems = findSQCDTriple( EmtQuark,1,event, PosFinalPartn, PosInitPartn);
3336 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3337 0 : systems.resize(0);
3338 : }
3339 :
3340 : // (3) Start from anti-quark and find all (rad,rec,emt=anti-quark)
3341 : // triples ( when g -> q qbar occured )
3342 0 : for( int i=0; i < nFiAntiq; ++i) {
3343 0 : int EmtAntiq = PosFinalAntiq[i];
3344 0 : systems = findSQCDTriple( EmtAntiq,1,event, PosFinalPartn, PosInitPartn);
3345 0 : ret.insert(ret.end(), systems.begin(), systems.end());
3346 0 : systems.resize(0);
3347 : }
3348 :
3349 0 : }
3350 :
3351 : return ret;
3352 0 : }
3353 :
3354 : //--------------------------------------------------------------------------
3355 :
3356 : // Function to construct (rad,rec,emt) triples from the event
3357 : // IN int : Position of Emitted in event record for which
3358 : // dipoles should be constructed
3359 : // int : Colour topogy to be tested
3360 : // 1= g -> qqbar, causing 2 -> 2 dipole splitting
3361 : // 2= q(bar) -> q(bar) g && g -> gg,
3362 : // causing a 2 -> 3 dipole splitting
3363 : // Event : event record to be checked for ptential partners
3364 : // OUT vector of all allowed radiator+recoiler+emitted triples
3365 :
3366 : vector<Clustering> History::findSQCDTriple (int EmtTagIn, int colTopIn,
3367 : const Event& event,
3368 : vector<int> PosFinalPartn,
3369 : vector <int> PosInitPartn ) {
3370 :
3371 : // Copy input parton tag
3372 : int EmtTag = EmtTagIn;
3373 : // Copy input colour topology tag
3374 : // (1: g --> qqbar splitting present, 2:rest)
3375 : int colTop = colTopIn;
3376 :
3377 : // PDG numbering offset for squarks
3378 : int offsetL = 1000000;
3379 : int offsetR = 2000000;
3380 :
3381 : // Initialise FinalSize
3382 0 : int FinalSize = int(PosFinalPartn.size());
3383 0 : int InitSize = int(PosInitPartn.size());
3384 0 : int Size = InitSize + FinalSize;
3385 :
3386 0 : vector<Clustering> clus;
3387 :
3388 : // Search final partons to find partons colour-connected to
3389 : // event[EmtTag], choose radiator, then choose recoiler
3390 0 : for ( int a = 0; a < Size; ++a ) {
3391 0 : int i = (a < FinalSize)? a : (a - FinalSize) ;
3392 0 : int iRad = (a < FinalSize)? PosFinalPartn[i] : PosInitPartn[i];
3393 :
3394 0 : if ( event[iRad].col() == event[EmtTag].col()
3395 0 : && event[iRad].acol() == event[EmtTag].acol() )
3396 0 : continue;
3397 :
3398 : // Save radiator flavour.
3399 0 : int radID = event[iRad].id();
3400 : // Remember if radiator is BSM.
3401 0 : bool isSQCDrad = (abs(radID) > offsetL);
3402 : // Remember if emitted is BSM.
3403 0 : bool isSQCDemt = (event[EmtTag].idAbs() > offsetL );
3404 :
3405 0 : if (iRad != EmtTag ) {
3406 0 : int pTdef = event[iRad].isFinal() ? 1 : -1;
3407 0 : int sign = (a < FinalSize)? 1 : -1 ;
3408 :
3409 : // Disalllow clusterings resulting in an initial state sQCD parton!
3410 0 : int radBefID = getRadBeforeFlav(iRad,EmtTag,event);
3411 0 : if ( pTdef == -1 && abs(radBefID) > offsetL ) continue;
3412 :
3413 : // First colour topology: g --> qqbar. Here, emt & rad should
3414 : // have same flavour (causes problems for gamma->qqbar).
3415 0 : if (colTop == 1) {
3416 :
3417 0 : int radSign = (event[iRad].id() < 0) ? -1 : 1;
3418 0 : int emtSign = (event[EmtTag].id() < 0) ? -1 : 1;
3419 :
3420 : // Final gluino splitting.
3421 : bool finalSplitting = false;
3422 0 : if ( abs(radID) < 10
3423 0 : && radSign*(abs(radID)+offsetL) == -sign*event[EmtTag].id() )
3424 0 : finalSplitting = true;
3425 0 : if ( abs(radID) < 10
3426 0 : && radSign*(abs(radID)+offsetR) == -sign*event[EmtTag].id() )
3427 0 : finalSplitting = true;
3428 0 : if ( abs(radID) > offsetL && abs(radID) < offsetL+10
3429 0 : && radID == -sign*emtSign*( event[EmtTag].idAbs() + offsetL) )
3430 0 : finalSplitting = true;
3431 0 : if ( abs(radID) > offsetR && abs(radID) < offsetR+10
3432 0 : && radID == -sign*emtSign*( event[EmtTag].idAbs() + offsetR) )
3433 0 : finalSplitting = true;
3434 :
3435 : // Initial gluon splitting.
3436 : bool initialSplitting = false;
3437 0 : if ( radID == 21 && ( ( event[EmtTag].idAbs() > offsetL
3438 0 : && event[EmtTag].idAbs() < offsetL+10)
3439 0 : || ( event[EmtTag].idAbs() > offsetR
3440 0 : && event[EmtTag].idAbs() < offsetR+10) )
3441 0 : && ( event[iRad].col() == event[EmtTag].col()
3442 0 : || event[iRad].acol() == event[EmtTag].acol() ) )
3443 0 : initialSplitting = true;
3444 :
3445 0 : if ( finalSplitting ) {
3446 :
3447 : int col = -1;
3448 : int acl = -1;
3449 0 : if ( radID < 0 && event[iRad].colType() == -1) {
3450 0 : acl = event[EmtTag].acol();
3451 0 : col = event[iRad].acol();
3452 0 : } else if ( event[iRad].colType() == 1 ) {
3453 0 : col = event[EmtTag].col();
3454 0 : acl = event[iRad].col();
3455 0 : }
3456 :
3457 : // Recoiler
3458 : int iRec = 0;
3459 : // Colour partner
3460 : int iPartner = 0;
3461 :
3462 0 : if (col > 0) {
3463 : // Find recoiler by colour
3464 0 : iRec = FindCol(col,iRad,EmtTag,event,1,true);
3465 : // In initial state splitting has final state colour partner,
3466 : // Save both partner and recoiler
3467 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
3468 : // Save colour recoiler
3469 : iPartner = iRec;
3470 : // Reset kinematic recoiler to initial state parton
3471 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3472 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
3473 : // For final state splittings, colour partner and recoiler are
3474 : // identical
3475 0 : } else {
3476 : iPartner = iRec;
3477 : }
3478 :
3479 : // Not interested in pure QCD triples here.
3480 0 : if ( !isSQCDrad && !isSQCDemt
3481 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3482 0 : iRec = 0;
3483 :
3484 0 : if ( iRec != 0 && iPartner != 0
3485 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
3486 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
3487 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
3488 0 : continue;
3489 : }
3490 :
3491 : // Reset partner
3492 : iPartner = 0;
3493 : // Find recoiler by colour
3494 0 : iRec = FindCol(col,iRad,EmtTag,event,2,true);
3495 : // In initial state splitting has final state colour partner,
3496 : // Save both partner and recoiler
3497 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
3498 : // Save colour recoiler
3499 : iPartner = iRec;
3500 : // Reset kinematic recoiler to initial state parton
3501 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3502 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
3503 : // For final state splittings, colour partner and recoiler are
3504 : // identical
3505 0 : } else {
3506 : iPartner = iRec;
3507 : }
3508 :
3509 : // Not interested in pure QCD triples here.
3510 0 : if ( !isSQCDrad && !isSQCDemt
3511 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3512 0 : iRec = 0;
3513 :
3514 0 : if ( iRec != 0 && iPartner != 0
3515 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
3516 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
3517 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
3518 0 : continue;
3519 : }
3520 : }
3521 :
3522 0 : if (acl > 0) {
3523 :
3524 : // Reset partner
3525 : iPartner = 0;
3526 : // Find recoiler by colour
3527 0 : iRec = FindCol(acl,iRad,EmtTag,event,1,true);
3528 : // In initial state splitting has final state colour partner,
3529 : // Save both partner and recoiler
3530 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
3531 : // Save colour recoiler
3532 : iPartner = iRec;
3533 : // Reset kinematic recoiler to initial state parton
3534 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3535 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
3536 : // For final state splittings, colour partner and recoiler are
3537 : // identical
3538 0 : } else {
3539 : iPartner = iRec;
3540 : }
3541 :
3542 : // Not interested in pure QCD triples here.
3543 0 : if ( !isSQCDrad && !isSQCDemt
3544 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3545 0 : iRec = 0;
3546 :
3547 0 : if ( iRec != 0 && iPartner != 0
3548 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
3549 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
3550 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
3551 0 : continue;
3552 : }
3553 :
3554 : // Reset partner
3555 : iPartner = 0;
3556 : // Find recoiler by colour
3557 0 : iRec = FindCol(acl,iRad,EmtTag,event,2,true);
3558 : // In initial state splitting has final state colour partner,
3559 : // Save both partner and recoiler
3560 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) {
3561 : // Save colour recoiler
3562 : iPartner = iRec;
3563 : // Reset kinematic recoiler to initial state parton
3564 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3565 0 : if (PosInitPartn[l] != iRad) iRec = PosInitPartn[l];
3566 : // For final state splittings, colour partner and recoiler are
3567 : // identical
3568 0 : } else {
3569 : iPartner = iRec;
3570 : }
3571 :
3572 : // Not interested in pure QCD triples here.
3573 0 : if ( !isSQCDrad && !isSQCDemt
3574 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3575 0 : iRec = 0;
3576 :
3577 0 : if ( iRec != 0 && iPartner != 0
3578 0 : && allowedClustering( iRad, EmtTag, iRec, iPartner, event) ) {
3579 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iPartner,
3580 0 : pTLund(event[iRad], event[EmtTag], event[iRec], pTdef) ));
3581 0 : continue;
3582 : }
3583 : }
3584 : // Initial gluon splitting
3585 0 : } else if ( initialSplitting ) {
3586 :
3587 : // SM splittings already taken care of in findQCDTriple.
3588 0 : if ( !isSQCDrad && !isSQCDemt ) continue;
3589 :
3590 : // For an initial state radiator, always set recoiler
3591 : // to the other initial state parton (recoil is taken
3592 : // by full remaining system, so this is just a
3593 : // labelling for such a process)
3594 : int RecInit = 0;
3595 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3596 0 : if (PosInitPartn[l] != iRad) RecInit = PosInitPartn[l];
3597 :
3598 : // Find the colour connected partner
3599 : // Find colour index of radiator before splitting
3600 0 : int col = getRadBeforeCol(iRad, EmtTag, event);
3601 0 : int acl = getRadBeforeAcol(iRad, EmtTag, event);
3602 :
3603 : // Find the correct partner: If a colour line has split,
3604 : // the partner is connected to the radiator before the splitting
3605 : // by a colour line (same reasoning for anticolour). The colour
3606 : // that split is the colour appearing twice in the
3607 : // radiator + emitted pair.
3608 : // Thus, if we remove a colour index with the clustering,
3609 : // we should look for a colour partner, else look for
3610 : // an anticolour partner
3611 0 : int colRemove = (event[iRad].col() == event[EmtTag].col())
3612 0 : ? event[iRad].col() : 0;
3613 :
3614 : int iPartner = 0;
3615 0 : if (colRemove > 0 && col > 0)
3616 0 : iPartner = FindCol(col,iRad,EmtTag,event,1,true)
3617 0 : + FindCol(col,iRad,EmtTag,event,2,true);
3618 0 : else if (colRemove > 0 && acl > 0)
3619 0 : iPartner = FindCol(acl,iRad,EmtTag,event,1,true)
3620 0 : + FindCol(acl,iRad,EmtTag,event,2,true);
3621 :
3622 0 : if ( allowedClustering( iRad, EmtTag, RecInit, iPartner, event ) ) {
3623 0 : clus.push_back( Clustering(EmtTag, iRad, RecInit, iPartner,
3624 0 : pTLund(event[iRad],event[EmtTag],event[RecInit], pTdef) ));
3625 0 : continue;
3626 : }
3627 0 : }
3628 :
3629 : // Second colour topology: Gluino emission
3630 :
3631 0 : } else {
3632 :
3633 0 : if ( (event[iRad].col() == event[EmtTag].acol())
3634 0 : || (event[iRad].acol() == event[EmtTag].col())
3635 0 : || (event[iRad].col() == event[EmtTag].col())
3636 0 : || (event[iRad].acol() == event[EmtTag].acol()) ) {
3637 : // For the rest, choose recoiler to have a common colour
3638 : // tag with radiator, while not being the "Emitted"
3639 :
3640 : int col = -1;
3641 : int acl = -1;
3642 :
3643 0 : if (event[iRad].isFinal() ) {
3644 :
3645 0 : if ( radID < 0 && event[iRad].colType() == -1) {
3646 0 : acl = event[EmtTag].acol();
3647 0 : col = event[iRad].col();
3648 0 : } else if ( radID > 0 && event[iRad].colType() == 1 ) {
3649 0 : col = event[EmtTag].col();
3650 0 : acl = event[iRad].acol();
3651 0 : } else {
3652 0 : col = event[iRad].col();
3653 0 : acl = event[iRad].acol();
3654 : }
3655 :
3656 : int iRec = 0;
3657 0 : if (col > 0) {
3658 0 : iRec = FindCol(col,iRad,EmtTag,event,1,true);
3659 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3660 : // Not interested in pure QCD triples here.
3661 0 : if ( !isSQCDrad && !isSQCDemt
3662 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3663 0 : iRec = 0;
3664 0 : if (iRec != 0
3665 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3666 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3667 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3668 0 : continue;
3669 : }
3670 :
3671 0 : iRec = FindCol(col,iRad,EmtTag,event,2,true);
3672 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3673 : // Not interested in pure QCD triples here.
3674 0 : if ( !isSQCDrad && !isSQCDemt
3675 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3676 0 : iRec = 0;
3677 0 : if (iRec != 0
3678 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3679 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3680 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3681 0 : continue;
3682 : }
3683 : }
3684 :
3685 0 : if (acl > 0) {
3686 0 : iRec = FindCol(acl,iRad,EmtTag,event,1,true);
3687 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3688 : // Not interested in pure QCD triples here.
3689 0 : if ( !isSQCDrad && !isSQCDemt
3690 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3691 0 : iRec = 0;
3692 0 : if (iRec != 0
3693 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3694 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3695 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3696 0 : continue;
3697 : }
3698 :
3699 0 : iRec = FindCol(acl,iRad,EmtTag,event,2,true);
3700 0 : if ( (sign < 0) && (event[iRec].isFinal()) ) iRec = 0;
3701 : // Not interested in pure QCD triples here.
3702 0 : if ( !isSQCDrad && !isSQCDemt
3703 0 : && (event[iRec].idAbs() < 10 || event[iRec].id() == 21) )
3704 0 : iRec = 0;
3705 0 : if (iRec != 0
3706 0 : && allowedClustering( iRad, EmtTag, iRec, iRec, event) ) {
3707 0 : clus.push_back( Clustering(EmtTag, iRad, iRec, iRec,
3708 0 : pTLund(event[iRad],event[EmtTag],event[iRec], pTdef) ));
3709 0 : continue;
3710 : }
3711 : }
3712 :
3713 0 : } else {
3714 :
3715 : // SM splittings already taken care of in findQCDTriple. Since
3716 : // initial state splittings will not know if the true
3717 : // colour-connected recoiler is a SM particle, any ISR splitting
3718 : // of a SM particle will be included by findQCDTriple. To not
3719 : // include the same splitting twice, continue for SM ISR radiator
3720 0 : if ( !isSQCDrad || !isSQCDemt ) continue;
3721 :
3722 : // For an initial state radiator, always set recoiler
3723 : // to the other initial state parton (recoil is taken
3724 : // by full remaining system, so this is just a
3725 : // labelling for such a process)
3726 : int RecInit = 0;
3727 : int iPartner = 0;
3728 0 : for(int l = 0; l < int(PosInitPartn.size()); ++l)
3729 0 : if (PosInitPartn[l] != iRad) RecInit = PosInitPartn[l];
3730 :
3731 : // Find the colour connected partner
3732 : // Find colour index of radiator before splitting
3733 0 : col = getRadBeforeCol(iRad, EmtTag, event);
3734 0 : acl = getRadBeforeAcol(iRad, EmtTag, event);
3735 :
3736 : // Find the correct partner: If a colour line has split,
3737 : // the partner is connected to the radiator before the splitting
3738 : // by a colour line (same reasoning for anticolour). The colour
3739 : // that split is the colour appearing twice in the
3740 : // radiator + emitted pair.
3741 : // Thus, if we remove a colour index with the clustering,
3742 : // we should look for a colour partner, else look for
3743 : // an anticolour partner
3744 0 : int colRemove = (event[iRad].col() == event[EmtTag].col())
3745 0 : ? event[iRad].col() : 0;
3746 0 : iPartner = (colRemove > 0)
3747 0 : ? FindCol(col,iRad,EmtTag,event,1,true)
3748 0 : + FindCol(col,iRad,EmtTag,event,2,true)
3749 0 : : FindCol(acl,iRad,EmtTag,event,1,true)
3750 0 : + FindCol(acl,iRad,EmtTag,event,2,true);
3751 :
3752 0 : if ( allowedClustering( iRad, EmtTag, RecInit, iPartner, event)) {
3753 0 : clus.push_back( Clustering(EmtTag, iRad, RecInit, iPartner,
3754 0 : pTLund(event[iRad],event[EmtTag],event[RecInit], pTdef)));
3755 :
3756 0 : continue;
3757 : }
3758 0 : }
3759 0 : }
3760 : }
3761 0 : }
3762 0 : }
3763 :
3764 : // Done
3765 : return clus;
3766 :
3767 0 : }
3768 :
3769 : //--------------------------------------------------------------------------
3770 :
3771 : // Calculate and return the probability of a clustering.
3772 : // IN Clustering : rad,rec,emt - System for which the splitting
3773 : // probability should be calcuated
3774 : // OUT splitting probability
3775 :
3776 : double History::getProb(const Clustering & SystemIn) {
3777 :
3778 : // Get local copies of input system
3779 0 : int Rad = SystemIn.emittor;
3780 0 : int Rec = SystemIn.recoiler;
3781 0 : int Emt = SystemIn.emitted;
3782 :
3783 : // Initialise shower probability
3784 : double showerProb = 0.0;
3785 :
3786 : // If the splitting resulted in disallowed evolution variable,
3787 : // disallow the splitting
3788 0 : if (SystemIn.pT() <= 0.) return 0.;
3789 :
3790 : // Initialise all combinatorical factors
3791 : double CF = 4./3.;
3792 : double NC = 3.;
3793 : // Flavour is known when reclustring, thus n_f=1
3794 : double TR = 1./2.;
3795 :
3796 : // Split up in FSR and ISR
3797 0 : bool isFSR = (state[Rad].isFinal() && state[Rec].isFinal());
3798 0 : bool isFSRinREC = (state[Rad].isFinal() && !state[Rec].isFinal());
3799 0 : bool isISR = !state[Rad].isFinal();
3800 :
3801 : // Check if this is the clustering 2->3 to 2->2.
3802 : // If so, use weight for joined evolution
3803 : int nFinal = 0;
3804 0 : for(int i=0; i < state.size(); ++i)
3805 0 : if (state[i].isFinal()) nFinal++;
3806 0 : bool isLast = (nFinal == (mergingHooksPtr->hardProcess.nQuarksOut()
3807 0 : +mergingHooksPtr->hardProcess.nLeptonOut()+1));
3808 :
3809 0 : if (isISR) {
3810 : // Find incoming particles
3811 :
3812 : int inP = 0;
3813 : int inM = 0;
3814 0 : for(int i=0;i< int(state.size()); ++i) {
3815 0 : if (state[i].mother1() == 1) inP = i;
3816 0 : if (state[i].mother1() == 2) inM = i;
3817 : }
3818 : // Construct dipole mass, eCM and sHat = x1*x2*s
3819 0 : Vec4 sum = state[Rad].p() + state[Rec].p() - state[Emt].p();
3820 0 : double m2Dip = sum.m2Calc();
3821 0 : double sHat = (state[inM].p() + state[inP].p()).m2Calc();
3822 : // Energy fraction z=E_q1/E_qi in branch q(i)q(2) -> q(1)g(3)q(2)
3823 0 : double z1 = m2Dip / sHat;
3824 : // Virtuality of the splittings
3825 0 : Vec4 Q1( state[Rad].p() - state[Emt].p() );
3826 0 : Vec4 Q2( state[Rec].p() - state[Emt].p() );
3827 : // Q^2 for emission off radiator line
3828 0 : double Q1sq = -Q1.m2Calc();
3829 : // pT^2 for emission off radiator line
3830 0 : double pT1sq = pow(SystemIn.pT(),2);
3831 : // Remember if massive particles involved: Mass corrections for
3832 : // to g->QQ and Q->Qg splittings
3833 0 : bool g2QQmassive = mergingHooksPtr->includeMassive()
3834 0 : && state[Rad].id() == 21
3835 0 : && ( (state[Emt].idAbs() >= 4 && state[Emt].idAbs() < 7)
3836 0 : || (state[Emt].idAbs() > 1000000 && state[Emt].idAbs() < 1000010 )
3837 0 : || (state[Emt].idAbs() > 2000000 && state[Emt].idAbs() < 2000010 ));
3838 0 : bool Q2Qgmassive = mergingHooksPtr->includeMassive()
3839 0 : && state[Emt].id() == 21
3840 0 : && ( (state[Rad].idAbs() >= 4 && state[Rad].idAbs() < 7)
3841 0 : || (state[Rad].idAbs() > 1000000 && state[Rad].idAbs() < 1000010 )
3842 0 : || (state[Rad].idAbs() > 2000000 && state[Rad].idAbs() < 2000010 ));
3843 0 : bool isMassive = mergingHooksPtr->includeMassive()
3844 0 : && ( g2QQmassive || Q2Qgmassive
3845 0 : || state[Emt].id() == 1000021);
3846 0 : double m2Emt0 = pow(particleDataPtr->m0(state[Emt].id()),2);
3847 0 : double m2Rad0 = pow(particleDataPtr->m0(state[Rad].id()),2);
3848 :
3849 : // Correction of virtuality for massive splittings
3850 0 : if ( g2QQmassive) Q1sq += m2Emt0;
3851 0 : else if (Q2Qgmassive) Q1sq += m2Rad0;
3852 :
3853 : // pT0 dependence!!!
3854 0 : double pT0sq = pow(mergingHooksPtr->pT0ISR(),2);
3855 0 : double Q2sq = -Q2.m2Calc();
3856 :
3857 : // Correction of virtuality of other splitting
3858 0 : bool g2QQmassiveRec = mergingHooksPtr->includeMassive()
3859 0 : && state[Rec].id() == 21
3860 0 : && ( state[Emt].idAbs() >= 4 && state[Emt].idAbs() < 7);
3861 0 : bool Q2QgmassiveRec = mergingHooksPtr->includeMassive()
3862 0 : && state[Emt].id() == 21
3863 0 : && ( state[Rec].idAbs() >= 4 && state[Rec].idAbs() < 7);
3864 0 : double m2Rec0 = pow(particleDataPtr->m0(state[Rad].id()),2);
3865 0 : if ( g2QQmassiveRec) Q2sq += m2Emt0;
3866 0 : else if (Q2QgmassiveRec) Q2sq += m2Rec0;
3867 :
3868 0 : bool hasJoinedEvol = (state[Emt].id() == 21
3869 0 : || state[Rad].id() == state[Rec].id());
3870 :
3871 : // Initialise normalization factor multiplying the splitting
3872 : // function numerator
3873 : double fac = 1.;
3874 0 : if ( mergingHooksPtr->pickByFull() || mergingHooksPtr->pickBySumPT()) {
3875 0 : double facJoined = ( Q2sq + pT0sq/(1.-z1) )
3876 0 : * 1./(Q1sq*Q2sq + pT0sq*sHat + pow(pT0sq/(1.-z1),2));
3877 0 : double facSingle = mergingHooksPtr->nonJoinedNorm()*1./( pT1sq + pT0sq);
3878 :
3879 0 : fac = (hasJoinedEvol && isLast) ? facJoined : facSingle;
3880 :
3881 0 : } else if (mergingHooksPtr->pickByPoPT2()) {
3882 0 : fac = 1./(pT1sq + pT0sq);
3883 0 : } else {
3884 0 : string message="Error in History::getProb: Scheme for calculating";
3885 0 : message+=" shower splitting probability is undefined.";
3886 0 : infoPtr->errorMsg(message);
3887 0 : }
3888 :
3889 : // Calculate shower splitting probability:
3890 : // Splitting functions*normalization*ME reweighting factors
3891 :
3892 : // Calculate branching probability for q -> q g
3893 0 : if ( state[Emt].id() == 21 && state[Rad].id() != 21) {
3894 : // Find splitting kernel
3895 0 : double num = CF*(1. + pow(z1,2)) / (1.-z1);
3896 0 : if (isMassive) num -= CF * z1 * (1.-z1) * (m2Rad0/pT1sq);
3897 :
3898 : // Find ME reweighting factor
3899 : double meReweighting = 1.;
3900 : // Find the number of final state coloured particles, apart
3901 : // from those coming from the hard process
3902 : int nCol = 0;
3903 0 : for(int i=0; i < state.size(); ++i)
3904 0 : if (state[i].isFinal() && state[i].colType() != 0
3905 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,state) )
3906 0 : nCol++;
3907 : // For first splitting of single vector boson production,
3908 : // apply ME corrections
3909 0 : if (nCol == 1
3910 0 : && int(mergingHooksPtr->hardProcess.hardIntermediate.size()) == 1) {
3911 0 : double sH = m2Dip / z1;
3912 0 : double tH = -Q1sq;
3913 0 : double uH = Q1sq - m2Dip * (1. - z1) / z1;
3914 0 : double misMatch = (uH*tH - (uH + tH)*pT0sq/(1.-z1)
3915 0 : + pow(pT0sq/(1.-z1),2) ) / (uH*tH);
3916 0 : meReweighting *= (tH*tH + uH*uH + 2. * m2Dip * sH)
3917 0 : / (sH*sH + m2Dip*m2Dip);
3918 0 : meReweighting *= misMatch;
3919 0 : }
3920 : // Multiply factors
3921 0 : showerProb = num*fac*meReweighting;
3922 :
3923 : // Calculate branching probability for g -> g g
3924 0 : } else if ( state[Emt].id() == 21 && state[Rad].id() == 21) {
3925 : // Calculate splitting kernel
3926 0 : double num = 2.*NC*pow2(1. - z1*(1.-z1)) / (z1*(1.-z1));
3927 :
3928 : // Include ME reweighting for higgs!!
3929 : // Find ME reweighting factor
3930 : double meReweighting = 1.;
3931 : // Find the number of final state coloured particles, apart
3932 : // from those coming from the hard process
3933 : int nCol = 0;
3934 0 : for(int i=0; i < state.size(); ++i)
3935 0 : if (state[i].isFinal() && state[i].colType() != 0
3936 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,state) )
3937 0 : nCol++;
3938 : // For first splitting of single vector boson production,
3939 : // apply ME corrections
3940 0 : if ( nCol == 1
3941 0 : && mergingHooksPtr->getProcessString().compare("pp>h") == 0
3942 0 : && int(mergingHooksPtr->hardProcess.hardIntermediate.size()) == 1 ) {
3943 0 : double sH = m2Dip / z1;
3944 0 : double tH = -Q1sq;
3945 0 : double uH = Q1sq - m2Dip * (1. - z1) / z1;
3946 : meReweighting *= 0.5
3947 0 : * (pow4(sH) + pow4(tH) + pow4(uH) + pow4(m2Dip))
3948 0 : / pow2(sH*sH - m2Dip * (sH - m2Dip));
3949 0 : }
3950 :
3951 : // Multiply factors
3952 0 : showerProb = num*fac*meReweighting;
3953 :
3954 : // Calculate branching probability for q -> g q
3955 0 : } else if ( state[Emt].id() != 21 && state[Rad].id() != 21 ) {
3956 : // Calculate splitting kernel
3957 0 : double num = CF*(1. + pow2(1.-z1)) / z1;
3958 :
3959 : // Include ME reweighting for higgs!!
3960 : // Find ME reweighting factor
3961 : double meReweighting = 1.;
3962 : // Find the number of final state coloured particles, apart
3963 : // from those coming from the hard process
3964 : int nCol = 0;
3965 0 : for ( int i=0; i < state.size(); ++i )
3966 0 : if ( state[i].isFinal() && state[i].colType() != 0
3967 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,state) )
3968 0 : nCol++;
3969 : // For first splitting of single vector boson production,
3970 : // apply ME corrections
3971 0 : if (nCol == 1
3972 0 : && mergingHooksPtr->getProcessString().compare("pp>h") == 0
3973 0 : && int(mergingHooksPtr->hardProcess.hardIntermediate.size()) == 1) {
3974 0 : double sH = m2Dip / z1;
3975 0 : double uH = Q1sq - m2Dip * (1. - z1) / z1;
3976 0 : meReweighting *= (sH*sH + uH*uH)
3977 0 : / (sH*sH + pow2(sH -m2Dip));
3978 0 : }
3979 :
3980 : // Multiply factors
3981 0 : showerProb = num*fac*meReweighting;
3982 :
3983 : // Calculate branching probability for g -> q qbar
3984 0 : } else if ( state[Emt].id() != 21 && state[Rad].id() == 21 ) {
3985 : // Calculate splitting kernel
3986 0 : double num = TR * ( pow(z1,2) + pow(1.-z1,2) );
3987 0 : if (isMassive) num += TR * 2.*z1*(1.-z1)*(m2Emt0/pT1sq);
3988 : // Calculate ME reweighting factor
3989 : double meReweighting = 1.;
3990 : // Find the number of final state coloured particles, apart
3991 : // from those coming from the hard process
3992 : int nCol = 0;
3993 0 : for ( int i=0; i < state.size(); ++i )
3994 0 : if ( state[i].isFinal() && state[i].colType() != 0
3995 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,state) )
3996 0 : nCol++;
3997 : // For first splitting of single vector boson production,
3998 : // apply ME corrections
3999 0 : if (nCol == 1
4000 0 : && int(mergingHooksPtr->hardProcess.hardIntermediate.size()) == 1) {
4001 0 : double sH = m2Dip / z1;
4002 0 : double tH = -Q1sq;
4003 0 : double uH = Q1sq - m2Dip * (1. - z1) / z1;
4004 0 : swap( tH, uH);
4005 0 : double misMatch = ( uH - pT0sq/(1.-z1) ) / uH;
4006 0 : double me = (sH*sH + uH*uH + 2. * m2Dip * tH)
4007 0 : / (pow2(sH - m2Dip) + m2Dip*m2Dip);
4008 : // Weight with me/overestimate
4009 : meReweighting *= me;
4010 0 : meReweighting *= misMatch;
4011 0 : }
4012 : // Multiply factors
4013 0 : showerProb = num*fac*meReweighting;
4014 :
4015 : // Print error if no kernel calculated
4016 0 : } else {
4017 0 : string message = "Error in History::getProb: Splitting kernel"
4018 : " undefined in ISR in clustering.";
4019 0 : infoPtr->errorMsg(message);
4020 0 : }
4021 :
4022 : // If corrected pT below zero in ISR, put probability to zero
4023 0 : double m2Sister0 = pow(state[Emt].m0(),2);
4024 0 : double pT2corr = (Q1sq - z1*(m2Dip + Q1sq)*(Q1sq + m2Sister0)/m2Dip);
4025 0 : if (pT2corr < 0.) showerProb *= 1e-9;
4026 :
4027 : // If creating heavy quark by Q -> gQ then next need g -> Q + Qbar.
4028 : // So minimum total mass2 is 4 * m2Sister, but use more to be safe.
4029 0 : if ( state[Emt].id() == state[Rad].id()
4030 0 : && ( state[Rad].idAbs() == 4 || state[Rad].idAbs() == 5 )) {
4031 0 : double m2QQsister = 2.*4.*m2Sister0;
4032 0 : double pT2QQcorr = Q1sq - z1*(m2Dip + Q1sq)*(Q1sq + m2QQsister)
4033 0 : / m2Dip;
4034 0 : if (pT2QQcorr < 0.0) showerProb *= 1e-9;
4035 0 : }
4036 :
4037 0 : if (mergingHooksPtr->includeRedundant()) {
4038 : // Initialise the spacelike shower alpha_S
4039 0 : AlphaStrong* asISR = mergingHooksPtr->AlphaS_ISR();
4040 0 : double as = (*asISR).alphaS(pT1sq + pT0sq) / (2.*M_PI);
4041 : // Multiply with alpha_S
4042 0 : showerProb *= as;
4043 0 : }
4044 :
4045 : // Done for ISR case, begin FSR case
4046 :
4047 0 : } else if (isFSR || isFSRinREC) {
4048 :
4049 : // Construct dipole mass
4050 0 : Vec4 sum = state[Rad].p() + state[Rec].p() + state[Emt].p();
4051 0 : double m2Dip = sum.m2Calc();
4052 : // Construct 2->3 variables for FSR
4053 0 : double x1 = 2. * (sum * state[Rad].p()) / m2Dip;
4054 0 : double x2 = 2. * (sum * state[Rec].p()) / m2Dip;
4055 0 : double prop1 = max(1e-12, 1. - x1);
4056 0 : double prop2 = max(1e-12, 1. - x2);
4057 0 : double x3 = max(1e-12, 2. - x1 - x2);
4058 : // Energy fraction z=E_q1/E_qi in branch q(i)q(2) -> q(1)g(3)q(2)
4059 0 : double z1 = x1/(x1 + x3);
4060 :
4061 : // Virtuality of the splittings
4062 0 : Vec4 Q1( state[Rad].p() + state[Emt].p() );
4063 0 : Vec4 Q2( state[Rec].p() + state[Emt].p() );
4064 :
4065 : // Q^2 for emission off radiator line
4066 0 : double Q1sq = Q1.m2Calc();
4067 : // pT^2 for emission off radiator line
4068 0 : double pT1sq = pow(SystemIn.pT(),2);
4069 : // Q^2 for emission off recoiler line
4070 0 : double Q2sq = Q2.m2Calc();
4071 :
4072 : // Remember if radiator or recoiler is massive.
4073 0 : bool isMassiveRad = ( state[Rad].idAbs() >= 4
4074 0 : && state[Rad].id() != 21 );
4075 0 : bool isMassiveRec = ( state[Rec].idAbs() >= 4
4076 0 : && state[Rec].id() != 21 );
4077 : // Correction of virtuality for massive splittings.
4078 0 : double m2Rad0 = pow(particleDataPtr->m0(state[Rad].id()),2);
4079 0 : double m2Rec0 = pow(particleDataPtr->m0(state[Rad].id()),2);
4080 0 : if ( mergingHooksPtr->includeMassive() && isMassiveRad ) Q1sq -= m2Rad0;
4081 0 : if ( mergingHooksPtr->includeMassive() && isMassiveRec ) Q2sq -= m2Rec0;
4082 :
4083 : // Initialise normalization factor multiplying the splitting
4084 : // function numerator
4085 : double fac = 1.;
4086 0 : if ( mergingHooksPtr->pickByFull() || mergingHooksPtr->pickBySumPT()) {
4087 0 : double facJoined = (1.-z1)/Q1sq * m2Dip/( Q1sq + Q2sq );
4088 0 : double facSingle = mergingHooksPtr->fsrInRecNorm() * 1./ pT1sq;
4089 0 : fac = (!isFSRinREC && isLast) ? facJoined : facSingle;
4090 0 : } else if (mergingHooksPtr->pickByPoPT2()) {
4091 0 : fac = 1. / pT1sq;
4092 0 : } else {
4093 0 : string message="Error in History::getProb: Scheme for calculating";
4094 0 : message+=" shower splitting probability is undefined.";
4095 0 : infoPtr->errorMsg(message);
4096 0 : }
4097 : // Calculate shower splitting probability:
4098 : // Splitting functions*normalization*ME reweighting factors
4099 :
4100 : // Calculate branching probability for g -> g_1 g_2
4101 0 : if ( state[Emt].id() == 21 && state[Rad].id() == 21) {
4102 : // Calculate splitting kernel
4103 0 : double num = 0.5* NC * (1. + pow3(z1)) / (1.-z1);
4104 : // Multiply factors
4105 0 : showerProb = num*fac;
4106 :
4107 : // Calculate branching probability for q -> q g with quark recoiler
4108 0 : } else if ( state[Emt].id() == 21
4109 0 : && state[Rad].id() != 21 && state[Rec].id() != 21) {
4110 : // For a qqbar dipole in FSR, ME corrections exist and the
4111 : // splitting function "z-weight" is set to 1.0 (only for 2->2 ??)
4112 0 : double num = CF * 2./(1.-z1);
4113 : // Find the number of final state coloured particles, apart
4114 : // from those coming from the hard process
4115 : int nCol = 0;
4116 0 : for(int i=0; i < state.size(); ++i)
4117 0 : if (state[i].isFinal() && state[i].colType() != 0
4118 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,state) )
4119 0 : nCol++;
4120 : // Calculate splitting kernel
4121 0 : if ( nCol > 3
4122 0 : || int(mergingHooksPtr->hardProcess.hardIntermediate.size()) > 1)
4123 0 : num = CF * (1. + pow2(z1)) /(1.-z1);
4124 : // Calculate ME reweighting factor
4125 : double meReweighting = 1.;
4126 : // Correct if this is the process created by the first
4127 : // FSR splitting of a 2->2 process
4128 0 : if ( nCol == 3
4129 0 : && int(mergingHooksPtr->hardProcess.hardIntermediate.size()) == 1 ) {
4130 : // Calculate the ME reweighting factor
4131 0 : double ShowerRate1 = 2./( x3 * prop2 );
4132 0 : double meDividingFactor1 = prop1 / x3;
4133 0 : double me = (pow(x1,2) + pow(x2,2))/(prop1*prop2);
4134 0 : meReweighting = meDividingFactor1 * me / ShowerRate1;
4135 0 : }
4136 : // Multiply factors
4137 0 : showerProb = num*fac*meReweighting;
4138 :
4139 : // Calculate branching probability for q1 -> q2 w+- with quark recoiler
4140 0 : } else if ( state[Emt].idAbs() == 24
4141 0 : && state[Rad].id() != 21 && state[Rec].id() != 21 ) {
4142 0 : double m2W = state[Emt].p().m2Calc();
4143 0 : double num = ( 3.*pow2(m2W / m2Dip)
4144 0 : + 2.* (m2W/m2Dip)*(x1 + x2)
4145 0 : + pow2(x1) + pow2(x2) ) / ( prop1*prop2 )
4146 0 : - (m2W/m2Dip) / pow2(prop1)
4147 0 : - (m2W/m2Dip) / pow2(prop2);
4148 : // Multiply factors
4149 0 : showerProb = num*fac;
4150 :
4151 : // Calculate branching probability for q -> q g with gluon recoiler
4152 0 : } else if ( state[Emt].id() == 21 && state[Rad].id() != 21
4153 0 : && state[Rec].id() == 21 ) {
4154 : // For qg /qbarg dipoles, the splitting function is
4155 : // calculated and not weighted by a ME correction factor
4156 : // Shower splitting function
4157 0 : double num = CF * (1. + pow2(z1)) / (1.-z1);
4158 0 : showerProb = num*fac;
4159 :
4160 : // Calculate branching probability for g -> q qbar
4161 0 : } else if ( state[Emt].id() != 21 ) {
4162 : // Get flavour of quark / antiquark
4163 0 : int flavour = state[Emt].id();
4164 : // Get correct masses for the quarks
4165 : // (needed to calculate splitting function?)
4166 0 : double mFlavour = particleDataPtr->m0(flavour);
4167 : // Get mass of quark/antiquark pair
4168 0 : double mDipole = m(state[Rad].p(), state[Emt].p());
4169 : // Factor determining if gluon decay was allowed
4170 0 : double beta = sqrtpos( 1. - 4.*pow2(mFlavour)/pow2(mDipole) );
4171 : // Shower splitting function
4172 0 : double num = 0.5*TR * ( z1*z1 + (1.-z1)*(1.-z1) );
4173 0 : if (beta <= 0.) beta = 0.;
4174 :
4175 0 : showerProb = num*fac*beta;
4176 :
4177 : // Print error if no kernel calculated
4178 0 : } else {
4179 0 : string message="Error in History::getProb: Splitting kernel undefined";
4180 0 : message+=" in FSR clustering.";
4181 0 : infoPtr->errorMsg(message);
4182 0 : }
4183 :
4184 0 : if (mergingHooksPtr->includeRedundant()) {
4185 : // Initialise the spacelike shower alpha_S
4186 0 : AlphaStrong* asFSR = mergingHooksPtr->AlphaS_FSR();
4187 0 : double as = (*asFSR).alphaS(pT1sq) / (2.*M_PI);
4188 : // Multiply with alpha_S
4189 0 : showerProb *= as;
4190 0 : }
4191 :
4192 : // Done for FSR
4193 0 : } else {
4194 0 : string message="Error in History::getProb: Radiation could not be";
4195 0 : message+=" interpreted as FSR or ISR.";
4196 0 : infoPtr->errorMsg(message);
4197 0 : }
4198 :
4199 0 : if (showerProb <= 0.) showerProb = 0.;
4200 :
4201 : // // Different coupling constants for qcd and ew splittings
4202 : // if ( state[Emt].colType() != 0 ) {
4203 : // AlphaStrong* asFSR = mergingHooksPtr->AlphaS_FSR();
4204 : // double as = (*asFSR).alphaS(91.188*91.188) / (2.*M_PI);
4205 : // showerProb *= as;
4206 : // } else {
4207 : // AlphaEM* aEMFSR = mergingHooksPtr->AlphaEM_FSR();
4208 : // double aEM = (*aEMFSR).alphaEM(91.188*91.188) / (2.*M_PI);
4209 : // showerProb *= aEM;
4210 : // }
4211 :
4212 : // Done
4213 : return showerProb;
4214 0 : }
4215 :
4216 :
4217 : //--------------------------------------------------------------------------
4218 :
4219 : // Set up the beams (fill the beam particles with the correct
4220 : // current incoming particles) to allow calculation of splitting
4221 : // probability.
4222 : // For interleaved evolution, set assignments dividing PDFs into
4223 : // sea and valence content. This assignment is, until a history path
4224 : // is chosen and a first trial shower performed, not fully correct
4225 : // (since content is chosen form too high x and too low scale). The
4226 : // assignment used for reweighting will be corrected after trial
4227 : // showering
4228 :
4229 : void History::setupBeams() {
4230 :
4231 : // Do nothing for empty event, possible if sequence of
4232 : // clusterings was ill-advised in that it results in
4233 : // colour-disconnected states
4234 0 : if (state.size() < 4) return;
4235 : // Do nothing for e+e- beams
4236 0 : if ( state[3].colType() == 0 ) return;
4237 0 : if ( state[4].colType() == 0 ) return;
4238 :
4239 : // Incoming partons to hard process are stored in slots 3 and 4.
4240 : int inS = 0;
4241 : int inP = 0;
4242 : int inM = 0;
4243 0 : for(int i=0;i< int(state.size()); ++i) {
4244 0 : if (state[i].mother1() == 1) inP = i;
4245 0 : if (state[i].mother1() == 2) inM = i;
4246 : }
4247 :
4248 : // Save some info before clearing beams
4249 : // Mothers of incoming partons companion code
4250 : int motherPcompRes = -1;
4251 : int motherMcompRes = -1;
4252 :
4253 : bool sameFlavP = false;
4254 : bool sameFlavM = false;
4255 :
4256 0 : if (mother) {
4257 : int inMotherP = 0;
4258 : int inMotherM = 0;
4259 0 : for(int i=0;i< int(mother->state.size()); ++i) {
4260 0 : if (mother->state[i].mother1() == 1) inMotherP = i;
4261 0 : if (mother->state[i].mother1() == 2) inMotherM = i;
4262 : }
4263 0 : sameFlavP = (state[inP].id() == mother->state[inMotherP].id());
4264 0 : sameFlavM = (state[inM].id() == mother->state[inMotherM].id());
4265 :
4266 0 : motherPcompRes = (sameFlavP) ? beamA[0].companion() : -2;
4267 0 : motherMcompRes = (sameFlavM) ? beamB[0].companion() : -2;
4268 0 : }
4269 :
4270 : // Append the current incoming particles to the beam
4271 0 : beamA.clear();
4272 0 : beamB.clear();
4273 :
4274 : // Get energy of incoming particles
4275 0 : double Ep = 2. * state[inP].e();
4276 0 : double Em = 2. * state[inM].e();
4277 :
4278 : // If incoming partons are massive then recalculate to put them massless.
4279 0 : if (state[inP].m() != 0. || state[inM].m() != 0.) {
4280 0 : Ep = state[inP].pPos() + state[inM].pPos();
4281 0 : Em = state[inP].pNeg() + state[inM].pNeg();
4282 0 : }
4283 :
4284 : // Add incoming hard-scattering partons to list in beam remnants.
4285 0 : double x1 = Ep / state[inS].m();
4286 0 : beamA.append( inP, state[inP].id(), x1);
4287 0 : double x2 = Em / state[inS].m();
4288 0 : beamB.append( inM, state[inM].id(), x2);
4289 :
4290 : // Scale. For ME multiplicity history, put scale to mu_F
4291 : // (since sea/valence quark content is chosen from this scale)
4292 0 : double scalePDF = (mother) ? scale : infoPtr->QFac();
4293 : // Find whether incoming partons are valence or sea. Store.
4294 : // Can I do better, e.g. by setting the scale to the hard process
4295 : // scale (= M_W) or by replacing one of the x values by some x/z??
4296 0 : beamA.xfISR( 0, state[inP].id(), x1, scalePDF*scalePDF);
4297 0 : if (!mother) {
4298 0 : beamA.pickValSeaComp();
4299 0 : } else {
4300 0 : beamA[0].companion(motherPcompRes);
4301 : }
4302 0 : beamB.xfISR( 0, state[inM].id(), x2, scalePDF*scalePDF);
4303 0 : if (!mother) {
4304 0 : beamB.pickValSeaComp();
4305 0 : } else {
4306 0 : beamB[0].companion(motherMcompRes);
4307 : }
4308 :
4309 0 : }
4310 :
4311 : //--------------------------------------------------------------------------
4312 :
4313 : // Calculate the PDF ratio used in the argument of the no-emission
4314 : // probability
4315 :
4316 : double History::pdfForSudakov() {
4317 :
4318 : // Do nothing for e+e- beams
4319 0 : if ( state[3].colType() == 0 ) return 1.0;
4320 0 : if ( state[4].colType() == 0 ) return 1.0;
4321 :
4322 : // Check if splittings was ISR or FSR
4323 0 : bool FSR = ( mother->state[clusterIn.emittor].isFinal()
4324 0 : && mother->state[clusterIn.recoiler].isFinal());
4325 0 : bool FSRinRec = ( mother->state[clusterIn.emittor].isFinal()
4326 0 : && !mother->state[clusterIn.recoiler].isFinal());
4327 :
4328 : // Done for pure FSR
4329 0 : if (FSR) return 1.0;
4330 :
4331 0 : int iInMother = (FSRinRec)? clusterIn.recoiler : clusterIn.emittor;
4332 : // Find side of event that was reclustered
4333 0 : int side = ( mother->state[iInMother].pz() > 0 ) ? 1 : -1;
4334 :
4335 : int inP = 0;
4336 : int inM = 0;
4337 0 : for(int i=0;i< int(state.size()); ++i) {
4338 0 : if (state[i].mother1() == 1) inP = i;
4339 0 : if (state[i].mother1() == 2) inM = i;
4340 : }
4341 :
4342 : // Save mother id
4343 0 : int idMother = mother->state[iInMother].id();
4344 : // Find daughter position and id
4345 0 : int iDau = (side == 1) ? inP : inM;
4346 0 : int idDaughter = state[iDau].id();
4347 : // Get mother x value
4348 0 : double xMother = 2. * mother->state[iInMother].e() / mother->state[0].e();
4349 : // Get daughter x value of daughter
4350 0 : double xDaughter = 2.*state[iDau].e() / state[0].e(); // x1 before isr
4351 :
4352 : // Calculate pdf ratio
4353 0 : double ratio = getPDFratio(side, true, false, idMother, xMother, scale,
4354 : idDaughter, xDaughter, scale);
4355 :
4356 : // For FSR with incoming recoiler, maximally return 1.0, as
4357 : // is done in Pythia::TimeShower.
4358 : // For ISR, return ratio
4359 0 : return ( (FSRinRec)? min(1.,ratio) : ratio);
4360 0 : }
4361 :
4362 : //--------------------------------------------------------------------------
4363 :
4364 : // Calculate the hard process matrix element to include in the selection
4365 : // probability.
4366 :
4367 : double History::hardProcessME( const Event& event ) {
4368 :
4369 : // Get hard process.
4370 0 : string process = mergingHooksPtr->getProcessString();
4371 : double result = 1.;
4372 :
4373 0 : if ( process.compare("pp>e+ve") == 0
4374 0 : || process.compare("pp>e-ve~") == 0
4375 0 : || process.compare("pp>LEPTONS,NEUTRINOS") == 0 ) {
4376 : // Do nothing for incomplete process.
4377 : int nFinal = 0;
4378 0 : for ( int i=0; i < int(event.size()); ++i )
4379 0 : if ( event[i].isFinal() ) nFinal++;
4380 0 : if ( nFinal != 2 ) return 1.;
4381 : // Get W-boson mass and width.
4382 0 : double mW = particleDataPtr->m0(24);
4383 0 : double gW = particleDataPtr->mWidth(24) / mW;
4384 : // Get incoming particles.
4385 0 : int inP = (event[3].pz() > 0) ? 3 : 4;
4386 0 : int inM = (event[3].pz() > 0) ? 4 : 3;
4387 : // Get outgoing particles.
4388 : int outP = 0;
4389 0 : for ( int i=0; i < int(event.size()); ++i ) {
4390 0 : if ( event[i].isFinal() && event[i].px() > 0 ) outP = i;
4391 : }
4392 : // Get Mandelstam variables.
4393 0 : double sH = (event[inP].p() + event[inM].p()).m2Calc();
4394 0 : double tH = (event[inP].p() - event[outP].p()).m2Calc();
4395 0 : double uH = - sH - tH;
4396 :
4397 : // Return kinematic part of matrix element.
4398 0 : result = ( 1. + (tH - uH)/sH ) / ( pow2(sH - mW*mW) + pow2(sH*gW) );
4399 0 : } else
4400 0 : result = mergingHooksPtr->hardProcessME(event);
4401 :
4402 0 : return result;
4403 :
4404 0 : }
4405 :
4406 : //--------------------------------------------------------------------------
4407 :
4408 : // Perform the clustering of the current state and return the
4409 : // clustered state.
4410 : // IN Clustering : rad,rec,emt triple to be clustered to two partons
4411 : // OUT clustered state
4412 :
4413 : Event History::cluster( const Clustering & inSystem ) {
4414 :
4415 : // Initialise tags of particles to be changed
4416 0 : int Rad = inSystem.emittor;
4417 0 : int Rec = inSystem.recoiler;
4418 0 : int Emt = inSystem.emitted;
4419 : // Initialise eCM,mHat
4420 0 : double eCM = state[0].e();
4421 : // Flags for type of radiation
4422 0 : int radType = state[Rad].isFinal() ? 1 : -1;
4423 0 : int recType = state[Rec].isFinal() ? 1 : -1;
4424 :
4425 : // Construct the clustered event
4426 0 : Event NewEvent = Event();
4427 0 : NewEvent.init("(hard process-modified)", particleDataPtr);
4428 0 : NewEvent.clear();
4429 : // Copy all unchanged particles to NewEvent
4430 0 : for (int i = 0; i < state.size(); ++i)
4431 0 : if ( i != Rad && i != Rec && i != Emt )
4432 0 : NewEvent.append( state[i] );
4433 :
4434 : // Copy all the junctions one by one
4435 0 : for (int i = 0; i < state.sizeJunction(); ++i)
4436 0 : NewEvent.appendJunction( state.getJunction(i) );
4437 : // Find an appropriate scale for the hard process
4438 0 : double mu = choseHardScale(state);
4439 : // Initialise scales for new event
4440 0 : NewEvent.saveSize();
4441 0 : NewEvent.saveJunctionSize();
4442 0 : NewEvent.scale(mu);
4443 0 : NewEvent.scaleSecond(mu);
4444 :
4445 : // Set properties of radiator/recoiler after the clustering
4446 : // Recoiler properties will be unchanged
4447 0 : Particle RecBefore = Particle( state[Rec] );
4448 0 : RecBefore.setEvtPtr(&NewEvent);
4449 0 : RecBefore.daughters(0,0);
4450 : // Find flavour of radiator before splitting
4451 0 : int radID = getRadBeforeFlav(Rad, Emt, state);
4452 0 : int recID = state[Rec].id();
4453 0 : Particle RadBefore = Particle( state[Rad] );
4454 0 : RadBefore.setEvtPtr(&NewEvent);
4455 0 : RadBefore.id(radID);
4456 0 : RadBefore.daughters(0,0);
4457 : // Put dummy values for colours
4458 0 : RadBefore.cols(RecBefore.acol(),RecBefore.col());
4459 :
4460 : // Reset status if the reclustered radiator is a resonance.
4461 0 : if ( particleDataPtr->isResonance(radID) && radType == 1)
4462 0 : RadBefore.status(state[Rad].status());
4463 :
4464 : // Put mass for radiator and recoiler
4465 0 : double radMass = particleDataPtr->m0(radID);
4466 0 : double recMass = particleDataPtr->m0(recID);
4467 0 : if (radType == 1 ) RadBefore.m(radMass);
4468 0 : else RadBefore.m(0.0);
4469 0 : if (recType == 1 ) RecBefore.m(recMass);
4470 0 : else RecBefore.m(0.0);
4471 :
4472 : // Construct momenta and colours of clustered particles
4473 : // ISR/FSR splittings are treated differently
4474 0 : if ( radType + recType == 2 && state[Emt].idAbs() != 24 ) {
4475 : // Clustering of final(rad)/final(rec) dipole splitting
4476 : // Get eCM of (rad,rec,emt) triple
4477 0 : Vec4 sum = state[Rad].p() + state[Rec].p() + state[Emt].p();
4478 0 : double eCMME = sum.mCalc();
4479 :
4480 : // Define radiator and recoiler back-to-back in the dipole
4481 : // rest frame [=(state[rad]+state[emt])+state[rec] rest frame]
4482 0 : Vec4 Rad4mom;
4483 0 : Vec4 Rec4mom;
4484 0 : double mDsq = pow2(eCMME);
4485 : // If possible, keep the invariant mass of the radiator.
4486 0 : double mRsq = (radID == state[Rad].id() )
4487 0 : ? abs(state[Rad].p().m2Calc())
4488 0 : : pow2(particleDataPtr->m0(radID));
4489 0 : double mSsq = abs(state[Rec].p().m2Calc());
4490 0 : double a = 0.5*sqrt(mDsq);
4491 0 : double b = 0.25*(mRsq - mSsq) / a;
4492 0 : double c = sqrt(pow2(a) + pow2(b) - 2.*a*b - mSsq);
4493 :
4494 0 : Rad4mom.p( 0., 0., c, a+b);
4495 0 : Rec4mom.p( 0., 0.,-c, a-b);
4496 :
4497 : // Find boost from Rad4mom+Rec4mom rest frame to event cm frame
4498 0 : Vec4 old1 = Vec4(state[Rad].p() + state[Emt].p());
4499 0 : Vec4 old2 = Vec4(state[Rec].p());
4500 0 : RotBstMatrix fromCM;
4501 0 : fromCM.fromCMframe(old1, old2);
4502 : // Transform momenta
4503 0 : Rad4mom.rotbst(fromCM);
4504 0 : Rec4mom.rotbst(fromCM);
4505 :
4506 0 : RadBefore.p(Rad4mom);
4507 0 : RecBefore.p(Rec4mom);
4508 0 : RadBefore.m(sqrt(mRsq));
4509 0 : RecBefore.m(sqrt(mSsq));
4510 :
4511 0 : } else if ( radType + recType == 2 && state[Emt].idAbs() == 24 ) {
4512 : // Clustering of final(rad)/final(rec) dipole splitting
4513 : // Get eCM of (rad,rec,emt) triple
4514 0 : Vec4 sum = state[Rad].p() + state[Rec].p() + state[Emt].p();
4515 0 : double eCMME = sum.mCalc();
4516 :
4517 : // Define radiator and recoiler back-to-back in the dipole
4518 : // rest frame [=(state[rad]+state[emt])+state[rec] rest frame]
4519 0 : Vec4 Rad4mom;
4520 0 : Vec4 Rec4mom;
4521 0 : double mDsq = pow2(eCMME);
4522 : // If possible, keep the invariant mass of the radiator.
4523 0 : double mRsq = (radID == state[Rad].id() )
4524 0 : ? abs(state[Rad].p().m2Calc())
4525 0 : : pow2(particleDataPtr->m0(radID));
4526 0 : double mSsq = abs(state[Rec].p().m2Calc());
4527 0 : double a = 0.5*sqrt(mDsq);
4528 0 : double b = 0.25*(mRsq - mSsq) / a;
4529 0 : double c = sqrt(pow2(a) + pow2(b) - 2.*a*b - mSsq);
4530 :
4531 0 : Rad4mom.p( 0., 0., c, a+b);
4532 0 : Rec4mom.p( 0., 0.,-c, a-b);
4533 :
4534 : // Find boost from Rad4mom+Rec4mom rest frame to event cm frame
4535 0 : Vec4 old1 = Vec4(state[Rad].p() + state[Emt].p());
4536 0 : Vec4 old2 = Vec4(state[Rec].p());
4537 0 : RotBstMatrix fromCM;
4538 0 : fromCM.fromCMframe(old1, old2);
4539 : // Transform momenta
4540 0 : Rad4mom.rotbst(fromCM);
4541 0 : Rec4mom.rotbst(fromCM);
4542 :
4543 0 : RadBefore.p(Rad4mom);
4544 0 : RecBefore.p(Rec4mom);
4545 0 : RadBefore.m(sqrt(mRsq));
4546 0 : RecBefore.m(sqrt(mSsq));
4547 :
4548 0 : } else if ( radType + recType == 0 ) {
4549 : // Clustering of final(rad)/initial(rec) dipole splitting
4550 : // Get eCM of (rad,rec,emt) triple
4551 0 : Vec4 sum = state[Rad].p() + state[Rec].p() + state[Emt].p();
4552 0 : double eCMME = sum.mCalc();
4553 : // Define radiator and recoiler back-to-back in the dipole
4554 : // rest frame [=(state[rad]+state[emt])+state[rec] rest frame]
4555 0 : Vec4 Rad4mom;
4556 0 : Vec4 Rec4mom;
4557 0 : double mDsq = pow2(eCMME);
4558 : // If possible, keep the invariant mass of the radiator.
4559 0 : double mRsq = (radID == state[Rad].id() )
4560 0 : ? abs(state[Rad].p().m2Calc())
4561 0 : : pow2(particleDataPtr->m0(radID));
4562 0 : double mSsq = abs(state[Rec].p().m2Calc());
4563 0 : double a = 0.5*sqrt(mDsq);
4564 0 : double b = 0.25*(mRsq - mSsq) / a;
4565 0 : double c = sqrt(pow2(a) + pow2(b) - 2.*a*b - mSsq);
4566 :
4567 0 : Rad4mom.p( 0., 0., c, a+b);
4568 0 : Rec4mom.p( 0., 0.,-c, a-b);
4569 :
4570 : // Find boost from Rad4mom+Rec4mom rest frame to event cm frame
4571 0 : Vec4 old1 = Vec4(state[Rad].p() + state[Emt].p());
4572 0 : Vec4 old2 = Vec4(state[Rec].p());
4573 0 : RotBstMatrix fromCM;
4574 0 : fromCM.fromCMframe(old1, old2);
4575 : // Transform momenta
4576 0 : Rad4mom.rotbst(fromCM);
4577 0 : Rec4mom.rotbst(fromCM);
4578 :
4579 : // Rescale recoiler momentum
4580 0 : Rec4mom = 2.*state[Rec].p() - Rec4mom;
4581 :
4582 0 : RadBefore.p(Rad4mom);
4583 0 : RecBefore.p(Rec4mom);
4584 0 : RadBefore.m(sqrt(mRsq));
4585 :
4586 : // Set mass of initial recoiler to zero
4587 0 : RecBefore.m( 0.0 );
4588 :
4589 0 : } else {
4590 : // Clustering of initial(rad)/initial(rec) dipole splitting
4591 : // We want to cluster: Meaning doing the inverse of a process
4592 : // ( pDaughter + pRecoiler -> pOut )
4593 : // ==> ( pMother + pPartner -> pOut' + pSister )
4594 : // produced by an initial state splitting. The matrix element
4595 : // provides us with pMother, pPartner, pSister and pOut'
4596 0 : Vec4 pMother( state[Rad].p() );
4597 0 : Vec4 pSister( state[Emt].p() );
4598 0 : Vec4 pPartner( state[Rec].p() );
4599 0 : Vec4 pDaughter( 0.,0.,0.,0. );
4600 0 : Vec4 pRecoiler( 0.,0.,0.,0. );
4601 :
4602 : // Find side that radiates event (mother moving in sign * p_z direction).
4603 0 : int sign = (state[Rad].pz() > 0.) ? 1 : -1;
4604 :
4605 : // Find rotation by phi that would have been done for a
4606 : // splitting daughter -> mother + sister
4607 0 : double phi = pSister.phi();
4608 : // Find rotation with -phi
4609 0 : RotBstMatrix rot_by_mphi;
4610 0 : rot_by_mphi.rot(0.,-phi);
4611 : // Find rotation with +phi
4612 0 : RotBstMatrix rot_by_pphi;
4613 0 : rot_by_pphi.rot(0.,phi);
4614 :
4615 : // Transform pMother and outgoing momenta
4616 0 : pMother.rotbst( rot_by_mphi );
4617 0 : pSister.rotbst( rot_by_mphi );
4618 0 : pPartner.rotbst( rot_by_mphi );
4619 0 : for(int i=3; i< NewEvent.size(); ++i)
4620 0 : NewEvent[i].rotbst( rot_by_mphi );
4621 :
4622 : // Get mother and partner x values
4623 : // x1 after isr
4624 0 : double x1 = 2. * pMother.e() / eCM;
4625 : // x2 after isr
4626 0 : double x2 = 2. * pPartner.e() / eCM;
4627 :
4628 0 : pDaughter.p( pMother - pSister);
4629 0 : pRecoiler.p( pPartner );
4630 :
4631 : // Find boost from event cm frame to rest frame of
4632 : // of-shell daughter + on-shell recoiler
4633 0 : RotBstMatrix from_CM_to_DR;
4634 0 : if (sign == 1)
4635 0 : from_CM_to_DR.toCMframe(pDaughter, pRecoiler);
4636 : else
4637 0 : from_CM_to_DR.toCMframe(pRecoiler, pDaughter);
4638 :
4639 : // Transform all momenta
4640 0 : pMother.rotbst( from_CM_to_DR );
4641 0 : pPartner.rotbst( from_CM_to_DR );
4642 0 : pSister.rotbst( from_CM_to_DR );
4643 0 : for(int i=3; i< NewEvent.size(); ++i)
4644 0 : NewEvent[i].rotbst( from_CM_to_DR );
4645 :
4646 : // Find theta angle between pMother and z-axis and undo
4647 : // rotation that would have been done by shower
4648 0 : double theta = pMother.theta();
4649 0 : if ( pMother.px() < 0. ) theta *= -1.;
4650 0 : if (sign == -1) theta += M_PI;
4651 :
4652 : // Find rotation by +theta
4653 0 : RotBstMatrix rot_by_ptheta;
4654 0 : rot_by_ptheta.rot(theta, 0.);
4655 :
4656 : // Transform all momenta
4657 0 : pMother.rotbst( rot_by_ptheta );
4658 0 : pPartner.rotbst( rot_by_ptheta );
4659 0 : pSister.rotbst( rot_by_ptheta );
4660 0 : for(int i=3; i< NewEvent.size(); ++i)
4661 0 : NewEvent[i].rotbst( rot_by_ptheta );
4662 :
4663 : // Find z of the splitting
4664 0 : Vec4 qDip( pMother - pSister);
4665 0 : Vec4 qAfter(pMother + pPartner);
4666 0 : Vec4 qBefore(qDip + pPartner);
4667 0 : double z = qBefore.m2Calc() / qAfter.m2Calc();
4668 :
4669 : // Calculate new e_CM^2
4670 0 : double x1New = z*x1; // x1 before isr
4671 : double x2New = x2; // x2 before isr
4672 0 : double sHat = x1New*x2New*eCM*eCM;
4673 :
4674 : // Construct daughter and recoiler momenta
4675 0 : pDaughter.p( 0., 0., sign*0.5*sqrt(sHat), 0.5*sqrt(sHat));
4676 0 : pRecoiler.p( 0., 0., -sign*0.5*sqrt(sHat), 0.5*sqrt(sHat));
4677 :
4678 : // Find boost from current (daughter+recoiler rest frame)
4679 : // frame to rest frame of daughter+unchanged recoiler to
4680 : // recover the old x2 value
4681 0 : RotBstMatrix from_DR_to_CM;
4682 0 : from_DR_to_CM.bst( 0., 0., sign*( x1New - x2New ) / ( x1New + x2New ) );
4683 :
4684 : // Correct for momentum mismatch by transforming all momenta
4685 0 : pMother.rotbst( from_DR_to_CM );
4686 0 : pPartner.rotbst( from_DR_to_CM );
4687 0 : pSister.rotbst( from_DR_to_CM );
4688 0 : pDaughter.rotbst( from_DR_to_CM );
4689 0 : pRecoiler.rotbst( from_DR_to_CM );
4690 0 : for(int i=3; i< NewEvent.size(); ++i)
4691 0 : NewEvent[i].rotbst( from_DR_to_CM );
4692 :
4693 : // Transform pMother and outgoing momenta
4694 0 : pMother.rotbst( rot_by_pphi );
4695 0 : pPartner.rotbst( rot_by_pphi );
4696 0 : pSister.rotbst( rot_by_pphi );
4697 0 : pDaughter.rotbst( rot_by_pphi );
4698 0 : pRecoiler.rotbst( rot_by_pphi );
4699 0 : for(int i=3; i< NewEvent.size(); ++i)
4700 0 : NewEvent[i].rotbst( rot_by_pphi );
4701 :
4702 : // Set momenta of particles to be attached to new event record
4703 0 : RecBefore.p( pRecoiler );
4704 0 : RadBefore.p( pDaughter );
4705 0 : if (RecBefore.pz() > 0.) RecBefore.mother1(1);
4706 0 : else RecBefore.mother1(2);
4707 0 : if (RadBefore.pz() > 0.) RadBefore.mother1(1);
4708 0 : else RadBefore.mother1(2);
4709 :
4710 0 : }
4711 :
4712 : // Put some dummy production scales for RecBefore, RadBefore
4713 0 : RecBefore.scale(mu);
4714 0 : RadBefore.scale(mu);
4715 :
4716 : // Append new recoiler and find new radiator colour
4717 0 : NewEvent.append(RecBefore);
4718 :
4719 : // Assign the correct colour to re-clustered radiator.
4720 : // Keep old radiator colours for electroweak emission.
4721 0 : int emtID = state[Emt].id();
4722 0 : if ( emtID == 22 || emtID == 23 || abs(emtID) == 24 )
4723 0 : RadBefore.cols( state[Rad].col(), state[Rad].acol() );
4724 : // For QCD, carefully construct colour.
4725 0 : else if ( !connectRadiator( RadBefore, radType, RecBefore, recType,
4726 : NewEvent ) ) {
4727 : // Could happen if previous clustering produced several colour
4728 : // singlett subsystems in the event
4729 0 : NewEvent.reset();
4730 0 : return NewEvent;
4731 : }
4732 :
4733 : // Build the clustered event
4734 0 : Event outState = Event();
4735 0 : outState.init("(hard process-modified)", particleDataPtr);
4736 0 : outState.clear();
4737 :
4738 : // Copy system and incoming beam particles to outState
4739 0 : for (int i = 0; i < 3; ++i)
4740 0 : outState.append( NewEvent[i] );
4741 : // Copy all the junctions one by one
4742 0 : for (int i = 0; i < state.sizeJunction(); ++i)
4743 0 : outState.appendJunction( state.getJunction(i) );
4744 : // Initialise scales for new event
4745 0 : outState.saveSize();
4746 0 : outState.saveJunctionSize();
4747 0 : outState.scale(mu);
4748 0 : outState.scaleSecond(mu);
4749 : bool radAppended = false;
4750 : bool recAppended = false;
4751 0 : int size = int(outState.size());
4752 : // Save position of radiator in new event record
4753 : int radPos = 0;
4754 :
4755 : // Append first incoming particle
4756 0 : if ( RecBefore.mother1() == 1) {
4757 0 : outState.append( RecBefore );
4758 : recAppended = true;
4759 0 : } else if ( RadBefore.mother1() == 1 ) {
4760 0 : radPos = outState.append( RadBefore );
4761 : radAppended = true;
4762 0 : } else {
4763 : // Find second incoming in input event
4764 : int in1 = 0;
4765 0 : for(int i=0; i < int(state.size()); ++i)
4766 0 : if (state[i].mother1() == 1) in1 =i;
4767 0 : outState.append( state[in1] );
4768 0 : size++;
4769 : }
4770 : // Append second incoming particle
4771 0 : if ( RecBefore.mother1() == 2) {
4772 0 : outState.append( RecBefore );
4773 : recAppended = true;
4774 0 : } else if ( RadBefore.mother1() == 2 ) {
4775 0 : radPos = outState.append( RadBefore );
4776 : radAppended = true;
4777 0 : } else {
4778 : // Find second incoming in input event
4779 : int in2 = 0;
4780 0 : for(int i=0; i < int(state.size()); ++i)
4781 0 : if (state[i].mother1() == 2) in2 =i;
4782 :
4783 0 : outState.append( state[in2] );
4784 : size++;
4785 : }
4786 :
4787 : // Append new recoiler if not done already
4788 0 : if (!recAppended && !RecBefore.isFinal()) {
4789 : recAppended = true;
4790 0 : outState.append( RecBefore);
4791 : }
4792 : // Append new radiator if not done already
4793 0 : if (!radAppended && !RadBefore.isFinal()) {
4794 : radAppended = true;
4795 0 : radPos = outState.append( RadBefore);
4796 0 : }
4797 :
4798 : // Append intermediate particle
4799 : // (careful not to append reclustered recoiler)
4800 : // Append intermediate particle
4801 : // (careful not to append reclustered recoiler)
4802 0 : for (int i = 0; i < int(NewEvent.size()-1); ++i)
4803 0 : if (NewEvent[i].status() == -22) outState.append( NewEvent[i] );
4804 : // Append final state particles, resonances first
4805 0 : for (int i = 0; i < int(NewEvent.size()-1); ++i)
4806 0 : if (NewEvent[i].status() == 22) outState.append( NewEvent[i] );
4807 : // Then start appending partons
4808 0 : if (!radAppended && RadBefore.statusAbs() == 22)
4809 0 : radPos = outState.append(RadBefore);
4810 0 : if (!recAppended)
4811 0 : outState.append(RecBefore);
4812 0 : if (!radAppended && RadBefore.statusAbs() != 22)
4813 0 : radPos = outState.append(RadBefore);
4814 : // Then partons (not reclustered recoiler)
4815 0 : for(int i = 0; i < int(NewEvent.size()-1); ++i)
4816 0 : if ( NewEvent[i].status() != 22
4817 0 : && NewEvent[i].colType() != 0
4818 0 : && NewEvent[i].isFinal())
4819 0 : outState.append( NewEvent[i] );
4820 : // Then the rest
4821 0 : for(int i = 0; i < int(NewEvent.size()-1); ++i)
4822 0 : if ( NewEvent[i].status() != 22
4823 0 : && NewEvent[i].colType() == 0
4824 0 : && NewEvent[i].isFinal() )
4825 0 : outState.append( NewEvent[i]);
4826 :
4827 : // Find intermediate and respective daughters
4828 0 : vector<int> PosIntermediate;
4829 0 : vector<int> PosDaughter1;
4830 0 : vector<int> PosDaughter2;
4831 0 : for(int i=0; i < int(outState.size()); ++i)
4832 0 : if (outState[i].status() == -22) {
4833 0 : PosIntermediate.push_back(i);
4834 0 : int d1 = outState[i].daughter1();
4835 0 : int d2 = outState[i].daughter2();
4836 : // Find daughters in output state
4837 0 : int daughter1 = FindParticle( state[d1], outState);
4838 0 : int daughter2 = FindParticle( state[d2], outState);
4839 : // If both daughters found, done
4840 : // Else put first final particle as first daughter
4841 : // and last final particle as second daughter
4842 0 : if (daughter1 > 0)
4843 0 : PosDaughter1.push_back( daughter1);
4844 : else {
4845 0 : daughter1 = 0;
4846 0 : while(!outState[daughter1].isFinal() ) daughter1++;
4847 0 : PosDaughter1.push_back( daughter1);
4848 : }
4849 0 : if (daughter2 > 0)
4850 0 : PosDaughter2.push_back( daughter2);
4851 : else {
4852 0 : daughter2 = outState.size()-1;
4853 0 : while(!outState[daughter2].isFinal() ) daughter2--;
4854 0 : PosDaughter2.push_back( daughter2);
4855 : }
4856 0 : }
4857 : // Set daughters and mothers
4858 0 : for(int i=0; i < int(PosIntermediate.size()); ++i) {
4859 0 : outState[PosIntermediate[i]].daughters(PosDaughter1[i],PosDaughter2[i]);
4860 0 : outState[PosDaughter1[i]].mother1(PosIntermediate[i]);
4861 0 : outState[PosDaughter2[i]].mother1(PosIntermediate[i]);
4862 : }
4863 :
4864 : // Find range of final state partons
4865 0 : int minParFinal = int(outState.size());
4866 0 : int maxParFinal = 0;
4867 0 : for(int i=0; i < int(outState.size()); ++i)
4868 0 : if (outState[i].mother1() == 3 && outState[i].mother2() == 4) {
4869 0 : minParFinal = min(i,minParFinal);
4870 0 : maxParFinal = max(i,maxParFinal);
4871 0 : }
4872 :
4873 0 : if (minParFinal == maxParFinal) maxParFinal = 0;
4874 0 : outState[3].daughters(minParFinal,maxParFinal);
4875 0 : outState[4].daughters(minParFinal,maxParFinal);
4876 :
4877 : // Update event properties
4878 0 : outState.saveSize();
4879 0 : outState.saveJunctionSize();
4880 :
4881 : // Almost there...
4882 : // If an intermediate coloured parton exists which was directly
4883 : // colour connected to the radiator before the splitting, and the
4884 : // radiator before and after the splitting had only one colour, problems
4885 : // will arise since the colour of the radiator will be changed, whereas
4886 : // the intermediate parton still has the old colour. In effect, this
4887 : // means that when setting up a event for trial showering, one colour will
4888 : // be free.
4889 : // Hence, check for an intermediate coloured triplet resonance has been
4890 : // colour-connected to the "old" radiator.
4891 : // Find resonance
4892 : int iColRes = 0;
4893 0 : if ( radType == -1 && state[Rad].colType() == 1) {
4894 : // Find resonance connected to initial colour
4895 0 : for(int i=0; i < int(state.size()); ++i)
4896 0 : if ( i != Rad && i != Emt && i != Rec
4897 0 : && state[i].status() == -22
4898 0 : && state[i].col() == state[Rad].col() )
4899 0 : iColRes = i;
4900 0 : } else if ( radType == -1 && state[Rad].colType() == -1) {
4901 : // Find resonance connected to initial anticolour
4902 0 : for(int i=0; i < int(state.size()); ++i)
4903 0 : if ( i != Rad && i != Emt && i != Rec
4904 0 : && state[i].status() == -22
4905 0 : && state[i].acol() == state[Rad].acol() )
4906 0 : iColRes = i;
4907 0 : } else if ( radType == 1 && state[Rad].colType() == 1) {
4908 : // Find resonance connected to final state colour
4909 0 : for(int i=0; i < int(state.size()); ++i)
4910 0 : if ( i != Rad && i != Emt && i != Rec
4911 0 : && state[i].status() == -22
4912 0 : && state[i].col() == state[Rad].col() )
4913 0 : iColRes = i;
4914 0 : } else if ( radType == 1 && state[Rad].colType() == -1) {
4915 : // Find resonance connected to final state anticolour
4916 0 : for(int i=0; i < int(state.size()); ++i)
4917 0 : if ( i != Rad && i != Emt && i != Rec
4918 0 : && state[i].status() == -22
4919 0 : && state[i].acol() == state[Rad].acol() )
4920 0 : iColRes = i;
4921 0 : }
4922 :
4923 0 : if (iColRes > 0) {
4924 : // Now find this resonance in the reclustered state
4925 0 : int iColResNow = FindParticle( state[iColRes], outState);
4926 :
4927 : // Find reclustered radiator colours
4928 0 : int radCol = outState[radPos].col();
4929 0 : int radAcl = outState[radPos].acol();
4930 : // Find resonance radiator colours
4931 0 : int resCol = outState[iColResNow].col();
4932 0 : int resAcl = outState[iColResNow].acol();
4933 : // Check if any of the reclustered radiators colours match the resonance
4934 0 : bool matchesRes = (radCol > 0
4935 0 : && ( radCol == resCol || radCol == resAcl))
4936 0 : || (radAcl > 0
4937 0 : && ( radAcl == resCol || radAcl == resAcl));
4938 :
4939 : // If a resonance has been found, but no colours match, change
4940 : // the colour of the resonance
4941 0 : if (!matchesRes && iColResNow > 0) {
4942 0 : if ( radType == -1 && outState[radPos].colType() == 1)
4943 0 : outState[iColResNow].col(radCol);
4944 0 : else if ( radType ==-1 && outState[radPos].colType() ==-1)
4945 0 : outState[iColResNow].acol(radAcl);
4946 0 : else if ( radType == 1 && outState[radPos].colType() == 1)
4947 0 : outState[iColResNow].col(radCol);
4948 0 : else if ( radType == 1 && outState[radPos].colType() ==-1)
4949 0 : outState[iColResNow].acol(radAcl);
4950 : }
4951 :
4952 :
4953 : // If a resonance has been found, but no colours match, and the position
4954 : // of the resonance in the event record has been changed, update the
4955 : // radiator mother
4956 0 : if (!matchesRes && iColResNow > 0 && iColRes != iColResNow)
4957 0 : outState[radPos].mother1(iColResNow);
4958 :
4959 0 : }
4960 :
4961 : // If event is not constructed properly, return false
4962 0 : if ( !validEvent(outState) ) {
4963 0 : outState.reset();
4964 0 : return outState;
4965 : }
4966 :
4967 : // Remember position of reclustered radiator in state
4968 0 : iReclusteredNew = radPos;
4969 :
4970 : // Done
4971 0 : return outState;
4972 0 : }
4973 :
4974 : //--------------------------------------------------------------------------
4975 :
4976 : // Function to get the flavour of the radiator before the splitting
4977 : // for clustering
4978 : // IN int : Flavour of the radiator after the splitting
4979 : // int : Flavour of the emitted after the splitting
4980 : // OUT int : Flavour of the radiator before the splitting
4981 :
4982 : int History::getRadBeforeFlav(const int RadAfter, const int EmtAfter,
4983 : const Event& event) {
4984 :
4985 0 : int type = event[RadAfter].isFinal() ? 1 :-1;
4986 0 : int emtID = event[EmtAfter].id();
4987 0 : int radID = event[RadAfter].id();
4988 0 : int emtCOL = event[EmtAfter].col();
4989 0 : int radCOL = event[RadAfter].col();
4990 0 : int emtACL = event[EmtAfter].acol();
4991 0 : int radACL = event[RadAfter].acol();
4992 :
4993 0 : bool colConnected = ((type == 1) && ( (emtCOL !=0 && (emtCOL ==radACL))
4994 0 : || (emtACL !=0 && (emtACL ==radCOL)) ))
4995 0 : ||((type ==-1) && ( (emtCOL !=0 && (emtCOL ==radCOL))
4996 0 : || (emtACL !=0 && (emtACL ==radACL)) ));
4997 : // QCD splittings
4998 : // Gluon radiation
4999 0 : if ( emtID == 21 )
5000 0 : return radID;
5001 : // Final state gluon splitting
5002 0 : if ( type == 1 && emtID == -radID && !colConnected )
5003 0 : return 21;
5004 : // Initial state s-channel gluon splitting
5005 0 : if ( type ==-1 && radID == 21 )
5006 0 : return -emtID;
5007 : // Initial state t-channel gluon splitting
5008 0 : if ( type ==-1 && !colConnected
5009 0 : && emtID != 21 && radID != 21 && abs(emtID) < 10 && abs(radID) < 10)
5010 0 : return 21;
5011 :
5012 : // SQCD splittings
5013 0 : int radSign = (radID < 0) ? -1 : 1;
5014 : int offsetL = 1000000;
5015 : int offsetR = 2000000;
5016 : // Gluino radiation
5017 0 : if ( emtID == 1000021 ) {
5018 : // Gluino radiation combined with quark yields squark.
5019 0 : if (abs(radID) < 10 ) {
5020 : int offset = offsetL;
5021 : // Check if righthanded squark present. If so, make the reclustered
5022 : // squark match. Works for squark pair production + gluino emission.
5023 0 : for (int i=0; i < int(event.size()); ++i)
5024 0 : if ( event[i].isFinal()
5025 0 : && event[i].idAbs() < offsetR+10 && event[i].idAbs() > offsetR)
5026 0 : offset = offsetR;
5027 0 : return radSign*(abs(radID)+offset);
5028 : }
5029 : // Gluino radiation combined with squark yields quark.
5030 0 : if (abs(radID) > offsetL && abs(radID) < offsetL+10 )
5031 0 : return radSign*(abs(radID)-offsetL);
5032 0 : if (abs(radID) > offsetR && abs(radID) < offsetR+10 )
5033 0 : return radSign*(abs(radID)-offsetR);
5034 : // Gluino radiation off gluon yields gluino.
5035 0 : if (radID == 21 ) return emtID;
5036 : }
5037 :
5038 0 : int emtSign = (emtID < 0) ? -1 : 1;
5039 : // Get PDG numbering offsets.
5040 : int emtOffset = 0;
5041 0 : if ( abs(emtID) > offsetL && abs(emtID) < offsetL+10 )
5042 0 : emtOffset = offsetL;
5043 0 : if ( abs(emtID) > offsetR && abs(emtID) < offsetR+10 )
5044 0 : emtOffset = offsetR;
5045 : int radOffset = 0;
5046 0 : if ( abs(radID) > offsetL && abs(radID) < offsetL+10 )
5047 0 : radOffset = offsetL;
5048 0 : if ( abs(radID) > offsetR && abs(radID) < offsetR+10 )
5049 0 : radOffset = offsetR;
5050 :
5051 : // Final state gluino splitting
5052 0 : if ( type == 1 && !colConnected ) {
5053 : // Emitted squark, radiating quark.
5054 0 : if ( emtOffset > 0 && radOffset == 0
5055 0 : && emtSign*(abs(emtID) - emtOffset) == -radID )
5056 0 : return 1000021;
5057 : // Emitted quark, radiating squark.
5058 0 : if ( emtOffset == 0 && radOffset > 0
5059 0 : && emtID == -radSign*(abs(radID) - radOffset) )
5060 0 : return 1000021;
5061 : }
5062 :
5063 : // Initial state s-channel gluino splitting
5064 0 : if ( type ==-1 && radID == 1000021 ) {
5065 : // Quark entering underlying hard process.
5066 0 : if ( emtOffset > 0 ) return -emtSign*(abs(emtID) - emtOffset);
5067 : // Squark entering underlying hard process.
5068 0 : else return -emtSign*(abs(emtID) + emtOffset);
5069 : }
5070 :
5071 : // Initial state t-channel gluino splitting.
5072 0 : if ( type ==-1
5073 0 : && ( (abs(emtID) > offsetL && abs(emtID) < offsetL+10)
5074 0 : || (abs(emtID) > offsetR && abs(emtID) < offsetR+10))
5075 0 : && ( (abs(radID) > offsetL && abs(radID) < offsetL+10)
5076 0 : || (abs(radID) > offsetR && abs(radID) < offsetR+10))
5077 0 : && emtSign*(abs(emtID)+emtOffset) == radSign*(abs(radID) - radOffset)
5078 0 : && !colConnected ) {
5079 0 : return 1000021;
5080 : }
5081 :
5082 : // Electroweak splittings splittings
5083 : // Photon / Z radiation: Calculate invariant mass of system
5084 0 : double m2final = (event[RadAfter].p()+ event[EmtAfter].p()).m2Calc();
5085 :
5086 0 : if ( emtID == 22 || emtID == 23 ) return radID;
5087 : // Final state Photon splitting
5088 0 : if ( type == 1 && emtID == -radID && colConnected && sqrt(m2final) <= 10. )
5089 0 : return 22;
5090 : // Final state Photon splitting
5091 0 : if ( type == 1 && emtID == -radID && colConnected && sqrt(m2final) > 10. )
5092 0 : return 23;
5093 : // Initial state s-channel photon/ Z splitting
5094 0 : if ( type ==-1 && (radID == 22 || radID == 23) )
5095 0 : return -emtID;
5096 : // Initial state t-channel photon / Z splitting: Always bookkeep as photon
5097 0 : if ( type ==-1 && abs(emtID) < 10 && abs(radID) < 10 && colConnected )
5098 0 : return 22;
5099 :
5100 : // W+ radiation
5101 : // Final state W+ splitting
5102 0 : if ( emtID == 24 && radID < 0 ) return radID + 1;
5103 0 : if ( emtID == 24 && radID > 0 ) return radID + 1;
5104 :
5105 : // W- radiation
5106 : // Final state W- splitting
5107 0 : if ( emtID ==-24 && radID < 0 ) return radID - 1;
5108 0 : if ( emtID ==-24 && radID > 0 ) return radID - 1;
5109 :
5110 : // Done.
5111 0 : return 0;
5112 :
5113 0 : }
5114 :
5115 : //--------------------------------------------------------------------------
5116 :
5117 : // Function to properly colour-connect the radiator to the rest of
5118 : // the event, as needed during clustering
5119 : // IN Particle& : Particle to be connected
5120 : // Particle : Recoiler forming a dipole with Radiator
5121 : // Event : event to which Radiator shall be appended
5122 : // OUT true : Radiator could be connected to the event
5123 : // false : Radiator could not be connected to the
5124 : // event or the resulting event was
5125 : // non-valid
5126 :
5127 : bool History::connectRadiator( Particle& Radiator, const int RadType,
5128 : const Particle& Recoiler, const int RecType,
5129 : const Event& event ) {
5130 :
5131 : // Start filling radiator colour indices with dummy values
5132 0 : Radiator.cols( -1, -1 );
5133 :
5134 : // Radiator should always be colour-connected to recoiler.
5135 : // Three cases (rad = Anti-Quark, Quark, Gluon) to be considered
5136 0 : if ( Radiator.colType() == -1 ) {
5137 : // For final state antiquark radiator, the anticolour is fixed
5138 : // by the final / initial state recoiler colour / anticolour
5139 0 : if ( RadType + RecType == 2 )
5140 0 : Radiator.cols( 0, Recoiler.col());
5141 0 : else if ( RadType + RecType == 0 )
5142 0 : Radiator.cols( 0, Recoiler.acol());
5143 : // For initial state antiquark radiator, the anticolour is fixed
5144 : // by the colour of the emitted gluon (which will be the
5145 : // leftover anticolour of a final state particle or the leftover
5146 : // colour of an initial state particle ( = the recoiler))
5147 : else {
5148 : // Set colour of antiquark radiator to zero
5149 0 : Radiator.col( 0 );
5150 0 : for (int i = 0; i < event.size(); ++i) {
5151 0 : int col = event[i].col();
5152 0 : int acl = event[i].acol();
5153 :
5154 0 : if ( event[i].isFinal()) {
5155 : // Search for leftover anticolour in final / initial state
5156 0 : if ( acl > 0 && FindCol(acl,i,0,event,1,true) == 0
5157 0 : && FindCol(acl,i,0,event,2,true) == 0 )
5158 0 : Radiator.acol(event[i].acol());
5159 : } else {
5160 : // Search for leftover colour in initial / final state
5161 0 : if ( col > 0 && FindCol(col,i,0,event,1,true) == 0
5162 0 : && FindCol(col,i,0,event,2,true) == 0 )
5163 0 : Radiator.acol(event[i].col());
5164 : }
5165 : } // end loop over particles in event record
5166 : }
5167 :
5168 0 : } else if ( Radiator.colType() == 1 ) {
5169 : // For final state quark radiator, the colour is fixed
5170 : // by the final / initial state recoiler anticolour / colour
5171 0 : if ( RadType + RecType == 2 )
5172 0 : Radiator.cols( Recoiler.acol(), 0);
5173 :
5174 0 : else if ( RadType + RecType == 0 )
5175 0 : Radiator.cols( Recoiler.col(), 0);
5176 : // For initial state quark radiator, the colour is fixed
5177 : // by the anticolour of the emitted gluon (which will be the
5178 : // leftover colour of a final state particle or the leftover
5179 : // anticolour of an initial state particle ( = the recoiler))
5180 :
5181 : else {
5182 : // Set anticolour of quark radiator to zero
5183 0 : Radiator.acol( 0 );
5184 0 : for (int i = 0; i < event.size(); ++i) {
5185 0 : int col = event[i].col();
5186 0 : int acl = event[i].acol();
5187 :
5188 0 : if ( event[i].isFinal()) {
5189 : // Search for leftover colour in final / initial state
5190 0 : if ( col > 0 && FindCol(col,i,0,event,1,true) == 0
5191 0 : && FindCol(col,i,0,event,2,true) == 0)
5192 0 : Radiator.col(event[i].col());
5193 : } else {
5194 : // Search for leftover anticolour in initial / final state
5195 0 : if ( acl > 0 && FindCol(acl,i,0,event,1,true) == 0
5196 0 : && FindCol(acl,i,0,event,2,true) == 0)
5197 0 : Radiator.col(event[i].acol());
5198 : }
5199 : } // end loop over particles in event record
5200 :
5201 : } // end distinction between fsr / fsr+initial recoiler / isr
5202 :
5203 0 : } else if ( Radiator.colType() == 2 ) {
5204 : // For a gluon radiator, one (anticolour) colour index is defined
5205 : // by the recoiler colour (anticolour).
5206 : // The remaining index is chosen to match the free index in the
5207 : // event
5208 : // Search for leftover colour (anticolour) in the final state
5209 0 : for (int i = 0; i < event.size(); ++i) {
5210 0 : int col = event[i].col();
5211 0 : int acl = event[i].acol();
5212 : int iEx = i;
5213 :
5214 0 : if ( event[i].isFinal()) {
5215 0 : if ( col > 0 && FindCol(col,iEx,0,event,1,true) == 0
5216 0 : && FindCol(col,iEx,0,event,2,true) == 0) {
5217 0 : if (Radiator.status() < 0 ) Radiator.col(event[i].col());
5218 0 : else Radiator.acol(event[i].col());
5219 : }
5220 0 : if ( acl > 0 && FindCol(acl,iEx,0,event,2,true) == 0
5221 0 : && FindCol(acl,iEx,0,event,1,true) == 0 ) {
5222 0 : if (Radiator.status() < 0 ) Radiator.acol(event[i].acol());
5223 0 : else Radiator.col(event[i].acol());
5224 : }
5225 : } else {
5226 0 : if ( col > 0 && FindCol(col,iEx,0,event,1,true) == 0
5227 0 : && FindCol(col,iEx,0,event,2,true) == 0) {
5228 0 : if (Radiator.status() < 0 ) Radiator.acol(event[i].col());
5229 0 : else Radiator.col(event[i].col());
5230 : }
5231 0 : if ( acl > 0 && (FindCol(acl,iEx,0,event,2,true) == 0
5232 0 : && FindCol(acl,iEx,0,event,1,true) == 0)) {
5233 0 : if (Radiator.status() < 0 ) Radiator.col(event[i].acol());
5234 0 : else Radiator.acol(event[i].acol());
5235 : }
5236 : }
5237 : } // end loop over particles in event record
5238 0 : } // end cases of different radiator colour type
5239 :
5240 : // If either colour or anticolour has not been set, return false
5241 0 : if (Radiator.col() < 0 || Radiator.acol() < 0) return false;
5242 : // Done
5243 0 : return true;
5244 0 : }
5245 :
5246 : //--------------------------------------------------------------------------
5247 :
5248 : // Function to find a colour (anticolour) index in the input event
5249 : // IN int col : Colour tag to be investigated
5250 : // int iExclude1 : Identifier of first particle to be excluded
5251 : // from search
5252 : // int iExclude2 : Identifier of second particle to be excluded
5253 : // from search
5254 : // Event event : event to be searched for colour tag
5255 : // int type : Tag to define if col should be counted as
5256 : // colour (type = 1) [->find anti-colour index
5257 : // contracted with col]
5258 : // anticolour (type = 2) [->find colour index
5259 : // contracted with col]
5260 : // OUT int : Position of particle in event record
5261 : // contraced with col [0 if col is free tag]
5262 :
5263 : int History::FindCol(int col, int iExclude1, int iExclude2,
5264 : const Event& event, int type, bool isHardIn) {
5265 :
5266 0 : bool isHard = isHardIn;
5267 : int index = 0;
5268 :
5269 0 : if (isHard) {
5270 : // Search event record for matching colour & anticolour
5271 0 : for(int n = 0; n < event.size(); ++n) {
5272 0 : if ( n != iExclude1 && n != iExclude2
5273 0 : && event[n].colType() != 0
5274 0 : &&( event[n].status() > 0 // Check outgoing
5275 0 : || event[n].status() == -21) ) { // Check incoming
5276 0 : if ( event[n].acol() == col ) {
5277 0 : index = -n;
5278 0 : break;
5279 : }
5280 0 : if ( event[n].col() == col ) {
5281 : index = n;
5282 0 : break;
5283 : }
5284 : }
5285 : }
5286 0 : } else {
5287 :
5288 : // Search event record for matching colour & anticolour
5289 0 : for(int n = 0; n < event.size(); ++n) {
5290 0 : if ( n != iExclude1 && n != iExclude2
5291 0 : && event[n].colType() != 0
5292 0 : &&( event[n].status() == 43 // Check outgoing from ISR
5293 0 : || event[n].status() == 51 // Check outgoing from FSR
5294 0 : || event[n].status() == -41 // first initial
5295 0 : || event[n].status() == -42) ) { // second initial
5296 0 : if ( event[n].acol() == col ) {
5297 0 : index = -n;
5298 0 : break;
5299 : }
5300 0 : if ( event[n].col() == col ) {
5301 : index = n;
5302 0 : break;
5303 : }
5304 : }
5305 : }
5306 : }
5307 : // if no matching colour / anticolour has been found, return false
5308 0 : if ( type == 1 && index < 0) return abs(index);
5309 0 : if ( type == 2 && index > 0) return abs(index);
5310 :
5311 0 : return 0;
5312 0 : }
5313 :
5314 : //--------------------------------------------------------------------------
5315 :
5316 : // Function to in the input event find a particle with quantum
5317 : // numbers matching those of the input particle
5318 : // IN Particle : Particle to be searched for
5319 : // Event : Event to be searched in
5320 : // OUT int : > 0 : Position of matching particle in event
5321 : // < 0 : No match in event
5322 :
5323 : int History::FindParticle( const Particle& particle, const Event& event,
5324 : bool checkStatus ) {
5325 :
5326 : int index = -1;
5327 :
5328 0 : for ( int i = int(event.size()) - 1; i > 0; --i )
5329 0 : if ( event[i].id() == particle.id()
5330 0 : && event[i].colType() == particle.colType()
5331 0 : && event[i].chargeType() == particle.chargeType()
5332 0 : && event[i].col() == particle.col()
5333 0 : && event[i].acol() == particle.acol()
5334 0 : && event[i].charge() == particle.charge() ) {
5335 : index = i;
5336 0 : break;
5337 : }
5338 :
5339 0 : if ( checkStatus && event[index].status() != particle.status() )
5340 0 : index = -1;
5341 :
5342 0 : return index;
5343 : }
5344 :
5345 : //--------------------------------------------------------------------------
5346 :
5347 : // Function to get the colour of the radiator before the splitting
5348 : // for clustering
5349 : // IN int : Position of the radiator after the splitting, in the event
5350 : // int : Position of the emitted after the splitting, in the event
5351 : // Event : Reference event
5352 : // OUT int : Colour of the radiator before the splitting
5353 :
5354 : int History::getRadBeforeCol(const int rad, const int emt,
5355 : const Event& event) {
5356 :
5357 : // Save type of splitting
5358 0 : int type = (event[rad].isFinal()) ? 1 :-1;
5359 : // Get flavour of radiator after potential clustering
5360 0 : int radBeforeFlav = getRadBeforeFlav(rad,emt,event);
5361 : // Get colours of the radiator before the potential clustering
5362 : int radBeforeCol = -1;
5363 : // Get reconstructed gluon colours
5364 0 : if (radBeforeFlav == 21) {
5365 :
5366 : // Start with quark emissions in FSR
5367 0 : if (type == 1 && event[emt].id() != 21) {
5368 0 : radBeforeCol = (event[rad].col() > 0)
5369 0 : ? event[rad].col() : event[emt].col();
5370 : // Quark emissions in ISR
5371 0 : } else if (type == -1 && event[emt].id() != 21) {
5372 0 : radBeforeCol = (event[rad].col() > 0)
5373 0 : ? event[rad].col() : event[emt].acol();
5374 : //Gluon emissions in FSR
5375 0 : } else if (type == 1 && event[emt].id() == 21) {
5376 : // If emitted is a gluon, remove the repeated index, and take
5377 : // the remaining indices as colour and anticolour
5378 0 : int colRemove = (event[rad].col() == event[emt].acol())
5379 0 : ? event[rad].acol() : event[rad].col();
5380 0 : radBeforeCol = (event[rad].col() == colRemove)
5381 0 : ? event[emt].col() : event[rad].col();
5382 : //Gluon emissions in ISR
5383 0 : } else if (type == -1 && event[emt].id() == 21) {
5384 : // If emitted is a gluon, remove the repeated index, and take
5385 : // the remaining indices as colour and anticolour
5386 0 : int colRemove = (event[rad].col() == event[emt].col())
5387 0 : ? event[rad].col() : event[rad].acol();
5388 0 : radBeforeCol = (event[rad].col() == colRemove)
5389 0 : ? event[emt].acol() : event[rad].col();
5390 0 : }
5391 :
5392 : // Get reconstructed quark colours
5393 0 : } else if ( radBeforeFlav != 21 && radBeforeFlav > 0) {
5394 :
5395 : // Quark emission in FSR
5396 0 : if (type == 1 && event[emt].id() != 21) {
5397 : // If radiating is a quark, remove the repeated index, and take
5398 : // the remaining indices as colour and anticolour
5399 0 : int colRemove = (event[rad].col() == event[emt].acol())
5400 0 : ? event[rad].acol() : 0;
5401 0 : radBeforeCol = (event[rad].col() == colRemove)
5402 0 : ? event[emt].col() : event[rad].col();
5403 : //Gluon emissions in FSR
5404 0 : } else if (type == 1 && event[emt].id() == 21) {
5405 : // If emitted is a gluon, remove the repeated index, and take
5406 : // the remaining indices as colour and anticolour
5407 0 : int colRemove = (event[rad].col() == event[emt].acol())
5408 0 : ? event[rad].col() : 0;
5409 0 : radBeforeCol = (event[rad].col() == colRemove)
5410 0 : ? event[emt].col() : event[rad].col();
5411 : //Quark emissions in ISR
5412 0 : } else if (type == -1 && event[emt].id() != 21) {
5413 : // If emitted is a quark, remove the repeated index, and take
5414 : // the remaining indices as colour and anticolour
5415 0 : int colRemove = (event[rad].col() == event[emt].col())
5416 0 : ? event[rad].col() : 0;
5417 0 : radBeforeCol = (event[rad].col() == colRemove)
5418 0 : ? event[emt].acol() : event[rad].col();
5419 : //Gluon emissions in ISR
5420 0 : } else if (type == -1 && event[emt].id() == 21) {
5421 : // If emitted is a gluon, remove the repeated index, and take
5422 : // the remaining indices as colour and anticolour
5423 0 : int colRemove = (event[rad].col() == event[emt].col())
5424 0 : ? event[rad].col() : 0;
5425 0 : radBeforeCol = (event[rad].col() == colRemove)
5426 0 : ? event[emt].acol() : event[rad].col();
5427 0 : }
5428 : // Other particles are assumed uncoloured
5429 : } else {
5430 : radBeforeCol = 0;
5431 : }
5432 :
5433 0 : return radBeforeCol;
5434 :
5435 : }
5436 :
5437 : //--------------------------------------------------------------------------
5438 :
5439 : // Function to get the anticolour of the radiator before the splitting
5440 : // for clustering
5441 : // IN int : Position of the radiator after the splitting, in the event
5442 : // int : Position of the emitted after the splitting, in the event
5443 : // Event : Reference event
5444 : // OUT int : Anticolour of the radiator before the splitting
5445 :
5446 : int History::getRadBeforeAcol(const int rad, const int emt,
5447 : const Event& event) {
5448 :
5449 : // Save type of splitting
5450 0 : int type = (event[rad].isFinal()) ? 1 :-1;
5451 : // Get flavour of radiator after potential clustering
5452 :
5453 0 : int radBeforeFlav = getRadBeforeFlav(rad,emt,event);
5454 : // Get colours of the radiator before the potential clustering
5455 : int radBeforeAcl = -1;
5456 : // Get reconstructed gluon colours
5457 0 : if (radBeforeFlav == 21) {
5458 :
5459 : // Start with quark emissions in FSR
5460 0 : if (type == 1 && event[emt].id() != 21) {
5461 0 : radBeforeAcl = (event[rad].acol() > 0)
5462 0 : ? event[rad].acol() : event[emt].acol();
5463 : // Quark emissions in ISR
5464 0 : } else if (type == -1 && event[emt].id() != 21) {
5465 0 : radBeforeAcl = (event[rad].acol() > 0)
5466 0 : ? event[rad].acol() : event[emt].col();
5467 : //Gluon emissions in FSR
5468 0 : } else if (type == 1 && event[emt].id() == 21) {
5469 : // If emitted is a gluon, remove the repeated index, and take
5470 : // the remaining indices as colour and anticolour
5471 0 : int colRemove = (event[rad].col() == event[emt].acol())
5472 0 : ? event[rad].acol() : event[rad].col();
5473 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5474 0 : ? event[emt].acol() : event[rad].acol();
5475 : //Gluon emissions in ISR
5476 0 : } else if (type == -1 && event[emt].id() == 21) {
5477 : // If emitted is a gluon, remove the repeated index, and take
5478 : // the remaining indices as colour and anticolour
5479 0 : int colRemove = (event[rad].col() == event[emt].col())
5480 0 : ? event[rad].col() : event[rad].acol();
5481 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5482 0 : ? event[emt].col() : event[rad].acol();
5483 0 : }
5484 :
5485 : // Get reconstructed anti-quark colours
5486 0 : } else if ( radBeforeFlav != 21 && radBeforeFlav < 0) {
5487 :
5488 : // Antiquark emission in FSR
5489 0 : if (type == 1 && event[emt].id() != 21) {
5490 : // If radiating is a antiquark, remove the repeated index, and take
5491 : // the remaining indices as colour and anticolour
5492 0 : int colRemove = (event[rad].col() == event[emt].acol())
5493 0 : ? event[rad].acol() : 0;
5494 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5495 0 : ? event[emt].acol() : event[rad].acol();
5496 : //Gluon emissions in FSR
5497 0 : } else if (type == 1 && event[emt].id() == 21) {
5498 : // If emitted is a gluon, remove the repeated index, and take
5499 : // the remaining indices as colour and anticolour
5500 0 : int colRemove = (event[rad].acol() == event[emt].col())
5501 0 : ? event[rad].acol() : 0;
5502 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5503 0 : ? event[emt].acol() : event[rad].acol();
5504 : //Antiquark emissions in ISR
5505 0 : } else if (type == -1 && event[emt].id() != 21) {
5506 : // If emitted is an antiquark, remove the repeated index, and take
5507 : // the remaining indices as colour and anticolour
5508 0 : int colRemove = (event[rad].acol() == event[emt].acol())
5509 0 : ? event[rad].acol() : 0;
5510 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5511 0 : ? event[emt].col() : event[rad].acol();
5512 : //Gluon emissions in ISR
5513 0 : } else if (type == -1 && event[emt].id() == 21) {
5514 : // If emitted is a gluon, remove the repeated index, and take
5515 : // the remaining indices as colour and anticolour
5516 0 : int colRemove = (event[rad].acol() == event[emt].acol())
5517 0 : ? event[rad].acol() : 0;
5518 0 : radBeforeAcl = (event[rad].acol() == colRemove)
5519 0 : ? event[emt].col() : event[rad].acol();
5520 0 : }
5521 : // Other particles are considered uncoloured
5522 : } else {
5523 : radBeforeAcl = 0;
5524 : }
5525 :
5526 0 : return radBeforeAcl;
5527 :
5528 : }
5529 :
5530 : //--------------------------------------------------------------------------
5531 :
5532 : // Function to get the parton connected to in by a colour line
5533 : // IN int : Position of parton for which partner should be found
5534 : // Event : Reference event
5535 : // OUT int : If a colour line connects the "in" parton with another
5536 : // parton, return the Position of the partner, else return 0
5537 :
5538 : int History::getColPartner(const int in, const Event& event) {
5539 :
5540 0 : if (event[in].col() == 0) return 0;
5541 :
5542 : int partner = 0;
5543 : // Try to find anticolour index first
5544 0 : partner = FindCol(event[in].col(),in,0,event,1,true);
5545 : // If no anticolour index has been found, try colour
5546 0 : if (partner == 0)
5547 0 : partner = FindCol(event[in].col(),in,0,event,2,true);
5548 :
5549 : return partner;
5550 :
5551 0 : }
5552 :
5553 : //--------------------------------------------------------------------------
5554 :
5555 :
5556 : // Function to get the parton connected to in by an anticolour line
5557 : // IN int : Position of parton for which partner should be found
5558 : // Event : Reference event
5559 : // OUT int : If an anticolour line connects the "in" parton with another
5560 : // parton, return the Position of the partner, else return 0
5561 :
5562 : int History::getAcolPartner(const int in, const Event& event) {
5563 :
5564 0 : if (event[in].acol() == 0) return 0;
5565 :
5566 : int partner = 0;
5567 : // Try to find colour index first
5568 0 : partner = FindCol(event[in].acol(),in,0,event,2,true);
5569 : // If no colour index has been found, try anticolour
5570 0 : if (partner == 0)
5571 0 : partner = FindCol(event[in].acol(),in,0,event,1,true);
5572 :
5573 : return partner;
5574 :
5575 0 : }
5576 :
5577 : //--------------------------------------------------------------------------
5578 :
5579 : // Function to get the list of partons connected to the particle
5580 : // formed by reclusterinf emt and rad by colour and anticolour lines
5581 : // IN int : Position of radiator in the clustering
5582 : // IN int : Position of emitted in the clustering
5583 : // Event : Reference event
5584 : // OUT vector<int> : List of positions of all partons that are connected
5585 : // to the parton that will be formed
5586 : // by clustering emt and rad.
5587 :
5588 : vector<int> History::getReclusteredPartners(const int rad, const int emt,
5589 : const Event& event) {
5590 :
5591 : // Save type
5592 0 : int type = event[rad].isFinal() ? 1 : -1;
5593 : // Get reclustered colours
5594 0 : int radBeforeCol = getRadBeforeCol(rad, emt, event);
5595 0 : int radBeforeAcl = getRadBeforeAcol(rad, emt, event);
5596 : // Declare output
5597 0 : vector<int> partners;
5598 :
5599 :
5600 : // Start with FSR clusterings
5601 0 : if (type == 1) {
5602 :
5603 0 : for(int i=0; i < int(event.size()); ++i) {
5604 : // Check all initial state partons
5605 0 : if ( i != emt && i != rad
5606 0 : && event[i].status() == -21
5607 0 : && event[i].col() > 0
5608 0 : && event[i].col() == radBeforeCol)
5609 0 : partners.push_back(i);
5610 : // Check all final state partons
5611 0 : if ( i != emt && i != rad
5612 0 : && event[i].isFinal()
5613 0 : && event[i].acol() > 0
5614 0 : && event[i].acol() == radBeforeCol)
5615 0 : partners.push_back(i);
5616 : // Check all initial state partons
5617 0 : if ( i != emt && i != rad
5618 0 : && event[i].status() == -21
5619 0 : && event[i].acol() > 0
5620 0 : && event[i].acol() == radBeforeAcl)
5621 0 : partners.push_back(i);
5622 : // Check all final state partons
5623 0 : if ( i != emt && i != rad
5624 0 : && event[i].isFinal()
5625 0 : && event[i].col() > 0
5626 0 : && event[i].col() == radBeforeAcl)
5627 0 : partners.push_back(i);
5628 : }
5629 : // Start with ISR clusterings
5630 0 : } else {
5631 :
5632 0 : for(int i=0; i < int(event.size()); ++i) {
5633 : // Check all initial state partons
5634 0 : if ( i != emt && i != rad
5635 0 : && event[i].status() == -21
5636 0 : && event[i].acol() > 0
5637 0 : && event[i].acol() == radBeforeCol)
5638 0 : partners.push_back(i);
5639 : // Check all final state partons
5640 0 : if ( i != emt && i != rad
5641 0 : && event[i].isFinal()
5642 0 : && event[i].col() > 0
5643 0 : && event[i].col() == radBeforeCol)
5644 0 : partners.push_back(i);
5645 : // Check all initial state partons
5646 0 : if ( i != emt && i != rad
5647 0 : && event[i].status() == -21
5648 0 : && event[i].col() > 0
5649 0 : && event[i].col() == radBeforeAcl)
5650 0 : partners.push_back(i);
5651 : // Check all final state partons
5652 0 : if ( i != emt && i != rad
5653 0 : && event[i].isFinal()
5654 0 : && event[i].acol() > 0
5655 0 : && event[i].acol() == radBeforeAcl)
5656 0 : partners.push_back(i);
5657 : }
5658 :
5659 : }
5660 : // Done
5661 : return partners;
5662 0 : }
5663 :
5664 : //--------------------------------------------------------------------------
5665 :
5666 : // Function to extract a chain of colour-connected partons in
5667 : // the event
5668 : // IN int : Type of parton from which to start extracting a
5669 : // parton chain. If the starting point is a quark
5670 : // i.e. flavType = 1, a chain of partons that are
5671 : // consecutively connected by colour-lines will be
5672 : // extracted. If the starting point is an antiquark
5673 : // i.e. flavType =-1, a chain of partons that are
5674 : // consecutively connected by anticolour-lines
5675 : // will be extracted.
5676 : // IN int : Position of the parton from which a
5677 : // colour-connected chain should be derived
5678 : // IN Event : Refernence event
5679 : // IN/OUT vector<int> : Partons that should be excluded from the search.
5680 : // OUT vector<int> : Positions of partons along the chain
5681 : // OUT bool : Found singlet / did not find singlet
5682 :
5683 : bool History::getColSinglet( const int flavType, const int iParton,
5684 : const Event& event, vector<int>& exclude, vector<int>& colSinglet) {
5685 :
5686 : // If no possible flavour to start from has been found
5687 0 : if (iParton < 0) return false;
5688 :
5689 : // If no further partner has been found in a previous iteration,
5690 : // and the whole final state has been excluded, we're done
5691 0 : if (iParton == 0) {
5692 :
5693 : // Count number of final state partons
5694 : int nFinal = 0;
5695 0 : for(int i=0; i < int(event.size()); ++i)
5696 0 : if ( event[i].isFinal() && event[i].colType() != 0)
5697 0 : nFinal++;
5698 :
5699 : // Get number of initial state partons in the list of
5700 : // excluded partons
5701 0 : int nExclude = int(exclude.size());
5702 : int nInitExclude = 0;
5703 0 : if (!event[exclude[2]].isFinal())
5704 0 : nInitExclude++;
5705 0 : if (!event[exclude[3]].isFinal())
5706 0 : nInitExclude++;
5707 :
5708 : // If the whole final state has been considered, return
5709 0 : if (nFinal == nExclude - nInitExclude)
5710 0 : return true;
5711 : else
5712 0 : return false;
5713 :
5714 : }
5715 :
5716 : // Declare colour partner
5717 : int colP = 0;
5718 : // Save the colour partner
5719 0 : colSinglet.push_back(iParton);
5720 : // Remove the partner from the list
5721 0 : exclude.push_back(iParton);
5722 : // When starting out from a quark line, follow the colour lines
5723 0 : if (flavType == 1)
5724 0 : colP = getColPartner(iParton,event);
5725 : // When starting out from an antiquark line, follow the anticolour lines
5726 : else
5727 0 : colP = getAcolPartner(iParton,event);
5728 :
5729 : // Do not count excluded partons twice
5730 0 : for(int i = 0; i < int(exclude.size()); ++i)
5731 0 : if (colP == exclude[i])
5732 0 : return true;
5733 :
5734 : // Recurse
5735 0 : return getColSinglet(flavType,colP,event,exclude,colSinglet);
5736 :
5737 0 : }
5738 :
5739 : //--------------------------------------------------------------------------
5740 :
5741 : // Function to check that a set of partons forms a colour singlet
5742 : // IN Event : Reference event
5743 : // IN vector<int> : Positions of the partons in the set
5744 : // OUT bool : Is a colour singlet / is not
5745 :
5746 : bool History::isColSinglet( const Event& event,
5747 : vector<int> system ) {
5748 :
5749 : // Check if system forms a colour singlet
5750 0 : for(int i=0; i < int(system.size()); ++i ) {
5751 : // Match quark and gluon colours
5752 0 : if ( system[i] > 0
5753 0 : && (event[system[i]].colType() == 1
5754 0 : || event[system[i]].colType() == 2) ) {
5755 0 : for(int j=0; j < int(system.size()); ++j)
5756 : // If flavour matches, remove both partons and continue
5757 0 : if ( system[i] > 0
5758 0 : && system[j] > 0
5759 0 : && event[system[i]].col() == event[system[j]].acol()) {
5760 : // Remove index and break
5761 0 : system[i] = 0;
5762 0 : system[j] = 0;
5763 0 : break;
5764 : }
5765 0 : }
5766 : // Match antiquark and gluon anticolours
5767 0 : if ( system[i] > 0
5768 0 : && (event[system[i]].colType() == -1
5769 0 : || event[system[i]].colType() == 2) ) {
5770 0 : for(int j=0; j < int(system.size()); ++j)
5771 : // If flavour matches, remove both partons and continue
5772 0 : if ( system[i] > 0
5773 0 : && system[j] > 0
5774 0 : && event[system[i]].acol() == event[system[j]].col()) {
5775 : // Remove index and break
5776 0 : system[i] = 0;
5777 0 : system[j] = 0;
5778 0 : break;
5779 : }
5780 0 : }
5781 :
5782 : }
5783 :
5784 : // The system is a colour singlet if for all colours,
5785 : // an anticolour was found
5786 : bool isColSing = true;
5787 0 : for(int i=0; i < int(system.size()); ++i)
5788 0 : if ( system[i] != 0 )
5789 0 : isColSing = false;
5790 :
5791 : // Return
5792 0 : return isColSing;
5793 :
5794 :
5795 : }
5796 :
5797 : //--------------------------------------------------------------------------
5798 :
5799 : // Function to check that a set of partons forms a flavour singlet
5800 : // IN Event : Reference event
5801 : // IN vector<int> : Positions of the partons in the set
5802 : // IN int : Flavour of all the quarks in the set, if
5803 : // all quarks in a set should have a fixed flavour
5804 : // OUT bool : Is a flavour singlet / is not
5805 :
5806 : bool History::isFlavSinglet( const Event& event,
5807 : vector<int> system, int flav) {
5808 :
5809 : // If a decoupled colour singlet has been found, check if this is also
5810 : // a flavour singlet
5811 : // Check that each quark matches an antiquark
5812 0 : for(int i=0; i < int(system.size()); ++i)
5813 0 : if ( system[i] > 0 ) {
5814 0 : for(int j=0; j < int(system.size()); ++j) {
5815 : // If flavour of outgoing partons matches,
5816 : // remove both partons and continue.
5817 : // Skip all bosons
5818 0 : if ( event[i].idAbs() != 21
5819 0 : && event[i].idAbs() != 22
5820 0 : && event[i].idAbs() != 23
5821 0 : && event[i].idAbs() != 24
5822 0 : && system[i] > 0
5823 0 : && system[j] > 0
5824 0 : && event[system[i]].isFinal()
5825 0 : && event[system[j]].isFinal()
5826 0 : && event[system[i]].id() == -1*event[system[j]].id()) {
5827 : // If we want to check if only one flavour of quarks
5828 : // exists
5829 0 : if (abs(flav) > 0 && event[system[i]].idAbs() != flav)
5830 0 : return false;
5831 : // Remove index and break
5832 0 : system[i] = 0;
5833 0 : system[j] = 0;
5834 0 : break;
5835 : }
5836 : // If flavour of outgoing and incoming partons match,
5837 : // remove both partons and continue.
5838 : // Skip all bosons
5839 0 : if ( event[i].idAbs() != 21
5840 0 : && event[i].idAbs() != 22
5841 0 : && event[i].idAbs() != 23
5842 0 : && event[i].idAbs() != 24
5843 0 : && system[i] > 0
5844 0 : && system[j] > 0
5845 0 : && ( ( !event[system[i]].isFinal() && event[system[j]].isFinal())
5846 0 : ||( !event[system[j]].isFinal() && event[system[i]].isFinal()) )
5847 0 : && event[system[i]].id() == event[system[j]].id()) {
5848 : // If we want to check if only one flavour of quarks
5849 : // exists
5850 0 : if (abs(flav) > 0 && event[system[i]].idAbs() != flav)
5851 0 : return false;
5852 : // Remove index and break
5853 0 : system[i] = 0;
5854 0 : system[j] = 0;
5855 0 : break;
5856 : }
5857 :
5858 : }
5859 : }
5860 :
5861 : // The colour singlet is a flavour singlet if for all quarks,
5862 : // an antiquark was found
5863 : bool isFlavSing = true;
5864 0 : for(int i=0; i < int(system.size()); ++i)
5865 0 : if ( system[i] != 0 )
5866 0 : isFlavSing = false;
5867 :
5868 : // Return
5869 0 : return isFlavSing;
5870 :
5871 0 : }
5872 :
5873 : //--------------------------------------------------------------------------
5874 :
5875 : // Function to check if rad,emt,rec triple is allowed for clustering
5876 : // IN int rad,emt,rec : Positions (in event record) of the three
5877 : // particles considered for clustering
5878 : // Event event : Reference event
5879 :
5880 : bool History::allowedClustering( int rad, int emt, int rec, int partner,
5881 : const Event& event ) {
5882 :
5883 : // Declare output
5884 : bool allowed = true;
5885 :
5886 : // CONSTRUCT SOME PROPERTIES FOR LATER INVESTIGATION
5887 :
5888 : // Check if the triple forms a colour singlett
5889 0 : bool isSing = isSinglett(rad,emt,partner,event);
5890 0 : int type = (event[rad].isFinal()) ? 1 :-1;
5891 : // Get flavour of radiator after potential clustering
5892 0 : int radBeforeFlav = getRadBeforeFlav(rad,emt,event);
5893 : // Get colours of the radiator before the potential clustering
5894 0 : int radBeforeCol = getRadBeforeCol(rad,emt,event);
5895 0 : int radBeforeAcl = getRadBeforeAcol(rad,emt,event);
5896 : // Get colour partner of reclustered parton
5897 0 : vector<int> radBeforeColP = getReclusteredPartners(rad, emt, event);
5898 :
5899 : // Count coloured partons in hard process
5900 : int nPartonInHard = 0;
5901 0 : for(int i=0; i < int(event.size()); ++i)
5902 : // Check all final state partons
5903 0 : if ( event[i].isFinal()
5904 0 : && event[i].colType() != 0
5905 0 : && mergingHooksPtr->hardProcess.matchesAnyOutgoing(i, event) )
5906 0 : nPartonInHard++;
5907 :
5908 : // Count coloured final state partons in event, excluding
5909 : // rad, rec, emt and hard process
5910 : int nPartons = 0;
5911 0 : for(int i=0; i < int(event.size()); ++i)
5912 : // Check all final state partons
5913 0 : if ( i!=emt && i!=rad && i!=rec
5914 0 : && event[i].isFinal()
5915 0 : && event[i].colType() != 0
5916 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i, event) )
5917 0 : nPartons++;
5918 :
5919 : // Count number of initial state partons
5920 : int nInitialPartons = 0;
5921 0 : for(int i=0; i < int(event.size()); ++i)
5922 0 : if ( event[i].status() == -21
5923 0 : && event[i].colType() != 0 )
5924 0 : nInitialPartons++;
5925 :
5926 : // Get number of non-charged final state particles
5927 : int nFinalEW = 0;
5928 0 : for(int i=0; i < int(event.size()); ++i)
5929 0 : if ( event[i].isFinal()
5930 0 : &&( event[i].id() == 22
5931 0 : || event[i].id() == 23
5932 0 : || event[i].id() == 24
5933 0 : ||(event[i].idAbs() > 10 && event[i].idAbs() < 20)
5934 0 : ||(event[i].idAbs() > 10 && event[i].idAbs() < 20)
5935 0 : ||(event[i].idAbs() > 1000010 && event[i].idAbs() < 1000020)
5936 0 : ||(event[i].idAbs() > 2000010 && event[i].idAbs() < 2000020) ))
5937 0 : nFinalEW++;
5938 :
5939 : // Check if event after potential clustering contains an even
5940 : // number of quarks and/or antiquarks
5941 : // (otherwise no electroweak vertex could be formed!)
5942 : // Get number of final quarks
5943 : int nFinalQuark = 0;
5944 : // Get number of excluded final state quarks as well
5945 : int nFinalQuarkExc = 0;
5946 0 : for(int i=0; i < int(event.size()); ++i) {
5947 0 : if (i !=rad && i != emt && i != rec) {
5948 0 : if (event[i].isFinal() && abs(event[i].colType()) == 1 ) {
5949 0 : if ( !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,event) )
5950 0 : nFinalQuark++;
5951 : else
5952 0 : nFinalQuarkExc++;
5953 : }
5954 : }
5955 : }
5956 :
5957 : // Add recoiler to number of final quarks
5958 0 : if (event[rec].isFinal() && event[rec].isQuark()) nFinalQuark++;
5959 : // Add radiator after clustering to number of final quarks
5960 0 : if (event[rad].isFinal() && abs(radBeforeFlav) < 10) nFinalQuark++;
5961 :
5962 : // Get number of initial quarks
5963 : int nInitialQuark = 0;
5964 0 : if (type == 1) {
5965 0 : if (event[rec].isFinal()) {
5966 0 : if (event[3].isQuark()) nInitialQuark++;
5967 0 : if (event[4].isQuark()) nInitialQuark++;
5968 : } else {
5969 0 : int iOtherIn = (rec == 3) ? 4 : 3;
5970 0 : if (event[rec].isQuark()) nInitialQuark++;
5971 0 : if (event[iOtherIn].isQuark()) nInitialQuark++;
5972 : }
5973 : } else {
5974 : // Add recoiler to number of initial quarks
5975 0 : if (event[rec].isQuark()) nInitialQuark++;
5976 : // Add radiator after clustering to number of initial quarks
5977 0 : if (abs(radBeforeFlav) < 10) nInitialQuark++;
5978 : }
5979 :
5980 : // BEGIN CHECKING THE CLUSTERING
5981 :
5982 : // Do not allow clusterings that lead to a disallowed proton content.
5983 0 : int proton[] = {1,2,3,4,5,21,22,23,24};
5984 : bool isInProton = false;
5985 0 : for(int i=0; i < 9; ++i)
5986 0 : if (abs(radBeforeFlav) == proton[i]) isInProton = true;
5987 0 : if (type == -1 && !isInProton) return false;
5988 :
5989 : // Check if colour is conserved
5990 0 : vector<int> unmatchedCol;
5991 0 : vector<int> unmatchedAcl;
5992 : // Check all unmatched colours
5993 0 : for ( int i = 0; i < event.size(); ++i)
5994 0 : if ( i != emt && i != rad
5995 0 : && (event[i].isFinal() || event[i].status() == -21)
5996 0 : && event[i].colType() != 0 ) {
5997 :
5998 0 : int colP = getColPartner(i,event);
5999 0 : int aclP = getAcolPartner(i,event);
6000 :
6001 0 : if (event[i].col() > 0
6002 0 : && (colP == emt || colP == rad || colP == 0) )
6003 0 : unmatchedCol.push_back(i);
6004 0 : if (event[i].acol() > 0
6005 0 : && (aclP == emt || aclP == rad || aclP == 0) )
6006 0 : unmatchedAcl.push_back(i);
6007 :
6008 0 : }
6009 :
6010 : // If more than one colour or more than one anticolour are unmatched,
6011 : // there is no way to make this clustering work
6012 0 : if (int(unmatchedCol.size()) + int(unmatchedAcl.size()) > 2)
6013 0 : return false;
6014 :
6015 : // If triple forms colour singlett, check that resulting state
6016 : // matches hard core process
6017 0 : if (isSing)
6018 0 : allowed = false;
6019 0 : if (isSing && (abs(radBeforeFlav)<10 && event[rec].isQuark()) )
6020 0 : allowed = true;
6021 :
6022 : // Never recluster any outgoing partons of the core V -> qqbar' splitting!
6023 0 : if ( mergingHooksPtr->hardProcess.matchesAnyOutgoing(emt,event) ) {
6024 : // Check if any other particle could replace "emt" as part of the candidate
6025 : // core process. If so, replace emt with the new candidate and allow the
6026 : // clustering.
6027 0 : bool canReplace = mergingHooksPtr->hardProcess.findOtherCandidates(emt,
6028 : event, true);
6029 0 : if (canReplace) allowed = true;
6030 : else allowed = false;
6031 0 : }
6032 :
6033 : // Never allow clustering of any outgoing partons of the hard process
6034 : // which would change the flavour of one of the hard process partons!
6035 0 : if ( mergingHooksPtr->hardProcess.matchesAnyOutgoing(rad,event)
6036 0 : && event[rad].id() != radBeforeFlav )
6037 0 : allowed = false;
6038 :
6039 : // If only gluons in initial state and no quarks in final state,
6040 : // reject (no electroweak vertex can be formed)
6041 0 : if (nFinalEW != 0 && nInitialQuark == 0
6042 0 : && nFinalQuark == 0 && nFinalQuarkExc == 0)
6043 0 : allowed = false;
6044 :
6045 0 : if ( (nInitialQuark + nFinalQuark + nFinalQuarkExc)%2 != 0 )
6046 0 : allowed = false;
6047 :
6048 : // Disallow final state splittings that lead to a purely gluonic final
6049 : // state, while having a completely colour-connected initial state.
6050 : // This means that the clustering is discarded if it does not lead to the
6051 : // t-channel gluon needed to connect the final state to a qq~ initial state.
6052 : // Here, partons excluded from clustering are not counted as possible
6053 : // partners to form a t-channel gluon
6054 0 : if (event[3].col() == event[4].acol()
6055 0 : && event[3].acol() == event[4].col()
6056 0 : && nFinalQuark == 0){
6057 : // Careful if rad and rec are the only quarks in the final state, but
6058 : // were both excluded from the list of final state quarks.
6059 0 : int nTripletts = abs(event[rec].colType())
6060 0 : + abs(particleDataPtr->colType(radBeforeFlav));
6061 0 : if (event[3].isGluon()) allowed = false;
6062 0 : else if (nTripletts != 2 && nFinalQuarkExc%2 == 0) allowed = false;
6063 0 : }
6064 :
6065 : // No problems with gluon radiation
6066 0 : if (event[emt].id() == 21)
6067 0 : return allowed;
6068 :
6069 : // No problems with gluino radiation
6070 0 : if (event[emt].id() == 1000021)
6071 0 : return allowed;
6072 :
6073 : // Save all hard process candidates
6074 0 : vector<int> outgoingParticles;
6075 0 : int nOut1 = int(mergingHooksPtr->hardProcess.PosOutgoing1.size());
6076 0 : for ( int i=0; i < nOut1; ++i ) {
6077 0 : int iPos = mergingHooksPtr->hardProcess.PosOutgoing1[i];
6078 0 : outgoingParticles.push_back(
6079 0 : mergingHooksPtr->hardProcess.state[iPos].id() );
6080 : }
6081 0 : int nOut2 = int(mergingHooksPtr->hardProcess.PosOutgoing2.size());
6082 0 : for ( int i=0; i < nOut2; ++i ) {
6083 0 : int iPos = mergingHooksPtr->hardProcess.PosOutgoing2[i];
6084 0 : outgoingParticles.push_back(
6085 0 : mergingHooksPtr->hardProcess.state[iPos].id() );
6086 : }
6087 :
6088 : // Start more involved checks. g -> q_1 qbar_1 splittings are
6089 : // particularly problematic if more than one quark of the emitted
6090 : // flavour is present.
6091 : // Count number of initial quarks of radiator or emitted flavour
6092 0 : vector<int> iInQuarkFlav;
6093 0 : for(int i=0; i < int(event.size()); ++i)
6094 : // Check all initial state partons
6095 0 : if ( i != emt && i != rad
6096 0 : && event[i].status() == -21
6097 0 : && event[i].idAbs() == event[emt].idAbs() )
6098 0 : iInQuarkFlav.push_back(i);
6099 :
6100 : // Count number of final quarks of radiator or emitted flavour
6101 0 : vector<int> iOutQuarkFlav;
6102 0 : for(int i=0; i < int(event.size()); ++i)
6103 : // Check all final state partons
6104 0 : if ( i != emt && i != rad
6105 0 : && event[i].isFinal()
6106 0 : && event[i].idAbs() == event[emt].idAbs() ) {
6107 :
6108 : // Loop through final state hard particles. If one matches, remove the
6109 : // matching one, and do not count.
6110 : bool matchOut = false;
6111 0 : for (int j = 0; j < int(outgoingParticles.size()); ++j)
6112 0 : if ( event[i].idAbs() == abs(outgoingParticles[j])) {
6113 : matchOut = true;
6114 0 : outgoingParticles[j] = 99;
6115 0 : }
6116 0 : if (!matchOut) iOutQuarkFlav.push_back(i);
6117 :
6118 0 : }
6119 :
6120 : // Save number of potentially dangerous quarks
6121 0 : int nInQuarkFlav = int(iInQuarkFlav.size());
6122 0 : int nOutQuarkFlav = int(iOutQuarkFlav.size());
6123 :
6124 : // Easiest problem 0:
6125 : // Radiator before splitting exactly matches the partner
6126 : // after the splitting
6127 0 : if ( event[partner].isFinal()
6128 0 : && event[partner].id() == 21
6129 0 : && radBeforeFlav == 21
6130 0 : && event[partner].col() == radBeforeCol
6131 0 : && event[partner].acol() == radBeforeAcl)
6132 0 : return false;
6133 :
6134 : // If there are no ambiguities in qqbar pairs, return
6135 0 : if (nInQuarkFlav + nOutQuarkFlav == 0)
6136 0 : return allowed;
6137 :
6138 : // Save all quarks and gluons that will not change colour
6139 0 : vector<int> gluon;
6140 0 : vector<int> quark;
6141 0 : vector<int> antiq;
6142 0 : vector<int> partons;
6143 0 : for(int i=0; i < int(event.size()); ++i)
6144 : // Check initial and final state partons
6145 0 : if ( i!=emt && i!=rad
6146 0 : && event[i].colType() != 0
6147 0 : && (event[i].isFinal() || event[i].status() == -21) ) {
6148 : // Save index
6149 0 : partons.push_back(i);
6150 : // Split into components
6151 0 : if (event[i].colType() == 2)
6152 0 : gluon.push_back(i);
6153 0 : else if (event[i].colType() == 1)
6154 0 : quark.push_back(i);
6155 0 : else if (event[i].colType() == -1)
6156 0 : antiq.push_back(i);
6157 : }
6158 :
6159 : // We split up the test of the g->qq splitting into final state
6160 : // and initial state problems
6161 0 : bool isFSRg2qq = ((type == 1) && (event[rad].id() == -1*event[emt].id()) );
6162 0 : bool isISRg2qq = ((type ==-1) && (event[rad].id() == event[emt].id()) );
6163 :
6164 : // First check general things about colour connections
6165 : // Check that clustering does not produce a gluon that is exactly
6166 : // matched in the final state, or does not have any colour connections
6167 0 : if ( (isFSRg2qq || isISRg2qq)
6168 0 : && int(quark.size()) + int(antiq.size())
6169 0 : + int(gluon.size()) > nPartonInHard ) {
6170 :
6171 0 : vector<int> colours;
6172 0 : vector<int> anticolours;
6173 : // Add the colour and anticolour of the gluon before the emission
6174 : // to the list, bookkeep initial colour as final anticolour, and
6175 : // initial anticolour as final colour
6176 0 : if (type == 1) {
6177 0 : colours.push_back(radBeforeCol);
6178 0 : anticolours.push_back(radBeforeAcl);
6179 : } else {
6180 0 : colours.push_back(radBeforeAcl);
6181 0 : anticolours.push_back(radBeforeCol);
6182 : }
6183 : // Now store gluon colours and anticolours.
6184 0 : for(int i=0; i < int(gluon.size()); ++i)
6185 0 : if (event[gluon[i]].isFinal()) {
6186 0 : colours.push_back(event[gluon[i]].col());
6187 0 : anticolours.push_back(event[gluon[i]].acol());
6188 : } else {
6189 0 : colours.push_back(event[gluon[i]].acol());
6190 0 : anticolours.push_back(event[gluon[i]].col());
6191 : }
6192 :
6193 : // Loop through colours and check if any match with
6194 : // anticolours. If colour matches, remove from list
6195 0 : for(int i=0; i < int(colours.size()); ++i)
6196 0 : for(int j=0; j < int(anticolours.size()); ++j)
6197 0 : if (colours[i] > 0 && anticolours[j] > 0
6198 0 : && colours[i] == anticolours[j]) {
6199 0 : colours[i] = 0;
6200 0 : anticolours[j] = 0;
6201 0 : }
6202 :
6203 :
6204 : // If all gluon anticolours and all colours matched, disallow
6205 : // the clustering
6206 : bool allMatched = true;
6207 0 : for(int i=0; i < int(colours.size()); ++i)
6208 0 : if (colours[i] != 0)
6209 0 : allMatched = false;
6210 0 : for(int i=0; i < int(anticolours.size()); ++i)
6211 0 : if (anticolours[i] != 0)
6212 0 : allMatched = false;
6213 :
6214 0 : if (allMatched)
6215 0 : return false;
6216 :
6217 : // Now add the colours of the hard process, and check if all
6218 : // colours match.
6219 0 : for(int i=0; i < int(quark.size()); ++i)
6220 0 : if ( event[quark[i]].isFinal()
6221 0 : && mergingHooksPtr->hardProcess.matchesAnyOutgoing(quark[i], event) )
6222 0 : colours.push_back(event[quark[i]].col());
6223 :
6224 0 : for(int i=0; i < int(antiq.size()); ++i)
6225 0 : if ( event[antiq[i]].isFinal()
6226 0 : && mergingHooksPtr->hardProcess.matchesAnyOutgoing(antiq[i], event) )
6227 0 : anticolours.push_back(event[antiq[i]].acol());
6228 :
6229 : // Loop through colours again and check if any match with
6230 : // anticolours. If colour matches, remove from list
6231 0 : for(int i=0; i < int(colours.size()); ++i)
6232 :
6233 0 : for(int j=0; j < int(anticolours.size()); ++j)
6234 0 : if (colours[i] > 0 && anticolours[j] > 0
6235 0 : && colours[i] == anticolours[j]) {
6236 0 : colours[i] = 0;
6237 0 : anticolours[j] = 0;
6238 0 : }
6239 :
6240 : // Check if clustering would produce the hard process
6241 : int nNotInHard = 0;
6242 0 : for ( int i=0; i < int(quark.size()); ++i )
6243 0 : if ( !mergingHooksPtr->hardProcess.matchesAnyOutgoing( quark[i],
6244 : event) )
6245 0 : nNotInHard++;
6246 0 : for ( int i=0; i < int(antiq.size()); ++i )
6247 0 : if ( !mergingHooksPtr->hardProcess.matchesAnyOutgoing( antiq[i],
6248 : event) )
6249 0 : nNotInHard++;
6250 0 : for(int i=0; i < int(gluon.size()); ++i)
6251 0 : if ( event[gluon[i]].isFinal() )
6252 0 : nNotInHard++;
6253 0 : if ( type == 1 )
6254 0 : nNotInHard++;
6255 :
6256 : // If all colours are matched now, and since we have more quarks than
6257 : // present in the hard process, disallow the clustering
6258 : allMatched = true;
6259 0 : for(int i=0; i < int(colours.size()); ++i)
6260 0 : if (colours[i] != 0)
6261 0 : allMatched = false;
6262 0 : for(int i=0; i < int(anticolours.size()); ++i)
6263 0 : if (anticolours[i] != 0)
6264 0 : allMatched = false;
6265 :
6266 0 : if (allMatched && nNotInHard > 0)
6267 0 : return false;
6268 :
6269 0 : }
6270 :
6271 : // FSR PROBLEMS
6272 :
6273 0 : if (isFSRg2qq && nInQuarkFlav + nOutQuarkFlav > 0) {
6274 :
6275 : // Easiest problem 1:
6276 : // RECLUSTERED FINAL STATE GLUON MATCHES INITIAL STATE GLUON
6277 0 : for(int i=0; i < int(gluon.size()); ++i) {
6278 0 : if (!event[gluon[i]].isFinal()
6279 0 : && event[gluon[i]].col() == radBeforeCol
6280 0 : && event[gluon[i]].acol() == radBeforeAcl)
6281 0 : return false;
6282 : }
6283 :
6284 : // Easiest problem 2:
6285 : // RECLUSTERED FINAL STATE GLUON MATCHES FINAL STATE GLUON
6286 0 : for(int i=0; i < int(gluon.size()); ++i) {
6287 0 : if (event[gluon[i]].isFinal()
6288 0 : && event[gluon[i]].col() == radBeforeAcl
6289 0 : && event[gluon[i]].acol() == radBeforeCol)
6290 0 : return false;
6291 : }
6292 :
6293 : // Easiest problem 3:
6294 : // RECLUSTERED FINAL STATE GLUON MATCHES FINAL STATE Q-QBAR PAIR
6295 0 : if ( int(radBeforeColP.size()) == 2
6296 0 : && event[radBeforeColP[0]].isFinal()
6297 0 : && event[radBeforeColP[1]].isFinal()
6298 0 : && event[radBeforeColP[0]].id() == -1*event[radBeforeColP[1]].id() ) {
6299 :
6300 : // This clustering is allowed if there is no colour in the
6301 : // initial state
6302 0 : if (nInitialPartons > 0)
6303 0 : return false;
6304 : }
6305 :
6306 : // Next-to-easiest problem 1:
6307 : // RECLUSTERED FINAL STATE GLUON MATCHES ONE FINAL STARE Q_1
6308 : // AND ONE INITIAL STATE Q_1
6309 0 : if ( int(radBeforeColP.size()) == 2
6310 0 : && (( event[radBeforeColP[0]].status() == -21
6311 0 : && event[radBeforeColP[1]].isFinal())
6312 0 : ||( event[radBeforeColP[0]].isFinal()
6313 0 : && event[radBeforeColP[1]].status() == -21))
6314 0 : && event[radBeforeColP[0]].id() == event[radBeforeColP[1]].id() ) {
6315 :
6316 : // In principle, clustering this splitting can disconnect
6317 : // the colour lines of a graph. However, the colours can be connected
6318 : // again if a final or initial partons of the correct flavour exists.
6319 :
6320 : // Check which of the partners are final / initial
6321 0 : int incoming = (event[radBeforeColP[0]].isFinal())
6322 0 : ? radBeforeColP[1] : radBeforeColP[0];
6323 0 : int outgoing = (event[radBeforeColP[0]].isFinal())
6324 0 : ? radBeforeColP[0] : radBeforeColP[1];
6325 :
6326 : // Loop through event to find "recovery partons"
6327 : bool clusPossible = false;
6328 0 : for(int i=0; i < int(event.size()); ++i)
6329 0 : if ( i != emt && i != rad
6330 0 : && i != incoming && i != outgoing
6331 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,event) ) {
6332 : // Check if an incoming parton matches
6333 0 : if ( event[i].status() == -21
6334 0 : && (event[i].id() == event[outgoing].id()
6335 0 : ||event[i].id() == -1*event[incoming].id()) )
6336 0 : clusPossible = true;
6337 : // Check if a final parton matches
6338 0 : if ( event[i].isFinal()
6339 0 : && (event[i].id() == -1*event[outgoing].id()
6340 0 : ||event[i].id() == event[incoming].id()) )
6341 0 : clusPossible = true;
6342 : }
6343 :
6344 : // There can be a further complication: If e.g. in
6345 : // t-channel photon exchange topologies, both incoming
6346 : // partons are quarks, and form colour singlets with any
6347 : // number of final state partons, at least try to
6348 : // recluster as much as possible.
6349 : // For this, check if the incoming parton
6350 : // connected to the radiator is connected to a
6351 : // colour and flavour singlet
6352 0 : vector<int> excludeIn1;
6353 0 : for(int i=0; i < 4; ++i)
6354 0 : excludeIn1.push_back(0);
6355 0 : vector<int> colSingletIn1;
6356 0 : int flavIn1Type = (event[incoming].id() > 0) ? 1 : -1;
6357 : // Try finding colour singlets
6358 0 : bool isColSingIn1 = getColSinglet(flavIn1Type,incoming,event,
6359 : excludeIn1,colSingletIn1);
6360 : // Check if colour singlet also is a flavour singlet
6361 0 : bool isFlavSingIn1 = isFlavSinglet(event,colSingletIn1);
6362 :
6363 : // Check if the incoming parton not
6364 : // connected to the radiator is connected to a
6365 : // colour and flavour singlet
6366 0 : int incoming2 = (incoming == 3) ? 4 : 3;
6367 0 : vector<int> excludeIn2;
6368 0 : for(int i=0; i < 4; ++i)
6369 0 : excludeIn2.push_back(0);
6370 0 : vector<int> colSingletIn2;
6371 0 : int flavIn2Type = (event[incoming2].id() > 0) ? 1 : -1;
6372 : // Try finding colour singlets
6373 0 : bool isColSingIn2 = getColSinglet(flavIn2Type,incoming2,event,
6374 : excludeIn2,colSingletIn2);
6375 : // Check if colour singlet also is a flavour singlet
6376 0 : bool isFlavSingIn2 = isFlavSinglet(event,colSingletIn2);
6377 :
6378 : // If no "recovery clustering" is possible, reject clustering
6379 0 : if (!clusPossible
6380 0 : && (!isColSingIn1 || !isFlavSingIn1
6381 0 : || !isColSingIn2 || !isFlavSingIn2))
6382 0 : return false;
6383 :
6384 0 : }
6385 :
6386 : // Next-to-easiest problem 2:
6387 : // FINAL STATE Q-QBAR CLUSTERING DISCONNECTS SINGLETT SUBSYSTEM WITH
6388 : // FINAL STATE Q-QBAR PAIR FROM GRAPH
6389 :
6390 : // Prepare to check for colour singlet combinations of final state quarks
6391 : // Start by building a list of partons to exclude when checking for
6392 : // colour singlet combinations
6393 0 : int flav = event[emt].id();
6394 0 : vector<int> exclude;
6395 0 : exclude.push_back(emt);
6396 0 : exclude.push_back(rad);
6397 0 : exclude.push_back(radBeforeColP[0]);
6398 0 : exclude.push_back(radBeforeColP[1]);
6399 0 : vector<int> colSinglet;
6400 : // Now find parton from which to start checking colour singlets
6401 : int iOther = -1;
6402 : // Loop through event to find a parton of correct flavour
6403 0 : for(int i=0; i < int(event.size()); ++i)
6404 : // Check final state for parton equalling emitted flavour.
6405 : // Exclude the colour system coupled to the clustering
6406 0 : if ( i != emt
6407 0 : && i != rad
6408 0 : && i != radBeforeColP[0]
6409 0 : && i != radBeforeColP[1]
6410 0 : && event[i].isFinal() ) {
6411 : // Stop if one parton of the correct flavour is found
6412 0 : if (event[i].id() == flav) {
6413 : iOther = i;
6414 0 : break;
6415 : }
6416 : }
6417 : // Save the type of flavour
6418 0 : int flavType = (event[iOther].id() > 0) ? 1 : -1;
6419 : // Try finding colour singlets
6420 0 : bool isColSing = getColSinglet(flavType,iOther,event,exclude,colSinglet);
6421 : // Check if colour singlet also is a flavour singlet
6422 0 : bool isFlavSing = isFlavSinglet(event,colSinglet);
6423 :
6424 : // Check if the colour singlet is precisely contained in the hard process.
6425 : // If so, then we're safe to recluster.
6426 : bool isHardSys = true;
6427 0 : for(int i=0; i < int(colSinglet.size()); ++i)
6428 0 : isHardSys =
6429 0 : mergingHooksPtr->hardProcess.matchesAnyOutgoing(colSinglet[i], event);
6430 :
6431 : // Nearly there...
6432 : // If the decoupled colour singlet system is NOT contained in the hard
6433 : // process, we need to check the whole final state.
6434 0 : if (isColSing && isFlavSing && !isHardSys) {
6435 :
6436 : // In a final check, ensure that the final state does not only
6437 : // consist of colour singlets that are also flavour singlets
6438 : // of the identical (!) flavours
6439 : // Loop through event and save all final state partons
6440 0 : vector<int> allFinal;
6441 0 : for(int i=0; i < int(event.size()); ++i)
6442 0 : if ( event[i].isFinal() )
6443 0 : allFinal.push_back(i);
6444 :
6445 : // Check if all final partons form a colour singlet
6446 0 : bool isFullColSing = isColSinglet(event,allFinal);
6447 : // Check if all final partons form a flavour singlet
6448 0 : bool isFullFlavSing = isFlavSinglet(event,allFinal,flav);
6449 :
6450 : // If all final quarks are of identical flavour,
6451 : // no possible clustering should be discriminated.
6452 : // Otherwise, disallow
6453 0 : if (!isFullColSing || !isFullFlavSing)
6454 0 : return false;
6455 0 : }
6456 0 : }
6457 :
6458 : // ISR PROBLEMS
6459 :
6460 0 : if (isISRg2qq && nInQuarkFlav + nOutQuarkFlav > 0) {
6461 :
6462 : // Easiest problem 1:
6463 : // RECLUSTERED INITIAL STATE GLUON MATCHES FINAL STATE GLUON
6464 0 : for(int i=0; i < int(gluon.size()); ++i) {
6465 0 : if (event[gluon[i]].isFinal()
6466 0 : && event[gluon[i]].col() == radBeforeCol
6467 0 : && event[gluon[i]].acol() == radBeforeAcl)
6468 0 : return false;
6469 : }
6470 :
6471 : // Easiest problem 2:
6472 : // RECLUSTERED INITIAL STATE GLUON MATCHES INITIAL STATE GLUON
6473 0 : for(int i=0; i < int(gluon.size()); ++i) {
6474 0 : if (event[gluon[i]].status() == -21
6475 0 : && event[gluon[i]].acol() == radBeforeCol
6476 0 : && event[gluon[i]].col() == radBeforeAcl)
6477 0 : return false;
6478 : }
6479 :
6480 : // Next-to-easiest problem 1:
6481 : // RECLUSTERED INITIAL STATE GLUON MATCHES FINAL STATE Q-QBAR PAIR
6482 0 : if ( int(radBeforeColP.size()) == 2
6483 0 : && event[radBeforeColP[0]].isFinal()
6484 0 : && event[radBeforeColP[1]].isFinal()
6485 0 : && event[radBeforeColP[0]].id() == -1*event[radBeforeColP[1]].id() ) {
6486 :
6487 : // In principle, clustering this splitting can disconnect
6488 : // the colour lines of a graph. However, the colours can be connected
6489 : // again if final state partons of the correct (anti)flavour, or
6490 : // initial state partons of the correct flavour exist
6491 : // Loop through event to check
6492 : bool clusPossible = false;
6493 0 : for(int i=0; i < int(event.size()); ++i)
6494 0 : if ( i != emt && i != rad
6495 0 : && i != radBeforeColP[0]
6496 0 : && i != radBeforeColP[1]
6497 0 : && !mergingHooksPtr->hardProcess.matchesAnyOutgoing(i,event) ) {
6498 0 : if (event[i].status() == -21
6499 0 : && ( event[radBeforeColP[0]].id() == event[i].id()
6500 0 : || event[radBeforeColP[1]].id() == event[i].id() ))
6501 :
6502 0 : clusPossible = true;
6503 0 : if (event[i].isFinal()
6504 0 : && ( event[radBeforeColP[0]].id() == -1*event[i].id()
6505 0 : || event[radBeforeColP[1]].id() == -1*event[i].id() ))
6506 0 : clusPossible = true;
6507 : }
6508 :
6509 : // There can be a further complication: If e.g. in
6510 : // t-channel photon exchange topologies, both incoming
6511 : // partons are quarks, and form colour singlets with any
6512 : // number of final state partons, at least try to
6513 : // recluster as much as possible.
6514 : // For this, check if the incoming parton
6515 : // connected to the radiator is connected to a
6516 : // colour and flavour singlet
6517 : int incoming1 = 3;
6518 0 : vector<int> excludeIn1;
6519 0 : for(int i=0; i < 4; ++i)
6520 0 : excludeIn1.push_back(0);
6521 0 : vector<int> colSingletIn1;
6522 0 : int flavIn1Type = (event[incoming1].id() > 0) ? 1 : -1;
6523 : // Try finding colour singlets
6524 0 : bool isColSingIn1 = getColSinglet(flavIn1Type,incoming1,event,
6525 : excludeIn1,colSingletIn1);
6526 : // Check if colour singlet also is a flavour singlet
6527 0 : bool isFlavSingIn1 = isFlavSinglet(event,colSingletIn1);
6528 :
6529 : // Check if the incoming parton not
6530 : // connected to the radiator is connected to a
6531 : // colour and flavour singlet
6532 : int incoming2 = 4;
6533 0 : vector<int> excludeIn2;
6534 0 : for(int i=0; i < 4; ++i)
6535 0 : excludeIn2.push_back(0);
6536 0 : vector<int> colSingletIn2;
6537 0 : int flavIn2Type = (event[incoming2].id() > 0) ? 1 : -1;
6538 : // Try finding colour singlets
6539 0 : bool isColSingIn2 = getColSinglet(flavIn2Type,incoming2,event,
6540 : excludeIn2,colSingletIn2);
6541 : // Check if colour singlet also is a flavour singlet
6542 0 : bool isFlavSingIn2 = isFlavSinglet(event,colSingletIn2);
6543 :
6544 : // If no "recovery clustering" is possible, reject clustering
6545 0 : if (!clusPossible
6546 0 : && (!isColSingIn1 || !isFlavSingIn1
6547 0 : || !isColSingIn2 || !isFlavSingIn2))
6548 0 : return false;
6549 :
6550 0 : }
6551 :
6552 : }
6553 :
6554 : // Done
6555 0 : return allowed;
6556 0 : }
6557 :
6558 : //--------------------------------------------------------------------------
6559 :
6560 : // Function to check if rad,emt,rec triple is results in
6561 : // colour singlet radBefore+recBefore
6562 : // IN int rad,emt,rec : Positions (in event record) of the three
6563 : // particles considered for clustering
6564 : // Event event : Reference event
6565 :
6566 : bool History::isSinglett( int rad, int emt, int rec, const Event& event ) {
6567 :
6568 0 : int radCol = event[rad].col();
6569 0 : int emtCol = event[emt].col();
6570 0 : int recCol = event[rec].col();
6571 0 : int radAcl = event[rad].acol();
6572 0 : int emtAcl = event[emt].acol();
6573 0 : int recAcl = event[rec].acol();
6574 0 : int recType = event[rec].isFinal() ? 1 : -1;
6575 :
6576 : bool isSing = false;
6577 :
6578 0 : if ( ( recType == -1
6579 0 : && radCol + emtCol == recCol && radAcl + emtAcl == recAcl)
6580 0 : ||( recType == 1
6581 0 : && radCol + emtCol == recAcl && radAcl + emtAcl == recCol) )
6582 0 : isSing = true;
6583 :
6584 0 : return isSing;
6585 :
6586 : }
6587 :
6588 : //--------------------------------------------------------------------------
6589 :
6590 : // Function to check if event is sensibly constructed: Meaning
6591 : // that all colour indices are contracted and that the charge in
6592 : // initial and final states matches
6593 : // IN event : event to be checked
6594 : // OUT TRUE : event is properly construced
6595 : // FALSE : event not valid
6596 :
6597 : bool History::validEvent( const Event& event ) {
6598 :
6599 : // Check if event is coloured
6600 : bool validColour = true;
6601 0 : for ( int i = 0; i < event.size(); ++i)
6602 : // Check colour of quarks
6603 0 : if ( event[i].isFinal() && event[i].colType() == 1
6604 : // No corresponding anticolour in final state
6605 0 : && ( FindCol(event[i].col(),i,0,event,1,true) == 0
6606 : // No corresponding colour in initial state
6607 0 : && FindCol(event[i].col(),i,0,event,2,true) == 0 )) {
6608 : validColour = false;
6609 0 : break;
6610 : // Check anticolour of antiquarks
6611 0 : } else if ( event[i].isFinal() && event[i].colType() == -1
6612 : // No corresponding colour in final state
6613 0 : && ( FindCol(event[i].acol(),i,0,event,2,true) == 0
6614 : // No corresponding anticolour in initial state
6615 0 : && FindCol(event[i].acol(),i,0,event,1,true) == 0 )) {
6616 : validColour = false;
6617 0 : break;
6618 : // No uncontracted colour (anticolour) charge of gluons
6619 0 : } else if ( event[i].isFinal() && event[i].colType() == 2
6620 : // No corresponding anticolour in final state
6621 0 : && ( FindCol(event[i].col(),i,0,event,1,true) == 0
6622 : // No corresponding colour in initial state
6623 0 : && FindCol(event[i].col(),i,0,event,2,true) == 0 )
6624 : // No corresponding colour in final state
6625 0 : && ( FindCol(event[i].acol(),i,0,event,2,true) == 0
6626 : // No corresponding anticolour in initial state
6627 0 : && FindCol(event[i].acol(),i,0,event,1,true) == 0 )) {
6628 : validColour = false;
6629 0 : break;
6630 : }
6631 :
6632 : // Check charge sum in initial and final state
6633 : bool validCharge = true;
6634 0 : double initCharge = event[3].charge() + event[4].charge();
6635 : double finalCharge = 0.0;
6636 0 : for(int i = 0; i < event.size(); ++i)
6637 0 : if (event[i].isFinal()) finalCharge += event[i].charge();
6638 0 : if (abs(initCharge-finalCharge) > 1e-12) validCharge = false;
6639 :
6640 0 : return (validColour && validCharge);
6641 :
6642 : }
6643 :
6644 : //--------------------------------------------------------------------------
6645 :
6646 : // Function to check whether two clusterings are identical, used
6647 : // for finding the history path in the mother -> children direction
6648 :
6649 : bool History::equalClustering( Clustering clus1 , Clustering clus2 ) {
6650 0 : return ( (clus1.emittor == clus2.emittor)
6651 0 : && (clus1.emitted == clus2.emitted)
6652 0 : && (clus1.recoiler == clus2.recoiler)
6653 0 : && (clus1.partner == clus2.partner)
6654 0 : && (clus1.pT() == clus2.pT()) );
6655 : }
6656 :
6657 : //--------------------------------------------------------------------------
6658 :
6659 : // Chose dummy scale for event construction. By default, choose
6660 : // sHat for 2->Boson(->2)+ n partons processes and
6661 : // M_Boson for 2->Boson(->) processes
6662 :
6663 : double History::choseHardScale( const Event& event ) const {
6664 :
6665 : // Get sHat
6666 0 : double mHat = (event[3].p() + event[4].p()).mCalc();
6667 :
6668 : // Find number of final state particles and bosons
6669 : int nFinal = 0;
6670 : int nFinBos= 0;
6671 : int nBosons= 0;
6672 : double mBos = 0.0;
6673 0 : for(int i = 0; i < event.size(); ++i)
6674 0 : if ( event[i].isFinal() ) {
6675 0 : nFinal++;
6676 : // Remember final state unstable bosons
6677 0 : if ( event[i].idAbs() == 23
6678 0 : || event[i].idAbs() == 24 ) {
6679 0 : nFinBos++;
6680 0 : nBosons++;
6681 0 : mBos += event[i].m();
6682 0 : }
6683 0 : } else if ( abs(event[i].status()) == 22
6684 0 : && ( event[i].idAbs() == 23
6685 0 : || event[i].idAbs() == 24 )) {
6686 0 : nBosons++;
6687 0 : mBos += event[i].m(); // Real mass
6688 0 : }
6689 :
6690 : // Return averaged boson masses
6691 0 : if ( nBosons > 0 && (nFinal + nFinBos*2) <= 3)
6692 0 : return (mBos / double(nBosons));
6693 0 : else return
6694 : mHat;
6695 0 : }
6696 :
6697 :
6698 : //--------------------------------------------------------------------------
6699 :
6700 : // If the state has an incoming hadron return the flavour of the
6701 : // parton entering the hard interaction. Otherwise return 0
6702 :
6703 : int History::getCurrentFlav(const int side) const {
6704 0 : int in = (side == 1) ? 3 : 4;
6705 0 : return state[in].id();
6706 : }
6707 :
6708 : //--------------------------------------------------------------------------
6709 :
6710 : double History::getCurrentX(const int side) const {
6711 0 : int in = (side == 1) ? 3 : 4;
6712 0 : return ( 2.*state[in].e()/state[0].e() );
6713 : }
6714 :
6715 : //--------------------------------------------------------------------------
6716 :
6717 : double History::getCurrentZ(const int rad,
6718 : const int rec, const int emt) const {
6719 :
6720 0 : int type = state[rad].isFinal() ? 1 : -1;
6721 : double z = 0.;
6722 :
6723 0 : if (type == 1) {
6724 : // Construct 2->3 variables for FSR
6725 0 : Vec4 sum = state[rad].p() + state[rec].p()
6726 0 : + state[emt].p();
6727 0 : double m2Dip = sum.m2Calc();
6728 0 : double x1 = 2. * (sum * state[rad].p()) / m2Dip;
6729 0 : double x3 = 2. * (sum * state[emt].p()) / m2Dip;
6730 : // Calculate z of splitting, different for FSR
6731 0 : z = x1/(x1+x3);
6732 0 : } else {
6733 : // Construct momenta of dipole before/after splitting for ISR
6734 0 : Vec4 qBR(state[rad].p() - state[emt].p() + state[rec].p());
6735 0 : Vec4 qAR(state[rad].p() + state[rec].p());
6736 : // Calculate z of splitting, different for ISR
6737 0 : z = (qBR.m2Calc())/( qAR.m2Calc());
6738 0 : }
6739 :
6740 0 : return z;
6741 :
6742 : }
6743 :
6744 : //--------------------------------------------------------------------------
6745 :
6746 : // Function to compute "pythia pT separation" from Particle input
6747 :
6748 : double History::pTLund(const Particle& RadAfterBranch,
6749 : const Particle& EmtAfterBranch,
6750 : const Particle& RecAfterBranch, int ShowerType) {
6751 :
6752 : // Save type: 1 = FSR pT definition, else ISR definition
6753 : int Type = ShowerType;
6754 : // Calculate virtuality of splitting
6755 0 : int sign = (Type==1) ? 1 : -1;
6756 0 : Vec4 Q(RadAfterBranch.p() + sign*EmtAfterBranch.p());
6757 0 : double Qsq = sign * Q.m2Calc();
6758 : // Mass term of radiator: Consider all non-light quark or gluon radiators
6759 : // massive partons.
6760 0 : bool isMassive = ( RadAfterBranch.idAbs() >= 4
6761 0 : && RadAfterBranch.id() != 21 );
6762 0 : double m2Rad = ( mergingHooksPtr->includeMassive() && isMassive )
6763 0 : ? pow2( particleDataPtr->m0(RadAfterBranch.id()) ) : 0.;
6764 : // Construct 2->3 variables for FSR
6765 0 : Vec4 sum = RadAfterBranch.p() + RecAfterBranch.p()
6766 0 : + EmtAfterBranch.p();
6767 0 : double m2Dip = sum.m2Calc();
6768 0 : double x1 = 2. * (sum * RadAfterBranch.p()) / m2Dip;
6769 0 : double x3 = 2. * (sum * EmtAfterBranch.p()) / m2Dip;
6770 : // Construct momenta of dipole before/after splitting for ISR
6771 0 : Vec4 qBR(RadAfterBranch.p() - EmtAfterBranch.p() + RecAfterBranch.p());
6772 0 : Vec4 qAR(RadAfterBranch.p() + RecAfterBranch.p());
6773 : // Calculate z of splitting, different for FSR and ISR
6774 :
6775 0 : double z = (Type==1) ? x1/(x1+x3)
6776 0 : : (qBR.m2Calc())/( qAR.m2Calc());
6777 : // Separation of splitting, different for FSR and ISR
6778 0 : double pTpyth = (Type==1) ? z*(1.-z) : (1.-z);
6779 : // pT^2 = separation*virtuality
6780 0 : pTpyth *= (Qsq - sign*m2Rad);
6781 0 : if ( pTpyth < 0. ) pTpyth = 0.;
6782 :
6783 : // Return pT
6784 0 : return sqrt(pTpyth);
6785 0 : }
6786 :
6787 : //--------------------------------------------------------------------------
6788 :
6789 : // Function to return the position of the initial line before (or after)
6790 : // a single (!) splitting.
6791 :
6792 : int History::posChangedIncoming(const Event& event, bool before) {
6793 :
6794 : // Check for initial state splittings.
6795 : // Consider a splitting to exist if both mother and sister were found.
6796 : // Find sister
6797 : int iSister = 0;
6798 0 : for (int i =0; i < event.size(); ++i)
6799 0 : if (event[i].status() == 43) {
6800 : iSister = i;
6801 0 : break;
6802 : }
6803 : // Find mother
6804 : int iMother = 0;
6805 0 : if (iSister > 0) iMother = event[iSister].mother1();
6806 :
6807 : // Initial state splitting has been found.
6808 0 : if (iSister > 0 && iMother > 0) {
6809 :
6810 : // Find flavour, mother flavour
6811 0 : int flavSister = event[iSister].id();
6812 0 : int flavMother = event[iMother].id();
6813 :
6814 : // Find splitting flavour
6815 : int flavDaughter = 0;
6816 0 : if ( abs(flavMother) < 21 && flavSister == 21)
6817 0 : flavDaughter = flavMother;
6818 0 : else if ( flavMother == 21 && flavSister == 21)
6819 0 : flavDaughter = flavMother;
6820 0 : else if ( flavMother == 21 && abs(flavSister) < 21)
6821 0 : flavDaughter = -1*flavSister;
6822 0 : else if ( abs(flavMother) < 21 && abs(flavSister) < 21)
6823 0 : flavDaughter = 21;
6824 :
6825 : // Find initial state (!) daughter
6826 : int iDaughter = 0;
6827 0 : for (int i =0; i < event.size(); ++i)
6828 0 : if ( !event[i].isFinal()
6829 0 : && event[i].mother1() == iMother
6830 0 : && event[i].id() == flavDaughter )
6831 0 : iDaughter = i;
6832 :
6833 : // Done for initial state splitting.
6834 0 : if ( !before ) return iMother;
6835 0 : else return iDaughter;
6836 :
6837 : }
6838 :
6839 : // Check for final state splittings with initial state recoiler.
6840 : // Consider a splitting to exist if both mother and daughter were found.
6841 : // Find new mother
6842 : iMother = 0;
6843 0 : for (int i =0; i < event.size(); ++i)
6844 0 : if ( abs(event[i].status()) == 53 || abs(event[i].status()) == 54) {
6845 : iMother = i;
6846 0 : break;
6847 : }
6848 : // Find daughter
6849 : int iDaughter = 0;
6850 0 : if (iMother > 0) iDaughter = event[iMother].daughter1();
6851 :
6852 : // Done if final state splitting has been found.
6853 0 : if (iDaughter > 0 && iMother > 0) {
6854 :
6855 : // Done for final state splitting.
6856 0 : if ( !before ) return iMother;
6857 0 : else return iDaughter;
6858 :
6859 : }
6860 :
6861 : // If no splitting has been found, return zero.
6862 0 : return 0;
6863 :
6864 0 : }
6865 :
6866 : //--------------------------------------------------------------------------
6867 :
6868 : // Function to give back the ratio of PDFs and PDF * splitting kernels needed
6869 : // to convert a splitting at scale pdfScale, chosen with running PDFs, to a
6870 : // splitting chosen with PDFs at a fixed scale mu. As needed to properly count
6871 : // emissions.
6872 :
6873 : double History::pdfFactor( const Event& event, const int type,
6874 : double pdfScale, double mu ) {
6875 :
6876 : double weight = 1.;
6877 :
6878 : // Final state splittings
6879 0 : if (type >= 3) {
6880 :
6881 : // Find new mother
6882 : int iMother = 0;
6883 0 : for (int i =0; i < event.size(); ++i)
6884 0 : if ( abs(event[i].status()) == 53 || abs(event[i].status()) == 54) {
6885 : iMother = i;
6886 0 : break;
6887 : }
6888 0 : int flavMother = event[iMother].id();
6889 :
6890 : // Done if no initial state recoiler was found
6891 0 : if ( iMother == 0 ) return 1.;
6892 :
6893 : // Find daughter
6894 0 : int iDaughter = event[iMother].daughter1();
6895 0 : int flavDaughter = event[iDaughter].id();
6896 :
6897 : // Find x values
6898 0 : double xMother = 2.*event[iMother].e() / event[0].e();
6899 0 : double xDaughter = 2.*event[iDaughter].e() / event[0].e();
6900 :
6901 : // Calculate PDF ratios
6902 :
6903 0 : int sideSplit = ( event[iMother].pz() > 0.) ? 1 : -1;
6904 : double pdfDen1, pdfDen2, pdfNum1, pdfNum2;
6905 : pdfDen1 = pdfDen2 = pdfNum1 = pdfNum2 = 1.;
6906 0 : if ( sideSplit == 1 ) {
6907 : // Find PDFs
6908 0 : pdfDen1 = max(1e-15,beamA.xfISR(0, flavDaughter, xDaughter, pow2(mu)) );
6909 0 : pdfNum1 = beamA.xfISR(0, flavDaughter, xDaughter, pow2(pdfScale) );
6910 0 : pdfNum2 = beamA.xfISR(0, flavMother, xMother, pow2(mu) );
6911 0 : pdfDen2 = max(1e-15,beamA.xfISR(0,flavMother, xMother, pow2(pdfScale)) );
6912 0 : } else {
6913 : // Find PDFs
6914 0 : pdfDen1 = max(1e-15,beamB.xfISR(0, flavDaughter, xDaughter, pow2(mu)) );
6915 0 : pdfNum1 = beamB.xfISR(0, flavDaughter, xDaughter, pow2(pdfScale) );
6916 0 : pdfNum2 = beamB.xfISR(0, flavMother, xMother, pow2(mu) );
6917 0 : pdfDen2 = max(1e-15,beamB.xfISR(0,flavMother, xMother, pow2(pdfScale)) );
6918 : }
6919 :
6920 : // The magnitude of the PDF ratio in FSR is limited to one. If that was
6921 : // the case, return one.
6922 0 : if ( pdfDen2/pdfNum1 > 1. ) return 1.;
6923 :
6924 : // Calculate PDF weight to reweight emission to emission evaluated at
6925 : // constant factorisation scale. No need to include the splitting kernel in
6926 : // the weight, since it will drop out anyway.
6927 0 : weight = (pdfNum1/pdfDen1) * (pdfNum2)/(pdfDen2);
6928 :
6929 : // Initial state splittings
6930 0 : } else if (type == 2) {
6931 :
6932 : // Find sister
6933 : int iSister = 0;
6934 0 : for (int i =0; i < event.size(); ++i)
6935 0 : if (event[i].status() == 43) {
6936 : iSister = i;
6937 0 : break;
6938 : }
6939 0 : int flavSister = event[iSister].id();
6940 :
6941 : // Find mother
6942 0 : int iMother = event[iSister].mother1();
6943 0 : int flavMother = event[iMother].id();
6944 :
6945 : // Find splitting flavour
6946 : int flavDaughter = 0;
6947 0 : if ( abs(flavMother) < 21 && flavSister == 21)
6948 0 : flavDaughter = flavMother;
6949 0 : else if ( flavMother == 21 && flavSister == 21)
6950 0 : flavDaughter = flavMother;
6951 0 : else if ( flavMother == 21 && abs(flavSister) < 21)
6952 0 : flavDaughter = -1*flavSister;
6953 0 : else if ( abs(flavMother) < 21 && abs(flavSister) < 21)
6954 0 : flavDaughter = 21;
6955 :
6956 : // Find x values
6957 0 : double xMother = 2.*event[iMother].e() / event[0].e();
6958 :
6959 : // Find initial state (!) daughter
6960 : int iDaughter = 0;
6961 0 : for (int i =0; i < event.size(); ++i)
6962 0 : if ( !event[i].isFinal()
6963 0 : && event[i].mother1() == iMother
6964 0 : && event[i].id() == flavDaughter )
6965 0 : iDaughter = i;
6966 0 : double xDaughter = 2.*event[iDaughter].e() / event[0].e();
6967 :
6968 : // Calculate PDF weight to reweight emission to emission evaluated at
6969 : // constant factorisation scale. No need to include the splitting kernel
6970 : // in the weight, since it will drop out anyway.
6971 0 : int sideSplit = ( event[iMother].pz() > 0.) ? 1 : -1;
6972 0 : double ratio1 = getPDFratio( sideSplit, false, false, flavDaughter,
6973 0 : xDaughter, pdfScale, flavDaughter, xDaughter, mu );
6974 0 : double ratio2 = getPDFratio( sideSplit, false, false, flavMother,
6975 0 : xMother, mu, flavMother, xMother, pdfScale );
6976 :
6977 0 : weight = ratio1*ratio2;
6978 :
6979 : // Do nothing for MPI
6980 0 : } else {
6981 : weight = 1.;
6982 : }
6983 :
6984 : // Done
6985 0 : return weight;
6986 0 : }
6987 :
6988 : //--------------------------------------------------------------------------
6989 :
6990 : // Function giving the product of splitting kernels and PDFs so that the
6991 : // resulting flavour is given by flav. This is used as a helper routine
6992 : // to dgauss
6993 :
6994 : double History::integrand(int flav, double x, double scaleInt, double z) {
6995 :
6996 : // Declare constants
6997 : double CF = 4./3.;
6998 : double TR = 1./2.;
6999 : double CA = 3.;
7000 :
7001 : double result = 0.;
7002 :
7003 : // Integrate NLL sudakov remainder
7004 0 : if (flav==0) {
7005 :
7006 0 : AlphaStrong* as = mergingHooksPtr->AlphaS_ISR();
7007 0 : double asNow = (*as).alphaS(z);
7008 0 : result = 1./z *asNow*asNow* ( log(scaleInt/z) -3./2. );
7009 :
7010 : // Integrand for PDF ratios. Careful about factors if 1/z, since formulae
7011 : // are expressed in terms if f(x,mu), while Pythia uses x*f(x,mu)!
7012 0 : } else if (flav==21) {
7013 :
7014 0 : double measure1 = 1./(1. - z);
7015 : double measure2 = 1.;
7016 :
7017 : double integrand1 =
7018 : 2.*CA
7019 0 : * z * beamB.xf( 21,x/z,pow(scaleInt,2))
7020 0 : / beamB.xf( 21,x, pow(scaleInt,2))
7021 0 : - 2.*CA;
7022 :
7023 : double integrand2 =
7024 : // G -> G terms
7025 0 : 2.*CA *((1. -z)/z + z*(1.-z))
7026 0 : * beamB.xf( 21,x/z,pow(scaleInt,2))
7027 0 : / beamB.xf( 21,x, pow(scaleInt,2))
7028 : // G -> Q terms
7029 0 : + CF * ((1+pow(1-z,2))/z)
7030 0 : *( beamB.xf( 1, x/z,pow(scaleInt,2))
7031 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7032 0 : + beamB.xf( -1, x/z,pow(scaleInt,2))
7033 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7034 0 : + beamB.xf( 2, x/z,pow(scaleInt,2))
7035 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7036 0 : + beamB.xf( -2, x/z,pow(scaleInt,2))
7037 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7038 0 : + beamB.xf( 3, x/z,pow(scaleInt,2))
7039 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7040 0 : + beamB.xf( -3, x/z,pow(scaleInt,2))
7041 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7042 0 : + beamB.xf( 4, x/z,pow(scaleInt,2))
7043 0 : / beamB.xf( 21, x, pow(scaleInt,2))
7044 0 : + beamB.xf( -4, x/z,pow(scaleInt,2))
7045 0 : / beamB.xf( 21, x, pow(scaleInt,2)) );
7046 :
7047 : // Done
7048 0 : result = integrand1*measure1 + integrand2*measure2;
7049 :
7050 0 : } else {
7051 :
7052 0 : double measure1 = 1./(1. -z);
7053 : double measure2 = 1.;
7054 :
7055 : // Q -> Q terms
7056 : double integrand1 =
7057 0 : CF * (1+pow(z,2))
7058 0 : * beamB.xf( flav, x/z, pow(scaleInt,2))
7059 0 : / beamB.xf( flav, x, pow(scaleInt,2))
7060 0 : - 2.*CF;
7061 :
7062 : // Q -> G terms
7063 : double integrand2 =
7064 0 : + TR * (pow(z,2) + pow(1-z,2))
7065 0 : * beamB.xf( 21, x/z, pow(scaleInt,2))
7066 0 : / beamB.xf( flav, x, pow(scaleInt,2));
7067 :
7068 : // Done
7069 0 : result = measure1*integrand1 + measure2*integrand2;
7070 : }
7071 :
7072 0 : return result;
7073 :
7074 : }
7075 :
7076 : //==========================================================================
7077 :
7078 : } // end namespace Pythia8
|