diff --git a/Contrib/AlpGen/AlpGenHandler.cc b/Contrib/AlpGen/AlpGenHandler.cc --- a/Contrib/AlpGen/AlpGenHandler.cc +++ b/Contrib/AlpGen/AlpGenHandler.cc @@ -1,1392 +1,1392 @@ #include "AlpGenHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" using namespace Herwig; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> inputIsNLO_ >> highestNLOMultiplicity_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV); } ClassDescription AlpGenHandler::initAlpGenHandler; // Definition of the static class description member. void AlpGenHandler::Init() { static ClassDocumentation documentation ("The AlpGenHandler class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &AlpGenHandler::alphaS_, false, false, true, false, false); static Parameter interfaceNoCellsInRapidity ("NoCellsInRapidity", "The number of cells spanning the rapidity interval of " "the calorimeter", &AlpGenHandler::ncy_, 100, 1, 10000, false, false, Interface::limited); static Parameter interfaceNoCellsInPhi ("NoCellsInPhi", "The number of cells spanning the phi interval of " "the calorimeter", &AlpGenHandler::ncphi_, 60, 1, 10000, false, false, Interface::limited); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &AlpGenHandler::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &AlpGenHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &AlpGenHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &AlpGenHandler::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &AlpGenHandler::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &AlpGenHandler::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The AlpGen hard process code", &AlpGenHandler::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjets ("njets", "The number of light jets in the AlpGen process (i.e. the " "extra ones)", &AlpGenHandler::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &AlpGenHandler::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandler::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfacehighestNLOMultiplicity ("highestNLOMultiplicity", "If true it indicates that this is the highest NLO multiplicity input " "ME-level configuration to be processed.", &AlpGenHandler::highestNLOMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &AlpGenHandler::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &AlpGenHandler::jetAlgorithm_, 2, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static SwitchOption GetJet (interfaceJetAlgorithm, "GetJet", "Calorimeter-based GetJet algorithm (default).", 2); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &AlpGenHandler::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceInputIsNLO ("InputIsNLO", "Signals whether the input LH file is tree-level accurate " "or contains NLO (Powheg) events.", &AlpGenHandler::inputIsNLO_, false, false, false); static SwitchOption InputIsNotNLO (interfaceInputIsNLO, "InputIsNotNLO", "The input LH events have tree-level accuracy.", false); static SwitchOption InputIsNLO (interfaceInputIsNLO, "InputIsNLO", "The input LH events have NLO accuracy.", true); } void AlpGenHandler::dofinish() { ShowerHandler::dofinish(); } void AlpGenHandler::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999) { cout << "Error: AlpGenHandler:ihrd not set!" << endl; exit(1); } ShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; // Initialise calorimeter. calini_m(); } // Throws a veto according to MLM strategy ... when we finish writing it. bool AlpGenHandler::showerHardProcessVeto() const { if(vetoIsTurnedOff_) return false; // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "AlpGenHandler::showerHardProcessVeto() - warning." << "MLM merging not implemented for AlpGen " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. doSanityChecks(0); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // <--- TO DO: add remnants in here ??? // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. caldel_m(); double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } if(jetAlgorithm_==2) { // If using GetJet fill the calorimeter cells now from particlesToCluster_ calsim_m(); // Make jets from the calorimeter blobs. getjet_m(rclus_,etclus_,etaclmax_); } else { // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); } // If there are less jets than partons then parton-jet matching is // bound to fail: reject the event already. Also, if the input is // an NLO event file it will 99.5% of the time contain a number of // light partons in the F.S. equal to that in the real emission // process in the NLO calculation, moreover, it has already // effectively merged njets_-1 and njets jet events. So in that // case we do not reject events on the grounds they have jet // multiplicity less than partonsToMatch_.size() but rather less // jets than partonsToMatch.size()-1; such events are better // described by the lower-by-one-unit (partonsToMatch_.size()-1) // of multiplicity NLO event file, or the lower-by-two-units // (partonsToMatch_.size()-2) of multiplicity LO event file. // If it is not jet production apply rejection criterion as above. if(ihrd_!=9) { if(!inputIsNLO_) { if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(pjet_.size() < partonsToMatch_.size()-1) return true; } // Otherwise, in the case of jet production allow the lowest // contributing multiplicity process (just at NLO), namely, // dijet production, to give rise to 1-jet and even 0-jet // events, since these can contribute to, for example, the // inclusive jet cross section i.e. in this case the rejection // is only applied in the case of the next-to-lowest multiplicity // processes (>2 parton events at LO and >3 parton events at NLO). } else { if(!inputIsNLO_) { // KH - March 5th // Removed the following line giving special treatment // also to the LO events, to maintain consistency with // the fortran algorithm, at least for now. So now jet // production at LO is being treated the same as all // other processes. // if(partonsToMatch_.size()==2 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(partonsToMatch_.size()<=3 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()-1) return true; } } // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Match light progenitors to jets. vector jetToPartonMap(pjet_.size(),-999); Energy etmin(777e100*GeV); // If the input is NLO events then don't do any jet-parton matching! if(!inputIsNLO_) { // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]partonsToMatch_.size() && !inputIsNLO_) return true; if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(highestMultiplicity_ && !inputIsNLO_ ) { for(unsigned int ixx=0; ixxid())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } } } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double AlpGenHandler::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) const { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Initialize calorimeter for calsim_m and getjet_m. Note that // because initialization is separte calsim_m can be called more // than once to simulate pileup of several events. void AlpGenHandler::calini_m() const { // Making sure arrays are clear before filling; cphcal_.clear(); sphcal_.clear(); cthcal_.clear(); sthcal_.clear(); // Fill array holding phi values of calorimeter cell centres. double deltaPhi(2*M_PI/ncphi_); for(unsigned int iphi=1; iphi<=ncphi_; iphi++) { double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi). cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi). sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi). } // Fill array holding theta values of calorimeter cell centres in Y. double deltaY((ycmax_-ycmin_)/double(ncy_)); for(unsigned int iy=1; iy<=ncy_; iy++) { double Y(deltaY*(iy-0.5)+ycmin_); double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy). cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy). sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy). } return; } // Get FastJets void AlpGenHandler::getFastJets(double rjet, Energy ejcut, double etajcut) const { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it goes in the calorimeter. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().x()/GeV)); if(phi<0) phi+=2*M_PI; unsigned int iy(int((y-ycmin_)/dely_)); unsigned int iphi(int(phi/delphi_)); et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy]; } } } return; } // Find highest remaining cell > etstop and sum surrounding cells // with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets // with ET>ejcut and abs(eta)=etstop) { // Find the cell with the highest ET from // those not already assigned to a jet. etmax=0*GeV; int iymx(0), iphimx(0); for(unsigned int iphi=0; iphietmax&&jetIdx_[iy][iphi]<0) { etmax = et_[iy][iphi]; iymx = iy; iphimx = iphi; } // If the remaining cell with the highest ET has ET < etstop, stop. if(etmax(ncy_*ncphi_)) { cout << "AlpGenHandler::getjet_m() - Fatal error." << endl; cout << "We found " << ipass << " calo cells with the highest ET so" << "far\nbut the calorimeter only has " << ncy_*ncphi_ << " " << "cells in it!" << endl; exit(10); } // Add a jet vector (may get deleted if jet fails ET / eta cuts). etjet_.push_back(0*GeV); pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV)); // Loop over all calo cells in range iphimx +/- nphi1 (inclusive) // wrapping round in azimuth if required. for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) { int iphix(iphimx-nphi1+iphi1); if(iphix<0) iphix += ncphi_; if(iphix>=int(ncphi_)) iphix -= ncphi_; // Loop over all calo cells in range iymx +/- ny1 (inclusive). for(unsigned int iy1=0; iy1<=2*ny1; iy1++) { int iyx(iymx-ny1+iy1); // If the cell is outside the calorimeter OR if it was already // associated to a jet then skip to the next loop. if(iyx>=0&&iyx=eccut) { Energy ECell(et_[iyx][iphix]/sthcal_[iyx]); pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px ECell*sthcal_[iyx]*sphcal_[iphix], // py ECell*cthcal_[iyx],ECell); // pz, E. // N.B. This is the same reln as in ThePEG between phi and x,y. etjet_.back()+=et_[iyx][iphix]; jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet. } } } } // Compute the current jet's mass. pjet_.back().rescaleMass(); // Throw the jet away if it's ET is less than ejcut. if(etjet_.back()etajcut) { pjet_.pop_back(); etjet_.pop_back(); } } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void AlpGenHandler::caldel_m() const { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); for(unsigned int ixx=0; ixxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparticlesToCluster_.size()) { throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } // Acid test. unsigned int tmpUnsignedInt(njets_); if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) { for(unsigned int ixx=0; ixxid())>=6&& abs(partonsToMatch_[ixx]->id())!=21) throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "Found a parton to match to which is not a quark or gluon!" << *partonsToMatch_[ixx] << "\n" << Exception::eventerror; } throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of light jets (njets) in AlpGen process = " << njets_ << "\n" << "These should be equal." << "\n" << Exception::eventerror; } return; } // This looks for all descendents of a top up to but not including // the W and b children. void AlpGenHandler::getTopRadiation(PPtr theParticle) const { ParticleVector theChildren(theParticle->children()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24) return; else getTopRadiation(theChildren[ixx]); return; } void AlpGenHandler::caldel_hvq() const { // Fill partonsToMatch_ with only those pre-shower partons intended to // be used in heavy-quark-jet matching and fill particlesToCluster_ using // only those final state particles (post-shower) which are supposed // in the heavy-quark-jet clustering used to do merging. To begin with // these are made from the corresponding sets of particles that were // omitted from the initial jet-parton matching run. partonsToMatch_ = preshowerFSPsToDelete_; particlesToCluster_.resize(showeredFSPsToDelete_.size()); for(unsigned int ixx=0; ixxid())<4||abs(partonsToMatch_[ixx]->id())>6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxid())==5&& partonsToMatch_[ixx]->parents().size()>0&& abs(partonsToMatch_[ixx]->parents()[0]->id())==6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxparents().size()>0&& (abs(partonsToMatch_[ixx]->parents()[0]->id())==23|| abs(partonsToMatch_[ixx]->parents()[0]->id())==24|| abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->intermediates()); for(unsigned int ixx=0; ixxid())==6) { partonsToMatch_.push_back(intermediates[ixx]); tmpList_.clear(); getTopRadiation(partonsToMatch_.back()); for(unsigned int jxx=0; jxxid())>=4&&abs(partonsToMatch_[ixx]->id())<=6) { theProgenitor = partonsToMatch_[ixx]; // Follow the heavy quark line down to where it stops branching. while(theProgenitor->children().size()>0) { theLastProgenitor = theProgenitor; for(unsigned int jxx=0; jxxchildren().size(); jxx++) { if(theProgenitor->children()[jxx]->id()==theProgenitor->id()) theProgenitor=theProgenitor->children()[jxx]; } // If the progenitor had children but none of them had // the same particle id as it, then it must have undergone // a decay rather than a branching, i.e. it is the end of // the evolution line, so, if(theProgenitor==theLastProgenitor) break; } evolvedHeavyQuarks.push_back(theProgenitor); } } // Now delete the evolved heavy quark from the particlesToCluster. for(unsigned int ixx=0; ixxsubProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void AlpGenHandler::getShoweredParticles() const { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void AlpGenHandler::doSanityChecks(int debugLevel) const { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "AlpGenHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "AlpGenHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void AlpGenHandler::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" #include using namespace Herwig; using namespace ThePEG; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> vetoSoftThanMatched_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV) >> vetoHeavyQ_ >> mergemode_ >> hpdetect_ >> vetoHeavyFlavour_; } ClassDescription FxFxHandler::initFxFxHandler; // Definition of the static class description member. void FxFxHandler::Init() { static ClassDocumentation documentation ("The FxFxHandler class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &FxFxHandler::alphaS_, false, false, true, false, false); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &FxFxHandler::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &FxFxHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &FxFxHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &FxFxHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &FxFxHandler::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &FxFxHandler::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &FxFxHandler::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The hard process code", &FxFxHandler::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjetsmax ("njetsmax", "The number of light jets in the maximum-multiplicity process", &FxFxHandler::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &FxFxHandler::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &FxFxHandler::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &FxFxHandler::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &FxFxHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &FxFxHandler::jetAlgorithm_, 1, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static Switch interfaceMergeMode ("MergeMode", "The choice of merging mode", &FxFxHandler::mergemode_, 0, false, false); static SwitchOption FxFx (interfaceMergeMode, "FxFx", "FxFx merging.", 0); static SwitchOption Tree (interfaceMergeMode, "Tree", "Tree-level merging.", 1); static SwitchOption TreeMG (interfaceMergeMode, "TreeMG5", "Tree-level merging using the MadGraph pt clustering information.", 2); static Switch interfaceHardProcessDetection ("HardProcessDetection", "The choice of merging mode", &FxFxHandler::hpdetect_, true, false, false); static SwitchOption Automatic (interfaceHardProcessDetection, "Automatic", "Automatically determine which particles to include in the merging.", true); static SwitchOption Manual (interfaceHardProcessDetection, "Manual", "Use the ihrd code to determine which particles to include in the merging.", false); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &FxFxHandler::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceVetoHeavyFlavour ("VetoHeavyFlavour", "Allows the heavy flavour vetoing mechanism to be switched off.", &FxFxHandler::vetoHeavyFlavour_, false, false, false); static SwitchOption HeavyFVetoingIsOn (interfaceVetoHeavyFlavour, "Yes", "The MLM merging veto mechanism for heavy flavour is switched ON.", true); static SwitchOption HeavyFVetoingIsOff (interfaceVetoHeavyFlavour, "No", "The MLM merging veto mechanism for heavy flavour is switched OFF.", false); static Switch interfaceHeavyQVeto ("HeavyQVeto", "Allows the vetoing mechanism on the heavy quark products to be switched off.", &FxFxHandler::vetoHeavyQ_, false, false, false); static SwitchOption HQVetoingIsOn (interfaceHeavyQVeto, "Yes", "The MLM merging veto on Heavy quark decay produts mechanism is switched ON.", true); static SwitchOption HQVetoingIsOff (interfaceHeavyQVeto, "No", "The MLM merging veto on Heavy quark decay products mechanism is switched OFF.", false); static Switch interfaceVetoSoftThanMatched ("VetoSoftThanMatched", "Allows the vetoing mechanism to be switched off.", &FxFxHandler::vetoSoftThanMatched_, false, false, false); static SwitchOption VetoSoftIsOn (interfaceVetoSoftThanMatched, "VetoSoftIsOn", "The vetoing of highest-mult. events with jets softer than matched ones is ON", true); static SwitchOption VetoSoftIsOff (interfaceVetoSoftThanMatched, "VetoSoftIsOff", "The vetoing of highest-mult. events with jets softer than matched ones is OFF.", false); } void FxFxHandler::dofinish() { QTildeShowerHandler::dofinish(); } void FxFxHandler::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999 && !hpdetect_) { cout << "Error: FxFxHandler:ihrd not set and FxFx:HardProcessDetection set to Manual!" << endl; exit(1); } QTildeShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; } // Throws a veto according to MLM strategy ... when we finish writing it. bool FxFxHandler::showerHardProcessVeto() const { int debug_mode = 0; if(vetoIsTurnedOff_) { // cout << "Vetoing is turned OFF." << endl; return false; } //if(debug_mode) { cout << "debug_mode = " << 5 << endl; } // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "FxFxHandler::showerHardProcessVeto() - warning." << "MLM merging not implemented " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. doSanityChecks(debug_mode); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. if(mergemode_ == 0 || mergemode_ == 1) { caldel_m(); } else if(mergemode_ == 2) { caldel_mg(); } double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); if(mergemode_ == 0) { // Get npLO_ and npNLO_ for FxFx matching getnpFxFx(); // print the npXLO_ values obtained // cout << "HANDLER:\t\t\t\t" << npLO_ << "\t\t" << npNLO_ << endl; //FxFx modifications start here. // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Count the number of jets. int njets_found(pjet_.size()); // If the number of jets found is not equal to the number of partons in the Born // (i.e., the number of partons in the S-event, or one less than the number of partons in an H-event), // the jets cannot be matched and the event has to be rejected. The number of partons in the Born is written in the event file with a name “npNLO” // if there are no jets to match and no jets have been found, do not veto. if(njets_found == 0 && npNLO_ == 0) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", accepting" << endl;*/ return false; } //if the number of jets is smaller than npNLO -> reject the event. if(njets_found < npNLO_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; } // For the maximum-multiplicity sample, the number of jets obtained does not have to be exactly equal to npNLO, it may also be larger; if(njets_found > npNLO_ && npNLO_ != njets_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; } // Create the matrix-element jets. // Cluster also the partons at the hard-matrix element level into jets with the same algorithm as above, // but without the requirement of a minimal pT on the jets (or set it very small). // By construction, for S-events you should find exactly npNLO jets, while for the H-events it is either npNLO or npNLO+1. // Cluster partonsToMatch_ into jets with FastJet. getFastJetsToMatch(rclus_,0*GeV,etaclmax_); int me_njets_found(pjetME_.size()); // cout << "number of ME jets found = " << me_njets_found << "partons to match: " << partonsToMatch_.size() << endl; // Match light progenitors to jets. vector jetToPartonMap(pjetME_.size(),-999); Energy etmin(777e100*GeV); // Match the jets. // Try to match the “npNLO” hardest jets created post-shower with any of the jets pre-shower. Two jets are matched if the distance between them is smaller than 1.5*DeltaR. // If not all the npNLO hardest shower jets are matched the event has to be rejected. // Note that if the current event does not belong to the maximum multiplicity sample, this means that all the shower jets need to be matched, because the requirement above already rejects // events that do not have npNLO shower jets. // For those events, at the level of the matrix elements there can either be npNLO or npNLO+1 matrix-element jets, depending on S- or H-events and the kinematics of those partons. // Still only the shower jets need to be matched, so an event should not be rejected if a matrix-element jet cannot be matched. // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]id())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])id())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } } } } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double FxFxHandler::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) const { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } double FxFxHandler::partonJetDeltaR(LorentzMomentum jetmom1, LorentzMomentum jetmom2) const { // Calculate DY, DPhi and then DR double DY(jetmom1.eta()-jetmom2.eta()); double DPhi(jetmom1.phi()-jetmom2.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Get FastJets void FxFxHandler::getFastJets(double rjet, Energy ejcut, double etajcut) const { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixx particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(partonsToMatch_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(partonsToMatch_[ipar]->momentum().x()/GeV, partonsToMatch_[ipar]->momentum().y()/GeV, partonsToMatch_[ipar]->momentum().z()/GeV, partonsToMatch_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjetME_.clear(); pjetME_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void FxFxHandler::caldel_m() const { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); hvqfound = false; if(hpdetect_ && mergemode_!=2) { for(unsigned int ixx=0; ixxparents()[0]->id())==6) { hvqfound = true; // cout << "preshowerFSPs_[ixx]->id() = " << preshowerFSPs_[ixx]->id() << " " << preshowerFSPs_[ixx]->momentum().perp2() << endl; preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid() = " << tmpList_[jxx]->id() << " " << tmpList_[jxx]->momentum().perp2() << endl; showeredFSPsToDelete_.push_back(tmpList_[jxx]); } continue; } /* Exclude the v.bosons and any children they may have produced from the jet parton matching. */ if( (abs(preshowerFSPs_[ixx]->parents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25|| (abs(preshowerFSPs_[ixx]->id()) < 17 && abs(preshowerFSPs_[ixx]->id()) > 10)) && (abs(preshowerFSPs_[ixx]->parents()[0]->id())!=6)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==5&&ixx<2) { hvqfound = true; preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { // cout << "preshowerFSPs_[ixx]->id() = " << preshowerFSPs_[ixx]->id() << " " << preshowerFSPs_[ixx]->momentum().perp2() << endl; preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid() = " << tmpList_[jxx]->id() << " " << tmpList_[jxx]->momentum().perp2() << endl; showeredFSPsToDelete_.push_back(tmpList_[jxx]); } } if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=6) { throw Exception() << "FxFxHandler::caldel_m() - ERROR!\n" << "2Q process should have 6 particles to omit from" << "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror; } } else { if(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid() << " with parent " << preshowerFSPsToDelete_[ixx]->parents()[0]->id() << endl; // " energy = " << preshowerFSPsToDelete_[ixx]->momentum().e()*GeV << endl; partonsToMatch_.erase(partonsToMatch_.begin()+jxx); break; } } } //cout << "partonsToMatch_.size() (AFTER) = " << partonsToMatch_.size() << endl; //cout << "deleting showeredFSPs" << endl; for(unsigned int ixx=0; ixxid() << " with parent " << showeredFSPsToDelete_[ixx]->parents()[0]->id() << endl; //" energy = " << preshowerFSPsToDelete_[ixx]->momentum().e()*GeV << endl; particlesToCluster_.erase(particlesToCluster_.begin()+jxx); break; } } } // Sanity check! if(partonsToMatch_.size()>particlesToCluster_.size()) { throw Exception() << "FxFxHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } // cout << "partonsToMatch_.size() (AFTER2) = " << partonsToMatch_.size() << endl; // Acid test. /* unsigned int tmpUnsignedInt(njets_); if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) { for(unsigned int ixx=0; ixxid())>=6&& abs(partonsToMatch_[ixx]->id())!=21) throw Exception() << "FxFxHandler::caldel_m() - ERROR!\n" << "Found a parton to match to which is not a quark or gluon!" << *partonsToMatch_[ixx] << "\n" << Exception::eventerror; } throw Exception() << "FxFxHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of light jets (njets) in AlpGen process = " << njets_ << "\n" << "These should be equal." << "\n" << Exception::eventerror; } */ //cout << "partonsToMatch_.size() (AFTER3) = " << partonsToMatch_.size() << endl; return; } // This looks for all descendents of a top up to but not including // the W and b children. void FxFxHandler::getTopRadiation(PPtr theParticle) const { ParticleVector theChildren(theParticle->children()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24) return; else getTopRadiation(theChildren[ixx]); return; } void FxFxHandler::caldel_mg() const { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); /* * Get the MadGraph clustering information * from the Les Houches event tags */ ptclust_.clear(); getptclust(); //for(unsigned int izz = 0; izzid() << endl; partonsToMatch_.erase(partonsToMatch_.begin()+jxx); break; } } } for(unsigned int ixx=0; ixxid() << " with parent " << showeredFSPsToDelete_[ixx]->parents()[0]->id() << endl; //" energy = " << preshowerFSPsToDelete_[ixx]->momentum().e()*GeV << endl; particlesToCluster_.erase(particlesToCluster_.begin()+jxx); break; } } } // Sanity check! if(partonsToMatch_.size()>particlesToCluster_.size()) { throw Exception() << "FxFxHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } } void FxFxHandler::caldel_hvq() const { // Fill partonsToMatch_ with only those pre-shower partons intended to // be used in heavy-quark-jet matching and fill particlesToCluster_ using // only those final state particles (post-shower) which are supposed // in the heavy-quark-jet clustering used to do merging. To begin with // these are made from the corresponding sets of particles that were // omitted from the initial jet-parton matching run. partonsToMatch_ = preshowerFSPsToDelete_; particlesToCluster_.resize(showeredFSPsToDelete_.size()); for(unsigned int ixx=0; ixxid())<4||abs(partonsToMatch_[ixx]->id())>6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxid())==5&& partonsToMatch_[ixx]->parents().size()>0&& abs(partonsToMatch_[ixx]->parents()[0]->id())==6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxparents().size()>0&& (abs(partonsToMatch_[ixx]->parents()[0]->id())==23|| abs(partonsToMatch_[ixx]->parents()[0]->id())==24|| abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->intermediates()); for(unsigned int ixx=0; ixxid())==6) { partonsToMatch_.push_back(intermediates[ixx]); tmpList_.clear(); getTopRadiation(partonsToMatch_.back()); for(unsigned int jxx=0; jxxid())>=4&&abs(partonsToMatch_[ixx]->id())<=6) { theProgenitor = partonsToMatch_[ixx]; // Follow the heavy quark line down to where it stops branching. while(theProgenitor->children().size()>0) { theLastProgenitor = theProgenitor; for(unsigned int jxx=0; jxxchildren().size(); jxx++) { if(theProgenitor->children()[jxx]->id()==theProgenitor->id()) theProgenitor=theProgenitor->children()[jxx]; } // If the progenitor had children but none of them had // the same particle id as it, then it must have undergone // a decay rather than a branching, i.e. it is the end of // the evolution line, so, if(theProgenitor==theLastProgenitor) break; } evolvedHeavyQuarks.push_back(theProgenitor); } } // Now delete the evolved heavy quark from the particlesToCluster. for(unsigned int ixx=0; ixx optionalEventWeights = eventHandler()->currentEvent()->optionalWeights(); // loop over the optional weights and find np values for (map::const_iterator it=optionalEventWeights.begin(); it!=optionalEventWeights.end(); ++it){ // split the line boost::split( SplitVec, it->first, boost::is_any_of(" ") ); // if np is found, store the information if(SplitVec[0] == "np") { npLO_ = atof(SplitVec[1].c_str()); npNLO_ = atof(SplitVec[2].c_str()); } } return; } // get hadron COM energy void FxFxHandler::getECOM() const { split_vector_type SplitVec; // pull the optional weights from the current event map optionalEventWeights = eventHandler()->currentEvent()->optionalWeights(); // loop over the optional weights and find np values for (map::const_iterator it=optionalEventWeights.begin(); it!=optionalEventWeights.end(); ++it){ // split the line boost::split( SplitVec, it->first, boost::is_any_of(" ") ); // if np is found, store the information if(SplitVec[0] == "ecom") { ECOM_ = it->second; } } return; } // get pt_clust information void FxFxHandler::getptclust() const { split_vector_type SplitVec; // pull the optional weights from the current event map optionalEventWeights = eventHandler()->currentEvent()->optionalWeights(); // loop over the optional weights and find np values string str_eq = "="; string str_quote = "\""; int countptc_(0); for (map::const_iterator it=optionalEventWeights.begin(); it!=optionalEventWeights.end(); ++it){ // split the line double wgtid = it->second; //cout << "wgtdid = " << wgtid << endl; if(wgtid == -333) { // cout << "it->first for -333 = " << it->first << endl; boost::split( SplitVec, it->first, boost::is_any_of(" ") ); // if np is found, store the information double ptclust(0.); string stringtohandle(""); for(unsigned int i_ = 0; i_ < SplitVec.size(); ++i_) { if(SplitVec[i_].find("pt_clust_") != std::string::npos) { //cout << "pt_clust_ found in " << SplitVec[i_] << endl; countptc_++; // cout << "SplitVec[i_] = " << SplitVec[i_] << endl; stringtohandle = SplitVec[i_]; stringtohandle.erase(0,10); erase_substr(stringtohandle,str_eq); erase_substr(stringtohandle,str_quote); // cout << "stringtohandle = " << stringtohandle << endl; ptclust = atof(stringtohandle.c_str()); ptclust_.push_back(ptclust); } } } } return; } void FxFxHandler::getPreshowerParticles() const { // LH file initial-state partons: preshowerISPs_ = lastXCombPtr()->subProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void FxFxHandler::getShoweredParticles() const { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void FxFxHandler::doSanityChecks(int debugLevel) const { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "FxFxHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "FxFxHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void FxFxHandler::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" using namespace Herwig; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> highestNjets_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> vetoType_ >> inputIsNLO_ >> highestNLOMultiplicity_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV) >> smoothingtype_; } ClassDescription AlpGenHandlerOL::initAlpGenHandlerOL; // Definition of the static class description member. void AlpGenHandlerOL::Init() { static ClassDocumentation documentation ("The AlpGenHandlerOL class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &AlpGenHandlerOL::alphaS_, false, false, true, false, false); static Parameter interfaceNoCellsInRapidity ("NoCellsInRapidity", "The number of cells spanning the rapidity interval of " "the calorimeter", &AlpGenHandlerOL::ncy_, 100, 1, 10000, false, false, Interface::limited); static Parameter interfaceNoCellsInPhi ("NoCellsInPhi", "The number of cells spanning the phi interval of " "the calorimeter", &AlpGenHandlerOL::ncphi_, 60, 1, 10000, false, false, Interface::limited); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &AlpGenHandlerOL::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &AlpGenHandlerOL::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &AlpGenHandlerOL::nh_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandlerOL::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &AlpGenHandlerOL::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &AlpGenHandlerOL::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &AlpGenHandlerOL::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The AlpGen hard process code", &AlpGenHandlerOL::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjets ("njets", "The number of light jets in the AlpGen process (i.e. the " "extra ones)", &AlpGenHandlerOL::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &AlpGenHandlerOL::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfacehighestNjets ("highestNjets", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestNjets_, 1, 0, 100, false, false, Interface::limited); static Parameter interfacehighestNLOMultiplicity ("highestNLOMultiplicity", "If true it indicates that this is the highest NLO multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestNLOMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &AlpGenHandlerOL::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandlerOL::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceSmoothingType ("SmoothingType", "Determines the kind of smoothing to use ", &AlpGenHandlerOL::smoothingtype_, 0, false, false); static SwitchOption Sine (interfaceSmoothingType, "Sine", "Sinusoidal smoothing.", 0); static SwitchOption Unifnorm (interfaceSmoothingType, "Uniform", "Uniform smoothing.", 1); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &AlpGenHandlerOL::jetAlgorithm_, 2, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static SwitchOption GetJet (interfaceJetAlgorithm, "GetJet", "Calorimeter-based GetJet algorithm (default).", 2); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &AlpGenHandlerOL::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceVetoType ("VetoType", "Allows choosing betwewen the original vetoing mechanism and the one used for OL.", &AlpGenHandlerOL::vetoType_, 1, false, false); static SwitchOption Original (interfaceVetoType, "Original", "The MLM merging veto mechanism in the original form.", 0); static SwitchOption OpenLoops (interfaceVetoType, "OpenLoops", "The MLM merging veto meechanism in the OpenLoops implementation.", 1); static Switch interfaceInputIsNLO ("InputIsNLO", "Signals whether the input LH file is tree-level accurate " "or contains NLO (Powheg) events.", &AlpGenHandlerOL::inputIsNLO_, false, false, false); static SwitchOption InputIsNotNLO (interfaceInputIsNLO, "InputIsNotNLO", "The input LH events have tree-level accuracy.", false); static SwitchOption InputIsNLO (interfaceInputIsNLO, "InputIsNLO", "The input LH events have NLO accuracy.", true); } void AlpGenHandlerOL::dofinish() { ShowerHandler::dofinish(); } void AlpGenHandlerOL::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999) { cout << "Error: AlpGenHandlerOL:ihrd not set!" << endl; exit(1); } ShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; // Initialise calorimeter. calini_m(); } // Throws a veto according to MLM strategy ... when we finish writing it. bool AlpGenHandlerOL::showerHardProcessVeto() const { if(vetoIsTurnedOff_) return false; // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "AlpGenHandlerOL::showerHardProcessVeto() - warning." << "MLM merging not implemented for AlpGen " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. doSanityChecks(0); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // <--- TO DO: add remnants in here ??? // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. caldel_m(); double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } if(jetAlgorithm_==2) { // If using GetJet fill the calorimeter cells now from particlesToCluster_ calsim_m(); // Make jets from the calorimeter blobs. getjet_m(rclus_,etclus_,etaclmax_); } else { // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); } // If there are less jets than partons then parton-jet matching is // bound to fail: reject the event already. Also, if the input is // an NLO event file it will 99.5% of the time contain a number of // light partons in the F.S. equal to that in the real emission // process in the NLO calculation, moreover, it has already // effectively merged njets_-1 and njets jet events. So in that // case we do not reject events on the grounds they have jet // multiplicity less than partonsToMatch_.size() but rather less // jets than partonsToMatch.size()-1; such events are better // described by the lower-by-one-unit (partonsToMatch_.size()-1) // of multiplicity NLO event file, or the lower-by-two-units // (partonsToMatch_.size()-2) of multiplicity LO event file. // If it is not jet production apply rejection criterion as above. if(ihrd_!=9) { if(!inputIsNLO_) { if(pjet_.size() < partonsToMatch_.size()) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } } else { if(pjet_.size() < partonsToMatch_.size()-1) return true; } // Otherwise, in the case of jet production allow the lowest // contributing multiplicity process (just at NLO), namely, // dijet production, to give rise to 1-jet and even 0-jet // events, since these can contribute to, for example, the // inclusive jet cross section i.e. in this case the rejection // is only applied in the case of the next-to-lowest multiplicity // processes (>2 parton events at LO and >3 parton events at NLO). } else { if(!inputIsNLO_) { // KH - March 5th // Removed the following line giving special treatment // also to the LO events, to maintain consistency with // the fortran algorithm, at least for now. So now jet // production at LO is being treated the same as all // other processes. // if(partonsToMatch_.size()==2 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(partonsToMatch_.size()<=3 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()-1) return true; } } // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Match light progenitors to jets. vector jetToPartonMap(pjet_.size(),-999); Energy etmin(777e100*GeV); // If the input is NLO events then don't do any jet-parton matching! if(!inputIsNLO_) { // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]partonsToMatch_.size() && !inputIsNLO_) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(highestMultiplicity_ && !inputIsNLO_ ) { for(unsigned int ixx=0; ixxpartonsToMatch_.size() if(partonsToMatch_.size()partonsToMatch_.size() && !inputIsNLO_) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(partonsToMatch_.size()partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(partonsToMatch_.size()==highestNjets_ && !inputIsNLO_ ) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; for(unsigned int ixx=0; ixxid())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } } } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double AlpGenHandlerOL::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) const { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Initialize calorimeter for calsim_m and getjet_m. Note that // because initialization is separte calsim_m can be called more // than once to simulate pileup of several events. void AlpGenHandlerOL::calini_m() const { // Making sure arrays are clear before filling; cphcal_.clear(); sphcal_.clear(); cthcal_.clear(); sthcal_.clear(); // Fill array holding phi values of calorimeter cell centres. double deltaPhi(2*M_PI/ncphi_); for(unsigned int iphi=1; iphi<=ncphi_; iphi++) { double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi). cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi). sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi). } // Fill array holding theta values of calorimeter cell centres in Y. double deltaY((ycmax_-ycmin_)/double(ncy_)); for(unsigned int iy=1; iy<=ncy_; iy++) { double Y(deltaY*(iy-0.5)+ycmin_); double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy). cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy). sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy). } return; } // Get FastJets void AlpGenHandlerOL::getFastJets(double rjet, Energy ejcut, double etajcut) const { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it goes in the calorimeter. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().x()/GeV)); if(phi<0) phi+=2*M_PI; unsigned int iy(int((y-ycmin_)/dely_)); unsigned int iphi(int(phi/delphi_)); et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy]; } } } return; } // Find highest remaining cell > etstop and sum surrounding cells // with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets // with ET>ejcut and abs(eta)=etstop) { // Find the cell with the highest ET from // those not already assigned to a jet. etmax=0*GeV; int iymx(0), iphimx(0); for(unsigned int iphi=0; iphietmax&&jetIdx_[iy][iphi]<0) { etmax = et_[iy][iphi]; iymx = iy; iphimx = iphi; } // If the remaining cell with the highest ET has ET < etstop, stop. if(etmax(ncy_*ncphi_)) { cout << "AlpGenHandlerOL::getjet_m() - Fatal error." << endl; cout << "We found " << ipass << " calo cells with the highest ET so" << "far\nbut the calorimeter only has " << ncy_*ncphi_ << " " << "cells in it!" << endl; exit(10); } // Add a jet vector (may get deleted if jet fails ET / eta cuts). etjet_.push_back(0*GeV); pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV)); // Loop over all calo cells in range iphimx +/- nphi1 (inclusive) // wrapping round in azimuth if required. for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) { int iphix(iphimx-nphi1+iphi1); if(iphix<0) iphix += ncphi_; if(iphix>=int(ncphi_)) iphix -= ncphi_; // Loop over all calo cells in range iymx +/- ny1 (inclusive). for(unsigned int iy1=0; iy1<=2*ny1; iy1++) { int iyx(iymx-ny1+iy1); // If the cell is outside the calorimeter OR if it was already // associated to a jet then skip to the next loop. if(iyx>=0&&iyx=eccut) { Energy ECell(et_[iyx][iphix]/sthcal_[iyx]); pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px ECell*sthcal_[iyx]*sphcal_[iphix], // py ECell*cthcal_[iyx],ECell); // pz, E. // N.B. This is the same reln as in ThePEG between phi and x,y. etjet_.back()+=et_[iyx][iphix]; jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet. } } } } // Compute the current jet's mass. pjet_.back().rescaleMass(); // Throw the jet away if it's ET is less than ejcut. if(etjet_.back()etajcut) { pjet_.pop_back(); etjet_.pop_back(); } } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void AlpGenHandlerOL::caldel_m() const { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); for(unsigned int ixx=0; ixxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparticlesToCluster_.size()) { throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } // Acid test. unsigned int tmpUnsignedInt(njets_); if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) { for(unsigned int ixx=0; ixxid())>=6&& abs(partonsToMatch_[ixx]->id())!=21) throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "Found a parton to match to which is not a quark or gluon!" << *partonsToMatch_[ixx] << "\n" << Exception::eventerror; } if(vetoType_==0) { throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of light jets (njets) in AlpGen process = " << njets_ << "\n" << "These should be equal." << "\n" << Exception::eventerror; } } return; } // This looks for all descendents of a top up to but not including // the W and b children. void AlpGenHandlerOL::getTopRadiation(PPtr theParticle) const { ParticleVector theChildren(theParticle->children()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24) return; else getTopRadiation(theChildren[ixx]); return; } void AlpGenHandlerOL::caldel_hvq() const { // Fill partonsToMatch_ with only those pre-shower partons intended to // be used in heavy-quark-jet matching and fill particlesToCluster_ using // only those final state particles (post-shower) which are supposed // in the heavy-quark-jet clustering used to do merging. To begin with // these are made from the corresponding sets of particles that were // omitted from the initial jet-parton matching run. partonsToMatch_ = preshowerFSPsToDelete_; particlesToCluster_.resize(showeredFSPsToDelete_.size()); for(unsigned int ixx=0; ixxid())<4||abs(partonsToMatch_[ixx]->id())>6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxid())==5&& partonsToMatch_[ixx]->parents().size()>0&& abs(partonsToMatch_[ixx]->parents()[0]->id())==6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxparents().size()>0&& (abs(partonsToMatch_[ixx]->parents()[0]->id())==23|| abs(partonsToMatch_[ixx]->parents()[0]->id())==24|| abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->intermediates()); for(unsigned int ixx=0; ixxid())==6) { partonsToMatch_.push_back(intermediates[ixx]); tmpList_.clear(); getTopRadiation(partonsToMatch_.back()); for(unsigned int jxx=0; jxxid())>=4&&abs(partonsToMatch_[ixx]->id())<=6) { theProgenitor = partonsToMatch_[ixx]; // Follow the heavy quark line down to where it stops branching. while(theProgenitor->children().size()>0) { theLastProgenitor = theProgenitor; for(unsigned int jxx=0; jxxchildren().size(); jxx++) { if(theProgenitor->children()[jxx]->id()==theProgenitor->id()) theProgenitor=theProgenitor->children()[jxx]; } // If the progenitor had children but none of them had // the same particle id as it, then it must have undergone // a decay rather than a branching, i.e. it is the end of // the evolution line, so, if(theProgenitor==theLastProgenitor) break; } evolvedHeavyQuarks.push_back(theProgenitor); } } // Now delete the evolved heavy quark from the particlesToCluster. for(unsigned int ixx=0; ixxsubProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void AlpGenHandlerOL::getShoweredParticles() const { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void AlpGenHandlerOL::doSanityChecks(int debugLevel) const { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "AlpGenHandlerOL::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "AlpGenHandlerOL::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void AlpGenHandlerOL::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeMatching & operator=(const QTildeMatching &); /** * The shower handler to be used */ Ptr::ptr theShowerHandler; /** * The qtilde partner finder for calculating the hard scales */ Ptr::ptr theQTildeFinder; /** * The qtilde Sudakov to access the cutoff */ Ptr::ptr theQTildeSudakov; /** * True, if PDF weight should be corrected for z/x mismatch at the * hard phase space boundary */ bool theCorrectForXZMismatch; }; } #endif /* Herwig_QTildeMatching_H */ diff --git a/Shower/QTilde/Base/Branching.h b/Shower/QTilde/Base/Branching.h --- a/Shower/QTilde/Base/Branching.h +++ b/Shower/QTilde/Base/Branching.h @@ -1,69 +1,69 @@ // -*- C++ -*- #ifndef HERWIG_Branching_H #define HERWIG_Branching_H // // This is the declaration of the Branching struct. // #include "Herwig/Shower/QTilde/ShowerConfig.h" -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * The branching struct is used to store information on the branching. * The kinematics variable is a pointer to the ShowerKinematics for the branching * The sudakov variable is a pointer to the SudakovFormFactor for the branching * The ids variable is the list of particles in the branching */ struct Branching { /** * Pointer to the ShowerKinematics object for the branching */ ShoKinPtr kinematics; /** * PDG codes of the particles in the branching */ IdList ids; /** * The SudakovFormFactor for the branching */ tSudakovPtr sudakov; /** * The type of radiation line */ ShowerPartnerType type; /** * Whether or not it keep from forced hard emisson */ bool hard; /** * Which of the children is same as incoming */ unsigned int iout; /** * Constructor for the struct * @param a pointer to the ShowerKinematics object for the branching * @param c PDG codes of the particles in the branching * @param d The SudakovFormFactor for the branching */ Branching(ShoKinPtr a, IdList c,tSudakovPtr d,ShowerPartnerType t) : kinematics(a), ids(c), sudakov(d), type(t), hard(false), iout(0) {} /** * Default constructor */ Branching() : hard(false), iout(0) {} }; } #endif /* HERWIG_Branching_H */ diff --git a/Shower/QTilde/Base/HardBranching.h b/Shower/QTilde/Base/HardBranching.h --- a/Shower/QTilde/Base/HardBranching.h +++ b/Shower/QTilde/Base/HardBranching.h @@ -1,363 +1,363 @@ // -*- C++ -*- #ifndef HERWIG_HardBranching_H #define HERWIG_HardBranching_H // // This is the declaration of the HardBranching class. // #include "ThePEG/Config/ThePEG.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h" #include "HardBranching.fh" #include "HardTree.fh" namespace Herwig { using namespace ThePEG; /** * The HardBranching class is designed to contain the information needed for * an individual branching in the POWHEG approach */ class HardBranching : public Base { /** * The HardTree is friend */ friend class HardTree; public: /** * Enum for the status */ enum Status {Outgoing=0,Incoming,Decay}; public: /** * The default constructor * @param particle The particle which is branching * @param sudakov The Sudakov form factor for the branching * @param parent The parent for the branching * @param status Whether the particle is incoming or outgoing */ HardBranching(ShowerParticlePtr particle, SudakovPtr sudakov, tHardBranchingPtr parent,Status status); /** * Add a child of the branching * @param child The child of the branching */ void addChild(HardBranchingPtr child) {_children.push_back(child);} /** * Clear the children */ void clearChildren() { _children.clear(); } /** * Set the momenta of the particles */ void setMomenta(LorentzRotation R, double alpha, Lorentz5Momentum pt, bool setMomentum=true); /** * Set and get members for the private member variables */ //@{ /** * Return the branching particle. */ tShowerParticlePtr branchingParticle() const {return _particle;} /** * Set the branching particle */ void branchingParticle(ShowerParticlePtr in) {_particle=in;} /** * Get the original momentum */ const Lorentz5Momentum & original() const {return _original;} /** * Set the original momentum */ void original(const Lorentz5Momentum & in) {_original=in;} /** * Get the p reference vector */ const Lorentz5Momentum & pVector() const {return _p;} /** * Set the p reference vector */ void pVector(const Lorentz5Momentum & in) {_p=in;} /** * Get the n reference vector */ const Lorentz5Momentum & nVector() const {return _n;} /** * Set the n reference vector */ void nVector(const Lorentz5Momentum & in) {_n=in;} /** * Get the transverse momentum vector */ const Lorentz5Momentum & qPerp() const {return _qt;} /** * Set the transverse momentum vector */ void qPerp(const Lorentz5Momentum & in) {_qt=in;} /** * Get the momentum the particle should have as the start of a shower */ const Lorentz5Momentum & showerMomentum() const {return _shower;} /** * Set the momentum the particle should have as the start of a shower */ void showerMomentum(const Lorentz5Momentum & in ) {_shower=in;} /** * Get the transverse momentum */ Energy pT() const {return _pt;} /** * Set the transverse momentum */ void pT(Energy in) { _pt=in;} /** * Get the fraction of beam momentum x */ double x_frac() const {return _x_frac;} /** * Set the fraction of beam momentum x */ void x_frac( double x ) { _x_frac = x; } /** * Get whether the branching is incoming, outgoing or decay */ Status status() const {return _status;} /** * Set whether the branching is incoming, outgoing or decay */ void status(Status in) {_status=in;} /** * The parent of the branching */ tHardBranchingPtr parent() const {return _parent;} /** * Set the parent of the branching */ void parent(tHardBranchingPtr in) {_parent=in;} /** * The Sudakov form-factor */ SudakovPtr sudakov() const {return _sudakov;} /** * The Sudakov form-factor */ void sudakov(SudakovPtr in) {_sudakov=in;} /** * Get the beam particle */ PPtr beam() const {return _beam;} /** * Set the beam particle */ void beam(PPtr in) {_beam=in;} /** * The children */ vector & children() {return _children;} //@} /** * Information on the Shower variables for the branching */ //@{ /** * Get the evolution scale */ Energy scale() const {return _scale;} /** * The evolution scale */ void scale(Energy in) {_scale=in;} /** * The energy fraction */ double z() const {return _z;} /** * The energy fraction */ void z(double in) {_z=in;} /** * The azimthual angle */ double phi() const {return _phi;} /** * The azimthual angle */ void phi(double in) {_phi=in;} //@} /** * Colour partners */ //@{ /** * Get the colour partner */ tHardBranchingPtr colourPartner() const {return _partner;} /** * The colour partner of the branching */ void colourPartner(tHardBranchingPtr in) {_partner=in;} //@} /** * Type of branching */ ShowerPartnerType type() const { assert(type_!=ShowerPartnerType::Undefined); return type_; } /** * Type of branching */ void type(ShowerPartnerType in) { type_ = in; assert(type_!=ShowerPartnerType::Undefined); } private: /** * The branching particle */ ShowerParticlePtr _particle; /** * The rescaled momentum */ Lorentz5Momentum _original; /** * The \f$p\f$ reference vector */ Lorentz5Momentum _p; /** * The \f$n\f$ reference vector */ Lorentz5Momentum _n; /** * The transverse momentum vector */ Lorentz5Momentum _qt; /** * The momentum the particle should have as the start of a shower */ Lorentz5Momentum _shower; /** * The transverse momentum */ Energy _pt; /** * The beam momentum fraction carried by an incoming parton x */ double _x_frac; /** * Whether the branching is incoming, outgoing or a decay */ Status _status; /** * Information on the Shower variables for the branching */ //@{ /** * The evolution scale */ Energy _scale; /** * The energy fraction */ double _z; /** * The azimthual angle */ double _phi; //@} /** * The parent of the branching */ tHardBranchingPtr _parent; /** * The Sudakov form-factor */ SudakovPtr _sudakov; /** * The children */ vector _children; /** * The beam particle */ PPtr _beam; /** * The colour partner */ tHardBranchingPtr _partner; /** * The type of branching */ ShowerPartnerType type_; }; } #endif /* HERWIG_HardBranching_H */ diff --git a/Shower/QTilde/Base/HardTree.h b/Shower/QTilde/Base/HardTree.h --- a/Shower/QTilde/Base/HardTree.h +++ b/Shower/QTilde/Base/HardTree.h @@ -1,143 +1,143 @@ // -*- C++ -*- #ifndef HERWIG_HardTree_H #define HERWIG_HardTree_H // // This is the declaration of the HardTree class. // #include "ThePEG/Config/ThePEG.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h" #include "Herwig/Shower/RealEmissionProcess.fh" #include "HardBranching.h" #include "HardTree.fh" namespace Herwig { using namespace ThePEG; /** * The HardTree class is designed to contain the information required * to implement the POWHEG approach for Monte Carlo at next-to-leading order. */ class HardTree : public Base { /** * Output operator for testing */ friend ostream & operator << (ostream &, const HardTree & ); public: /** * The default constructor. */ HardTree(vector, vector, ShowerInteraction); /** * Contructor from Real emission process */ HardTree(RealEmissionProcessPtr real); /** * Match particles in the ShowerTree to branchings in the HardTree */ bool connect(ShowerParticlePtr particle, HardBranchingPtr branching) { if(branchings_.find(branching)==branchings_.end()) return false; particles_[particle]=branching; return true; } /** * Match the prticles in the ShowerTree to the branchings in the HardTree */ bool connect(ShowerTreePtr); /** * Access the map between the ShowerParticle and the HardBranching */ map & particles() {return particles_;} /** * Access the set of branchings */ set & branchings() {return branchings_;} /** * Access the incoming branchings */ set & incoming() {return spacelike_;} /** * Type of interaction */ ShowerInteraction interaction() {return interaction_;} /** * Get the Rotation to be applied to the tree */ LorentzRotation showerRot() { return showerRot_; } /** * Set the Rotation to be applied to the tree */ void showerRot( LorentzRotation r ) { showerRot_ = r; } /** * Whether or not the evolution partners are set */ bool partnersSet() const {return partnersSet_;} /** * Whether or not the evolution partners are set */ void partnersSet(bool in) {partnersSet_=in;} private: /** * Type of interaction */ ShowerInteraction interaction_; /** * The ShowerTree */ ShowerTreePtr _tree; /** * Map from the particles in the ShowerTree to the HardBranchings */ map particles_; /** * The HardBranchings in the hard process */ set branchings_; /** * The HardBranchings which initiate the space-like showers */ set spacelike_; /** * Rotation to shower frame */ LorentzRotation showerRot_; /** * Whether or not partners are set */ bool partnersSet_; }; /** * Output operator for testing */ ostream & operator << (ostream &, const HardTree & ); } #endif /* HERWIG_HardTree_H */ diff --git a/Shower/QTilde/Base/ShowerParticle.h b/Shower/QTilde/Base/ShowerParticle.h --- a/Shower/QTilde/Base/ShowerParticle.h +++ b/Shower/QTilde/Base/ShowerParticle.h @@ -1,528 +1,528 @@ // -*- C++ -*- // // ShowerParticle.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerParticle_H #define HERWIG_ShowerParticle_H // // This is the declaration of the ShowerParticle class. // #include "ThePEG/EventRecord/Particle.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.fh" #include "Herwig/Shower/QTilde/ShowerConfig.h" -#include "ShowerBasis.h" -#include "ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerBasis.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" #include "ShowerParticle.fh" #include namespace Herwig { using namespace ThePEG; /** \ingroup Shower * This class represents a particle in the showering process. * It inherits from the Particle class of ThePEG and has some * specifics information useful only during the showering process. * * Notice that: * - for forward evolution, it is clear what is meant by parent/child; * for backward evolution, however, it depends whether we want * to keep a physical picture or a Monte-Carlo effective one. * In the former case, an incoming particle (emitting particle) * splits into an emitted particle and the emitting particle after * the emission: the latter two are then children of the * emitting particle, the parent. In the Monte-Carlo effective * picture, we have that the particle close to the hard subprocess, * with higher (space-like) virtuality, splits into an emitted particle * and the emitting particle at lower virtuality: the latter two are, * in this case, the children of the first one, the parent. However we * choose a more physical picture where the new emitting particle is the * parented of the emitted final-state particle and the original emitting * particle. * - the pointer to a SplitFun object is set only in the case * that the particle has undergone a shower emission. This is similar to * the case of the decay of a normal Particle where * the pointer to a Decayer object is set only in the case * that the particle has undergone to a decay. * In the case of particle connected directly to the hard subprocess, * there is no pointer to the hard subprocess, but there is a method * isFromHardSubprocess() which returns true only in this case. * * @see Particle * @see ShowerConfig * @see ShowerKinematics */ class ShowerParticle: public Particle { public: /** * Struct for all the info on an evolution partner */ struct EvolutionPartner { /** * Constructor */ EvolutionPartner(tShowerParticlePtr p,double w, ShowerPartnerType t, Energy s) : partner(p), weight(w), type(t), scale(s) {} /** * The partner */ tShowerParticlePtr partner; /** * Weight */ double weight; /** * Type */ ShowerPartnerType type; /** * The assoicated evolution scale */ Energy scale; }; /** * Struct to store the evolution scales */ struct EvolutionScales { /** * Constructor */ EvolutionScales() : QED(),QCD_c(),QCD_ac(), QED_noAO(),QCD_c_noAO(),QCD_ac_noAO(), Max_Q2(Constants::MaxEnergy2) {} /** * QED scale */ Energy QED; /** * QCD colour scale */ Energy QCD_c; /** * QCD anticolour scale */ Energy QCD_ac; /** * QED scale */ Energy QED_noAO; /** * QCD colour scale */ Energy QCD_c_noAO; /** * QCD anticolour scale */ Energy QCD_ac_noAO; /** * Maximum allowed virtuality of the particle */ Energy2 Max_Q2; }; /** @name Construction and descruction functions. */ //@{ /** * Standard Constructor. Note that the default constructor is * private - there is no particle without a pointer to a * ParticleData object. * @param x the ParticleData object * @param fs Whether or not the particle is an inital or final-state particle * @param tls Whether or not the particle initiates a time-like shower */ ShowerParticle(tcEventPDPtr x, bool fs, bool tls=false) : Particle(x), _isFinalState(fs), _perturbative(0), _initiatesTLS(tls), _x(1.0), _showerKinematics(), _vMass(ZERO), _thePEGBase() {} /** * Copy constructor from a ThePEG Particle * @param x ThePEG particle * @param pert Where the particle came from * @param fs Whether or not the particle is an inital or final-state particle * @param tls Whether or not the particle initiates a time-like shower */ ShowerParticle(const Particle & x, unsigned int pert, bool fs, bool tls=false) : Particle(x), _isFinalState(fs), _perturbative(pert), _initiatesTLS(tls), _x(1.0), _showerKinematics(), _vMass(ZERO), _thePEGBase(&x) {} //@} public: /** * Set a preliminary momentum for the particle */ void setShowerMomentum(bool timelike); /** * Construct the spin info object for a shower particle */ void constructSpinInfo(bool timelike); /** * Perform any initial calculations needed after the branching has been selected */ void initializeDecay(); /** * Perform any initial calculations needed after the branching has been selected * @param parent The beam particle */ void initializeInitialState(PPtr parent); /** * Perform any initial calculations needed after the branching has been selected */ void initializeFinalState(); /** * Access/Set various flags about the state of the particle */ //@{ /** * Access the flag that tells if the particle is final state * or initial state. */ bool isFinalState() const { return _isFinalState; } /** * Access the flag that tells if the particle is initiating a * time like shower when it has been emitted in an initial state shower. */ bool initiatesTLS() const { return _initiatesTLS; } /** * Access the flag which tells us where the particle came from * This is 0 for a particle produced in the shower, 1 if the particle came * from the hard sub-process and 2 is it came from a decay. */ unsigned int perturbative() const { return _perturbative; } //@} /** * Set/Get the momentum fraction for initial-state particles */ //@{ /** * For an initial state particle get the fraction of the beam momentum */ void x(double x) { _x = x; } /** * For an initial state particle set the fraction of the beam momentum */ double x() const { return _x; } //@} /** * Set/Get methods for the ShowerKinematics objects */ //@{ /** * Access/ the ShowerKinematics object. */ const ShoKinPtr & showerKinematics() const { return _showerKinematics; } /** * Set the ShowerKinematics object. */ void showerKinematics(const ShoKinPtr in) { _showerKinematics = in; } //@} /** * Set/Get methods for the ShowerBasis objects */ //@{ /** * Access/ the ShowerBasis object. */ const ShowerBasisPtr & showerBasis() const { return _showerBasis; } /** * Set the ShowerBasis object. */ void showerBasis(const ShowerBasisPtr in, bool copy) { if(!copy) _showerBasis = in; else { _showerBasis = new_ptr(ShowerBasis()); _showerBasis->setBasis(in->pVector(),in->nVector(),in->frame()); } } //@} /** * Members relating to the initial evolution scale and partner for the particle */ //@{ /** * Veto emission at a given scale */ void vetoEmission(ShowerPartnerType type, Energy scale); /** * Access to the evolution scales */ const EvolutionScales & scales() const {return scales_;} /** * Access to the evolution scales */ EvolutionScales & scales() {return scales_;} /** * Return the virtual mass\f$ */ Energy virtualMass() const { return _vMass; } /** * Set the virtual mass */ void virtualMass(Energy mass) { _vMass = mass; } /** * Return the partner */ tShowerParticlePtr partner() const { return _partner; } /** * Set the partner */ void partner(const tShowerParticlePtr partner) { _partner = partner; } /** * Get the possible partners */ vector & partners() { return partners_; } /** * Add a possible partners */ void addPartner(EvolutionPartner in ); /** * Clear the evolution partners */ void clearPartners() { partners_.clear(); } /** * Return the progenitor of the shower */ tShowerParticlePtr progenitor() const { return _progenitor; } /** * Set the progenitor of the shower */ void progenitor(const tShowerParticlePtr progenitor) { _progenitor = progenitor; } //@} /** * Members to store and provide access to variables for a specific * shower evolution scheme */ //@{ struct Parameters { Parameters() : alpha(1.), beta(), ptx(), pty(), pt() {} double alpha; double beta; Energy ptx; Energy pty; Energy pt; }; /** * Set the vector containing dimensionless variables */ Parameters & showerParameters() { return _parameters; } //@} /** * If this particle came from the hard process get a pointer to ThePEG particle * it came from */ const tcPPtr thePEGBase() const { return _thePEGBase; } public: /** * Extract the rho matrix including mapping needed in the shower */ RhoDMatrix extractRhoMatrix(bool forward); /** * For a particle which came from the hard process get the spin density and * the mapping required to the basis used in the Shower * @param rho The \f$\rho\f$ matrix * @param mapping The mapping * @param showerkin The ShowerKinematics object */ bool getMapping(SpinPtr &, RhoDMatrix & map); protected: /** * Standard clone function. */ virtual PPtr clone() const; /** * Standard clone function. */ virtual PPtr fullclone() const; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initShowerParticle; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerParticle & operator=(const ShowerParticle &); private: /** * Whether the particle is in the final or initial state */ bool _isFinalState; /** * Whether the particle came from */ unsigned int _perturbative; /** * Does a particle produced in the backward shower initiate a time-like shower */ bool _initiatesTLS; /** * Dimensionless parameters */ Parameters _parameters; /** * The beam energy fraction for particle's in the initial state */ double _x; /** * The shower kinematics for the particle */ ShoKinPtr _showerKinematics; /** * The shower basis for the particle */ ShowerBasisPtr _showerBasis; /** * Storage of the evolution scales */ EvolutionScales scales_; /** * Virtual mass */ Energy _vMass; /** * Partners */ tShowerParticlePtr _partner; /** * Pointer to ThePEG Particle this ShowerParticle was created from */ const tcPPtr _thePEGBase; /** * Progenitor */ tShowerParticlePtr _progenitor; /** * Partners */ vector partners_; }; inline ostream & operator<<(ostream & os, const ShowerParticle::EvolutionScales & es) { os << "Scales: QED=" << es.QED / GeV << " QCD_c=" << es.QCD_c / GeV << " QCD_ac=" << es.QCD_ac / GeV << " QED_noAO=" << es.QED_noAO / GeV << " QCD_c_noAO=" << es.QCD_c_noAO / GeV << " QCD_ac_noAO=" << es.QCD_ac_noAO / GeV << '\n'; return os; } } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ShowerParticle. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ShowerParticle. */ typedef Particle NthBase; }; /** This template specialization informs ThePEG about the name of * the ShowerParticle class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::ShowerParticle"; } /** Create a Event object. */ static TPtr create() { return TPtr::Create(Herwig::ShowerParticle(tcEventPDPtr(),true)); } }; /** @endcond */ } #endif /* HERWIG_ShowerParticle_H */ diff --git a/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h b/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h --- a/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h @@ -1,101 +1,101 @@ // -*- C++ -*- // // Decay_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_Decay_QTildeShowerKinematics1to2_H #define HERWIG_Decay_QTildeShowerKinematics1to2_H // // This is the declaration of the Decay_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific decay shower * kinematics information. * * @see ShowerKinematics * @see IS_QTildeShowerKinematics1to2 * @see FS_QTildeShowerKinematics1to2 * @see KinematicsReconstructor * */ class Decay_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType, bool massVeto) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle to update * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Decay_QTildeShowerKinematics1to2 & operator=(const Decay_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_Decay_QTildeShowerKinematics1to2_H */ diff --git a/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.cc --- a/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.cc +++ b/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.cc @@ -1,203 +1,203 @@ // -*- C++ -*- // // FS_QTildeShowerKinematics1to2.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FS_QTildeShowerKinematics1to2 class. // #include "FS_QTildeShowerKinematics1to2.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/Debug.h" #include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/Shower/QTilde/Base/ShowerVertex.h" using namespace Herwig; void FS_QTildeShowerKinematics1to2:: updateParameters(tShowerParticlePtr theParent, tShowerParticlePtr theChild0, tShowerParticlePtr theChild1, bool setAlpha) const { const ShowerParticle::Parameters & parent = theParent->showerParameters(); ShowerParticle::Parameters & child0 = theChild0->showerParameters(); ShowerParticle::Parameters & child1 = theChild1->showerParameters(); // determine alphas of children according to interpretation of z if ( setAlpha ) { child0.alpha = z() * parent.alpha; child1.alpha = (1.-z()) * parent.alpha; } // set the values double cphi = cos(phi()); double sphi = sin(phi()); child0.ptx = pT() * cphi + z() * parent.ptx; child0.pty = pT() * sphi + z() * parent.pty; child0.pt = sqrt( sqr(child0.ptx) + sqr(child0.pty) ); child1.ptx = -pT() * cphi + (1.-z())* parent.ptx; child1.pty = -pT() * sphi + (1.-z())* parent.pty; child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) ); } void FS_QTildeShowerKinematics1to2:: updateChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType, bool massVeto) const { assert(children.size()==2); // calculate the scales splittingFn()->evaluateFinalStateScales(partnerType,scale(),z(),parent, children[0],children[1]); // set the maximum virtual masses if(massVeto) { Energy2 q2 = z()*(1.-z())*sqr(scale()); IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); if(ids[0]->id()!=ParticleID::g && ids[0]->id()!=ParticleID::gamma ) { q2 += sqr(virtualMasses[0]); } // limits on further evolution children[0]->scales().Max_Q2 = z() *(q2-sqr(virtualMasses[2])/(1.-z())); children[1]->scales().Max_Q2 = (1.-z())*(q2-sqr(virtualMasses[1])/ z() ); } // update the parameters updateParameters(parent, children[0], children[1], true); // set up the colour connections splittingFn()->colourConnection(parent,children[0],children[1],partnerType,false); // make the products children of the parent parent->addChild(children[0]); parent->addChild(children[1]); // set the momenta of the children for(ShowerParticleVector::const_iterator pit=children.begin(); pit!=children.end();++pit) { (**pit).showerBasis(parent->showerBasis(),true); (**pit).setShowerMomentum(true); } // sort out the helicity stuff if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return; SpinPtr pspin(parent->spinInfo()); if(!pspin || !dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations() ) return; Energy2 t = sqr(scale())*z()*(1.-z()); IdList ids; ids.push_back(parent->dataPtr()); ids.push_back(children[0]->dataPtr()); ids.push_back(children[1]->dataPtr()); // create the vertex SVertexPtr vertex(new_ptr(ShowerVertex())); // set the matrix element vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),true)); RhoDMatrix mapping; SpinPtr inspin; bool needMapping = parent->getMapping(inspin,mapping); if(needMapping) vertex->incomingBasisTransform(mapping); // set the incoming particle for the vertex parent->spinInfo()->decayVertex(vertex); for(ShowerParticleVector::const_iterator pit=children.begin(); pit!=children.end();++pit) { // construct the spin info for the children (**pit).constructSpinInfo(true); // connect the spinInfo object to the vertex (*pit)->spinInfo()->productionVertex(vertex); } } void FS_QTildeShowerKinematics1to2:: reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children ) const { assert(children.size() == 2); ShowerParticlePtr c1 = dynamic_ptr_cast(children[0]); ShowerParticlePtr c2 = dynamic_ptr_cast(children[1]); parent->showerParameters().beta= c1->showerParameters().beta + c2->showerParameters().beta; Lorentz5Momentum pnew = c1->momentum() + c2->momentum(); Energy2 m2 = sqr(pT())/z()/(1.-z()) + sqr(c1->mass())/z() + sqr(c2->mass())/(1.-z()); pnew.setMass(sqrt(m2)); parent->set5Momentum( pnew ); } void FS_QTildeShowerKinematics1to2::reconstructLast(const tShowerParticlePtr last, Energy mass) const { // set beta component and consequently all missing data from that, // using the nominal (i.e. PDT) mass. Energy theMass = mass > ZERO ? mass : last->data().constituentMass(); Lorentz5Momentum pVector = last->showerBasis()->pVector(); ShowerParticle::Parameters & lastParam = last->showerParameters(); Energy2 denom = 2. * lastParam.alpha * last->showerBasis()->p_dot_n(); if(abs(denom)/(sqr(pVector.e())+pVector.rho2())<1e-10) { throw KinematicsReconstructionVeto(); } lastParam.beta = ( sqr(theMass) + sqr(lastParam.pt) - sqr(lastParam.alpha) * pVector.m2() ) / denom; // set that new momentum Lorentz5Momentum newMomentum = last->showerBasis()-> sudakov2Momentum( lastParam.alpha, lastParam.beta, lastParam.ptx , lastParam.pty); newMomentum.setMass(theMass); newMomentum.rescaleEnergy(); if(last->data().stable()) { last->set5Momentum( newMomentum ); } else { last->boost(last->momentum().findBoostToCM()); last->boost(newMomentum.boostVector()); } } void FS_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType) const { IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); if(children[0]->children().empty()) children[0]->virtualMass(virtualMasses[1]); if(children[1]->children().empty()) children[1]->virtualMass(virtualMasses[2]); // compute the new pT of the branching Energy2 pt2=sqr(z()*(1.-z()))*sqr(scale()) - sqr(children[0]->virtualMass())*(1.-z()) - sqr(children[1]->virtualMass())* z() ; if(ids[0]->id()!=ParticleID::g) pt2 += z()*(1.-z())*sqr(virtualMasses[0]); if(pt2>ZERO) { pT(sqrt(pt2)); } else { pt2=ZERO; pT(ZERO); } Energy2 q2 = sqr(children[0]->virtualMass())/z() + sqr(children[1]->virtualMass())/(1.-z()) + pt2/z()/(1.-z()); parent->virtualMass(sqrt(q2)); } void FS_QTildeShowerKinematics1to2:: resetChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children) const { updateParameters(parent, children[0], children[1], false); for(unsigned int ix=0;ixchildren().empty()) continue; ShowerParticleVector newChildren; for(unsigned int iy=0;iychildren().size();++iy) newChildren.push_back(dynamic_ptr_cast (children[ix]->children()[iy])); children[ix]->showerKinematics()->resetChildren(children[ix],newChildren); } } diff --git a/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h --- a/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h @@ -1,117 +1,117 @@ // -*- C++ -*- // // FS_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FS_QTildeShowerKinematics1to2_H #define HERWIG_FS_QTildeShowerKinematics1to2_H // // This is the declaration of the FS_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific Final State shower * kinematics information. * * @see ShowerKinematics * @see IS_QTildeShowerKinematics1to2 * @see Decay_QTildeShowerKinematics1to2 * @see KinematicsReconstructor */ class FS_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** * Default constructor */ inline FS_QTildeShowerKinematics1to2() {} /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ private: void updateParameters(tShowerParticlePtr theParent, tShowerParticlePtr theChild0, tShowerParticlePtr theChild1, bool setAlpha) const; public: virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType, bool massVeto ) const; virtual void resetChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle to update * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FS_QTildeShowerKinematics1to2 & operator=(const FS_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_FS_QTildeShowerKinematics1to2_H */ diff --git a/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.cc --- a/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.cc +++ b/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.cc @@ -1,149 +1,149 @@ // -*- C++ -*- // // IS_QTildeShowerKinematics1to2.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IS_QTildeShowerKinematics1to2 class. // #include "IS_QTildeShowerKinematics1to2.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/Debug.h" #include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/Shower/QTilde/Base/ShowerVertex.h" #include using namespace Herwig; void IS_QTildeShowerKinematics1to2:: updateChildren( const tShowerParticlePtr theParent, const ShowerParticleVector & children, ShowerPartnerType, bool massVeto) const { const ShowerParticle::Parameters & parent = theParent->showerParameters(); ShowerParticle::Parameters & child0 = children[0]->showerParameters(); ShowerParticle::Parameters & child1 = children[1]->showerParameters(); double cphi = cos(phi()); double sphi = sin(phi()); child1.alpha = (1.-z()) * parent.alpha; child1.ptx = (1.-z()) * parent.ptx - cphi * pT(); child1.pty = (1.-z()) * parent.pty - sphi * pT(); child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) ); // space-like child child0.alpha = parent.alpha - child1.alpha; child0.beta = parent.beta - child1.beta; child0.ptx = parent.ptx - child1.ptx; child0.pty = parent.pty - child1.pty; if(massVeto) { Energy2 q2 = (1.-z())*sqr(scale()); children[1]->scales().Max_Q2 = (1.-z())*q2/z(); } } void IS_QTildeShowerKinematics1to2:: updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType) const { // calculate the scales splittingFn()->evaluateInitialStateScales(partnerType,scale(),z(),parent, children[0],children[1]); // set proper colour connections splittingFn()->colourConnection(parent,children[0],children[1], partnerType,true); // set proper parent/child relationships parent->addChild(children[0]); parent->addChild(children[1]); parent->x(children[0]->x()/z()); // sort out the helicity stuff // construct the spin info for parent and timelike child // temporary assignment of shower parameters to calculate correlations parent->showerParameters().alpha = parent->x(); children[1]->showerParameters().alpha = (1.-z()) * parent->x(); children[1]->showerParameters().ptx = - cos(phi()) * pT(); children[1]->showerParameters().pty = - sin(phi()) * pT(); children[1]->showerParameters().pt = pT(); parent ->showerBasis(children[0]->showerBasis(),true); children[1]->showerBasis(children[0]->showerBasis(),true); parent ->setShowerMomentum(false); children[1]->setShowerMomentum(true); if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return; SpinPtr pspin(children[0]->spinInfo()); if(!pspin || !dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations() ) return; // compute the matrix element for spin correlations IdList ids; ids.push_back(parent->dataPtr()); ids.push_back(children[0]->dataPtr()); ids.push_back(children[1]->dataPtr()); Energy2 t = (1.-z())*sqr(scale())/z(); // create the vertex SVertexPtr vertex(new_ptr(ShowerVertex())); // set the matrix element vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),false)); // set the incoming particle for the vertex // (in reality the first child as going backwards) pspin->decayVertex(vertex); // construct the spin infos parent ->constructSpinInfo(false); children[1]->constructSpinInfo(true); // connect the spinInfo objects to the vertex parent ->spinInfo()->productionVertex(vertex); children[1]->spinInfo()->productionVertex(vertex); } void IS_QTildeShowerKinematics1to2:: reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children ) const { PPtr c1 = children[0]; ShowerParticlePtr c2 = dynamic_ptr_cast(children[1]); ShowerParticle::Parameters & c2param = c2->showerParameters(); // get shower variables from 1st child in order to keep notation // parent->(c1, c2) clean even though the splitting was initiated // from c1. The name updateParent is still referring to the // timelike branching though. // on-shell child c2param.beta = 0.5*( sqr(c2->data().constituentMass()) + sqr(c2param.pt) ) / ( c2param.alpha * parent->showerBasis()->p_dot_n() ); Lorentz5Momentum pnew = parent->showerBasis()-> sudakov2Momentum(c2param.alpha, c2param.beta, c2param.ptx , c2param.pty); pnew.setMass(c2->data().constituentMass()); pnew.rescaleEnergy(); c2->set5Momentum( pnew ); // spacelike child Lorentz5Momentum pc1(parent->momentum() - c2->momentum()); pc1.rescaleMass(); c1->set5Momentum(pc1); } void IS_QTildeShowerKinematics1to2:: updateLast( const tShowerParticlePtr theLast,Energy px,Energy py) const { if(theLast->isFinalState()) return; ShowerParticle::Parameters & last = theLast->showerParameters(); Lorentz5Momentum pVector = theLast->showerBasis()->pVector(); Energy2 pt2 = sqr(px) + sqr(py); last.alpha = theLast->x(); last.beta = 0.5 * pt2 / last.alpha / theLast->showerBasis()->p_dot_n(); last.ptx = ZERO; last.pty = ZERO; last.pt = ZERO; // momentum Lorentz5Momentum ntemp = Lorentz5Momentum(ZERO,-pVector.vect()); double beta = 0.5 * pt2 / last.alpha / ( pVector * ntemp); Lorentz5Momentum plast = Lorentz5Momentum( (pVector.z()>ZERO ? px : -px), py, ZERO, ZERO) + theLast->x() * pVector + beta * ntemp; plast.rescaleMass(); theLast->set5Momentum(plast); } diff --git a/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h --- a/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h @@ -1,112 +1,112 @@ // -*- C++ -*- // // IS_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IS_QTildeShowerKinematics1to2_H #define HERWIG_IS_QTildeShowerKinematics1to2_H // // This is the declaration of the IS_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific Intial State shower * kinematics information. * * @see ShowerKinematics * @see FS_QTildeShowerKinematics1to2 * @see Decay_QTildeShowerKinematics1to2 * @see KinematicsReconstructor */ class IS_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** @name Standard constructors and destructors. */ //@{ /** * Construct in terms of the basis states */ inline IS_QTildeShowerKinematics1to2() {} //@} public: /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType, bool massVeto) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateParent( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param theLast The particle. * @param px The \f$x\f$ component of the \f$p_T\f$. * @param py The \f$y\f$ component of the \f$p_T\f$. */ virtual void updateLast(const tShowerParticlePtr theLast, Energy px, Energy py) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IS_QTildeShowerKinematics1to2 & operator=(const IS_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_IS_QTildeShowerKinematics1to2_H */ diff --git a/Shower/QTilde/Base/KinematicsReconstructor.cc b/Shower/QTilde/Kinematics/KinematicsReconstructor.cc rename from Shower/QTilde/Base/KinematicsReconstructor.cc rename to Shower/QTilde/Kinematics/KinematicsReconstructor.cc diff --git a/Shower/QTilde/Base/KinematicsReconstructor.fh b/Shower/QTilde/Kinematics/KinematicsReconstructor.fh rename from Shower/QTilde/Base/KinematicsReconstructor.fh rename to Shower/QTilde/Kinematics/KinematicsReconstructor.fh diff --git a/Shower/QTilde/Base/KinematicsReconstructor.h b/Shower/QTilde/Kinematics/KinematicsReconstructor.h rename from Shower/QTilde/Base/KinematicsReconstructor.h rename to Shower/QTilde/Kinematics/KinematicsReconstructor.h --- a/Shower/QTilde/Base/KinematicsReconstructor.h +++ b/Shower/QTilde/Kinematics/KinematicsReconstructor.h @@ -1,656 +1,656 @@ // -*- C++ -*- // // KinematicsReconstructor.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_KinematicsReconstructor_H #define HERWIG_KinematicsReconstructor_H // // This is the declaration of the KinematicsReconstructor class. // #include "ThePEG/Interface/Interfaced.h" -#include "ShowerParticle.h" -#include "ShowerProgenitor.h" -#include "ShowerTree.h" -#include "HardTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/HardTree.h" #include "KinematicsReconstructor.fh" #include namespace Herwig { using namespace ThePEG; /**\ingroup Shower * Exception class * used to communicate failure of kinematics * reconstruction. */ struct KinematicsReconstructionVeto {}; /** \ingroup Shower * A simple struct to store the information we need on the * showering */ struct JetKinStruct { /** * Parent particle of the jet */ tShowerParticlePtr parent; /** * Momentum of the particle before reconstruction */ Lorentz5Momentum p; /** * Momentum of the particle after reconstruction */ Lorentz5Momentum q; }; /** * typedef for a vector of JetKinStruct */ typedef vector JetKinVect; /** * Enum to identify types of colour singlet systems */ enum SystemType { UNDEFINED=-1, II, IF, F ,I }; /** * Struct to store colour singlets */ template struct ColourSinglet { typedef vector > VecType; ColourSinglet() : type(UNDEFINED) {} ColourSinglet(SystemType intype,Value inpart) : type(intype),jets(1,inpart) {} /** * The type of system */ SystemType type; /** * The jets in the system */ vector jets; }; /** * Struct to store a colour singlet system of particles */ typedef ColourSinglet ColourSingletSystem; /** * Struct to store a colour singlet shower */ typedef ColourSinglet ColourSingletShower; /** \ingroup Shower * * This class is responsible for the kinematical reconstruction * after each showering step, and also for the necessary Lorentz boosts * in order to preserve energy-momentum conservation in the overall collision, * and also the invariant mass and the rapidity of the hard subprocess system. * In the case of multi-step showering, there will be not unnecessary * kinematical reconstructions. * * There is also the option of taking a set of momenta for the particles * and inverting the reconstruction to give the evolution variables for the * shower. * * Notice: * - although we often use the term "jet" in either methods or variables names, * or in comments, which could appear applicable only for QCD showering, * there is indeed no "dynamics" represented in this class: only kinematics * is involved, as the name of this class remainds. Therefore it can be used * for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung). * * @see ShowerParticle * @see ShowerKinematics * @see \ref KinematicsReconstructorInterfaces "The interfaces" * defined for KinematicsReconstructor. */ class KinematicsReconstructor: public Interfaced { public: /** * Default constructor */ KinematicsReconstructor() : _reconopt(0), _initialBoost(0), _finalStateReconOption(0), _initialStateReconOption(0), _minQ(MeV) {}; /** * Methods to reconstruct the kinematics of a scattering or decay process */ //@{ /** * Given in input a vector of the particles which initiated the showers * the method does the reconstruction of such jets, * including the appropriate boosts (kinematics reshufflings) * needed to conserve the total energy-momentum of the collision * and preserving the invariant mass and the rapidity of the * hard subprocess system. */ virtual bool reconstructHardJets(ShowerTreePtr hard, const map > & pt, ShowerInteraction type, bool switchRecon) const; /** * Given in input a vector of the particles which initiated the showers * the method does the reconstruction of such jets, * including the appropriate boosts (kinematics reshufflings) * needed to conserve the total energy-momentum of the collision * and preserving the invariant mass and the rapidity of the * hard subprocess system. */ virtual bool reconstructDecayJets(ShowerTreePtr decay, ShowerInteraction type) const; //@} /** * Methods to invert the reconstruction of the shower for * a scattering or decay process and calculate * the variables used to generate the * shower given the particles produced. * This is needed for the CKKW and POWHEG approaches */ //@{ /** * Given the particles, with a history which we wish to interpret * as a shower reconstruct the variables used to generate the * shower */ virtual bool deconstructDecayJets(HardTreePtr,ShowerInteraction) const; /** * Given the particles, with a history which we wish to interpret * as a shower reconstruct the variables used to generate the shower * for a hard process */ virtual bool deconstructHardJets(HardTreePtr,ShowerInteraction) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * Methods to reconstruct the kinematics of individual jets */ //@{ /** * Given the particle (ShowerParticle object) that * originates a forward (time-like) jet, this method reconstructs the kinematics * of the jet. That is, by starting from the final grand-children (which * originates directly or indirectly from particleJetParent, * and which don't have children), and moving "backwards" (in a physical * time picture), towards the particleJetParent, the * ShowerKinematics objects associated with the various particles, * which have been created during the showering, are now completed. * In particular, at the end, we get the mass of the jet, which is the * main information we want. * This methods returns false if there was no radiation or rescaling required */ virtual bool reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const; /** * Exactly similar to the previous one, but for a space-like jet. * Also in this case we start from the final grand-children (which * are childless) of the particle which originates the jet, but in * this case we proceed "forward" (in the physical time picture) * towards the particleJetParent. * This methods returns false if there was no radiation or rescaling required */ bool reconstructSpaceLikeJet(const tShowerParticlePtr particleJetParent) const; /** * Exactly similar to the previous one, but for a decay jet * This methods returns false if there was no radiation or rescaling required */ bool reconstructDecayJet(const tShowerParticlePtr particleJetParent) const; //@} /** * Methods to perform the reconstruction of various types of colour * singlet systems */ //@{ /** * Perform the reconstruction of a system with one incoming and at least one * outgoing particle */ void reconstructInitialFinalSystem(vector) const; /** * Perform the reconstruction of a system with only final-state * particles */ void reconstructFinalStateSystem(bool applyBoost, const LorentzRotation & toRest, const LorentzRotation & fromRest, vector) const; /** * Reconstruction of a general coloured system */ void reconstructGeneralSystem(vector & ShowerHardJets) const; /** * Reconstruction of a general coloured system doing * final-final, then initial-final and then initial-initial */ void reconstructFinalFirst(vector & ShowerHardJets) const; /** * Reconstruction of a general coloured system doing * colour parners */ void reconstructColourPartner(vector & ShowerHardJets) const; /** * Reconstruction based on colour singlet systems */ void reconstructColourSinglets(vector & ShowerHardJets, ShowerInteraction type) const; /** * Perform the reconstruction of a system with only final-state * particles */ void reconstructInitialInitialSystem(bool & applyBoost, LorentzRotation & toRest, LorentzRotation & fromRest, vector) const; //@} /** * Methods to perform the inverse reconstruction of various types of * colour singlet systems */ //@{ /** * Perform the inverse reconstruction of a system with only final-state * particles */ void deconstructFinalStateSystem(const LorentzRotation & toRest, const LorentzRotation & fromRest, HardTreePtr, vector, ShowerInteraction) const; /** * Perform the inverse reconstruction of a system with only initial-state * particles */ void deconstructInitialInitialSystem(bool & applyBoost, LorentzRotation & toRest, LorentzRotation & fromRest, HardTreePtr, vector, ShowerInteraction ) const; /** * Perform the inverse reconstruction of a system with only initial-state * particles */ void deconstructInitialFinalSystem(HardTreePtr, vector, ShowerInteraction ) const; bool deconstructGeneralSystem(HardTreePtr, ShowerInteraction) const; bool deconstructColourSinglets(HardTreePtr, ShowerInteraction) const; bool deconstructColourPartner(HardTreePtr, ShowerInteraction) const; //@} /** * Recursively treat the most off-shell paricle seperately * for final-final reconstruction */ void reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s, bool recursive) const; /** * Various methods for the Lorentz transforms needed to do the * rescalings */ //@{ /** * Compute the boost to get from the the old momentum to the new */ LorentzRotation solveBoost(const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp) const; /** * Compute the boost to get from the the old momentum to the new */ LorentzRotation solveBoost(const Lorentz5Momentum & newq, const Lorentz5Momentum & oldq) const; /** * Compute the boost to get from the the old momentum to the new */ LorentzRotation solveBoostZ(const Lorentz5Momentum & newq, const Lorentz5Momentum & oldq) const; /** * Recursively boost the initial-state shower * @param p The particle * @param bv The boost * @param parent The parent of the chain */ void boostChain(tPPtr p, const LorentzRotation & bv, tPPtr & parent) const; /** * Given a 5-momentum and a scale factor, the method returns the * Lorentz boost that transforms the 3-vector vec{momentum} ---> * k*vec{momentum}. The method returns the null boost in the case no * solution exists. This will only work in the case where the * outgoing jet-momenta are parallel to the momenta of the particles * leaving the hard subprocess. */ Boost solveBoostBeta( const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp); /** * Compute boost parameter along z axis to get (Ep, any perp, qp) * from (E, same perp, q). */ double getBeta(const double E, const double q, const double Ep, const double qp) const {return (q*E-qp*Ep)/(sqr(qp)+sqr(E));} //@} /** * Methods to calculate the various scaling factors */ //@{ /** * Given a vector of 5-momenta of jets, where the 3-momenta are the initial * ones before showering and the masses are reconstructed after the showering, * this method returns the overall scaling factor for the 3-momenta of the * vector of particles, vec{P}_i -> k * vec{P}_i, such to preserve energy- * momentum conservation, i.e. after the rescaling the center of mass 5-momentum * is equal to the one specified in input, cmMomentum. * The method returns 0 if such factor cannot be found. * @param root_s Centre-of-mass energy * @param jets The jets */ double solveKfactor( const Energy & root_s, const JetKinVect & jets ) const; /** * Calculate the rescaling factors for the jets in a particle decay where * there was initial-state radiation * @param mb The mass of the decaying particle * @param n The reference vector for the initial state radiation * @param pjet The momentum of the initial-state jet * @param jetKinematics The JetKinStruct objects for the jets * @param partner The colour partner * @param ppartner The momentum of the colour partner of the decaying particle * before and after radiation * @param k1 The rescaling parameter for the partner * @param k2 The rescaling parameter for the outgoing singlet * @param qt The transverse momentum vector */ bool solveDecayKFactor(Energy mb, const Lorentz5Momentum & n, const Lorentz5Momentum & pjet, const JetKinVect & jetKinematics, ShowerParticlePtr partner, Lorentz5Momentum ppartner[2], double & k1, double & k2, Lorentz5Momentum & qt) const; /** * Compute the momentum rescaling factor needed to invert the shower * @param pout The momenta of the outgoing particles * @param mon The on-shell masses * @param roots The mass of the decaying particle */ double inverseRescalingFactor(vector pout, vector mon,Energy roots) const; /** * Compute the momentum rescaling factor needed to invert the shower * @param pout The momenta of the outgoing particles * @param mon The on-shell masses * @param roots The mass of the decaying particle * @param ppartner The momentum of the colour partner * @param mbar The mass of the decaying particle * @param k1 The first scaling factor * @param k2 The second scaling factor */ bool inverseDecayRescalingFactor(vector pout, vector mon,Energy roots, Lorentz5Momentum ppartner, Energy mbar, double & k1, double & k2) const; /** * Check the rescaling conserves momentum * @param k The rescaling * @param root_s The centre-of-mass energy * @param jets The jets */ Energy momConsEq(double k, const Energy & root_s, const JetKinVect & jets) const; void findInitialBoost(const Lorentz5Momentum & pold, const Lorentz5Momentum & pnew, LorentzRotation & toRest, LorentzRotation & fromRest) const; //@} /** * Find the colour partners of a particle to identify the colour singlet * systems for the reconstruction. */ template void findPartners(Value branch,set & done, const set & branchings, vector & jets) const; /** * Add the intrinsic \f$p_T\f$ to the system if needed */ bool addIntrinsicPt(vector) const; /** * Apply a transform to the particle and any child, including child ShowerTree * objects * @param particle The particle * @param r The Lorentz transformation * @param match Whether or not to look at children etc * @param original The original particle */ void deepTransform(PPtr particle,const LorentzRotation & r, bool match=true,PPtr original=PPtr()) const; /** * Find the mass of a particle in the hard branching */ Energy findMass(HardBranchingPtr) const; /** * Calculate the initial-state rescaling factors */ vector initialStateRescaling(double x1, double x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq, const vector& highespts) const; /** * Calculate the inverse of the initial-state rescaling factor */ vector inverseInitialStateRescaling(double & x1, double & x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq) const; /** * Find the colour singlet systems */ template typename ColourSinglet::VecType identifySystems(set jets, unsigned int & nnun,unsigned int & nnii, unsigned int & nnif,unsigned int & nnf, unsigned int & nni) const; /** * Combine final-state colour systems */ template void combineFinalState(vector > & systems) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ KinematicsReconstructor & operator=(const KinematicsReconstructor &) = delete; private: /** * Option for handling the reconstruction */ unsigned int _reconopt; /** * Option for the boost for initial-initial reconstruction */ unsigned int _initialBoost; /** * Option for the reconstruction of final state systems */ unsigned int _finalStateReconOption; /** * Option for the initial state reconstruction */ unsigned int _initialStateReconOption; /** * Minimum invariant mass for initial-final dipoles to allow the * reconstruction */ Energy _minQ; /** * The progenitor of the jet currently being reconstructed */ mutable tShowerParticlePtr _progenitor; /** * Storage of the intrinsic \f$p_T\f$ */ mutable map > _intrinsic; /** * Current ShowerTree */ mutable tShowerTreePtr _currentTree; /** * Particles which shouldn't have their masses rescaled as * vector for the interface */ PDVector _noRescaleVector; /** * Particles which shouldn't have their masses rescaled as * set for quick access */ set _noRescale; /** * Storage of the boosts applied to enable resetting after failure */ mutable map > _boosts; /** * Storage of the boosts applied to enable resetting after failure */ mutable map > _treeBoosts; }; } #include "KinematicsReconstructor.tcc" #endif /* HERWIG_KinematicsReconstructor_H */ diff --git a/Shower/QTilde/Base/KinematicsReconstructor.tcc b/Shower/QTilde/Kinematics/KinematicsReconstructor.tcc rename from Shower/QTilde/Base/KinematicsReconstructor.tcc rename to Shower/QTilde/Kinematics/KinematicsReconstructor.tcc diff --git a/Shower/QTilde/Kinematics/QTildeShowerKinematics1to2.h b/Shower/QTilde/Kinematics/QTildeShowerKinematics1to2.h --- a/Shower/QTilde/Kinematics/QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Kinematics/QTildeShowerKinematics1to2.h @@ -1,132 +1,132 @@ // -*- C++ -*- // // QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_QTildeShowerKinematics1to2_H #define HERWIG_QTildeShowerKinematics1to2_H // // This is the declaration of the QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "QTildeShowerKinematics1to2.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This abstract class describes the common features for initial and final * state radiation kinematics for \f$1\to2\f$ branchings and for * the choice of \f$\tilde{q}\f$ as evolution variable. * * @see ShowerKinematics * @see IS_QTildeShowerKinematics1to2 * @see FS_QTildeShowerKinematics1to2 * @see KinematicsReconstructor */ class QTildeShowerKinematics1to2: public ShowerKinematics { public: /** * Implementation of the virtual function returning a set of basis vectors, specific to * the type of evolution. This function will be used by the * ForwardShowerEvolver in order to access \f$p\f$ * and \f$n\f$. */ virtual vector getBasis() const; /** * Access to the \f$p\f$ vector used to describe the kinematics. */ const Lorentz5Momentum & pVector() const {return _pVector;} /** * Access to the \f$n\f$ vector used to describe the kinematics. */ const Lorentz5Momentum & nVector() const {return _nVector;} /** * Dot product of thew basis vectors */ Energy2 p_dot_n() const {return _pVector*_nVector;} /** * Converts a Sudakov parametrization of a momentum w.r.t. the given * basis \f$p\f$ and \f$n\f$ into a 5 momentum. * @param alpha The \f$\alpha\f$ parameter of the Sudakov parameterisation * @param beta The \f$\beta\f$ parameter of the Sudakov parameterisation * @param px The \f$x\f$-component of the transverse momentum in the Sudakov * parameterisation * @param py The \f$x\f$-component of the transverse momentum in the Sudakov * parameterisation */ Lorentz5Momentum sudakov2Momentum(double alpha, double beta, Energy px, Energy py) const { return alpha*_pVector + beta*_nVector + px*_xPerp+py*_yPerp; } /** * Transform the shower kinematics (usually the reference vectors) */ virtual void transform(const LorentzRotation & r); protected: /** * Set the basis vectors */ void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n, Frame frame); /** * Set a preliminary momentum for the particle */ void setMomentum(tShowerParticlePtr,bool timelike) const; /** * Construct the spin info object for a shower particle */ void constructSpinInfo(tShowerParticlePtr,bool timelike) const; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeShowerKinematics1to2 & operator=(const QTildeShowerKinematics1to2 &); private: /** * The \f$p\f$ reference vector */ Lorentz5Momentum _pVector; /** * The \f$n\f$ reference vector */ Lorentz5Momentum _nVector; /** * x \f$q_\perp\f$ reference vector */ LorentzVector _xPerp; /** * y \f$q_\perp\f$reference vector */ LorentzVector _yPerp; }; } #endif /* HERWIG_QTildeShowerKinematics1to2_H */ diff --git a/Shower/QTilde/Base/ShowerBasis.cc b/Shower/QTilde/Kinematics/ShowerBasis.cc rename from Shower/QTilde/Base/ShowerBasis.cc rename to Shower/QTilde/Kinematics/ShowerBasis.cc --- a/Shower/QTilde/Base/ShowerBasis.cc +++ b/Shower/QTilde/Kinematics/ShowerBasis.cc @@ -1,81 +1,81 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerBasis class. // #include "ShowerBasis.h" -#include "ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeHerwigShowerBasis("Herwig::ShowerBasis", "libHerwig.so"); void ShowerBasis::setBasis(const Lorentz5Momentum & p, const Lorentz5Momentum & n, Frame inframe) { pVector_ = p; nVector_ = n; frame_ = inframe; Boost beta_bb; if(frame()==BackToBack) { beta_bb = -(pVector_ + nVector_).boostVector(); } else if(frame()==Rest) { beta_bb = -pVector().boostVector(); } else assert(false); Lorentz5Momentum p_bb = pVector(); Lorentz5Momentum n_bb = nVector(); p_bb.boost( beta_bb ); n_bb.boost( beta_bb ); // rotate to have z-axis parallel to p/n Axis axis; if(frame()==BackToBack) { axis = p_bb.vect().unit(); } else if(frame()==Rest) { axis = n_bb.vect().unit(); } else assert(false); LorentzRotation rot; if(axis.perp2()>1e-10) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } xPerp_=LorentzVector(1.,0.,0.,0.); yPerp_=LorentzVector(0.,1.,0.,0.); xPerp_.transform(rot); yPerp_.transform(rot); // boost back xPerp_.boost( -beta_bb ); yPerp_.boost( -beta_bb ); } void ShowerBasis::transform(const LorentzRotation & r) { pVector_ *= r; nVector_ *= r; xPerp_ *= r; yPerp_ *= r; } vector ShowerBasis::getBasis() const { vector dum; dum.push_back( pVector_ ); dum.push_back( nVector_ ); return dum; } diff --git a/Shower/QTilde/Base/ShowerBasis.fh b/Shower/QTilde/Kinematics/ShowerBasis.fh rename from Shower/QTilde/Base/ShowerBasis.fh rename to Shower/QTilde/Kinematics/ShowerBasis.fh diff --git a/Shower/QTilde/Base/ShowerBasis.h b/Shower/QTilde/Kinematics/ShowerBasis.h rename from Shower/QTilde/Base/ShowerBasis.h rename to Shower/QTilde/Kinematics/ShowerBasis.h --- a/Shower/QTilde/Base/ShowerBasis.h +++ b/Shower/QTilde/Kinematics/ShowerBasis.h @@ -1,130 +1,130 @@ // -*- C++ -*- #ifndef Herwig_ShowerBasis_H #define Herwig_ShowerBasis_H // // This is the declaration of the ShowerBasis class. // #include "ShowerBasis.fh" -#include "ShowerParticle.fh" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh" #include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/Lorentz5Vector.h" namespace Herwig { using namespace ThePEG; /** * The ShowerBasis class stores the basis vectors used by the shower */ class ShowerBasis: public Base { public: /** * enum for the frame definition */ enum Frame {BackToBack,Rest}; public: /** * The default constructor. */ ShowerBasis() {} /** * Access to the frame definition */ Frame frame() const {return frame_;} /** * Implementation of the virtual function returning a set of basis vectors, specific to * the type of evolution. This function will be used by the * ForwardShowerEvolver in order to access \f$p\f$ * and \f$n\f$. */ virtual vector getBasis() const; /** * Set the basis vectors */ void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n, Frame frame); /** * Access to the \f$p\f$ vector used to describe the kinematics. */ const Lorentz5Momentum & pVector() const {return pVector_;} /** * Access to the \f$n\f$ vector used to describe the kinematics. */ const Lorentz5Momentum & nVector() const {return nVector_;} /** * Dot product of thew basis vectors */ Energy2 p_dot_n() const {return pVector_*nVector_;} /** * Transform the shower kinematics (usually the reference vectors) */ virtual void transform(const LorentzRotation & r); /** * Converts a Sudakov parametrization of a momentum w.r.t. the given * basis \f$p\f$ and \f$n\f$ into a 5 momentum. * @param alpha The \f$\alpha\f$ parameter of the Sudakov parameterisation * @param beta The \f$\beta\f$ parameter of the Sudakov parameterisation * @param px The \f$x\f$-component of the transverse momentum in the Sudakov * parameterisation * @param py The \f$x\f$-component of the transverse momentum in the Sudakov * parameterisation */ Lorentz5Momentum sudakov2Momentum(double alpha, double beta, Energy px, Energy py) const { return alpha*pVector_ + beta*nVector_ + px*xPerp_ + py*yPerp_; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerBasis & operator=(const ShowerBasis &); private: /** * The frame in which the basis vectors are defined */ Frame frame_; /** * The \f$p\f$ reference vector */ Lorentz5Momentum pVector_; /** * The \f$n\f$ reference vector */ Lorentz5Momentum nVector_; /** * x \f$q_\perp\f$ reference vector */ LorentzVector xPerp_; /** * y \f$q_\perp\f$reference vector */ LorentzVector yPerp_; }; } #endif /* Herwig_ShowerBasis_H */ diff --git a/Shower/QTilde/Base/ShowerKinematics.cc b/Shower/QTilde/Kinematics/ShowerKinematics.cc rename from Shower/QTilde/Base/ShowerKinematics.cc rename to Shower/QTilde/Kinematics/ShowerKinematics.cc diff --git a/Shower/QTilde/Base/ShowerKinematics.fh b/Shower/QTilde/Kinematics/ShowerKinematics.fh rename from Shower/QTilde/Base/ShowerKinematics.fh rename to Shower/QTilde/Kinematics/ShowerKinematics.fh diff --git a/Shower/QTilde/Base/ShowerKinematics.h b/Shower/QTilde/Kinematics/ShowerKinematics.h rename from Shower/QTilde/Base/ShowerKinematics.h rename to Shower/QTilde/Kinematics/ShowerKinematics.h --- a/Shower/QTilde/Base/ShowerKinematics.h +++ b/Shower/QTilde/Kinematics/ShowerKinematics.h @@ -1,276 +1,276 @@ // -*- C++ -*- // // ShowerKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerKinematics_H #define HERWIG_ShowerKinematics_H // // This is the declaration of the ShowerKinematics class. // #include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" -#include "ShowerKinematics.fh" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.fh" namespace Herwig { using namespace ThePEG; /**\ingroup Shower * * This is the abstract base class from which all other shower * kinematics classes derive. The main purpose of the * shower kinematics classes is to allow the reconstruction * of jet masses, at the end of the showering (indeed, for * multi-scale showering, at the end of each scale-range evolution). * This is necessary for the kinematics reshuffling * in order to compensate the recoil of the emissions. * The KinematicsReconstructor class is in * charge of this job, and which is the main "user" of * ShowerKinematics and its derived classes. * How this is done depends on the choice of kinematics variables * and whether the jet is time-like (forward evolved) or * space-like (backward evolved), whereas the class ShowerKinematics * describes only the common features which are independent by them. * * In general there are a number of methods specific to a shower approach * * @see KinematicsReconstructor */ class ShowerKinematics: public Base { public: /** * The default constructor. */ ShowerKinematics() : Base(), _isTheJetStartingPoint( false ), _scale(), _z( 0.0 ), _phi( 0.0 ), _pt(), _sudakov() {} /** * The updateChildren and updateParent * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType, bool massVeto ) const; virtual void resetChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType partnerType) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle. * @param px The \f$x\f$ component of the \f$p_T\f$. * @param py The \f$y\f$ component of the \f$p_T\f$. */ virtual void updateLast(const tShowerParticlePtr last, Energy px, Energy py) const; //@} /** * The reconstructLast, reconstructChildren and reconstructParent members * are used during the reconstruction */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. * @param parent The parent * @param children The children */ virtual void reconstructChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Reconstruct the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children */ virtual void reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle. * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; //@} public: /** * Set/access the flag that tells whether or not this ShowerKinematics * object is associated to the starting particle of the jet: only in this * case it is sensible to use the two main virtual methods below. */ //@{ /** * Set the starting point flag */ void isTheJetStartingPoint(const bool ); /** * Get the starting point flag */ bool isTheJetStartingPoint() const; //@} /** * Set/Get methods for the kinematic variables */ //@{ /** * Access the scale of the splitting. */ Energy scale() const { return _scale; } /** * Set the scale of the splitting. */ void scale(const Energy in) { _scale=in; } /** * Access the energy fraction, \f$z\f$. */ double z() const { return _z; } /** * Set the energy fraction, \f$z\f$. */ void z(const double in) { _z=in; } /** * Access the azimuthal angle, \f$\phi\f$. */ double phi() const { return _phi; } /** * Set the azimuthal angle, \f$\phi\f$. */ void phi(const double in) { _phi=in; } /** * Access the relative \f$p_T\f$ for the branching */ Energy pT() const { return _pt; } /** * Set the relative \f$p_T\f$ for the branching */ void pT(const Energy in) const { _pt=in; } //@} /** * Set and get methods for the SplittingFunction object */ //@{ /** * Access the SplittingFunction object responsible of the * eventual branching of this particle. */ tSplittingFnPtr splittingFn() const { return _sudakov-> splittingFn(); } //@} /** * Set and get methods for the SudakovFormFactor object */ /** * Access the SudakovFormFactor object responsible of the * eventual branching of this particle. */ tSudakovPtr SudakovFormFactor() const { return _sudakov; } /** * Set the SudakovFormFactor object responsible of the * eventual branching of this particle. */ void SudakovFormFactor(const tSudakovPtr sud) { _sudakov=sud; } //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerKinematics & operator=(const ShowerKinematics &); private: /** * Is this the starting point of the jet */ bool _isTheJetStartingPoint; /** * The \f$\tilde{q}\f$ evolution variable. */ Energy _scale; /** * The energy fraction, \f$z\f$ */ double _z; /** * The azimuthal angle, \f$\phi\f$. */ double _phi; /** * The relative \f$p_T\f$ */ mutable Energy _pt; /** * The splitting function for the branching of the particle */ tSudakovPtr _sudakov; }; } #endif /* HERWIG_ShowerKinematics_H */ diff --git a/Shower/QTilde/Makefile.am b/Shower/QTilde/Makefile.am --- a/Shower/QTilde/Makefile.am +++ b/Shower/QTilde/Makefile.am @@ -1,41 +1,41 @@ SUBDIRS = Matching pkglib_LTLIBRARIES = HwShower.la HwShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 25:0:0 HwShower_la_SOURCES = \ Couplings/ShowerAlphaQCD.h Couplings/ShowerAlphaQCD.cc \ Couplings/ShowerAlphaQED.h Couplings/ShowerAlphaQED.cc\ QTildeShowerHandler.h QTildeShowerHandler.fh QTildeShowerHandler.cc \ SplittingFunctions/HalfHalfOneSplitFn.h SplittingFunctions/HalfHalfOneSplitFn.cc\ SplittingFunctions/OneOneOneSplitFn.h SplittingFunctions/OneOneOneSplitFn.cc\ SplittingFunctions/OneOneOneMassiveSplitFn.h SplittingFunctions/OneOneOneMassiveSplitFn.cc\ SplittingFunctions/ZeroZeroOneSplitFn.h SplittingFunctions/ZeroZeroOneSplitFn.cc\ SplittingFunctions/OneHalfHalfSplitFn.h SplittingFunctions/OneHalfHalfSplitFn.cc\ SplittingFunctions/HalfOneHalfSplitFn.h SplittingFunctions/HalfOneHalfSplitFn.cc\ SplittingFunctions/CMWOneOneOneSplitFn.h SplittingFunctions/CMWOneOneOneSplitFn.cc\ SplittingFunctions/CMWHalfHalfOneSplitFn.h SplittingFunctions/CMWHalfHalfOneSplitFn.cc\ Kinematics/Decay_QTildeShowerKinematics1to2.cc \ Kinematics/Decay_QTildeShowerKinematics1to2.h \ Kinematics/IS_QTildeShowerKinematics1to2.cc Kinematics/IS_QTildeShowerKinematics1to2.h \ Kinematics/FS_QTildeShowerKinematics1to2.cc Kinematics/FS_QTildeShowerKinematics1to2.h \ -Base/KinematicsReconstructor.cc \ -Base/KinematicsReconstructor.tcc \ -Base/KinematicsReconstructor.h \ -Base/KinematicsReconstructor.fh \ +Kinematics/KinematicsReconstructor.cc \ +Kinematics/KinematicsReconstructor.tcc \ +Kinematics/KinematicsReconstructor.h \ +Kinematics/KinematicsReconstructor.fh \ Base/HardTree.cc Base/HardTree.h Base/HardTree.fh \ Base/HardBranching.h Base/HardBranching.fh Base/HardBranching.cc\ Base/PartnerFinder.h Base/PartnerFinder.fh Base/PartnerFinder.cc \ Base/ShowerVeto.h Base/ShowerVeto.fh Base/ShowerVeto.cc \ Base/FullShowerVeto.h Base/FullShowerVeto.fh Base/FullShowerVeto.cc \ SplittingFunctions/SplittingGenerator.cc SplittingFunctions/SplittingGenerator.h\ SplittingFunctions/SplittingGenerator.fh \ Base/ShowerTree.h Base/ShowerTree.fh Base/ShowerTree.cc \ ShowerConfig.h ShowerConfig.cc \ Base/Branching.h \ Base/ShowerParticle.cc Base/ShowerParticle.fh Base/ShowerParticle.h \ -Base/ShowerKinematics.fh Base/ShowerKinematics.h Base/ShowerKinematics.cc \ -Base/ShowerBasis.fh Base/ShowerBasis.h Base/ShowerBasis.cc \ +Kinematics/ShowerKinematics.fh Kinematics/ShowerKinematics.h Kinematics/ShowerKinematics.cc \ +Kinematics/ShowerBasis.fh Kinematics/ShowerBasis.h Kinematics/ShowerBasis.cc \ Base/ShowerProgenitor.fh Base/ShowerProgenitor.h \ -Base/SudakovFormFactor.cc Base/SudakovFormFactor.h Base/SudakovFormFactor.fh \ +SplittingFunctions/SudakovFormFactor.cc SplittingFunctions/SudakovFormFactor.h SplittingFunctions/SudakovFormFactor.fh \ SplittingFunctions/SplittingFunction.h SplittingFunctions/SplittingFunction.fh \ SplittingFunctions/SplittingFunction.cc \ Base/ShowerVertex.cc Base/ShowerVertex.fh Base/ShowerVertex.h diff --git a/Shower/QTilde/Matching/MatchingHandler.cc b/Shower/QTilde/Matching/MatchingHandler.cc --- a/Shower/QTilde/Matching/MatchingHandler.cc +++ b/Shower/QTilde/Matching/MatchingHandler.cc @@ -1,1088 +1,1088 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MatchingHandler class. // #include "MatchingHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/PDF/PDF.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Utilities/Throw.h" using namespace Herwig; namespace { struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; } MatchingHandler::MatchingHandler(bool reWeight) : reWeight_(reWeight), rejectNonAO_( true ), rejectNOHistories_( true ), includeDecays_(false) {} void MatchingHandler::persistentOutput(PersistentOStream & os) const { os << alphaS_ << matrixElement_ << HWmatrixElement_ << includeDecays_ << partonExtractor_ << cuts_ << rejectNonAO_ << rejectNOHistories_ << allowedInitial_ << allowedFinal_; } void MatchingHandler::persistentInput(PersistentIStream & is, int) { is >> alphaS_ >> matrixElement_ >> HWmatrixElement_ >> includeDecays_ >> partonExtractor_ >> cuts_ >> rejectNonAO_ >> rejectNOHistories_ >> allowedInitial_ >> allowedFinal_; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeHerwigMatchingHandler("Herwig::MatchingHandler", "HwMatching.so"); void MatchingHandler::Init() { static ClassDocumentation documentation ("The MatchingHandler class is the base class implementating" " many of the features needed for matching."); static Reference interfaceMatrixElement ("MatrixElement", "The matrix element class for the core 2->2 process", &MatchingHandler::matrixElement_, false, false, true, true, false); static Reference interfacePartonExtractor ("PartonExtractor", "The PartonExtractor object used to construct remnants. If no object is " "provided the LesHouchesEventHandler object must provide one instead.", &MatchingHandler::partonExtractor_, true, false, true, false, false); static Reference interfaceCuts ("Cuts", "The Cuts object to be used for this reader. Note that these " "must not be looser cuts than those used in the actual generation. " "If no object is provided the LesHouchesEventHandler object must " "provide one instead.", &MatchingHandler::cuts_, true, false, true, false, false); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &MatchingHandler::alphaS_, false, false, true, true, false); static Switch interfaceReject ("RejectNonOrdered", "Whether to reject non angular ordered cluster histories", &MatchingHandler::rejectNonAO_, true, false, false); static SwitchOption interfaceRejectYes (interfaceReject, "Reject", "Reject all non angular ordered events", true); static SwitchOption interfaceRejectNo (interfaceReject, "Select", "Select a history for non angular ordered events", false); static Switch interfaceRejectNoHist ("RejectNoHistories", "Whether to reject events with no shower interpretation", &MatchingHandler::rejectNOHistories_, true, false, false); static SwitchOption interfaceRejectNoHistYes (interfaceRejectNoHist, "Reject", "Reject all events with no shower interpretation", true); static SwitchOption interfaceRejectNoHistNo (interfaceRejectNoHist, "Shower", "Shower events with no shower interpretation directly", false); static Switch interfaceDecayingParticles ("IncludeDecayingParticles", "Separate production of decay of unstable particles", &MatchingHandler::includeDecays_, false, false, false); static SwitchOption interfaceDecayingParticlesYes (interfaceDecayingParticles, "Yes", "Separate them", true); static SwitchOption interfaceDecayingParticlesNo (interfaceDecayingParticles, "No", "Don't separate them", false); } void MatchingHandler::doinit() { ShowerHandler::doinit(); HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); // check if(reWeight_ && !alphaS_) { throw Exception() << "ShowerAlpha must be set in MatchingHandler if " << "reweighting events" << Exception::runerror; } // extract the allowed branchings // final-state for(BranchingList::const_iterator it = splittingGenerator()->finalStateBranchings().begin(); it != splittingGenerator()->finalStateBranchings().end(); ++it) { pair prod(make_pair(it->second.second[1],it->second.second[2])); allowedFinal_.insert(make_pair(prod,it->second)); swap(prod.first,prod.second); allowedFinal_.insert(make_pair(prod,it->second)); } // initial-state for(BranchingList::const_iterator it = splittingGenerator()->initialStateBranchings().begin(); it != splittingGenerator()->initialStateBranchings().end(); ++it) { allowedInitial_.insert(make_pair(it->second.second[0],it->second)); } } void MatchingHandler::fillProtoTrees( ProtoTreePtr currentProtoTree ) { if(currentProtoTree->branchings().size()==4) return; for( set::const_iterator ita = currentProtoTree->branchings().begin(); ita!=currentProtoTree->branchings().end();++ita) { for( set::const_iterator itb = currentProtoTree->branchings().begin(); itb!=ita;++itb) { // can't merge two incoming branchings if( (**ita).status() == HardBranching::Incoming && (**itb).status() == HardBranching::Incoming ) continue; // get a new branching for this pair ProtoBranchingPtr currentBranching = getCluster(*ita,*itb); if( ! currentBranching ) continue; // branching allowed so make a new Tree out of these branchings set< tProtoBranchingPtr > newTreeBranchings = currentProtoTree->branchings(); newTreeBranchings.erase(*ita); newTreeBranchings.erase(*itb); newTreeBranchings.insert(currentBranching); ProtoTreePtr newProtoTree = new_ptr( ProtoTree( newTreeBranchings ) ); // remove duplicate trees if( ! repeatProtoTree( newProtoTree ) ) protoTrees().insert( newProtoTree ); // remove the current tree if it hasn't already been removed if( protoTrees().find( currentProtoTree ) != protoTrees().end() ) protoTrees().erase( currentProtoTree ); // do recursion fillProtoTrees( newProtoTree ); } } } tProtoBranchingPtr MatchingHandler::getCluster( tProtoBranchingPtr b1, tProtoBranchingPtr b2 ) { //look for the clustered pair in protoBranchings_ for(set::const_iterator cit = protoBranchings().begin(); cit != protoBranchings().end(); ++cit) { // both outgoing if(b1->status()==HardBranching::Outgoing && b2->status()==HardBranching::Outgoing) { if((**cit).status()!=HardBranching::Outgoing|| (**cit).children().empty()) continue; if( ( b1 == (**cit).children()[0] && b2 == (**cit).children()[1] ) || ( b1 == (**cit).children()[1] && b2 == (**cit).children()[0] ) ) return *cit; } // first incoming else if(b1->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b1!=(**cit).backChildren()[0]) continue; if(b2==(**cit).backChildren()[1]) return *cit; } // second incoming else if(b2->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b2!=(**cit).backChildren()[0]) continue; if(b1==(**cit).backChildren()[1]) return *cit; } } // is branching incoming or outgoing bool incoming = b1->status()==HardBranching::Incoming || b2->status()==HardBranching::Incoming; // get the branching BranchingElement theBranching; if( !incoming ) theBranching = allowedFinalStateBranching( b1, b2 ); else theBranching = allowedInitialStateBranching( b1, b2 ); //if branching is not allowed return null ProtoBrancing if( !theBranching.first ) return ProtoBranchingPtr(); // get the PArticleData object for the new branching tcPDPtr particle_data = incoming ? getParticleData( theBranching.second[1] ) : getParticleData( theBranching.second[0] ); // create clustered ProtoBranching ProtoBranchingPtr clusteredBranch; // outgoing if( !incoming ){ Lorentz5Momentum pairMomentum = b1->momentum() + b2->momentum(); pairMomentum.setMass(ZERO); clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Outgoing, pairMomentum, theBranching.first)); } // incoming else { Lorentz5Momentum pairMomentum = b1->momentum() - b2->momentum(); pairMomentum.setMass( ZERO ); // check for CC if( particle_data->CC() && ( b1->id() != theBranching.second[0] || b2->id() != theBranching.second[2] ) ) { particle_data = particle_data->CC(); } clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Incoming, pairMomentum,theBranching.first)); } protoBranchings().insert(clusteredBranch); //set children relations // outgoing if( !incoming ){ clusteredBranch->addChild( b1 ); clusteredBranch->addChild( b2 ); } else { clusteredBranch->addBackChild( b1 ); clusteredBranch->addBackChild( b2 ); } return clusteredBranch; } BranchingElement MatchingHandler:: allowedFinalStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) { // check with normal ID's pair< long, long > ptest = make_pair( b1->id(), b2->id() ); map< pair< long, long >, pair< SudakovPtr, IdList > >::const_iterator split = allowedFinal_.find(ptest); if( split != allowedFinal_.end() ) { if( split->second.second[1] != ptest.first ) swap( b1, b2 ); return split->second; } // check with CC if( b1->particle()->CC() ) ptest.first *= -1; if( b2->particle()->CC() ) ptest.second *= -1; split = allowedFinal_.find( ptest ); if( split != allowedFinal_.end() ) { // cc the idlist only be for qbar g clusterings BranchingElement ccBranch = split->second; if( getParticleData( ccBranch.second[0] )->CC() ) ccBranch.second[0] *= -1; if( getParticleData( ccBranch.second[1] )->CC() ) ccBranch.second[1] *= -1; if( getParticleData( ccBranch.second[2] )->CC() ) ccBranch.second[2] *= -1; if( split->second.second[1] != ptest.first ) swap( b1, b2); return ccBranch; } // not found found null pointer return make_pair( SudakovPtr(), IdList() ); } BranchingElement MatchingHandler:: allowedInitialStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) { if(b2->status()==HardBranching::Incoming) swap(b1,b2); // is initial parton an antiparticle bool cc = b1->id() < 0; //gives range of allowedInitial_ with matching first abs( id ) pair< multimap< long, pair< SudakovPtr, IdList > >::const_iterator, multimap< long, pair< SudakovPtr, IdList > >::const_iterator > location = allowedInitial_.equal_range( abs( b1->id() ) ); //iterates over this range for( multimap< long, pair< SudakovPtr, IdList> >::const_iterator it = location.first; it != location.second; ++it ) { //test id for second particle in pair long idtest = it->second.second[2]; //if it is antiparticle *= -1 if( cc && getParticleData( idtest )->CC() ) idtest *= -1; // does second id match the test if( idtest == b2->id() ) return it->second; //if the the IS parton is a gluon and charge conjugate of second parton mathes accept if( idtest == -b2->id() && ! b1->particle()->CC() ) return it->second; } // not found found null pointer return make_pair(SudakovPtr(),IdList()); } bool MatchingHandler::repeatProtoTree( ProtoTreePtr currentProtoTree ) { // loop over all prototrees and see // how many ProtoBranchings of current ProtoTree are found in each for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { unsigned int no_matches = 0; for( set< tProtoBranchingPtr >::const_iterator ckt = currentProtoTree->branchings().begin(); ckt != currentProtoTree->branchings().end(); ckt++ ) { if( (*cit)->branchings().find( *ckt ) != (*cit)->branchings().end() ) ++no_matches; } // return true if all match if( no_matches == currentProtoTree->branchings().size() ) return true; } return false; } double MatchingHandler::getDiagram(PotentialTree & tree) { if(tree.diagrams().empty()) { set::const_iterator cit; tcPDPair incoming; multiset outgoing; //get the incoming and outgoing partons involved in hard process for( cit = tree.tree()->branchings().begin(); cit != tree.tree()->branchings().end(); ++cit ){ if( (*cit)->status() ==HardBranching::Incoming) { HardBranchingPtr parent = *cit; while(parent->parent()) parent = parent->parent(); if( parent->branchingParticle()->momentum().z()>ZERO ) incoming.first = (*cit)->branchingParticle()->dataPtr(); else incoming.second = (*cit)->branchingParticle()->dataPtr(); } else { outgoing.insert( (*cit)->branchingParticle()->dataPtr() ); } } if(!incoming.first || !incoming.second) return 0.; pair tag; tag.first = incoming.first ->PDGName() + "," + incoming.second->PDGName() + "->"; tag.second = incoming.second ->PDGName() + "," + incoming.first ->PDGName() + "->"; string tag_out; for ( multiset::iterator i = outgoing.begin(); i != outgoing.end(); ++i ) { if ( i != outgoing.begin() ) tag_out += ","; tag_out += (**i).PDGName(); } tag.first += tag_out; tag.second += tag_out; // find the diagrams for ( int i = 0, N = matrixElement()->diagrams().size(); i < N; ++i ) { string temp = matrixElement()->diagrams()[i]->getTag(); if ( temp == tag.first || temp == tag.second ) tree.diagrams().push_back(matrixElement()->diagrams()[i]); } } if(tree.diagrams().empty()) return 0.; // construct a set of on-shell momenta for the hard collison vector meMomenta; vector mePartonData; PVector particles; set::const_iterator it; // incoming particles for( it = tree.tree()->branchings().begin();it != tree.tree()->branchings().end(); ++it ) { if( (**it).status() == HardBranching::Incoming ) { meMomenta.push_back( (**it).branchingParticle()->momentum() ); mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); particles.push_back( (**it).branchingParticle() ); } } assert(particles.size()==2); for( it = tree.tree()->branchings().begin(); it != tree.tree()->branchings().end(); ++it ) { if( (**it).status() == HardBranching::Outgoing ) { meMomenta.push_back( (**it).branchingParticle()->momentum() ); mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); particles.push_back( (**it).branchingParticle() ); } } const cPDVector partons = tree.diagrams()[0]->partons(); // order of the incoming partons if(mePartonData[0] != partons[0]) { swap( mePartonData[0], mePartonData[1] ); swap( meMomenta[0], meMomenta[1] ); swap( particles[0], particles[1] ); } // order of the outgoing partons for(unsigned int ix=2;ix0.) { R.rotateZ(-axis.phi()); R.rotateY(-acos(axis.z())); } for( unsigned int ix = 0; ix < meMomenta.size(); ++ix ) meMomenta[ix].transform(R); // now rescale to put on shell Energy Ebeam = 0.5 * ( max(meMomenta[0].e(),abs(meMomenta[0].z())) + max(meMomenta[1].e(),abs(meMomenta[1].z())) ); for( unsigned int i = 0; i < 2; ++i ) { meMomenta[i].setZ( meMomenta[i].z() / abs(meMomenta[i].z()) * Ebeam ); meMomenta[i].setT( Ebeam ); } Energy2 s = 4.0 * sqr(Ebeam); Energy m1 = mePartonData[2]->mass(); Energy m2 = mePartonData[3]->mass(); // \todo need to improve this if(m1+m2>sqrt(s)) return 0.; double lambda = 0.25/Ebeam/meMomenta[2].rho() * sqrt( ( s - sqr(m1+m2) ) * ( s - sqr(m1-m2) ) ); for( unsigned int i = 2; i < meMomenta.size(); ++i ) { meMomenta[i] *= lambda; meMomenta[i].setMass(mePartonData[i]->mass()); meMomenta[i].rescaleEnergy(); } // incoming pair PPair in( mePartonData[0]->produceParticle( meMomenta[0] ), mePartonData[1]->produceParticle( meMomenta[1] ) ); // outgoing PVector out; for(unsigned int ix=2;ixproduceParticle(meMomenta[ix])); } // call the matrix element to initialize matrixElement()->setKinematics(in,out); if(HWMatrixElement()) { vector momenta; cPDVector data; data.push_back(in. first->dataPtr()); momenta.push_back(in. first->momentum()); data.push_back(in.second->dataPtr()); momenta.push_back(in.second->momentum()); for(unsigned int ix=0;ixdataPtr()); momenta.push_back(out[ix]->momentum()); } HWMatrixElement()->rescaleMomenta(momenta,data); } if(!cuts()->scale(matrixElement()->scale())) { return 0.; } matrixElement()->dSigHatDR(); // select the diagram if(!tree.diagram()) tree.diagram(tree.diagrams()[matrixElement()->diagram(tree.diagrams())]); // get the colour structure if(!tree.colourLines()) { Selector sel = matrixElement()->colourGeometries(tree.diagram()); tree.colourLines(sel.select(rnd())); } PVector slike; tPVector ret; slike.push_back(particles[0]); Ptr::const_pointer diagram2 = dynamic_ptr_cast::const_pointer>(tree.diagram()); for ( int i = 1; i < diagram2->nSpace() - 1; ++i ) slike.push_back(diagram2->allPartons()[i]->produceParticle()); slike.push_back(particles[1]); ret = tPVector(slike.begin(), slike.end()); int io = particles.size(); PVector tlike(diagram2->allPartons().size() - diagram2->nSpace()); for ( int i = diagram2->allPartons().size() - 1; i >= diagram2->nSpace(); --i ) { int it = i - diagram2->nSpace(); pair ch = diagram2->children(i); bool iso = ch.first < 0; if ( iso ) { tlike[it] = particles[--io]; } else { Lorentz5Momentum p = tlike[ch.first - diagram2->nSpace()]->momentum() + tlike[ch.second - diagram2->nSpace()]->momentum(); tlike[it] = diagram2->allPartons()[i]->produceParticle(p); } } ret.insert( ret.end(), tlike.begin(), tlike.end() ); tree.colourLines()->connect(ret); for( unsigned int ix = 0; ix < ret.size(); ++ix ) { PVector::iterator it = find( particles.begin(), particles.end(),ret[ix] ); if( it == particles.end() ) { ColinePtr line = ret[ix]->colourLine(); if(line) line->removeColoured(ret[ix]); line = ret[ix]->antiColourLine(); if(line) line->removeAntiColoured(ret[ix]); } } // now the colours of the rest of the particles // for( set::const_iterator it = tree.tree()->branchings().begin(); // it!=tree.tree()->branchings().end(); ++it ) (**it).fixColours(); // now make the colour connections in the tree ShowerParticleVector branchingParticles; map branchingMap; for( set< HardBranchingPtr >::iterator it = tree.tree()->branchings().begin(); it != tree.tree()->branchings().end(); ++it ) { branchingParticles.push_back((**it).branchingParticle()); branchingMap.insert(make_pair((**it).branchingParticle(),*it)); } // find the colour partners partnerFinder() ->setInitialEvolutionScales(branchingParticles,false, ShowerInteraction::QCD,true); for(unsigned int ix=0;ixpartner()) { HardBranchingPtr partner = branchingMap[branchingParticles[ix]->partner()]; branchingMap[branchingParticles[ix]]->colourPartner(partner); } } double weight = 1.; // calculate the weight if needed if(reWeight_) { if(matrixElement()->orderInAlphaS()>0) { weight = pow(alphaS_->value( max(matrixElement()->scale(),sqr(pdfScale_)) ) / alphaSMG_, int(matrixElement()->orderInAlphaS())); } } // return the weight return weight; } bool MatchingHandler::updateSubProcess() { assert( hardTree().diagram() && hardTree().tree() ); PPair beams = lastXCombPtr()->lastParticles(); // PPair remnants; // // remove children of beams // PVector beam_children = beams.first->children(); // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ // if (abs(beam_children[ix]->id())==82) // remnants.first=beam_children[ix]; // beams.first->abandonChild( beam_children[ix] ); // } // beam_children = beams.second->children(); // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ // if (abs(beam_children[ix]->id())==82) // remnants.second=beam_children[ix]; // beams.second->abandonChild( beam_children[ix] ); // } // remove children of beams PVector beam_children = beams.first->children(); for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) beams.first->abandonChild( beam_children[ix] ); beam_children = beams.second->children(); for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) beams.second->abandonChild( beam_children[ix] ); if( (**hardTree().tree()->incoming().begin()).branchingParticle()->momentum().z() / beams.first->momentum().z() < 0.) swap( beams.first, beams.second ); Ptr::const_pointer diagram = dynamic_ptr_cast::const_pointer>(hardTree().diagram()); assert(diagram); set::const_iterator it; map< ColinePtr, ColinePtr> colourMap; PPair incoming; // loop over the branchings and sort out incoming particles for( it = hardTree().tree()->branchings().begin(); it != hardTree().tree()->branchings().end(); ++it) { if( (*it)->status() == HardBranching::Outgoing ) continue; PPtr newParticle = new_ptr( Particle( (**it).branchingParticle()->dataPtr() ) ); newParticle->set5Momentum( (**it).showerMomentum() ); if( (**it).branchingParticle()->colourLine() ) { map< ColinePtr, ColinePtr>::iterator loc = colourMap.find( (**it).branchingParticle()->colourLine() ); if( loc != colourMap.end() ) { loc->second->addColoured( newParticle ); } else { ColinePtr newLine = new_ptr( ColourLine() ); colourMap[ (**it).branchingParticle()->colourLine() ] = newLine; newLine->addColoured( newParticle ); } } if( (**it).branchingParticle()->antiColourLine() ) { map< ColinePtr, ColinePtr> ::iterator loc = colourMap.find( (**it).branchingParticle()->antiColourLine() ); if( loc != colourMap.end() ) { loc->second->addAntiColoured( newParticle ); } else { ColinePtr newLine = new_ptr( ColourLine() ); colourMap[ (**it).branchingParticle()->antiColourLine() ] = newLine; newLine->addAntiColoured( newParticle ); } } if( lastXCombPtr()->subProcess()->incoming().first->momentum().z() / newParticle->momentum().z() > 0. ) incoming.first = newParticle; else incoming.second = newParticle; } bool mirror = incoming.first ->dataPtr() != diagram->partons()[0] && incoming.second->dataPtr() != diagram->partons()[1]; // create the new subprocess SubProPtr newSubProcess = new_ptr( SubProcess( incoming, lastXCombPtr()->subProcess()->collision(), lastXCombPtr()->subProcess()->handler() ) ); // add the spacelike intermediates PVector slike; slike.push_back( !mirror ? incoming.first : incoming.second); for ( int i = 1; i < diagram->nSpace() - 1; ++i ) slike.push_back(diagram->allPartons()[i]->produceParticle()); slike.push_back( !mirror ? incoming.second : incoming.first); tPVector ret = tPVector(slike.begin(), slike.end()); for ( size_t i = 1; i < slike.size() - 1; ++i ) { slike[i-1]->addChild(slike[i]); newSubProcess->addIntermediate(slike[ mirror ? i: slike.size() - 1 - i], false); } // get the parton bins from the parton extractor if first time static bool first = true; if(first) { first = false; Energy e1 = lastXCombPtr()->lastParticles().first ->momentum().e(); Energy e2 = lastXCombPtr()->lastParticles().second->momentum().e(); Energy emax = 2.0*sqrt(e1*e2); cPDPair inData = make_pair(lastXCombPtr()->lastParticles().first ->dataPtr(), lastXCombPtr()->lastParticles().second->dataPtr()); cuts()->initialize(sqr(emax),0.5*log(e1/e2)); partonBins(partonExtractor()->getPartons(emax, inData, *cuts())); } // get the parton bins for this event tcPBPair sel; for ( int i = 0, N = partonBins().size(); i < N; ++i ) { tcPBPtr bin = partonBins()[i].first; tPPtr p = incoming.first; while ( bin && p ) { if ( p->dataPtr() != bin->parton() ) break; bin = bin->incoming(); p = p != lastXCombPtr()->lastParticles().first ? lastXCombPtr()->lastParticles().first : PPtr(); } if ( bin || p ) continue; bin = partonBins()[i].second; p = incoming.second; while ( bin && p ) { if ( p->dataPtr() != bin->parton() ) break; bin = bin->incoming(); p = p != lastXCombPtr()->lastParticles().second ? lastXCombPtr()->lastParticles().second : PPtr(); } if ( bin || p ) continue; sel = partonBins()[i]; break; } if ( !sel.first || !sel.second ) Throw() << "Could not find appropriate " << "PartonBin objects for event in " << "MatchingHandler " << Exception::runerror; // create the new parton bin instances Direction<0> dir(true); PBIPair partonBinInstances; // temporary mother/daugther settings // to get parton bin instances correct lastXCombPtr()->lastParticles().first ->addChild(incoming.first ); lastXCombPtr()->lastParticles().second->addChild(incoming.second); // make the parton bin instances partonBinInstances.first = new_ptr(PartonBinInstance(incoming.first, sel.first, lastXCombPtr()->partonBinInstances().first->scale())); dir.reverse(); partonBinInstances.second = new_ptr(PartonBinInstance(incoming.second, sel.second, lastXCombPtr()->partonBinInstances().second->scale())); // remove temporary mother/daugther settings lastXCombPtr()->lastParticles().first ->abandonChild(incoming.first ); lastXCombPtr()->lastParticles().second->abandonChild(incoming.second); // set the parton bin instances lastXCombPtr()->setPartonBinInstances(partonBinInstances, lastXCombPtr()->lastScale()); // momenta of the time like partons vector meMomenta; vector mePartonData; vector branchings; for( it = hardTree().tree()->branchings().begin(); it != hardTree().tree()->branchings().end(); ++it ) { if( (**it).status() == HardBranching::Outgoing ) { meMomenta.push_back( (**it).showerMomentum() ); mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); branchings.push_back(*it); } } // order of the outgoing partons for(int ix=2;ixpartons().size());++ix) { for(int iy=ix-2;iypartons()[ix]==mePartonData[iy]) { if(ix!=iy) { swap(mePartonData[ix-2],mePartonData[iy]); swap(meMomenta [ix-2],meMomenta [iy]); swap(branchings [ix-2],branchings [iy]); } break; } } } // time like particles int io = meMomenta.size(); PVector tlike(diagram->allPartons().size() - diagram->nSpace()); vector tBranchings; tPVector out; for ( int i = diagram->allPartons().size() - 1; i >= diagram->nSpace(); --i ) { int it = i - diagram->nSpace(); pair ch = diagram->children(i); bool iso = ch.first < 0; if ( iso ) { tlike[it] = diagram->allPartons()[i]->produceParticle(meMomenta[--io]); } else { Lorentz5Momentum p = tlike[ch.first - diagram->nSpace()]->momentum() + tlike[ch.second - diagram->nSpace()]->momentum(); tlike[it] = diagram->allPartons()[i]->produceParticle(p); } if ( diagram->parent(i) < diagram->nSpace() ) { slike[diagram->parent(i)]->addChild(tlike[it]); if ( diagram->parent(i) == diagram->nSpace() - 2 ) slike[diagram->parent(i) + 1]->addChild(tlike[it]); } if ( !iso ) { tlike[it]->addChild(tlike[ch.first - diagram->nSpace()]); tlike[it]->addChild(tlike[ch.second - diagram->nSpace()]); } if ( iso ) { out.push_back(tlike[it]); tBranchings.push_back(branchings[io]); } else newSubProcess->addIntermediate(tlike[it], false); } ret.insert(ret.end(), tlike.begin(), tlike.end()); // select the colour structure now const ColourLines & cl = matrixElement()->selectColourGeometry(hardTree().diagram()); cl.connect(ret); // add the particles for ( int i = 0, N = out.size(); i < N; ++i ) { tPPtr particle = out[mirror ? i: out.size() - i - 1]; // if not including decays add as outgoing if(!includeDecays_) { newSubProcess->addOutgoing(particle, false); continue; } HardBranchingPtr branching = tBranchings[mirror ? i: out.size() - i - 1]; // move to end of chain for time-like branchings while(!branching->children().empty()) { bool found=false; for(unsigned int ix=0;ixchildren().size();++ix) { if(branching->children()[ix]->branchingParticle()->id()== branching->branchingParticle()->id()) { found = true; branching = branching->children()[ix]; break; } } if(!found) break; } // check if from decay map::const_iterator pit = parent(branching->branchingParticle()); // if not add as outgoing if(pit==decayingParticles_.end()) { newSubProcess->addOutgoing(particle, false); continue; } LorentzRotation decayBoost = branching->showerBoost(); // final boost if FSR Lorentz5Momentum pShower = decayBoost*(pit->first->momentum()); decayBoost = LorentzRotation(-pShower.boostVector())*decayBoost; decayBoost = LorentzRotation(particle->momentum().boostVector())*decayBoost; // add decayed particle as intermediate newSubProcess->addIntermediate(particle,false); // add decay products addDecayProducts(newSubProcess,particle,pit,decayBoost); } for ( PVector::size_type i = 0; i < slike.size() - 2; ++i ) { pair ch = diagram->children(i); slike[ch.first]->set5Momentum(slike[i]->momentum() - tlike[ch.second - diagram->nSpace()]->momentum()); } // // set parents of incoming particles?? // PPair inParents = lastXCombPtr()->lastParticles(); // if( incoming.first->momentum().z() / inParents.first->momentum().z() < 0.) // swap( inParents.first, inParents.second ); // if( remnants.first->momentum().z() / inParents.first->momentum().z() < 0.) // swap( remnants.first, remnants.second ); // if (incoming.first ->parents().empty()) { // inParents.first ->addChild(incoming.first ); // inParents.first ->addChild(remnants.first ); // } // if (incoming.second->parents().empty()){ // inParents.second->addChild(incoming.second); // inParents.second->addChild(remnants.second); // } // set the subprocess lastXCombPtr()->subProcess( newSubProcess ); decayingParticles_.clear(); return true; } void MatchingHandler::findDecayingParticles(PPtr parent) { ParticleVector decayProducts; for(unsigned int ix=0;ixchildren().size();++ix) { decayProducts.push_back(parent->children()[ix]); if(!parent->children()[ix]->children().empty()) findDecayingParticles(parent->children()[ix]); } if(decayingParticles_.find(parent)==decayingParticles_.end()) decayingParticles_[parent] = decayProducts; } PotentialTree MatchingHandler::doClustering() { noShowerHists_ = false; // clear storage of the protoTrees protoBranchings().clear(); protoTrees().clear(); nonOrderedTrees_.clear(); hardTrees_.clear(); assert( matrixElement() ); // get particles from the XComb object ParticleVector outgoing = lastXCombPtr()->subProcess()->outgoing(); PPair incoming = lastXCombPtr()->subProcess()->incoming(); // storage of decayed particles decayingParticles_.clear(); // all outgoing particles as a set for checking set outgoingset(outgoing.begin(),outgoing.end()); // loop through the FS particles and create ProtoBranchings for( unsigned int i = 0; i < outgoing.size(); ++i) { tPPtr parent = outgoing[i]->parents()[0]; bool decayProd = decayProduct(parent,lastXCombPtr()->subProcess()); if(!decayProd||!includeDecays_) { ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(outgoing[i]->dataPtr(),HardBranching::Outgoing, outgoing[i]->momentum(),tSudakovPtr())); protoBranchings().insert(currentBranching); } else { bool isHard = true; PPtr newParent = findParent(parent,isHard,outgoingset,false, lastXCombPtr()->subProcess()); assert(newParent); if(decayingParticles_.find(newParent)==decayingParticles_.end()) { ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(newParent->dataPtr(),HardBranching::Outgoing, newParent->momentum(),tSudakovPtr())); protoBranchings().insert(currentBranching); findDecayingParticles(newParent); } } } // add IS hardBranchings ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(incoming.first ->dataPtr(),HardBranching::Incoming, incoming.first ->momentum(),tSudakovPtr())); protoBranchings().insert(currentBranching); currentBranching = new_ptr(ProtoBranching(incoming.second->dataPtr(),HardBranching::Incoming, incoming.second->momentum(),tSudakovPtr())); protoBranchings().insert(currentBranching); //create and initialise the first tree ProtoTreePtr initialProtoTree = new_ptr( ProtoTree() ); for(set::const_iterator it=protoBranchings().begin(); it!=protoBranchings().end();++it) { initialProtoTree->addBranching(*it); } //fill _proto_trees with all possible trees protoTrees().insert(initialProtoTree ); fillProtoTrees( initialProtoTree ); double totalWeight = 0., nonOrderedWeight = 0.; // create a HardTree from each ProtoTree and fill hardTrees() for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { PotentialTree newTree; newTree.tree((**cit).createHardTree()); // check the created CKKWTree corresponds to an allowed LO configuration // (does matrix element have a corresponding diagram) double meWgt = getDiagram( newTree ); if( !newTree.diagram() ) continue; // set the beam particles PPair beams = lastXCombPtr()->lastParticles(); // remove children of beams PVector beam_children = beams.first->children(); if( (**newTree.tree()->incoming().begin()).branchingParticle()->momentum().z() / beams.first->momentum().z() < 0.) swap( beams.first, beams.second ); set::iterator it = newTree.tree()->incoming().begin(); HardBranchingPtr br = *it; br->beam( beams.first ); while ( !br->children().empty() ) { for(unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.first ); } ++it; br = *it; br->beam( beams.second ); while ( !br->children().empty() ) { for( unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.second ); } // do inverse momentum reconstruction if( !kinematicsReconstructor() ->deconstructHardJets( newTree.tree(), evolver(), ShowerInteraction::QCD ) ) continue; newTree.tree()->findNodes(); if( newTree.tree()->ordered() ) { // find the wgt and fill hardTrees() map double treeWeight = 1.; if(reWeight_) treeWeight = meWgt*sudakovWeight( newTree.tree() ); newTree.weight(treeWeight); hardTrees_.push_back( make_pair( newTree, treeWeight ) ); totalWeight += treeWeight; } else { nonOrderedTrees_.push_back( make_pair( newTree, 1. ) ); nonOrderedWeight += 1.; } } // if rejecting non-ordered trees return if( hardTrees_.empty() && rejectNonAO_ ) return PotentialTree(); // select the tree PotentialTree chosen_hardTree=chooseHardTree(totalWeight, nonOrderedWeight); protoBranchings().clear(); protoTrees().clear(); nonOrderedTrees_.clear(); hardTrees_.clear(); if(! chosen_hardTree.tree() ) { noShowerHists_ = true; return PotentialTree(); } else return chosen_hardTree; } void MatchingHandler::initialiseMatching(int minMult, int maxMult) { if (!matrixElement_){ tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); tStdXCombPtr headXC = lastXC->head(); if (headXC) matrixElement_ = dynamic_ptr_cast(headXC->matrixElement()); else if (lastXC) matrixElement_ = dynamic_ptr_cast(lastXC->matrixElement()); } HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); assert(matrixElement_); // check multiplicity of FS partons int nOut = lastXCombPtr()->subProcess()->outgoing().size(); // is it the lowest multiplicity lowestMult_ = nOut == minMult; // or the highest highestMult_ = nOut == maxMult; // centre-of-mass energy sHat(lastXCombPtr()->lastSHat()); // scale for the PDFs pdfScale(sqrt(lastXCombPtr()->lastScale())); // alphaS value used by the ME generate alphaSMG(lastXCombPtr()->lastAlphaS()); // create a hard tree by clustering the event hardTree(doClustering()); } map::const_iterator MatchingHandler::parent(PPtr parent) { long id = parent->id(); for(map::const_iterator it = decayingParticles_.begin(); it!=decayingParticles_.end();++it) { if(id!=it->first->id()) continue; Energy2 diff = sqr(it->first->momentum().x()-parent->momentum().x()) + sqr(it->first->momentum().y()-parent->momentum().y()) + sqr(it->first->momentum().z()-parent->momentum().z()) + sqr(it->first->momentum().t()-parent->momentum().t()); Energy2 sum = sqr(it->first->momentum().x()+parent->momentum().x()) + sqr(it->first->momentum().y()+parent->momentum().y()) + sqr(it->first->momentum().z()+parent->momentum().z()) + sqr(it->first->momentum().t()+parent->momentum().t()); double ratio = diff/sum; if(ratio<1e-10) return it; } return decayingParticles_.end(); } void MatchingHandler::addDecayProducts(SubProPtr subProcess, PPtr parent, map::const_iterator decay, const LorentzRotation & boost) const { // map colours of the parent map cmap; if(parent->colourLine()) cmap.insert(make_pair(decay->first-> colourLine(), parent-> colourLine())); if(parent->antiColourLine()) cmap.insert(make_pair(decay->first->antiColourLine(), parent->antiColourLine())); // add the decay products for(unsigned int ix=0;ixsecond.size();++ix) { Lorentz5Momentum pnew = boost*decay->second[ix]->momentum(); PPtr newParticle = decay->second[ix]->dataPtr()->produceParticle(pnew); parent->addChild(newParticle); if(decay->second[ix]->colourLine()) { if(cmap.find(decay->second[ix]->colourLine())==cmap.end()) { ColinePtr newLine(new_ptr(ColourLine())); cmap.insert(make_pair(decay->second[ix]->colourLine(),newLine)); } cmap[decay->second[ix]->colourLine()]->addColoured(newParticle); } if(decay->second[ix]->antiColourLine()) { if(cmap.find(decay->second[ix]->antiColourLine())==cmap.end()) { ColinePtr newLine(new_ptr(ColourLine())); cmap.insert(make_pair(decay->second[ix]->antiColourLine(),newLine)); } cmap[decay->second[ix]->antiColourLine()]->addAntiColoured(newParticle); } map::const_iterator pit = decayingParticles_.find(decay->second[ix]); if(pit!=decayingParticles_.end()) { subProcess->addIntermediate(newParticle, false); addDecayProducts(subProcess,newParticle,pit,boost); } else { subProcess->addOutgoing(newParticle, false); } } } diff --git a/Shower/QTilde/Matching/PowhegHandler.cc b/Shower/QTilde/Matching/PowhegHandler.cc --- a/Shower/QTilde/Matching/PowhegHandler.cc +++ b/Shower/QTilde/Matching/PowhegHandler.cc @@ -1,167 +1,167 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the PowhegHandler class. // #include "PowhegHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/PDF/PDF.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h" using namespace Herwig; IBPtr PowhegHandler::clone() const { return new_ptr(*this); } IBPtr PowhegHandler::fullclone() const { return new_ptr(*this); } void PowhegHandler::persistentOutput(PersistentOStream & os) const { os << pTDefinition_ << ounit(maxpT_,GeV); } void PowhegHandler::persistentInput(PersistentIStream & is, int) { is >> pTDefinition_ >> iunit(maxpT_,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigPowhegHandler("Herwig::PowhegHandler", "HwMatching.so"); void PowhegHandler::Init() { static ClassDocumentation documentation ("The PowhegHandler class handles the generation of the shower, including truncated" "showers for external processes using the POWHEG scheme."); static Switch interfacepTDefinition ("pTDefinition", "The choice of the definition of the pT for the maximum emission in the shower", &PowhegHandler::pTDefinition_, 0, false, false); static SwitchOption interfacepTDefinitionScale (interfacepTDefinition, "Scale", "Use the value of the lastScale(), which if reading Les Houches events is SCALUP", 0); static SwitchOption interfacepTDefinitionScaleAndpT (interfacepTDefinition, "ScaleAndpT", "Use the same choice as scale for non-emission events but the pT of the" " emitted particle for emission events", 1); static SwitchOption interfacepTDefinitionmaxpTAndpT (interfacepTDefinition, "maxpTAndpT", "Use the maxPt value fo non-emission events and the pT of the" " emitted particle for emission events", 2); static Parameter interfacemaxpT ("maxpT", "Maximum pT for emission from non-emission events.", &PowhegHandler::maxpT_, GeV, 1.0*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); } double PowhegHandler::reweightCKKW(int minMult, int maxMult) { // as not reweighting skip if in initialisation if(generator()->state()==InterfacedBase::initializing) return 1.; initialiseMatching(minMult,maxMult); if( ! hardTree().tree() ) return 1.; // update sub process based on hardTree() updateSubProcess(); return 1.; } HardTreePtr PowhegHandler::generateCKKW(ShowerTreePtr tree) const { //get com energy from the progenitors Energy2 s = (tree->incomingLines(). begin()->first->progenitor()->momentum() + tree->incomingLines().rbegin()->first->progenitor()->momentum()).m2(); // Get the HardTree from the CKKW handler. CKKWTreePtr hardtree = getCKKWTree(); // if no hard tree return if( ! hardtree ) return HardTreePtr(); // check the trees match if( ! hardtree->connect(tree) ) return HardTreePtr(); // choice of the veto pT Energy veto_pt = sqrt( s ); // use the scale if(pTDefinition_==0) { veto_pt = sqrt(lastXCombPtr()->lastScale()); } // otherwise pT of emission if emitted else if(!lowestMult()) { veto_pt = hardtree->lowestPt( 1, s ); for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = tree->outgoingLines().begin(); it != tree->outgoingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = tree->incomingLines().begin(); it != tree->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); } } else if(pTDefinition_==1) { veto_pt = sqrt(lastXCombPtr()->lastScale()); } else if(pTDefinition_==2) { veto_pt = maxpT_; } else assert(false); // that's it return hardtree; } PotentialTree PowhegHandler::chooseHardTree(double,double) { PotentialTree chosen_hardTree; Energy min_pt = Constants::MaxEnergy; if( !hardTrees().empty() ){ for(unsigned int ix = 0; ix < hardTrees().size(); ix++ ){ if( hardTrees()[ix].first.tree()->totalPt() < min_pt ) { min_pt = hardTrees()[ix].first.tree()->totalPt(); chosen_hardTree = hardTrees()[ix].first; } } } else { for(unsigned int ix = 0; ix < nonOrderedTrees().size(); ix++ ){ if( nonOrderedTrees()[ix].first.tree()->totalPt() < min_pt ){ min_pt = nonOrderedTrees()[ix].first.tree()->totalPt(); chosen_hardTree=nonOrderedTrees()[ix].first; } } } return chosen_hardTree; } diff --git a/Shower/QTilde/Matching/PowhegShowerHandler.cc b/Shower/QTilde/Matching/PowhegShowerHandler.cc --- a/Shower/QTilde/Matching/PowhegShowerHandler.cc +++ b/Shower/QTilde/Matching/PowhegShowerHandler.cc @@ -1,1103 +1,1103 @@ // -*- C++ -*- // // PowhegShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PowhegShowerHandler class. // #include #include "PowhegShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/DescribeClass.h" // include theses to have complete types #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" #include "Herwig/Shower/QTilde/Base/HardBranching.h" #include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/MatrixElement/HwMEBase.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/MatrixElement/DiagramBase.fh" #include "ThePEG/PDF/PartonExtractor.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/MatrixElement/Matchbox/Utility/DiagramDrawer.h" using namespace Herwig; namespace { struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; } IBPtr PowhegShowerHandler::clone() const { return new_ptr(*this); } IBPtr PowhegShowerHandler::fullclone() const { return new_ptr(*this); } HardTreePtr PowhegShowerHandler::generateCKKW(ShowerTreePtr showerTree) const { // hard subprocess tSubProPtr sub = lastXCombPtr()->subProcess(); // real emission sub-process tSubProPtr real = Factory()->hardTreeSubprocess(); // born emitter emitter_ = Factory()->hardTreeEmitter(); spectator_ = Factory()->hardTreeSpectator(); // if no hard emission return if ( !(real && emitter_>-1) ) return HardTreePtr(); // check emission if(sub->outgoing().size()>=real->outgoing().size()) return HardTreePtr(); // check if decay has radiated don't add it if(showerTree->outgoingLines().size() != sub->outgoing().size()) { // loop over the decay trees for(map >::const_iterator tit=showerTree->treelinks().begin(); tit != showerTree->treelinks().end(); ++tit) { if(tit->first->outgoingLines().empty()) continue; // match the particles set decayProducts; set outgoing(real->outgoing().begin(),real->outgoing().end()); for(map::const_iterator oit=tit->first->outgoingLines().begin(); oit!=tit->first->outgoingLines().end();++oit) { tPPtr decayProd; Energy2 dmin( 1e30*GeV2 ); tPPtr part = oit->second->original(); for( set::const_iterator it = outgoing.begin(); it != outgoing.end(); ++it ) { if((**it).id()!=part->id()) continue; Energy2 dtest = sqr( part->momentum().x() - (**it).momentum().x() ) + sqr( part->momentum().y() - (**it).momentum().y() ) + sqr( part->momentum().z() - (**it).momentum().z() ) + sqr( part->momentum().t() - (**it).momentum().t() ); dtest += 1e10*sqr(part->momentum().m()-(**it).momentum().m()); if( dtest < dmin ) { decayProd = *it; dmin = dtest; } } if(!decayProd) { throw Exception() << "PowhegShowerHandler::generateCKKW(). Can't match shower and hard trees." << Exception::eventerror; } outgoing .erase (decayProd); decayProducts.insert(decayProd); } bool coloured = false, foundParent = true; tPPtr parent,emitted; unsigned int nprod(0); for( set::const_iterator it = decayProducts.begin(); it != decayProducts.end(); ++it ) { coloured |= (**it).dataPtr()->coloured(); tPPtr newParent = !(**it).parents().empty() ? (**it).parents()[0] : tPPtr(); ++nprod; // check if from emission if(newParent->id()==(**it).id()) { if(newParent->children().size()!=2) foundParent=false; bool foundChild(false), foundGluon(false); for(unsigned int ix=0;ixchildren().size();++ix) { if(newParent->children()[ix]==*it) { foundChild = true; continue; } else if(newParent->children()[ix]->id()==ParticleID::g) { foundGluon = true; continue; } } if(foundChild && foundGluon) { newParent = !newParent->parents().empty() ? newParent->parents()[0] : tPPtr(); ++nprod; } else foundParent = false; } if(!newParent) { foundParent = false; } else if(!parent) { parent = newParent; } else { if(parent!=newParent) foundParent = false; } } if(nprod!=tit->first->outgoingLines().size()&&foundParent) { if(decayRadiation_==0) { throw Exception() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "you can either not simulated this process, " << "veto this class of events by using\n" << "set " << fullName() << ":DecayRadiation VetoEvent\n" << "or throw the hard radiation away using \n" << "set " << fullName() << ":DecayRadiation VetoRadiation\n" << "Please contact us at herwig@hepforge.org for advice\n" << "on how to simulate this process\n" << Exception::runerror; } else if(decayRadiation_==1) { throw Exception() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "vetoing event\n" << Exception::eventerror; } else if(decayRadiation_==2) { generator()->log() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "vetoing radiation\n"; return HardTreePtr(); } else assert(false); } } } tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); tStdXCombPtr headXC = lastXC->head(); if (headXC) matrixElement_ = dynamic_ptr_cast(headXC->matrixElement()); else if (lastXC) matrixElement_ = dynamic_ptr_cast(lastXC->matrixElement()); if (lastXC){ tStdXCombPtr projector= lastXC->lastProjector(); if (projector){ matrixElement_ = dynamic_ptr_cast(projector->matrixElement()); setSubtractionIntegral(true); } else setSubtractionIntegral(false); } assert(matrixElement_); // create a hard tree by clustering the event try { hardTree(doClustering(real,showerTree)); } catch(exception &e) { throw Exception() << "Caught a problem in PowhegShowerHandler::doClustering " << e.what() << Exception::eventerror; } // Get the HardTree from the CKKW handler. CKKWTreePtr hardtree = hardTree().tree(); // zero to avoid MPI problems Factory()->setHardTreeEmitter(-1); Factory()->setHardTreeSubprocess(SubProPtr()); return hardtree; } PotentialTree PowhegShowerHandler::doClustering(tSubProPtr real,ShowerTreePtr showerTree) const { // clear storage of the protoTrees protoBranchings().clear(); protoTrees().clear(); hardTrees_.clear(); assert( matrixElement() ); // extract the XComb for the Born process tStdXCombPtr lastXC; if (subtractionIntegral()){ tStdXCombPtr lastXCReal = dynamic_ptr_cast(lastXCombPtr()); lastXC = lastXCReal->lastProjector(); } else lastXC = dynamic_ptr_cast(lastXCombPtr()); const StandardXComb xc= *lastXC; // get the particles for the born process PPair incomingBorn = xc.subProcess()->incoming(); ParticleVector outgoingBorn = xc.subProcess()->outgoing(); // get particles from the XComb object for the real process ParticleVector outgoing = real->outgoing(); PPair incoming = real->incoming(); // loop through the FS particles and create ProtoBranchings for( unsigned int i = 0; i < outgoing.size(); ++i) { tPPtr parent = outgoing[i]->parents()[0]; ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(outgoing[i]->dataPtr(),HardBranching::Outgoing, outgoing[i]->momentum(),tSudakovPtr())); currentBranching-> colourLine(outgoing[i]-> colourLine()); currentBranching->antiColourLine(outgoing[i]->antiColourLine()); protoBranchings().insert(currentBranching); } // add IS hardBranchings ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(incoming.first ->dataPtr(),HardBranching::Incoming, incoming.first ->momentum(),tSudakovPtr())); currentBranching-> colourLine(incoming.first-> colourLine()); currentBranching->antiColourLine(incoming.first->antiColourLine()); protoBranchings().insert(currentBranching); currentBranching = new_ptr(ProtoBranching(incoming.second->dataPtr(),HardBranching::Incoming, incoming.second->momentum(),tSudakovPtr())); currentBranching-> colourLine(incoming.second-> colourLine()); currentBranching->antiColourLine(incoming.second->antiColourLine()); protoBranchings().insert(currentBranching); // create and initialise the first tree ProtoTreePtr initialProtoTree = new_ptr( ProtoTree() ); for(set::const_iterator it=protoBranchings().begin(); it!=protoBranchings().end();++it) { initialProtoTree->addBranching(*it); } // fill _proto_trees with all possible trees protoTrees().insert(initialProtoTree ); fillProtoTrees( initialProtoTree , xc.mePartonData()[emitter_]->id() ); // create a HardTree from each ProtoTree and fill hardTrees() for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { set bornParticles(outgoingBorn.begin(),outgoingBorn.end()); bornParticles.insert(incomingBorn.first ); bornParticles.insert(incomingBorn.second); PotentialTree newTree; newTree.tree((**cit).createHardTree()); // new check based on the colour structure map cmap; // make the colour connections in the tree ShowerParticleVector branchingParticles; map branchingMap; bool matched(true); int iemitter(-1); HardBranchingPtr emitter; map locMap; for( set< HardBranchingPtr >::iterator it = newTree.tree()->branchings().begin(); it != newTree.tree()->branchings().end(); ++it ) { matched = true; // map the particle to the branching for future use branchingParticles.push_back((**it).branchingParticle()); branchingMap.insert(make_pair((**it).branchingParticle(),*it)); tPPtr bornPartner; if((**it).status()==HardBranching::Incoming) { HardBranchingPtr parent=*it; while(parent->parent()) { parent = parent->parent(); }; if(parent->branchingParticle()->momentum().z()/incomingBorn.first->momentum().z()>0.) { bornPartner = incomingBorn.first; if(!parent->children().empty()) { iemitter = 0; emitter = *it; } locMap[0] = *it; } else { bornPartner = incomingBorn.second; if(!parent->children().empty()) { iemitter = 1; emitter = *it; } locMap[1] = *it; } } else { Energy2 dmin( 1e30*GeV2 ); for(set::const_iterator bit=bornParticles.begin();bit!=bornParticles.end(); ++bit) { if((**it).branchingParticle()->id()!=(**bit).id()) continue; if(*bit==incomingBorn.first||*bit==incomingBorn.second) continue; Energy2 dtest = sqr( (**bit).momentum().x() - (**it).branchingParticle()->momentum().x() ) + sqr( (**bit).momentum().y() - (**it).branchingParticle()->momentum().y() ) + sqr( (**bit).momentum().z() - (**it).branchingParticle()->momentum().z() ) + sqr( (**bit).momentum().t() - (**it).branchingParticle()->momentum().t() ); dtest += 1e10*sqr((**bit).momentum().m()-(**it).branchingParticle()->momentum().m()); if( dtest < dmin ) { bornPartner = *bit; dmin = dtest; } } // find the map int iloc(-1); for(unsigned int ix=0;ixcolourLine()) { if(cmap.find((**it).branchingParticle()->colourLine())!=cmap.end()) { if(cmap[(**it).branchingParticle()->colourLine()]!=bornPartner->colourLine()) { matched=false; } } else { cmap[(**it).branchingParticle()->colourLine()] = bornPartner->colourLine(); } } if((**it).branchingParticle()->antiColourLine()) { if(cmap.find((**it).branchingParticle()->antiColourLine())!=cmap.end()) { if(cmap[(**it).branchingParticle()->antiColourLine()]!=bornPartner->antiColourLine()) { matched=false; } } else { cmap[(**it).branchingParticle()->antiColourLine()] = bornPartner->antiColourLine(); } } // require a match if(!matched) break; } // if no match continue if(!matched) continue; // now sort out any decays if(showerTree->outgoingLines().size()+showerTree->incomingLines().size() != newTree.tree()->branchings().size()) { if(showerTree->treelinks().empty()) { matched = false; continue; } // loop over the decay trees for(map >::const_iterator tit=showerTree->treelinks().begin(); tit != showerTree->treelinks().end(); ++tit) { if(tit->first->outgoingLines().empty()) continue; set decayProducts; set branchings = newTree.tree()->branchings(); // match the particles for(map::const_iterator oit=tit->first->outgoingLines().begin(); oit!=tit->first->outgoingLines().end();++oit) { HardBranchingPtr decayProd; Energy2 dmin( 1e30*GeV2 ); tPPtr part = oit->second->original(); for( set< HardBranchingPtr >::iterator it = branchings.begin(); it != branchings.end(); ++it ) { if((**it).status()==HardBranching::Incoming ) continue; if((**it).branchingParticle()->id()!=part->id()) continue; Energy2 dtest = sqr( part->momentum().x() - (**it).branchingParticle()->momentum().x() ) + sqr( part->momentum().y() - (**it).branchingParticle()->momentum().y() ) + sqr( part->momentum().z() - (**it).branchingParticle()->momentum().z() ) + sqr( part->momentum().t() - (**it).branchingParticle()->momentum().t() ); dtest += 1e10*sqr(part->momentum().m()-(**it).branchingParticle()->momentum().m()); if( dtest < dmin ) { decayProd = *it; dmin = dtest; } } if(!decayProd) { throw Exception() << "PowhegShowerHandler::generateCKKW(). Can't match shower and hard trees." << Exception::eventerror; } branchings .erase (decayProd); decayProducts.insert(decayProd); } // erase the decay products Lorentz5Momentum pnew,pshower; for(set::iterator it = decayProducts.begin(); it!=decayProducts.end(); ++it) { newTree.tree()->branchings().erase(*it); pnew += (**it).branchingParticle()->momentum(); pshower += (**it).showerMomentum(); } pnew .setMass(tit->second.second->mass()); pshower.setMass(tit->second.second->mass()); pnew .rescaleEnergy(); pshower.rescaleEnergy(); // create the decaying particle ShowerParticlePtr particle = new_ptr( ShowerParticle( tit->second.second->dataPtr() , true ) ); particle->set5Momentum( pnew ); HardBranchingPtr newBranch = new_ptr( HardBranching( particle, tSudakovPtr(), HardBranchingPtr(), HardBranching::Outgoing ) ); newBranch->showerMomentum(pshower); newTree.tree()->branchings().insert(newBranch); } } // if no match continue if(!matched) continue; // find the colour partners try { partnerFinder() ->setInitialEvolutionScales(branchingParticles,false, ShowerInteraction::QCD,true); } catch( Exception & e ) { generator()->log() << "Problem in set evolution scales in " << "PowhegShowerHandler::doClustering(). Exception was" << e.what(); continue; } for(unsigned int ix=0;ixpartner()) { HardBranchingPtr partner = branchingMap[branchingParticles[ix]->partner()]; branchingMap[branchingParticles[ix]]->colourPartner(partner); } } if(forcePartners_) { locMap[emitter_ ]->colourPartner(locMap[spectator_]); locMap[spectator_]->colourPartner(locMap[emitter_ ]); locMap[emitter_ ]->branchingParticle()->partner(locMap[spectator_]->branchingParticle()); locMap[spectator_]->branchingParticle()->partner(locMap[emitter_ ]->branchingParticle()); } newTree.tree()->partnersSet(true); // set the beam particles PPair beams = lastXCombPtr()->lastParticles(); // remove children of beams PVector beam_children = beams.first->children(); if( (**newTree.tree()->incoming().begin()).branchingParticle()->momentum().z() / beams.first->momentum().z() < 0.) swap( beams.first, beams.second ); set::iterator it = newTree.tree()->incoming().begin(); HardBranchingPtr br = *it; br->beam( beams.first ); while ( !br->children().empty() ) { for(unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.first ); } ++it; br = *it; br->beam( beams.second ); while ( !br->children().empty() ) { for( unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.second ); } // check the emitter and the spectator some how if(iemitter!=emitter_) continue; //do inverse momentum reconstruction if( !kinematicsReconstructor() ->deconstructHardJets( newTree.tree(), ShowerInteraction::QCD ) ) continue; newTree.tree()->findNodes(); newTree.weight(1.); hardTrees_.push_back( make_pair( newTree, 1. ) ); } // select the tree PotentialTree chosen_hardTree; if (hardTrees_.size()==1) { chosen_hardTree = hardTrees_[0].first; } else { // if multiple trees pick the one with matching // intermediate particle momenta for (unsigned int il=0; il > particles; PotentialTree testTree = hardTrees_[il].first; CKKWTreePtr check = testTree.tree(); // get id and momenta of particles in hard tree for (set< HardBranchingPtr >::iterator it=check->branchings().begin(); it!=check->branchings().end(); ++it) { particles.push_back(make_pair((*it)->branchingParticle()->id(), (*it)->branchingParticle()->momentum())); if (!(*it)->children().empty()){ for (unsigned int ic=0; ic<(*it)->children().size(); ++ic) particles.push_back(make_pair((*it)->children()[ic]->branchingParticle()->id(), (*it)->children()[ic]->branchingParticle()->momentum())); } if ((*it)->parent()){ particles.push_back(make_pair((*it)->parent()->branchingParticle()->id(), (*it)->parent()->branchingParticle()->momentum())); if (!(*it)->parent()->children().empty()) { for (unsigned int ic=0; ic<(*it)->parent()->children().size(); ++ic) { if(*it==(*it)->parent()->children()[ic]) continue; particles.push_back(make_pair((*it)->parent()->children()[ic]->branchingParticle()->id(), (*it)->parent()->children()[ic]->branchingParticle()->momentum())); } } } } // loop through and match to particles in real subprocess vector >::iterator part = particles.begin(); // incoming for (; part!=particles.end(); ++part){ if ((*part).first==real->incoming().first->id() && fuzzyEqual((*part).second, real->incoming().first->momentum())) break; } if (part!=particles.end()) particles.erase(part); part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->incoming().second->id() && fuzzyEqual((*part).second, real->incoming().second->momentum())) break; } if (part!=particles.end()) particles.erase(part); // outgoing for (unsigned int io=0; iooutgoing().size(); ++io){ part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->outgoing()[io]->id() && fuzzyEqual((*part).second, real->outgoing()[io]->momentum())) break; } if (part!=particles.end()) particles.erase(part); } // intermediate for (unsigned int ii=0; iiintermediates().size(); ++ii){ part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->intermediates()[ii]->id() && fuzzyEqual((*part).second, real->intermediates()[ii]->momentum())) break; } if (part!=particles.end()) particles.erase(part); } // intermediate CC with -1*momentum for (unsigned int ii=0; iiintermediates().size(); ++ii){ part = particles.begin(); for (; part!=particles.end(); ++part){ if (!real->intermediates()[ii]->coloured() || (real->intermediates()[ii]->hasColour() && real->intermediates()[ii]->hasAntiColour())){ if ((*part).first==real->intermediates()[ii]->id() && fuzzyEqual((*part).second, -1.*real->intermediates()[ii]->momentum()) ) break; } else { if ((*part).first==-1.*real->intermediates()[ii]->id() && fuzzyEqual((*part).second, -1.*real->intermediates()[ii]->momentum()) ) break; } } if (part!=particles.end()) particles.erase(part); } // if all particles match, set as hardtree if (particles.empty()){ chosen_hardTree = testTree; break; } } } protoBranchings().clear(); protoTrees().clear(); hardTrees_.clear(); if(! chosen_hardTree.tree() ) { return PotentialTree(); } else return chosen_hardTree; } bool PowhegShowerHandler::checkDiagram(PotentialTree & tree, tcDiagPtr loDiagram) const { set::const_iterator cit; tcPDPair incoming; multiset outgoing; //get the incoming and outgoing partons involved in hard process for( cit = tree.tree()->branchings().begin(); cit != tree.tree()->branchings().end(); ++cit ){ if( (*cit)->status() ==HardBranching::Incoming) { HardBranchingPtr parent = *cit; while(parent->parent()) parent = parent->parent(); if( parent->branchingParticle()->momentum().z()>ZERO ) incoming.first = (*cit)->branchingParticle()->dataPtr(); else incoming.second = (*cit)->branchingParticle()->dataPtr(); } else { outgoing.insert( (*cit)->branchingParticle()->dataPtr() ); } } if(!incoming.first || !incoming.second) return 0.; pair tag; tag.first = incoming.first ->PDGName() + "," + incoming.second->PDGName() + "->"; tag.second = incoming.second ->PDGName() + "," + incoming.first ->PDGName() + "->"; string tag_out; for ( multiset::iterator i = outgoing.begin(); i != outgoing.end(); ++i ) { if ( i != outgoing.begin() ) tag_out += ","; tag_out += (**i).PDGName(); } tag.first += tag_out; tag.second += tag_out; // find the diagrams if( tag.first == loDiagram->getTag() || tag.second == loDiagram->getTag() ) tree.diagram(loDiagram); // check this is allowed return tree.diagram(); } void PowhegShowerHandler::fillProtoTrees( ProtoTreePtr currentProtoTree,long id ) const { if(currentProtoTree->branchings().size()==(lastXCombPtr()->subProcess()->outgoing().size()+2)) return; for( set::const_iterator ita = currentProtoTree->branchings().begin(); ita!=currentProtoTree->branchings().end();++ita) { for( set::const_iterator itb = currentProtoTree->branchings().begin(); itb!=ita;++itb) { // can't merge two incoming branchings if( (**ita).status() == HardBranching::Incoming && (**itb).status() == HardBranching::Incoming ) continue; // if branching must be outgoing, skip incoming if(emitter_>=2 && ( (**ita).status() == HardBranching::Incoming || (**itb).status() == HardBranching::Incoming )) continue; // if branching must be incoming, skip outgoing if(emitter_<2 && ( (**ita).status() != HardBranching::Incoming && (**itb).status() != HardBranching::Incoming )) continue; // get a new branching for this pair ProtoBranchingPtr currentBranching = getCluster(*ita,*itb); // check branching with the right PID if( ! currentBranching || currentBranching->id() != id) continue; // branching allowed so make a new Tree out of these branchings set< tProtoBranchingPtr > newTreeBranchings = currentProtoTree->branchings(); newTreeBranchings.erase(*ita); newTreeBranchings.erase(*itb); newTreeBranchings.insert(currentBranching); ProtoTreePtr newProtoTree = new_ptr( ProtoTree( newTreeBranchings ) ); // remove duplicate trees if( ! repeatProtoTree( newProtoTree ) ) protoTrees().insert( newProtoTree ); // remove the current tree if it hasn't already been removed if( protoTrees().find( currentProtoTree ) != protoTrees().end() ) protoTrees().erase( currentProtoTree ); // do recursion fillProtoTrees( newProtoTree , id); } } } bool PowhegShowerHandler::repeatProtoTree( ProtoTreePtr currentProtoTree ) const { // loop over all prototrees and see // how many ProtoBranchings of current ProtoTree are found in each for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { unsigned int no_matches = 0; for( set< tProtoBranchingPtr >::const_iterator ckt = currentProtoTree->branchings().begin(); ckt != currentProtoTree->branchings().end(); ckt++ ) { if( (*cit)->branchings().find( *ckt ) != (*cit)->branchings().end() ) ++no_matches; } // return true if all match if( no_matches == currentProtoTree->branchings().size() ) return true; } return false; } tProtoBranchingPtr PowhegShowerHandler::getCluster( tProtoBranchingPtr b1, tProtoBranchingPtr b2 ) const { // look for the clustered pair in protoBranchings_ for(set::const_iterator cit = protoBranchings().begin(); cit != protoBranchings().end(); ++cit) { // both outgoing if(b1->status()==HardBranching::Outgoing && b2->status()==HardBranching::Outgoing) { if((**cit).status()!=HardBranching::Outgoing|| (**cit).children().empty()) continue; if( ( b1 == (**cit).children()[0] && b2 == (**cit).children()[1] ) || ( b1 == (**cit).children()[1] && b2 == (**cit).children()[0] ) ) return *cit; } // first incoming else if(b1->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b1!=(**cit).backChildren()[0]) continue; if(b2==(**cit).backChildren()[1]) return *cit; } // second incoming else if(b2->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b2!=(**cit).backChildren()[0]) continue; if(b1==(**cit).backChildren()[1]) return *cit; } } // is branching incoming or outgoing bool incoming = b1->status()==HardBranching::Incoming || b2->status()==HardBranching::Incoming; // get the branching BranchingElement theBranching; if( !incoming ) theBranching = allowedFinalStateBranching( b1, b2 ); else theBranching = allowedInitialStateBranching( b1, b2 ); //if branching is not allowed return null ProtoBrancing if( !theBranching.sudakov ) return ProtoBranchingPtr(); // get the ParticleData object for the new branching tcPDPtr particle_data = incoming ? theBranching.particles[1] : theBranching.particles[0]; // create clustered ProtoBranching ProtoBranchingPtr clusteredBranch; // outgoing if( !incoming ) { Lorentz5Momentum pairMomentum = b1->momentum() + b2->momentum(); pairMomentum.setMass(ZERO); clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Outgoing, pairMomentum, theBranching.sudakov)); if(particle_data->iColour()==PDT::Colour0) return ProtoBranchingPtr(); else if(particle_data->iColour()==PDT::Colour3) { if(b1->particle()->iColour()==PDT::Colour3 && b2->particle()->iColour()==PDT::Colour8) { if(b1->colourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->colourLine(b2->colourLine()); } else if(b2->particle()->iColour()==PDT::Colour3 && b1->particle()->iColour()==PDT::Colour8) { if(b2->colourLine()!=b1->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->colourLine()); } else assert(false); clusteredBranch->type(ShowerPartnerType::QCDColourLine); } else if(particle_data->iColour()==PDT::Colour3bar) { if(b1->particle()->iColour()==PDT::Colour3bar && b2->particle()->iColour()==PDT::Colour8) { if(b1->antiColourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b2->antiColourLine()); } else if(b2->particle()->iColour()==PDT::Colour3bar && b1->particle()->iColour()==PDT::Colour8) { if(b2->antiColourLine()!=b1->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->antiColourLine()); } else assert(false); clusteredBranch->type(ShowerPartnerType::QCDAntiColourLine); } else if(particle_data->iColour()==PDT::Colour8) { tProtoBranchingPtr coloured,antiColoured; if(b1->particle()->iColour()==PDT::Colour3 && b2->particle()->iColour()==PDT::Colour3bar) { coloured = b1; antiColoured = b2; } else if(b2->particle()->iColour()==PDT::Colour3 && b1->particle()->iColour()==PDT::Colour3bar) { coloured = b2; antiColoured = b1; } else if(b1->particle()->iColour()==PDT::Colour8 && b2->particle()->iColour()==PDT::Colour8 ) { if(b1->colourLine()==b2->antiColourLine()) { coloured = b2; antiColoured = b1; } else if(b2->colourLine()==b1->antiColourLine()) { coloured = b1; antiColoured = b2; } else return ProtoBranchingPtr(); } else assert(false); // can't have colour self connected gluons if(coloured-> colourLine()==antiColoured->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine( coloured-> colourLine()); clusteredBranch->antiColourLine(antiColoured->antiColourLine()); // softest particle is the emitted if(coloured->momentum().t()>antiColoured->momentum().t()) { clusteredBranch->type(ShowerPartnerType::QCDAntiColourLine); } else { clusteredBranch->type(ShowerPartnerType::QCDColourLine); } } else assert(false); } // incoming else { Lorentz5Momentum pairMomentum = b1->momentum() - b2->momentum(); pairMomentum.setMass( ZERO ); // check for CC if( particle_data->CC() && ( b1->id() != theBranching.particles[0]->id() || b2->id() != theBranching.particles[2]->id() ) ) { particle_data = particle_data->CC(); } clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Incoming, pairMomentum,theBranching.sudakov)); // work out the type of branching if(b1->particle()->iColour()==PDT::Colour3) { b1->type(ShowerPartnerType::QCDColourLine); if(b2->particle()->iColour()==PDT::Colour3 && particle_data->iColour()==PDT::Colour8) { if(b1->colourLine()==b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b1->colourLine()); clusteredBranch->antiColourLine(b2->colourLine()); } else if(b2->particle()->iColour()==PDT::Colour8 && particle_data->iColour()==PDT::Colour3) { if(b1->colourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->colourLine(b2->antiColourLine()); } else assert(false); } else if(b1->particle()->iColour()==PDT::Colour3bar) { b1->type(ShowerPartnerType::QCDAntiColourLine); if(b2->particle()->iColour()==PDT::Colour3bar && particle_data->iColour()==PDT::Colour8) { if(b1->antiColourLine()==b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b2->antiColourLine()); clusteredBranch->antiColourLine(b1->antiColourLine()); } else if(b2->particle()->iColour()==PDT::Colour8 && particle_data->iColour()==PDT::Colour3bar) { if(b1->antiColourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b2->colourLine()); } else assert(false); } else if(b1->particle()->iColour()==PDT::Colour8) { if(b2->particle()->iColour()==PDT::Colour3) { if(b1->colourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->antiColourLine()); b1->type(ShowerPartnerType::QCDColourLine); } else if(b2->particle()->iColour()==PDT::Colour3bar) { if(b1->antiColourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b1->colourLine()); b1->type(ShowerPartnerType::QCDAntiColourLine); } else if(b2->particle()->iColour()==PDT::Colour8) { if(b1->colourLine()==b2->colourLine()) { b1->type(ShowerPartnerType::QCDColourLine); clusteredBranch->antiColourLine(b1->antiColourLine()); clusteredBranch->colourLine(b2->antiColourLine()); } else if(b1->antiColourLine()==b2->antiColourLine()) { b1->type(ShowerPartnerType::QCDAntiColourLine); clusteredBranch-> colourLine(b1->colourLine()); clusteredBranch->antiColourLine(b2->colourLine()); } else { return ProtoBranchingPtr(); } } else assert(false); } else assert(false); } protoBranchings().insert(clusteredBranch); //set children relations // outgoing if( !incoming ){ clusteredBranch->addChild( b1 ); clusteredBranch->addChild( b2 ); } else { clusteredBranch->addBackChild( b1 ); clusteredBranch->addBackChild( b2 ); } return clusteredBranch; } BranchingElement PowhegShowerHandler:: allowedFinalStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) const { // check with normal ID's pair< long, long > ptest = make_pair( b1->id(), b2->id() ); map< pair< long, long >, BranchingElement >::const_iterator split = allowedFinal_.find(ptest); if( split != allowedFinal_.end() ) { if( split->second.particles[1]->id() != ptest.first ) swap( b1, b2 ); return split->second; } // check with CC if( b1->particle()->CC() ) ptest.first *= -1; if( b2->particle()->CC() ) ptest.second *= -1; split = allowedFinal_.find( ptest ); if( split != allowedFinal_.end() ) { // cc the idlist only be for qbar g clusterings BranchingElement ccBranch = split->second; swap(ccBranch.particles,ccBranch.conjugateParticles); if( split->second.particles[1]->id() != ptest.first ) swap( b1, b2); return ccBranch; } // not found found null pointer return BranchingElement(); } BranchingElement PowhegShowerHandler::allowedInitialStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) const { if(b2->status()==HardBranching::Incoming) swap(b1,b2); // is initial parton an antiparticle bool cc = b1->id() < 0; //gives range of allowedInitial_ with matching first abs( id ) pair< multimap< long, BranchingElement >::const_iterator, multimap< long, BranchingElement >::const_iterator > location = allowedInitial_.equal_range( abs( b1->id() ) ); //iterates over this range for( multimap< long, BranchingElement >::const_iterator it = location.first; it != location.second; ++it ) { long idtest = cc ? it->second.conjugateParticles[2]->id() : it->second.particles[2]->id(); // does second id match the test if( idtest == b2->id() ) return it->second; //if the the IS parton is a gluon and charge conjugate of second parton mathes accept if( idtest == -b2->id() && ! b1->particle()->CC() ) return it->second; } // not found found null pointer return BranchingElement(); } bool PowhegShowerHandler::fuzzyEqual(Lorentz5Momentum a, Lorentz5Momentum b) const{ // check momenta are within 1% of each other if ( (a.e()==ZERO && b.e()==ZERO) || (a.e()/b.e()>0.99 && a.e()/b.e()<1.01) ){ if ((a.x()==ZERO && b.x()==ZERO) || (a.x()/b.x()>0.99 && a.x()/b.x()<1.01) ){ if ((a.y()==ZERO && b.y()==ZERO) || (a.y()/b.y()>0.99 && a.y()/b.y()<1.01) ){ if ((a.z()==ZERO && b.z()==ZERO) || (a.z()/b.z()>0.99 && a.z()/b.z()<1.01) ) return true; } } } return false; } void PowhegShowerHandler::doinit() { QTildeShowerHandler::doinit(); // extract the allowed branchings // final-state for(BranchingList::const_iterator it = splittingGenerator()->finalStateBranchings().begin(); it != splittingGenerator()->finalStateBranchings().end(); ++it) { pair prod(make_pair(it->second.particles[1]->id(), it->second.particles[2]->id())); allowedFinal_.insert(make_pair(prod,it->second)); swap(prod.first,prod.second); allowedFinal_.insert(make_pair(prod,it->second)); } // initial-state for(BranchingList::const_iterator it = splittingGenerator()->initialStateBranchings().begin(); it != splittingGenerator()->initialStateBranchings().end(); ++it) { allowedInitial_.insert(make_pair(it->second.particles[0]->id(),it->second)); } } void PowhegShowerHandler::persistentOutput(PersistentOStream & os) const { os << allowedInitial_ << allowedFinal_ << subtractionIntegral_ << enforceColourConsistency_ << forcePartners_ << decayRadiation_; } void PowhegShowerHandler::persistentInput(PersistentIStream & is, int) { is >> allowedInitial_ >> allowedFinal_ >> subtractionIntegral_ >> enforceColourConsistency_ >> forcePartners_ >> decayRadiation_; } // Static variable needed for the type description system in ThePEG. DescribeClass describeHerwigPowhegShowerHandler("Herwig::PowhegShowerHandler", "HwMatchbox.so HwMatching.so"); void PowhegShowerHandler::Init() { static ClassDocumentation documentation ("The PowhegShowerHandler class"); static Switch interfaceEnforceColourConsistency ("EnforceColourConsistency", "Force the Born and real emission colour flows to be consistent", &PowhegShowerHandler::enforceColourConsistency_, false, false, false); static SwitchOption interfaceEnforceColourConsistencyYes (interfaceEnforceColourConsistency, "Yes", "Enforce the consistency", true); static SwitchOption interfaceEnforceColourConsistencyNo (interfaceEnforceColourConsistency, "No", "Don't enforce consistency", false); static Switch interfaceForcePartners ("ForcePartners", "Whether or not to force the partners to be those from the kinematic generation", &PowhegShowerHandler::forcePartners_, false, false, false); static SwitchOption interfaceForcePartnersYes (interfaceForcePartners, "Yes", "Force them", true); static SwitchOption interfaceForcePartnersNo (interfaceForcePartners, "No", "Don't force them", false); static Switch interfaceDecayRadiation ("DecayRadiation", "Handling of radiation which is interpretted as having come from decays", &PowhegShowerHandler::decayRadiation_, 0, false,false); static SwitchOption interfaceDecayRadiationNotAllowed (interfaceDecayRadiation, "NotAllowed", "Not allowed at all, run error will be thrown", 0); static SwitchOption interfaceDecayRadiationVetoEvent (interfaceDecayRadiation, "VetoEvent", "Veto the whole event", 1); static SwitchOption interfaceDecayRadiationVetoRadiation (interfaceDecayRadiation, "VetoRadiation", "Throw the radiation away but keep the event", 2); } diff --git a/Shower/QTilde/QTildeShowerHandler.cc b/Shower/QTilde/QTildeShowerHandler.cc --- a/Shower/QTilde/QTildeShowerHandler.cc +++ b/Shower/QTilde/QTildeShowerHandler.cc @@ -1,3740 +1,3740 @@ // -*- C++ -*- // // QTildeShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // This is the implementation of the non-inlined, non-templated member // functions of the QTildeShowerHandler class. // #include "QTildeShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/EnumIO.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" #include "Herwig/Shower/QTilde/Base/HardTree.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/QTilde/Base/ShowerVertex.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/PDF/PartonExtractor.h" #include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; bool QTildeShowerHandler::_hardEmissionWarn = true; bool QTildeShowerHandler::_missingTruncWarn = true; QTildeShowerHandler::QTildeShowerHandler() : _maxtry(100), _meCorrMode(1), _reconOpt(0), _hardVetoReadOption(false), _iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(), _limitEmissions(0), _initialenhance(1.), _finalenhance(1.), _nReWeight(100), _reWeight(false), interaction_(ShowerInteraction::Both), _trunc_Mode(true), _hardEmission(1), _spinOpt(1), _softOpt(2), _hardPOWHEG(false), muPt(ZERO), _maxTryFSR(100000), _maxFailFSR(100), _fracFSR(0.001), _nFSR(0), _nFailedFSR(0) {} QTildeShowerHandler::~QTildeShowerHandler() {} IBPtr QTildeShowerHandler::clone() const { return new_ptr(*this); } IBPtr QTildeShowerHandler::fullclone() const { return new_ptr(*this); } void QTildeShowerHandler::persistentOutput(PersistentOStream & os) const { os << _splittingGenerator << _maxtry << _meCorrMode << _hardVetoReadOption << _limitEmissions << _spinOpt << _softOpt << _hardPOWHEG << ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV) << _vetoes << _fullShowerVetoes << _nReWeight << _reWeight << _trunc_Mode << _hardEmission << _reconOpt << ounit(muPt,GeV) << oenum(interaction_) << _maxTryFSR << _maxFailFSR << _fracFSR << _reconstructor << _partnerfinder; } void QTildeShowerHandler::persistentInput(PersistentIStream & is, int) { is >> _splittingGenerator >> _maxtry >> _meCorrMode >> _hardVetoReadOption >> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) >> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight >> _trunc_Mode >> _hardEmission >> _reconOpt >> iunit(muPt,GeV) >> ienum(interaction_) >> _maxTryFSR >> _maxFailFSR >> _fracFSR >> _reconstructor >> _partnerfinder; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigQTildeShowerHandler("Herwig::QTildeShowerHandler", "HwShower.so"); void QTildeShowerHandler::Init() { static ClassDocumentation documentation ("TheQTildeShowerHandler class is the main class" " for the angular-ordered parton shower", "The Shower evolution was performed using an algorithm described in " "\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.", "%\\cite{Marchesini:1983bm}\n" "\\bibitem{Marchesini:1983bm}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n" " %%CITATION = NUPHA,B238,1;%%\n" "%\\cite{Marchesini:1987cf}\n" "\\bibitem{Marchesini:1987cf}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n" " Radiation,''\n" " Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n" " %%CITATION = NUPHA,B310,461;%%\n" "%\\cite{Gieseke:2003rz}\n" "\\bibitem{Gieseke:2003rz}\n" " S.~Gieseke, P.~Stephens and B.~Webber,\n" " ``New formalism for QCD parton showers,''\n" " JHEP {\\bf 0312}, 045 (2003)\n" " [arXiv:hep-ph/0310083].\n" " %%CITATION = JHEPA,0312,045;%%\n" ); static Reference interfaceSplitGen("SplittingGenerator", "A reference to the SplittingGenerator object", &Herwig::QTildeShowerHandler::_splittingGenerator, false, false, true, false); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts to generate the shower from a" " particular ShowerTree", &QTildeShowerHandler::_maxtry, 100, 1, 100000, false, false, Interface::limited); static Parameter interfaceNReWeight ("NReWeight", "The number of attempts for the shower when reweighting", &QTildeShowerHandler::_nReWeight, 100, 10, 10000, false, false, Interface::limited); static Switch ifaceMECorrMode ("MECorrMode", "Choice of the ME Correction Mode", &QTildeShowerHandler::_meCorrMode, 1, false, false); static SwitchOption on (ifaceMECorrMode,"HardPlusSoft","hard+soft on", 1); static SwitchOption hard (ifaceMECorrMode,"Hard","only hard on", 2); static SwitchOption soft (ifaceMECorrMode,"Soft","only soft on", 3); static Switch ifaceHardVetoReadOption ("HardVetoReadOption", "Apply read-in scale veto to all collisions or just the primary one?", &QTildeShowerHandler::_hardVetoReadOption, false, false, false); static SwitchOption AllCollisions (ifaceHardVetoReadOption, "AllCollisions", "Read-in pT veto applied to primary and secondary collisions.", false); static SwitchOption PrimaryCollision (ifaceHardVetoReadOption, "PrimaryCollision", "Read-in pT veto applied to primary but not secondary collisions.", true); static Parameter ifaceiptrms ("IntrinsicPtGaussian", "RMS of intrinsic pT of Gaussian distribution:\n" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &QTildeShowerHandler::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, false, false, Interface::limited); static Parameter ifacebeta ("IntrinsicPtBeta", "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" "(1-Beta) is the proportion of Gaussian distribution", &QTildeShowerHandler::_beta, 0, 0, 1, false, false, Interface::limited); static Parameter ifacegamma ("IntrinsicPtGamma", "Parameter for inverse quadratic:\n" "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", &QTildeShowerHandler::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static Parameter ifaceiptmax ("IntrinsicPtIptmax", "Upper bound on intrinsic pT for inverse quadratic", &QTildeShowerHandler::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static RefVector ifaceVetoes ("Vetoes", "The vetoes to be checked during showering", &QTildeShowerHandler::_vetoes, -1, false,false,true,true,false); static RefVector interfaceFullShowerVetoes ("FullShowerVetoes", "The vetos to be appliede on the full final state of the shower", &QTildeShowerHandler::_fullShowerVetoes, -1, false, false, true, false, false); static Switch interfaceLimitEmissions ("LimitEmissions", "Limit the number and type of emissions for testing", &QTildeShowerHandler::_limitEmissions, 0, false, false); static SwitchOption interfaceLimitEmissionsNoLimit (interfaceLimitEmissions, "NoLimit", "Allow an arbitrary number of emissions", 0); static SwitchOption interfaceLimitEmissionsOneInitialStateEmission (interfaceLimitEmissions, "OneInitialStateEmission", "Allow one emission in the initial state and none in the final state", 1); static SwitchOption interfaceLimitEmissionsOneFinalStateEmission (interfaceLimitEmissions, "OneFinalStateEmission", "Allow one emission in the final state and none in the initial state", 2); static SwitchOption interfaceLimitEmissionsHardOnly (interfaceLimitEmissions, "HardOnly", "Only allow radiation from the hard ME correction", 3); static SwitchOption interfaceLimitEmissionsOneEmission (interfaceLimitEmissions, "OneEmission", "Allow one emission in either the final state or initial state, but not both", 4); static Switch interfaceTruncMode ("TruncatedShower", "Include the truncated shower?", &QTildeShowerHandler::_trunc_Mode, 1, false, false); static SwitchOption interfaceTruncMode0 (interfaceTruncMode,"No","Truncated Shower is OFF", 0); static SwitchOption interfaceTruncMode1 (interfaceTruncMode,"Yes","Truncated Shower is ON", 1); static Switch interfaceHardEmission ("HardEmission", "Whether to use ME corrections or POWHEG for the hardest emission", &QTildeShowerHandler::_hardEmission, 0, false, false); static SwitchOption interfaceHardEmissionNone (interfaceHardEmission, "None", "No Corrections", 0); static SwitchOption interfaceHardEmissionMECorrection (interfaceHardEmission, "MECorrection", "Old fashioned ME correction", 1); static SwitchOption interfaceHardEmissionPOWHEG (interfaceHardEmission, "POWHEG", "Powheg style hard emission", 2); static Switch interfaceInteractions ("Interactions", "The interactions to be used in the shower", &QTildeShowerHandler::interaction_, ShowerInteraction::Both, false, false); static SwitchOption interfaceInteractionsQCD (interfaceInteractions, "QCD", "Only QCD radiation", ShowerInteraction::QCD); static SwitchOption interfaceInteractionsQED (interfaceInteractions, "QED", "Only QEd radiation", ShowerInteraction::QED); static SwitchOption interfaceInteractionsQCDandQED (interfaceInteractions, "QCDandQED", "Both QED and QCD radiation", ShowerInteraction::Both); static Switch interfaceReconstructionOption ("ReconstructionOption", "Treatment of the reconstruction of the transverse momentum of " "a branching from the evolution scale.", &QTildeShowerHandler::_reconOpt, 0, false, false); static SwitchOption interfaceReconstructionOptionCutOff (interfaceReconstructionOption, "CutOff", "Use the cut-off masses in the calculation", 0); static SwitchOption interfaceReconstructionOptionOffShell (interfaceReconstructionOption, "OffShell", "Use the off-shell masses in the calculation veto the emission of the parent," " no veto in generation of emissions from children", 1); static SwitchOption interfaceReconstructionOptionOffShell2 (interfaceReconstructionOption, "OffShell2", "Use the off-shell masses in the calculation veto the emissions from the children." " no veto in generation of emissions from children", 2); static SwitchOption interfaceReconstructionOptionOffShell3 (interfaceReconstructionOption, "OffShell3", "Use the off-shell masses in the calculation veto the emissions from the children." " veto in generation of emissions from children using cut-off for second parton", 3); static SwitchOption interfaceReconstructionOptionOffShell4 (interfaceReconstructionOption, "OffShell4", "As OffShell3 but with a restriction on the mass of final-state" " jets produced via backward evolution.", 4); static SwitchOption interfaceReconstructionOptionOffShell5 (interfaceReconstructionOption, "OffShell5", "Try and preserve q2 but if pt negative just zero it", 5); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Treatment of spin correlations in the parton shower", &QTildeShowerHandler::_spinOpt, 1, false, false); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "No spin correlations", 0); static SwitchOption interfaceSpinCorrelationsSpin (interfaceSpinCorrelations, "Yes", "Include the azimuthal spin correlations only", 1); static Switch interfaceSoftCorrelations ("SoftCorrelations", "Option for the treatment of soft correlations in the parton shower", &QTildeShowerHandler::_softOpt, 2, false, false); static SwitchOption interfaceSoftCorrelationsNone (interfaceSoftCorrelations, "No", "No soft correlations", 0); static SwitchOption interfaceSoftCorrelationsFull (interfaceSoftCorrelations, "Full", "Use the full eikonal", 1); static SwitchOption interfaceSoftCorrelationsSingular (interfaceSoftCorrelations, "Singular", "Use original Webber-Marchisini form", 2); static Switch interfaceHardPOWHEG ("HardPOWHEG", "Treatment of powheg emissions which are too hard to have a shower interpretation", &QTildeShowerHandler::_hardPOWHEG, false, false, false); static SwitchOption interfaceHardPOWHEGAsShower (interfaceHardPOWHEG, "AsShower", "Still interpret as shower emissions", false); static SwitchOption interfaceHardPOWHEGRealEmission (interfaceHardPOWHEG, "RealEmission", "Generate shower from the real emmission configuration", true); static Parameter interfaceMaxTryFSR ("MaxTryFSR", "The maximum number of attempted FSR emissions in" " the generation of the FSR", &QTildeShowerHandler::_maxTryFSR, 100000, 10, 100000000, false, false, Interface::limited); static Parameter interfaceMaxFailFSR ("MaxFailFSR", "Maximum number of failures generating the FSR", &QTildeShowerHandler::_maxFailFSR, 100, 1, 100000000, false, false, Interface::limited); static Parameter interfaceFSRFailureFraction ("FSRFailureFraction", "Maximum fraction of events allowed to fail due to too many FSR emissions", &QTildeShowerHandler::_fracFSR, 0.001, 1e-10, 1, false, false, Interface::limited); static Reference interfaceKinematicsReconstructor ("KinematicsReconstructor", "Reference to the KinematicsReconstructor object", &QTildeShowerHandler::_reconstructor, false, false, true, false, false); static Reference interfacePartnerFinder ("PartnerFinder", "Reference to the PartnerFinder object", &QTildeShowerHandler::_partnerfinder, false, false, true, false, false); } tPPair QTildeShowerHandler::cascade(tSubProPtr sub, XCPtr xcomb) { // use me for reference in tex file etc useMe(); prepareCascade(sub); // set things up in the base class resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // check if anything needs doing if ( !doFSR() && ! doISR() ) return sub->incoming(); // start of the try block for the whole showering process unsigned int countFailures=0; while (countFailuresoutgoing().begin(), currentSubProcess()->outgoing().end()), hard,decay); ShowerTree::constructTrees(hard_,decay_,hard,decay); // if no hard process if(!hard_) throw Exception() << "Shower starting with a decay" << "is not implemented" << Exception::runerror; // perform the shower for the hard process showerHardProcess(hard_,xcomb); done_.push_back(hard_); hard_->updateAfterShower(decay_); // if no decaying particles to shower break out of the loop if(decay_.empty()) break; // shower the decay products while(!decay_.empty()) { // find particle whose production process has been showered ShowerDecayMap::iterator dit = decay_.begin(); while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit; assert(dit!=decay_.end()); // get the particle ShowerTreePtr decayingTree = dit->second; // remove it from the multimap decay_.erase(dit); // make sure the particle has been decayed QTildeShowerHandler::decay(decayingTree,decay_); // now shower the decay showerDecay(decayingTree); done_.push_back(decayingTree); decayingTree->updateAfterShower(decay_); } // suceeded break out of the loop break; } catch (KinematicsReconstructionVeto) { resetWeights(); ++countFailures; } catch ( ... ) { hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw; } } // if loop exited because of too many tries, throw event away if (countFailures >= maxtry()) { resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw Exception() << "Too many tries for main while loop " << "in QTildeShowerHandler::cascade()." << Exception::eventerror; } //enter the particles in the event record fillEventRecord(); // clear storage hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // non hadronic case return if (!isResolvedHadron(incomingBeams().first ) && !isResolvedHadron(incomingBeams().second) ) return incomingBeams(); // remake the remnants (needs to be after the colours are sorted // out in the insertion into the event record) if ( firstInteraction() ) return remakeRemnant(sub->incoming()); //Return the new pair of incoming partons. remakeRemnant is not //necessary here, because the secondary interactions are not yet //connected to the remnants. return make_pair(findFirstParton(sub->incoming().first ), findFirstParton(sub->incoming().second)); } void QTildeShowerHandler::fillEventRecord() { // create a new step StepPtr pstep = newStep(); assert(!done_.empty()); assert(done_[0]->isHard()); // insert the steps for(unsigned int ix=0;ixfillEventRecord(pstep,doISR(),doFSR()); } } HardTreePtr QTildeShowerHandler::generateCKKW(ShowerTreePtr ) const { return HardTreePtr(); } void QTildeShowerHandler::doinit() { ShowerHandler::doinit(); // interactions may have been changed through a setup file so we // clear it up here // calculate max no of FSR vetos _maxFailFSR = max(int(_maxFailFSR), int(_fracFSR*double(generator()->N()))); // check on the reweighting for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) { if(_fullShowerVetoes[ix]->behaviour()==1) { _reWeight = true; break; } } if(_reWeight && maximumTries()<_nReWeight) { throw Exception() << "Reweight being performed in the shower but the number of attempts for the" << "shower is less than that for the reweighting.\n" << "Maximum number of attempt for the shower " << fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is " << fullName() << ":NReWeight is " << _nReWeight << "\n" << "we recommend the number of attempts is 10 times the number for reweighting\n" << Exception::runerror; } ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::doinitrun() { ShowerHandler::doinitrun(); ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::generateIntrinsicpT(vector particlesToShower) { _intrinsic.clear(); if ( !ipTon() || !doISR() ) return; // don't do anything for the moment for secondary scatters if( !firstInteraction() ) return; // generate intrinsic pT for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; Energy ipt; if(UseRandom::rnd() > _beta) { ipt=_iptrms*sqrt(-log(UseRandom::rnd())); } else { ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); } pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); _intrinsic[particlesToShower[ix]] = pt; } } void QTildeShowerHandler::setupMaximumScales(const vector & p, XCPtr xcomb) { // let POWHEG events radiate freely if(_hardEmission==2&&hardTree()) { vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy); return; } // return if no vetos if (!restrictPhasespace()) return; // find out if hard partonic subprocess. bool isPartonic(false); map::const_iterator cit = _currenttree->incomingLines().begin(); Lorentz5Momentum pcm; for(; cit!=currentTree()->incomingLines().end(); ++cit) { pcm += cit->first->progenitor()->momentum(); isPartonic |= cit->first->progenitor()->coloured(); } // find minimum pt from hard process, the maximum pt from all outgoing // coloured lines (this is simpler and more general than // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will // be transverse mass. Energy ptmax = generator()->maximumCMEnergy(); // general case calculate the scale if ( !hardScaleIsMuF() || (hardVetoReadOption()&&!firstInteraction()) ) { // scattering process if(currentTree()->isHard()) { assert(xcomb); // coloured incoming particles if (isPartonic) { map::const_iterator cjt = currentTree()->outgoingLines().begin(); for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt()); } } if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m(); if(hardScaleIsMuF()&&hardVetoReadOption()&& !firstInteraction()) { ptmax=min(ptmax,sqrt(xcomb->lastShowerScale())); } } // decay, incoming() is the decaying particle. else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } // hepeup.SCALUP is written into the lastXComb by the // LesHouchesReader itself - use this by user's choice. // Can be more general than this. else { if(currentTree()->isHard()) { assert(xcomb); ptmax = sqrt( xcomb->lastShowerScale() ); } else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } ptmax *= hardScaleFactor(); // set maxHardPt for all progenitors. For partonic processes this // is now the max pt in the FS, for non-partonic processes or // processes with no coloured FS the invariant mass of the IS vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); } void QTildeShowerHandler::setupHardScales(const vector & p, XCPtr xcomb) { if ( hardScaleIsMuF() && (!hardVetoReadOption() || firstInteraction()) ) { Energy hardScale = ZERO; if(currentTree()->isHard()) { assert(xcomb); hardScale = sqrt( xcomb->lastShowerScale() ); } else { hardScale = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } hardScale *= hardScaleFactor(); vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale); muPt = hardScale; } } void QTildeShowerHandler::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) { _hardme = HwMEBasePtr(); // extract the matrix element tStdXCombPtr lastXC = dynamic_ptr_cast(xcomb); if(lastXC) { _hardme = dynamic_ptr_cast(lastXC->matrixElement()); } _decayme = HwDecayerBasePtr(); // set the current tree currentTree(hard); hardTree(HardTreePtr()); // work out the type of event currentTree()->xcombPtr(dynamic_ptr_cast(xcomb)); currentTree()->identifyEventType(); checkFlags(); // generate the showering doShowering(true,xcomb); } RealEmissionProcessPtr QTildeShowerHandler::hardMatrixElementCorrection(bool hard) { // set the initial enhancement factors for the soft correction _initialenhance = 1.; _finalenhance = 1.; // see if we can get the correction from the matrix element // or decayer RealEmissionProcessPtr real; if(hard) { if(_hardme&&_hardme->hasMECorrection()) { _hardme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _hardme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } else { if(_decayme&&_decayme->hasMECorrection()) { _decayme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _decayme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } return real; } ShowerParticleVector QTildeShowerHandler::createTimeLikeChildren(tShowerParticlePtr, IdList ids) { // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc ShowerParticleVector children; for(unsigned int ix=0;ix<2;++ix) { children.push_back(new_ptr(ShowerParticle(ids[ix+1],true))); if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()) children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass())); else children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass())); } return children; } bool QTildeShowerHandler::timeLikeShower(tShowerParticlePtr particle, ShowerInteraction type, Branching fb, bool first) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 2 && _nfs != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // too many tries if(_nFSR>=_maxTryFSR) { ++_nFailedFSR; // too many failed events if(_nFailedFSR>=_maxFailFSR) throw Exception() << "Too many events have failed due to too many shower emissions, in\n" << "QTildeShowerHandler::timeLikeShower(). Terminating run\n" << Exception::runerror; throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n" << Exception::eventerror; } // generate the emission ShowerParticleVector children; int ntry=0; // generate the emission if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching fc[2]; bool setupChildren = true; while (ntry<50) { fc[0] = Branching(); fc[1] = Branching(); ++ntry; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; particle->showerKinematics(fb.kinematics); // check highest pT if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type,_reconOpt==3 || _reconOpt==4); // update number of emissions ++_nfs; if(_limitEmissions!=0) { if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } setupChildren = false; } // select branchings for children fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); // old default if(_reconOpt==0||_reconOpt==5) { break; } // all other options else { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) { const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); Energy2 q2 = fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[ix+1] = sqrt(q2); } else { masses[ix+1] = virtualMasses[ix+1]; } } masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; double z = fb.kinematics->z(); Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; if(pt2>=ZERO) break; // clean up the vetoed emission if(_reconOpt==1) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } setupChildren = true; continue; } // clean up vetoed children else if(_reconOpt>=2) { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); children[ix]->virtualMass(ZERO); } } } }; // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(_reconOpt>=1) particle->showerKinematics()->updateParent(particle, children,fb.type); // branching has happened if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool QTildeShowerHandler::spaceLikeShower(tShowerParticlePtr particle, PPtr beam, ShowerInteraction type) { //using the pdf's associated with the ShowerHandler assures, that //modified pdf's are used for the secondary interactions via //CascadeHandler::resetPDFs(...) tcPDFPtr pdf; if(firstPDF().particle() == _beam) pdf = firstPDF().pdf(); if(secondPDF().particle() == _beam) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); // don't do anything if not needed if(_limitEmissions == 2 || hardOnly() || ( _limitEmissions == 1 && _nis != 0 ) || ( _limitEmissions == 4 && _nis + _nfs != 0 ) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching bb; // generate branching while (true) { bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, _initialenhance, _beam,type, pdf,freeze); // return if no emission if(!bb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // if not vetoed break if(!spaceLikeVetoed(bb,particle)) break; // otherwise reset scale and continue particle->vetoEmission(bb.type,bb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); } // assign the splitting function and shower kinematics particle->showerKinematics(bb.kinematics); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // particles as in Sudakov form factor tcPDPtr part[2]={bb.ids[0],bb.ids[2]}; // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false)); ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); ShowerParticleVector theChildren; theChildren.push_back(particle); theChildren.push_back(otherChild); //this updates the evolution scale particle->showerKinematics()-> updateParent(newParent, theChildren,bb.type); // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); _currenttree->addInitialStateBranching(particle,newParent,otherChild); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower ++_nis; bool emitted = _limitEmissions==0 ? spaceLikeShower(newParent,beam,type) : false; if(newParent->spinInfo()) newParent->spinInfo()->develop(); // now reconstruct the momentum if(!emitted) { if(_intrinsic.find(_progenitor)==_intrinsic.end()) { bb.kinematics->updateLast(newParent,ZERO,ZERO); } else { pair kt=_intrinsic[_progenitor]; bb.kinematics->updateLast(newParent, kt.first*cos(kt.second), kt.first*sin(kt.second)); } } particle->showerKinematics()-> updateChildren(newParent, theChildren,bb.type,_reconOpt>=4); if(_limitEmissions!=0) { if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // perform the shower of the final-state particle timeLikeShower(otherChild,type,Branching(),true); updateHistory(otherChild); if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop(); // return the emitted if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } void QTildeShowerHandler::showerDecay(ShowerTreePtr decay) { // work out the type of event currentTree()->xcombPtr(StdXCombPtr()); currentTree()->identifyEventType(); _decayme = HwDecayerBasePtr(); _hardme = HwMEBasePtr(); // find the decayer // try the normal way if possible tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode(); // otherwise make a string and look it up if(!dm) { string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name() + "->"; OrderedParticles outgoing; for(map::const_iterator it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) { if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t && abs(it->first->original()->id())==ParticleID::Wplus && decay->treelinks().size() == 1) { ShowerTreePtr Wtree = decay->treelinks().begin()->first; for(map::const_iterator it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) { outgoing.insert(it2->first->original()->dataPtr()); } } else { outgoing.insert(it->first->original()->dataPtr()); } } for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if(it!=outgoing.begin()) tag += ","; tag +=(**it).name(); } tag += ";"; dm = findDecayMode(tag); } if(dm) _decayme = dynamic_ptr_cast(dm->decayer()); // set the ShowerTree to be showered currentTree(decay); decay->applyTransforms(); hardTree(HardTreePtr()); // generate the showering doShowering(false,XCPtr()); // if no vetos // force calculation of spin correlations SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo(); if(spInfo) { if(!spInfo->developed()) spInfo->needsUpdate(); spInfo->develop(); } } bool QTildeShowerHandler::spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, Branching fb) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 3 && _nis != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { return false; } // too many tries if(_nFSR>=_maxTryFSR) { ++_nFailedFSR; // too many failed events if(_nFailedFSR>=_maxFailFSR) throw Exception() << "Too many events have failed due to too many shower emissions, in\n" << "QTildeShowerHandler::timeLikeShower(). Terminating run\n" << Exception::runerror; throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n" << Exception::eventerror; } // generate the emission ShowerParticleVector children; int ntry=0; // generate the emission if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) return false; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(particle->virtualMass()==ZERO) particle->virtualMass(_progenitor->progenitor()->mass()); fc[0] = Branching(); fc[1] = Branching(); ++ntry; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass, type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr()); // old default if(_reconOpt==0) { ++_nis; // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened break; } // Herwig default else if(_reconOpt==1) { // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) { return false; } setupChildren = true; continue; } else { ++_nis; break; } } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; // space-like children masses[1] = children[0]->virtualMass(); // time-like child if(fc[1].kinematics) { const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); Energy2 q2 = fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[2] = sqrt(q2); } else { masses[2] = virtualMasses[2]; } masses[0]=particle->virtualMass(); double z = fb.kinematics->z(); Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); if(pt2>=ZERO) { ++_nis; break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else { if(ix==0) children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); } } children[0]->virtualMass(_progenitor->progenitor()->mass()); children[1]->virtualMass(ZERO); } } }; if(_reconOpt>=2) { // In the case of splittings which involves coloured particles, // set properly the colour flow of the branching. // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); } // branching has happened return true; } vector QTildeShowerHandler::setupShower(bool hard) { RealEmissionProcessPtr real; // generate hard me if needed if(_hardEmission==1) { real = hardMatrixElementCorrection(hard); if(real&&!real->outgoing().empty()) setupMECorrection(real); } // generate POWHEG hard emission if needed else if(_hardEmission==2) hardestEmission(hard); // set the initial colour partners setEvolutionPartners(hard,interaction_,false); // get the particles to be showered vector particlesToShower = currentTree()->extractProgenitors(); // return the answer return particlesToShower; } void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction type, bool clear) { // match the particles in the ShowerTree and hardTree if(hardTree() && !hardTree()->connect(currentTree())) throw Exception() << "Can't match trees in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; // extract the progenitors vector particles = currentTree()->extractProgenitorParticles(); // clear the partners if needed if(clear) { for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } } // sort out the colour partners if(hardTree()) { // find the partner for(unsigned int ix=0;ixparticles()[particles[ix]]->branchingParticle()->partner(); if(!partner) continue; for(map::const_iterator it=hardTree()->particles().begin(); it!=hardTree()->particles().end();++it) { if(it->second->branchingParticle()==partner) { particles[ix]->partner(it->first); break; } } if(!particles[ix]->partner()) throw Exception() << "Can't match partners in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; } } // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,!_hardtree); if(hardTree() && _hardPOWHEG) { bool tooHard=false; map::const_iterator eit=hardTree()->particles().end(); for(unsigned int ix=0;ix::const_iterator mit = hardTree()->particles().find(particles[ix]); Energy hardScale(ZERO); ShowerPartnerType type(ShowerPartnerType::Undefined); // final-state if(particles[ix]->isFinalState()) { if(mit!= eit && !mit->second->children().empty()) { hardScale = mit->second->scale(); type = mit->second->type(); } } // initial-state else { if(mit!= eit && mit->second->parent()) { hardScale = mit->second->parent()->scale(); type = mit->second->parent()->type(); } } if(type!=ShowerPartnerType::Undefined) { if(type==ShowerPartnerType::QED) { tooHard |= particles[ix]->scales().QED_noAOscales().QCD_c_noAOscales().QCD_ac_noAOchildren().empty()) { ShowerParticleVector theChildren; for(unsigned int ix=0;ixchildren().size();++ix) { ShowerParticlePtr part = dynamic_ptr_cast (particle->children()[ix]); theChildren.push_back(part); } // update the history if needed if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) _currenttree->updateFinalStateShowerProduct(_progenitor, particle,theChildren); _currenttree->addFinalStateBranching(particle,theChildren); for(unsigned int ix=0;ixprogenitor()->partner()) return false; progenitor()->progenitor()->initializeFinalState(); if(hardTree()) { map::const_iterator eit=hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && !mit->second->children().empty() ) { bool output=truncatedTimeLikeShower(progenitor()->progenitor(), mit->second ,type,Branching(),true); if(output) updateHistory(progenitor()->progenitor()); return output; } } // do the shower bool output = hardOnly() ? false : timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ; if(output) updateHistory(progenitor()->progenitor()); return output; } bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction type) { // initialise the basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeInitialState(parent); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { return truncatedSpaceLikeShower( progenitor()->progenitor(), parent, mit->second->parent(), type ); } } // perform the shower return hardOnly() ? false : spaceLikeShower(progenitor()->progenitor(),parent,type); } bool QTildeShowerHandler:: startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction type) { _nFSR = 0; // set up the particle basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeDecay(); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { HardBranchingPtr branch=mit->second; while(branch->parent()) branch=branch->parent(); return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales, minimumMass, branch ,type, Branching()); } } // perform the shower return hardOnly() ? false : spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching()); } bool QTildeShowerHandler::timeLikeVetoed(const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // check whether emission was harder than largest pt of hard subprocess if ( restrictPhasespace() && fb.kinematics->pT() > _progenitor->maxHardPt() ) return true; // soft matrix element correction veto if( softMEC()) { if(_hardme && _hardme->hasMECorrection()) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } else if(_decayme && _decayme->hasMECorrection()) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } } // veto on maximum pt if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true; // general vetos if (fb.kinematics && !_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoTimeLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if(vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeVetoed(const Branching & bb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(bb.type); // check whether emission was harder than largest pt of hard subprocess if (restrictPhasespace() && bb.kinematics->pT() > _progenitor->maxHardPt()) return true; // apply the soft correction if( softMEC() && _hardme && _hardme->hasMECorrection() ) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), bb.ids, bb.kinematics->z(), bb.kinematics->scale(), bb.kinematics->pT())) return true; } // the more general vetos // check vs max pt for the shower if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true; if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,bb,currentTree()); switch ((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if (vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeDecayVetoed( const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // apply the soft correction if( softMEC() && _decayme && _decayme->hasMECorrection() ) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } // veto on hardest pt in the shower if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true; // general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } if (vetoed) return true; } } return false; } void QTildeShowerHandler::hardestEmission(bool hard) { HardTreePtr ISRTree; // internal POWHEG in production or decay if( (( _hardme && _hardme->hasPOWHEGCorrection()!=0 ) || ( _decayme && _decayme->hasPOWHEGCorrection()!=0 ) ) ) { RealEmissionProcessPtr real; unsigned int type(0); // production if(_hardme) { assert(hard); real = _hardme->generateHardest( currentTree()->perturbativeProcess(), interaction_); type = _hardme->hasPOWHEGCorrection(); } // decay else { assert(!hard); real = _decayme->generateHardest( currentTree()->perturbativeProcess() ); type = _decayme->hasPOWHEGCorrection(); } if(real) { // set up ther hard tree if(!real->outgoing().empty()) _hardtree = new_ptr(HardTree(real)); // set up the vetos currentTree()->setVetoes(real->pT(),type); } // store initial state POWHEG radiation if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1) ISRTree = _hardtree; } else if (hard) { // Get minimum pT cutoff used in shower approximation Energy maxpt = 1.*GeV; if ( currentTree()->showerApproximation() ) { int colouredIn = 0; int colouredOut = 0; for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredOut; } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredIn; } if ( currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->fiPtCut() && currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->iiPtCut() ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 0 ) maxpt = currentTree()->showerApproximation()->iiPtCut(); else if ( colouredIn == 0 && colouredOut > 1 ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 1 ) maxpt = min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()); else if ( colouredIn == 1 && colouredOut > 1 ) maxpt = min(currentTree()->showerApproximation()->ffPtCut(), currentTree()->showerApproximation()->fiPtCut()); else maxpt = min(min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()), currentTree()->showerApproximation()->ffPtCut()); } // Generate hardtree from born and real emission subprocesses _hardtree = generateCKKW(currentTree()); // Find transverse momentum of hardest emission if (_hardtree){ for(set::iterator it=_hardtree->branchings().begin(); it!=_hardtree->branchings().end();++it) { if ((*it)->parent() && (*it)->status()==HardBranching::Incoming) maxpt=(*it)->branchingParticle()->momentum().perp(); if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){ if ((*it)->branchingParticle()->id()!=21 && abs((*it)->branchingParticle()->id())>5 ){ if ((*it)->children()[0]->branchingParticle()->id()==21 || abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp(); else if ((*it)->children()[1]->branchingParticle()->id()==21 || abs((*it)->children()[1]->branchingParticle()->id())<6) maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp(); } else { if ( abs((*it)->branchingParticle()->id())<6){ if (abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); else maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp(); } else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); } } } } // Hardest (pt) emission should be the first powheg emission. maxpt=min(sqrt(lastXCombPtr()->lastShowerScale()),maxpt); // set maximum pT for subsequent emissions from S events if ( currentTree()->isPowhegSEvent() ) { for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } } } else _hardtree = generateCKKW(currentTree()); // if hard me doesn't have a FSR powheg // correction use decay powheg correction if (_hardme && _hardme->hasPOWHEGCorrection()<2) { addFSRUsingDecayPOWHEG(ISRTree); } // connect the trees if(_hardtree) { connectTrees(currentTree(),_hardtree,hard); } } void QTildeShowerHandler::addFSRUsingDecayPOWHEG(HardTreePtr ISRTree) { // check for intermediate colour singlet resonance const ParticleVector inter = _hardme->subProcess()->intermediates(); if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 || inter[0]->dataPtr()->iColour()!=PDT::Colour0) { return; } // ignore cases where outgoing particles are not coloured map out = currentTree()->outgoingLines(); if (out.size() != 2 || out. begin()->second->dataPtr()->iColour()==PDT::Colour0 || out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) { return; } // look up decay mode tDMPtr dm; string tag; string inParticle = inter[0]->dataPtr()->name() + "->"; vector outParticles; outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name()); outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name()); for (int it=0; it<2; ++it){ tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";"; dm = generator()->findDecayMode(tag); if(dm) break; } // get the decayer HwDecayerBasePtr decayer; if(dm) decayer = dynamic_ptr_cast(dm->decayer()); // check if decayer has a FSR POWHEG correction if (!decayer || decayer->hasPOWHEGCorrection()<2) { return; } // generate the hardest emission // create RealEmissionProcess PPtr in = new_ptr(*inter[0]); RealEmissionProcessPtr newProcess(new_ptr(RealEmissionProcess())); newProcess->bornIncoming().push_back(in); newProcess->bornOutgoing().push_back(out.begin ()->first->progenitor()); newProcess->bornOutgoing().push_back(out.rbegin()->first->progenitor()); // generate the FSR newProcess = decayer->generateHardest(newProcess); HardTreePtr FSRTree; if(newProcess) { // set up ther hard tree if(!newProcess->outgoing().empty()) FSRTree = new_ptr(HardTree(newProcess)); // set up the vetos currentTree()->setVetoes(newProcess->pT(),2); } if(!FSRTree) return; // if there is no ISRTree make _hardtree from FSRTree if (!ISRTree){ vector inBranch,hardBranch; for(map::const_iterator cit =currentTree()->incomingLines().begin(); cit!=currentTree()->incomingLines().end();++cit ) { inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(), HardBranchingPtr(), HardBranching::Incoming))); inBranch.back()->beam(cit->first->original()->parents()[0]); hardBranch.push_back(inBranch.back()); } if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) { inBranch[0]->colourPartner(inBranch[1]); inBranch[1]->colourPartner(inBranch[0]); } for(set::iterator it=FSRTree->branchings().begin(); it!=FSRTree->branchings().end();++it) { if((**it).branchingParticle()->id()!=in->id()) hardBranch.push_back(*it); } hardBranch[2]->colourPartner(hardBranch[3]); hardBranch[3]->colourPartner(hardBranch[2]); HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch, ShowerInteraction::QCD)); _hardtree = newTree; } // Otherwise modify the ISRTree to include the emission in FSRTree else { vector FSROut, ISROut; set::iterator itFSR, itISR; // get outgoing particles for(itFSR =FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).status()==HardBranching::Outgoing) FSROut.push_back((*itFSR)->branchingParticle()); } for(itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Outgoing) ISROut.push_back((*itISR)->branchingParticle()); } // find COM frame formed by outgoing particles LorentzRotation eventFrameFSR, eventFrameISR; eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM()); eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM()); // find rotation between ISR and FSR frames int j=0; if (ISROut[0]->id()!=FSROut[0]->id()) j=1; eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()- (eventFrameISR*ISROut[j]->momentum()).phi() ); eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()- (eventFrameISR*ISROut[j]->momentum()).theta() ); eventFrameISR.invert(); for (itFSR=FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).branchingParticle()->id()==in->id()) continue; for (itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Incoming) continue; if ((**itFSR).branchingParticle()->id()== (**itISR).branchingParticle()->id()){ // rotate FSRTree particle to ISRTree event frame (**itISR).branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).branchingParticle()->momentum()); (**itISR).branchingParticle()->rescaleMass(); // add the children of the FSRTree particles to the ISRTree if(!(**itFSR).children().empty()){ (**itISR).addChild((**itFSR).children()[0]); (**itISR).addChild((**itFSR).children()[1]); // rotate momenta to ISRTree event frame (**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[0]->branchingParticle()->momentum()); (**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[1]->branchingParticle()->momentum()); } } } } _hardtree = ISRTree; } } bool QTildeShowerHandler::truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first) { // select a branching if we don't have one if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; int ntry=0; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(!fc[0].hard) fc[0] = Branching(); if(!fc[1].hard) fc[1] = Branching(); ++ntry; // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children if(!fc[0].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==1 ) fc[0] = selectTimeLikeBranching(children[0],type,branch); else if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } // select branching for the second particle if(!fc[1].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==2 ) fc[1] = selectTimeLikeBranching(children[1],type,branch); else if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } // old default if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); break; } // H7 default else if(_reconOpt==1) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectTimeLikeBranching(particle,type,branch); // must be at least hard emission assert(fb.kinematics); setupChildren = true; continue; } else break; } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) { const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); Energy2 q2 = fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[ix+1] = sqrt(q2); } else { masses[ix+1] = virtualMasses[ix+1]; } } masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; double z = fb.kinematics->z(); Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; if(pt2>=ZERO) { break; } // if only the hard emission have to accept it else if ((fc[0].hard && !fc[1].kinematics) || (fc[1].hard && !fc[0].kinematics) ) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].hard) continue; if(fc[ix].kinematics && ! fc[ix].hard ) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); children[ix]->virtualMass(ZERO); } } } }; if(_reconOpt>=2) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); } if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool QTildeShowerHandler::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam, HardBranchingPtr branch, ShowerInteraction type) { tcPDFPtr pdf; if(firstPDF().particle() == beamParticle()) pdf = firstPDF().pdf(); if(secondPDF().particle() == beamParticle()) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); Branching bb; // parameters of the force branching double z(0.); HardBranchingPtr timelike; for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) { if( branch->children()[ix]->status() ==HardBranching::Outgoing) { timelike = branch->children()[ix]; } if( branch->children()[ix]->status() ==HardBranching::Incoming ) z = branch->children()[ix]->z(); } // generate truncated branching tcPDPtr part[2]; if(z>=0.&&z<=1.) { while (true) { if( !isTruncatedShowerON() || hardOnly() ) break; bb = splittingGenerator()->chooseBackwardBranching( *particle, beam, 1., beamParticle(), type , pdf,freeze); if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) { bb = Branching(); break; } // particles as in Sudakov form factor part[0] = bb.ids[0]; part[1] = bb.ids[2]; double zsplit = bb.kinematics->z(); // apply the vetos for the truncated shower // if doesn't carry most of momentum ShowerInteraction type2 = convertInteraction(bb.type); if(type2==branch->sudakov()->interactionType() && zsplit < 0.5) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // others if( part[0]->id() != particle->id() || // if particle changes type bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto bb.kinematics->scale() < branch->scale()) { // angular ordering veto particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // and those from the base class if(spaceLikeVetoed(bb,particle)) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } break; } } if( !bb.kinematics ) { //do the hard emission ShoKinPtr kinematics = branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(), branch->children()[0]->pT() ); // assign the splitting function and shower kinematics particle->showerKinematics( kinematics ); if(kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(), true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, branch->type()); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted=false; if(!hardOnly()) { if( branch->parent() ) { emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type); } else { emitted = spaceLikeShower( newParent, beam , type); } } if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[progenitor()]; kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren,bb.type,false); if(hardOnly()) return true; // perform the shower of the final-state particle if( timelike->children().empty() ) { timeLikeShower( otherChild , type,Branching(),true); } else { truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true); } updateHistory(otherChild); // return the emitted return true; } // assign the splitting function and shower kinematics particle->showerKinematics( bb.kinematics ); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, bb.type); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type); // now reconstruct the momentum if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { bb.kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[ progenitor() ]; bb.kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren, bb.type,false); // perform the shower of the final-state particle timeLikeShower( otherChild , type,Branching(),true); updateHistory(otherChild); // return the emitted return true; } bool QTildeShowerHandler:: truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass, HardBranchingPtr branch, ShowerInteraction type, Branching fb) { // select a branching if we don't have one if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; int ntry=0; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(!fc[0].hard) fc[0] = Branching(); if(!fc[1].hard) fc[1] = Branching(); ++ntry; if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children if(!fc[0].kinematics) { if(children[0]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[0]->children().empty() ) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, branch->children()[0]); else fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, HardBranchingPtr()); } else { // select branching for first particle if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } } // select branching for the second particle if(!fc[1].kinematics) { if(children[1]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[1]->children().empty() ) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, branch->children()[1]); else fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, HardBranchingPtr()); } else { if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } } // old default if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); // branching has happened break; } // H7 default else if(_reconOpt==1) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be at least hard emission assert(fb.kinematics); setupChildren = true; continue; } else { updateHistory(children[1]); break; } } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; // space-like children masses[1] = children[0]->virtualMass(); // time-like child if(fc[1].kinematics) { const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); Energy2 q2 = fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[2] = sqrt(q2); } else { masses[2] = virtualMasses[2]; } masses[0]=particle->virtualMass(); double z = fb.kinematics->z(); Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); if(pt2>=ZERO) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else { if(ix==0) children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); } } children[0]->virtualMass(_progenitor->progenitor()->mass()); children[1]->virtualMass(ZERO); } } }; if(_reconOpt>=2) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); } return true; } void QTildeShowerHandler::connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ) { ShowerParticleVector particles; // find the Sudakovs for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { // Sudakovs for ISR if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) { ++_nis; vector br(3); br[0] = (**cit).parent()->branchingParticle()->id(); br[1] = (**cit). branchingParticle()->id(); br[2] = (**cit).parent()->children()[0]==*cit ? (**cit).parent()->children()[1]->branchingParticle()->id() : (**cit).parent()->children()[0]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->initialStateBranchings(); if(br[1]<0&&br[0]==br[1]) { br[0] = abs(br[0]); br[1] = abs(br[1]); } else if(br[1]<0) { br[1] = -br[1]; br[2] = -br[2]; } long index = abs(br[1]); SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees() for ISR" << Exception::runerror; (**cit).parent()->sudakov(sudakov); } // Sudakovs for FSR else if(!(**cit).children().empty()) { ++_nfs; vector br(3); br[0] = (**cit) .branchingParticle()->id(); br[1] = (**cit).children()[0]->branchingParticle()->id(); br[2] = (**cit).children()[1]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->finalStateBranchings(); if(br[0]<0) { br[0] = abs(br[0]); br[1] = abs(br[1]); br[2] = abs(br[2]); } long index = br[0]; SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) { throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees()" << Exception::runerror; } (**cit).sudakov(sudakov); } } // calculate the evolution scale for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { particles.push_back((*cit)->branchingParticle()); } partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,true); hardTree->partnersSet(true); // inverse reconstruction if(hard) { kinematicsReconstructor()-> deconstructHardJets(hardTree,interaction_); } else kinematicsReconstructor()-> deconstructDecayJets(hardTree,interaction_); // now reset the momenta of the showering particles vector particlesToShower=showerTree->extractProgenitors(); // match them map partners; for(set::const_iterator bit=hardTree->branchings().begin(); bit!=hardTree->branchings().end();++bit) { Energy2 dmin( 1e30*GeV2 ); ShowerProgenitorPtr partner; for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { if(partners.find(*pit)!=partners.end()) continue; if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue; if( (**bit).branchingParticle()->isFinalState() != (**pit).progenitor()->isFinalState() ) continue; if( (**pit).progenitor()->isFinalState() ) { Energy2 dtest = sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) + sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) + sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) + sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() ); // add mass difference for identical particles (e.g. Z0 Z0 production) dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m()); if( dtest < dmin ) { partner = *pit; dmin = dtest; } } else { // ensure directions are right if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) { partner = *pit; break; } } } if(!partner) throw Exception() << "Failed to match shower and hard trees in QTildeShowerHandler::hardestEmission" << Exception::eventerror; partners[partner] = *bit; } for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { HardBranchingPtr partner = partners[*pit]; if((**pit).progenitor()->dataPtr()->stable()) { (**pit).progenitor()->set5Momentum(partner->showerMomentum()); (**pit).copy()->set5Momentum(partner->showerMomentum()); } else { Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum(); Lorentz5Momentum newMomentum = partner->showerMomentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); } } // correction boosts for daughter trees for(map >::const_iterator tit = showerTree->treelinks().begin(); tit != showerTree->treelinks().end();++tit) { ShowerTreePtr decayTree = tit->first; map::const_iterator cit = decayTree->incomingLines().begin(); // reset the momentum of the decay particle Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); Lorentz5Momentum newMomentum = tit->second.second->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); decayTree->transform(boost,true); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); decayTree->transform(boost,true); } } void QTildeShowerHandler::doShowering(bool hard,XCPtr xcomb) { // zero number of emissions _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } // extract particles to shower vector particlesToShower(setupShower(hard)); // check if we should shower bool colCharge = false; for(unsigned int ix=0;ixprogenitor()->dataPtr()->coloured() || particlesToShower[ix]->progenitor()->dataPtr()->charged()) { colCharge = true; break; } } if(!colCharge) { _currenttree->hasShowered(true); return; } // setup the maximum scales for the shower if (restrictPhasespace()) setupMaximumScales(particlesToShower,xcomb); // set the hard scales for the profiles setupHardScales(particlesToShower,xcomb); // specific stuff for hard processes and decays Energy minmass(ZERO), mIn(ZERO); // hard process generate the intrinsic p_T once and for all if(hard) { generateIntrinsicpT(particlesToShower); } // decay compute the minimum mass of the final-state else { for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(particlesToShower[ix]->progenitor()->dataPtr()->stable()) minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass(); else minmass += particlesToShower[ix]->progenitor()->mass(); } else { mIn = particlesToShower[ix]->progenitor()->mass(); } } // throw exception if decay can't happen if ( minmass > mIn ) { throw Exception() << "QTildeShowerHandler.cc: Mass of decaying particle is " << "below constituent masses of decay products." << Exception::eventerror; } } // setup for reweighted bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction(); double eventWeight=0.; unsigned int nTryReWeight(0); // create random particle vector (only need to do once) vector tmp; unsigned int nColouredIncoming = 0; while(particlesToShower.size()>0){ unsigned int xx=UseRandom::irnd(particlesToShower.size()); tmp.push_back(particlesToShower[xx]); particlesToShower.erase(particlesToShower.begin()+xx); } particlesToShower=tmp; for(unsigned int ix=0;ixprogenitor()->isFinalState() && particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming; } bool switchRecon = hard && nColouredIncoming !=1; // main shower loop unsigned int ntry(0); bool reconstructed = false; do { // clear results of last attempt if needed if(ntry!=0) { currentTree()->clear(); setEvolutionPartners(hard,interaction_,true); _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } for(unsigned int ix=0; ixprogenitor()->spinInfo(); if(spin && spin->decayVertex() && dynamic_ptr_cast(spin->decayVertex())) { spin->decayVertex(VertexPtr()); } } } // loop over particles for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(!doFSR()) continue; // perform shower progenitor()->hasEmitted(startTimeLikeShower(interaction_)); } // initial-state radiation else { if(!doISR()) continue; // hard process if(hard) { // get the PDF setBeamParticle(_progenitor->beam()); if(!beamParticle()) { throw Exception() << "Incorrect type of beam particle in " << "QTildeShowerHandler::doShowering(). " << "This should not happen for conventional choices but may happen if you have used a" << " non-default choice and have not changed the create ParticleData line in the input files" << " for this particle to create BeamParticleData." << Exception::runerror; } // perform the shower // set the beam particle tPPtr beamparticle=progenitor()->original(); if(!beamparticle->parents().empty()) beamparticle=beamparticle->parents()[0]; // generate the shower progenitor()->hasEmitted(startSpaceLikeShower(beamparticle, interaction_)); } // decay else { // skip colour and electrically neutral particles if(!progenitor()->progenitor()->dataPtr()->coloured() && !progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->hasEmitted(false); continue; } // perform shower // set the scales correctly. The current scale is the maximum scale for // emission not the starting scale ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales()); progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales(); if(progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasColour()) { progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasAntiColour()) { progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass(); } // perform the shower progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass, interaction_)); } } } // do the kinematic reconstruction, checking if it worked reconstructed = hard ? kinematicsReconstructor()-> reconstructHardJets (currentTree(),intrinsicpT(),interaction_, switchRecon && ntry>maximumTries()/2) : kinematicsReconstructor()-> reconstructDecayJets(currentTree(),interaction_); if(!reconstructed) continue; // apply vetos on the full shower for(vector::const_iterator it=_fullShowerVetoes.begin(); it!=_fullShowerVetoes.end();++it) { int veto = (**it).applyVeto(currentTree()); if(veto<0) continue; // veto the shower if(veto==0) { reconstructed = false; break; } // veto the shower and reweight else if(veto==1) { reconstructed = false; break; } // veto the event else if(veto==2) { throw Veto(); } } if(reWeighting) { if(reconstructed) eventWeight += 1.; reconstructed=false; ++nTryReWeight; if(nTryReWeight==_nReWeight) { reWeighting = false; if(eventWeight==0.) throw Veto(); } } } while(!reconstructed&&maximumTries()>++ntry); // check if failed to generate the shower if(ntry==maximumTries()) { if(hard) throw ShowerHandler::ShowerTriesVeto(ntry); else throw Exception() << "Failed to generate the shower after " << ntry << " attempts in QTildeShowerHandler::showerDecay()" << Exception::eventerror; } // handle the weights and apply any reweighting required if(nTryReWeight>0) { tStdEHPtr seh = dynamic_ptr_cast(generator()->currentEventHandler()); static bool first = true; if(seh) { seh->reweight(eventWeight/double(nTryReWeight)); } else if(first) { generator()->log() << "Reweighting the shower only works with internal Herwig7 processes" << "Presumably you are showering Les Houches Events. These will not be" << "reweighted\n"; first = false; } } // tree has now showered _currenttree->hasShowered(true); hardTree(HardTreePtr()); } void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction type) { map cmap; // incoming particles for(map::const_iterator cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) { map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = mit->second->parent(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->parent()->branchingParticle(); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false))); cit->first->progenitor(sp); currentTree()->incomingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle(); if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } if(hard) { // sort out the value of x if(mit->second->beam()->momentum().z()>ZERO) { sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus()); } else { sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus()); } } } // outgoing particles for(map::const_iterator cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) { map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==cit->first->progenitor()) break; } map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); if(mit==hardTree()->particles().end()) continue; // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ShowerParticlePtr newOut; ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = !mit->second->children().empty(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->children()[0]->branchingParticle(); newOut = mit->second->children()[1]->branchingParticle(); if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id()) swap(newParticle,newOut); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // special for unstable particles if(newParticle->id()==oldParticle->id() && (tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) { Lorentz5Momentum oldMomentum = oldParticle->momentum(); Lorentz5Momentum newMomentum = newParticle->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); oldParticle->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); oldParticle->transform(boost); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); newParticle=oldParticle; } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true))); cit->first->progenitor(sp); currentTree()->outgoingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } // update any decay products if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(cit->first,sp)); } // reset the tree currentTree()->resetShowerProducts(); // reextract the particles and set the colour partners vector particles = currentTree()->extractProgenitorParticles(); // clear the partners for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } // clear the tree hardTree(HardTreePtr()); // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,type,!_hardtree); } Branching QTildeShowerHandler::selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type); // no emission break if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); // only if same interaction for forced branching ShowerInteraction type2 = convertInteraction(fb.type); // and evolution if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // standard vetos for all emissions if(timeLikeVetoed(fb,particle)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } // special for already decayed particles // don't allow flavour changing branchings bool vetoDecay = false; for(map >::const_iterator tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first == progenitor()) { map::const_iterator it = currentTree()->outgoingLines().find(progenitor()); if(it!=currentTree()->outgoingLines().end() && particle == it->second && fb.ids[0]!=fb.ids[1] && fb.ids[1]!=fb.ids[2]) { vetoDecay = true; break; } } } if(vetoDecay) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin= branch->sudakov()->createFinalStateBranching(branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT()); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() ); fb.hard = true; fb.iout=0; // return it return fb; } Branching QTildeShowerHandler::selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; // select branching fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass, _initialenhance,type); // return if no radiation if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } ShowerInteraction type2 = convertInteraction(fb.type); double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // if not vetoed break if(spaceLikeDecayVetoed(fb,particle)) { // otherwise reset scale and continue particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin= branch->sudakov()->createDecayBranching(branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT()); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); // create the branching fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine ); fb.hard=true; fb.iout=0; // return it return fb; } void QTildeShowerHandler::checkFlags() { string error = "Inconsistent hard emission set-up in QTildeShowerHandler::showerHardProcess(). "; if ( ( currentTree()->isMCatNLOSEvent() || currentTree()->isMCatNLOHEvent() ) ) { if (_hardEmission ==2 ) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower " << "approximation. Add 'set QTildeShowerHandler:HardEmission 0' to input file." << Exception::runerror; if ( canHandleMatchboxTrunc() ) throw Exception() << error << "Cannot use truncated qtilde shower with MC@NLO shower " << "approximation. Set LHCGenerator:EventHandler" << ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or " << "'/Herwig/Shower/Dipole/DipoleShowerHandler'." << Exception::runerror; } else if ( ((currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) ) && _hardEmission != 2){ if ( canHandleMatchboxTrunc()) throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Set QTildeShowerHandler:HardEmission to " << "'POWHEG'." << Exception::runerror; else if (_hardEmissionWarn) { _hardEmissionWarn = false; _hardEmission=2; throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Changing QTildeShowerHandler:HardEmission from " << _hardEmission << " to 2" << Exception::warning; } } if ( currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) { if (currentTree()->showerApproximation()->needsTruncatedShower() && !canHandleMatchboxTrunc() ) throw Exception() << error << "Current shower handler cannot generate truncated shower. " << "Set Generator:EventHandler:CascadeHandler to " << "'/Herwig/Shower/PowhegShowerHandler'." << Exception::runerror; } else if ( currentTree()->truncatedShower() && _missingTruncWarn) { _missingTruncWarn=false; throw Exception() << "Warning: POWHEG shower approximation used without " << "truncated shower. Set Generator:EventHandler:" << "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and " << "'MEMatching:TruncatedShower Yes'." << Exception::warning; } // else if ( !dipme && _hardEmissionMode > 1 && // firstInteraction()) // throw Exception() << error // << "POWHEG matching requested for LO events. Include " // << "'set Factory:ShowerApproximation MEMatching' in input file." // << Exception::runerror; } tPPair QTildeShowerHandler::remakeRemnant(tPPair oldp){ // get the parton extractor PartonExtractor & pex = *lastExtractor(); // get the new partons tPPair newp = make_pair(findFirstParton(oldp.first ), findFirstParton(oldp.second)); // if the same do nothing if(newp == oldp) return oldp; // Creates the new remnants and returns the new PartonBinInstances // ATTENTION Broken here for very strange configuration PBIPair newbins = pex.newRemnants(oldp, newp, newStep()); newStep()->addIntermediate(newp.first); newStep()->addIntermediate(newp.second); // return the new partons return newp; } PPtr QTildeShowerHandler::findFirstParton(tPPtr seed) const{ if(seed->parents().empty()) return seed; tPPtr parent = seed->parents()[0]; //if no parent there this is a loose end which will //be connected to the remnant soon. if(!parent || parent == incomingBeams().first || parent == incomingBeams().second ) return seed; else return findFirstParton(parent); } void QTildeShowerHandler::decay(ShowerTreePtr tree, ShowerDecayMap & decay) { // must be one incoming particle assert(tree->incomingLines().size()==1); // apply any transforms tree->applyTransforms(); // if already decayed return if(!tree->outgoingLines().empty()) return; // now we need to replace the particle with a new copy after the shower // find particle after the shower map >::const_iterator tit = tree->parent()->treelinks().find(tree); assert(tit!=tree->parent()->treelinks().end()); ShowerParticlePtr newparent=tit->second.second; PerturbativeProcessPtr newProcess = new_ptr(PerturbativeProcess()); newProcess->incoming().push_back(make_pair(newparent,PerturbativeProcessPtr())); DecayProcessMap decayMap; ShowerHandler::decay(newProcess,decayMap); ShowerTree::constructTrees(tree,decay,newProcess,decayMap); } namespace { ShowerProgenitorPtr findFinalStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->outgoingLines().begin(); cit!=tree->outgoingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } ShowerProgenitorPtr findInitialStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->incomingLines().begin(); cit!=tree->incomingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } void fixSpectatorColours(PPtr newSpect,ShowerProgenitorPtr oldSpect, ColinePair & cline,ColinePair & aline, bool reconnect) { cline.first = oldSpect->progenitor()->colourLine(); cline.second = newSpect->colourLine(); aline.first = oldSpect->progenitor()->antiColourLine(); aline.second = newSpect->antiColourLine(); if(!reconnect) return; if(cline.first) { cline.first ->removeColoured(oldSpect->copy()); cline.first ->removeColoured(oldSpect->progenitor()); cline.second->removeColoured(newSpect); cline.first ->addColoured(newSpect); } if(aline.first) { aline.first ->removeAntiColoured(oldSpect->copy()); aline.first ->removeAntiColoured(oldSpect->progenitor()); aline.second->removeAntiColoured(newSpect); aline.first ->addAntiColoured(newSpect); } } void fixInitialStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline,double x) { // sort out the colours if(emitted->dataPtr()->iColour()==PDT::Colour8) { // emitter if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // emitted if(cline.first && cline.second==emitted->colourLine()) { cline.second->removeColoured(emitted); cline.first->addColoured(emitted); } else if(aline.first && aline.second==emitted->antiColourLine()) { aline.second->removeAntiColoured(emitted); aline.first->addAntiColoured(emitted); } else assert(false); } else { if(emitter->progenitor()->antiColourLine() ) { ColinePtr col = emitter->progenitor()->antiColourLine(); col->removeAntiColoured(emitter->copy()); col->removeAntiColoured(emitter->progenitor()); if(newEmit->antiColourLine()) { newEmit->antiColourLine()->removeAntiColoured(newEmit); col->addAntiColoured(newEmit); } else if (emitted->colourLine()) { emitted->colourLine()->removeColoured(emitted); col->addColoured(emitted); } else assert(false); } if(emitter->progenitor()->colourLine() ) { ColinePtr col = emitter->progenitor()->colourLine(); col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); if(newEmit->colourLine()) { newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } else if (emitted->antiColourLine()) { emitted->antiColourLine()->removeAntiColoured(emitted); col->addAntiColoured(emitted); } else assert(false); } } // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,false)); sp->x(x); emitter->progenitor(sp); tree->incomingLines()[emitter]=sp; emitter->perturbative(false); // add emitted sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } void fixFinalStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline) { map >::const_iterator tit; // special case if decayed for(tit = tree->treelinks().begin(); tit != tree->treelinks().end();++tit) { if(tit->second.first && tit->second.second==emitter->progenitor()) break; } // sort out the colour lines if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,true)); emitter->progenitor(sp); tree->outgoingLines()[emitter]=sp; emitter->perturbative(false); // update for decaying particles if(tit!=tree->treelinks().end()) tree->updateLink(tit->first,make_pair(emitter,sp)); // add the emitted particle // sort out the colour if(cline.first && cline.second==emitted->antiColourLine()) { cline.second->removeAntiColoured(emitted); cline.first->addAntiColoured(emitted); } else if(aline.first && aline.second==emitted->colourLine()) { aline.second->removeColoured(emitted); aline.first->addColoured(emitted); } else assert(false); sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(), emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } } void QTildeShowerHandler::setupMECorrection(RealEmissionProcessPtr real) { assert(real); currentTree()->hardMatrixElementCorrection(true); // II emission if(real->emitter() < real->incoming().size() && real->spectator() < real->incoming().size()) { // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // the the radiating system ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); // now for the emitter fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,cline,aline,iemit ==0 ? real->x().first :real->x().second); } // FF emission else if(real->emitter() >= real->incoming().size() && real->spectator() >= real->incoming().size()) { assert(real->outgoing()[real->emitted()-real->incoming().size()]->id()==ParticleID::g); // find the emitter and spectator in the shower tree ShowerProgenitorPtr emitter,spectator; int iemit = int(real->emitter())-int(real->incoming().size()); emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); int ispect = int(real->spectator())-int(real->incoming().size()); spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect]->id(), real->bornOutgoing()[ispect]->momentum()); map >::const_iterator tit; // first the spectator // special case if decayed for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->outgoing()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); // now the emitting particle int ig = int(real->emitted())-int(real->incoming().size()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig], emitter,cline,aline); } // IF emission else { // scattering process if(real->incoming().size()==2) { ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator if(ispect<2) { spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); } // outgoing spectator else { spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect-real->incoming().size()]->id(), real->bornOutgoing()[ispect-real->incoming().size()]->momentum()); // special case if decayed map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } fixSpectatorColours(real->outgoing()[ispect-real->incoming().size()],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect-real->incoming().size()]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect-real->incoming().size()],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); } // incoming emitter if(iemit<2) { emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,aline,cline,iemit ==0 ? real->x().first :real->x().second); } // outgoing emitter else { emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit-real->incoming().size()]->id(), real->bornOutgoing()[iemit-real->incoming().size()]->momentum()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit-real->incoming().size()], real->outgoing()[ig],emitter,aline,cline); } } // decay process else { assert(real->spectator()==0); unsigned int iemit = real->emitter()-real->incoming().size(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator ShowerProgenitorPtr spectator = findInitialStateLine(currentTree(), real->bornIncoming()[0]->id(), real->bornIncoming()[0]->momentum()); fixSpectatorColours(real->incoming()[0],spectator,cline,aline,false); // find the emitter ShowerProgenitorPtr emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { if(cjt->first==emitter) continue; cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // sort out the emitter fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig],emitter,aline,cline); } } // clean up the shower tree _currenttree->resetShowerProducts(); } diff --git a/Shower/QTilde/QTildeShowerHandler.h b/Shower/QTilde/QTildeShowerHandler.h --- a/Shower/QTilde/QTildeShowerHandler.h +++ b/Shower/QTilde/QTildeShowerHandler.h @@ -1,883 +1,883 @@ // -*- C++ -*- #ifndef Herwig_QTildeShowerHandler_H #define Herwig_QTildeShowerHandler_H // // This is the declaration of the QTildeShowerHandler class. // #include "QTildeShowerHandler.fh" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" #include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/Shower/QTilde/Base/Branching.h" #include "Herwig/Shower/QTilde/Base/ShowerVeto.h" #include "Herwig/Shower/QTilde/Base/FullShowerVeto.h" -#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.fh" +#include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.fh" #include "Herwig/Shower/QTilde/Base/PartnerFinder.fh" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.fh" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh" #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Decay/HwDecayerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Utilities/Statistic.h" namespace Herwig { using namespace ThePEG; /** * The QTildeShowerHandler class. * * @see \ref QTildeShowerHandlerInterfaces "The interfaces" * defined for QTildeShowerHandler. */ class QTildeShowerHandler: public ShowerHandler { public: /** * Pointer to an XComb object */ typedef Ptr::pointer XCPtr; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ QTildeShowerHandler(); /** * The destructor. */ virtual ~QTildeShowerHandler(); //@} public: /** * At the end of the Showering, transform ShowerParticle objects * into ThePEG particles and fill the event record with them. * Notice that the parent/child relationships and the * transformation from ShowerColourLine objects into ThePEG * ColourLine ones must be properly handled. */ void fillEventRecord(); /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const { return muPt; } /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ virtual bool showerHardProcessVeto() const { return false; } /** * Generate hard emissions for CKKW etc */ virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; /** * Members to perform the shower */ //@{ /** * Perform the shower of the hard process */ virtual void showerHardProcess(ShowerTreePtr,XCPtr); /** * Perform the shower of a decay */ virtual void showerDecay(ShowerTreePtr); //@} /** * Access to the flags and shower variables */ //@{ /** * Get the SplittingGenerator */ tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } /** * Mode for hard emissions */ int hardEmission() const {return _hardEmission;} //@} /** * Connect the Hard and Shower trees */ virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ); /** * Access to switches for spin correlations */ //@{ /** * Spin Correlations */ unsigned int spinCorrelations() const { return _spinOpt; } /** * Soft correlations */ unsigned int softCorrelations() const { return _softOpt; } /** * Any correlations */ bool correlations() const { return _spinOpt!=0||_softOpt!=0; } //@} public: /** * Access methods to access the objects */ //@{ /** * Access to the KinematicsReconstructor object */ tKinematicsReconstructorPtr kinematicsReconstructor() const { return _reconstructor; } /** * Access to the PartnerFinder object */ tPartnerFinderPtr partnerFinder() const { return _partnerfinder; } //@} protected: /** * Perform the shower */ void doShowering(bool hard,XCPtr); /** * Generate the hard matrix element correction */ virtual RealEmissionProcessPtr hardMatrixElementCorrection(bool); /** * Generate the hardest emission */ virtual void hardestEmission(bool hard); /** * Set up for applying a matrix element correction */ void setupMECorrection(RealEmissionProcessPtr real); /** * Extract the particles to be showered, set the evolution scales * and apply the hard matrix element correction * @param hard Whether this is a hard process or decay * @return The particles to be showered */ virtual vector setupShower(bool hard); /** * set the colour partners */ virtual void setEvolutionPartners(bool hard,ShowerInteraction, bool clear); /** * Methods to perform the evolution of an individual particle, including * recursive calling on the products */ //@{ /** * It does the forward evolution of the time-like input particle * (and recursively for all its radiation products). * accepting only emissions which conforms to the showerVariables * and soft matrix element correction. * If at least one emission has occurred then the method returns true. * @param particle The particle to be showered */ virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction, Branching fb, bool first); /** * It does the backward evolution of the space-like input particle * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * If at least one emission has occurred then the method returns true * @param particle The particle to be showered * @param beam The beam particle */ virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam, ShowerInteraction); /** * If does the forward evolution of the input on-shell particle * involved in a decay * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * @param particle The particle to be showered * @param maxscale The maximum scale for the shower. * @param minimumMass The minimum mass of the final-state system */ virtual bool spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction, Branching fb); /** * Truncated shower from a time-like particle */ virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first); /** * Truncated shower from a space-like particle */ virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam, HardBranchingPtr branch, ShowerInteraction type); /** * Truncated shower from a time-like particle */ virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass, HardBranchingPtr branch, ShowerInteraction type, Branching fb); //@} /** * Switches for matrix element corrections */ //@{ /** * Any ME correction? */ bool MECOn() const { return _hardEmission == 1; } /** * Any hard ME correction? */ bool hardMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode == 2); } /** * Any soft ME correction? */ bool softMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode > 2); } //@} /** * Is the truncated shower on? */ bool isTruncatedShowerON() const {return _trunc_Mode;} /** * Switch for intrinsic pT */ //@{ /** * Any intrinsic pT? */ bool ipTon() const { return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); } //@} /**@name Additional shower vetoes */ //@{ /** * Insert a veto. */ void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } /** * Remove a veto. */ void removeVeto (ShowerVetoPtr v) { vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); if (vit != _vetoes.end()) _vetoes.erase(vit); } //@} /** * Switches for vetoing hard emissions */ //@{ /** * Returns true if the hard veto read-in is to be applied to only * the primary collision and false otherwise. */ bool hardVetoReadOption() const {return _hardVetoReadOption;} //@} /** * Enhancement factors for radiation needed to generate the soft matrix * element correction. */ //@{ /** * Access the enhancement factor for initial-state radiation */ double initialStateRadiationEnhancementFactor() const { return _initialenhance; } /** * Access the enhancement factor for final-state radiation */ double finalStateRadiationEnhancementFactor() const { return _finalenhance; } /** * Set the enhancement factor for initial-state radiation */ void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } /** * Set the enhancement factor for final-state radiation */ void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } //@} /** * Access to set/get the HardTree currently beinging showered */ //@{ /** * The HardTree currently being showered */ tHardTreePtr hardTree() {return _hardtree;} /** * The HardTree currently being showered */ void hardTree(tHardTreePtr in) {_hardtree = in;} //@} /** * Access/set the beam particle for the current initial-state shower */ //@{ /** * Get the beam particle data */ Ptr::const_pointer beamParticle() const { return _beam; } /** * Set the beam particle data */ void setBeamParticle(Ptr::const_pointer in) { _beam=in; } //@} /** * Set/Get the current tree being evolver for inheriting classes */ //@{ /** * Get the tree */ tShowerTreePtr currentTree() { return _currenttree; } /** * Set the tree */ void currentTree(tShowerTreePtr tree) { _currenttree=tree; } //@} /** * Access the maximum number of attempts to generate the shower */ unsigned int maximumTries() const { return _maxtry; } /** * Set/Get the ShowerProgenitor for the current shower */ //@{ /** * Access the progenitor */ ShowerProgenitorPtr progenitor() { return _progenitor; } /** * Set the progenitor */ void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } //@} /** * Calculate the intrinsic \f$p_T\f$. */ virtual void generateIntrinsicpT(vector); /** * Access to the intrinsic \f$p_T\f$ for inheriting classes */ map > & intrinsicpT() { return _intrinsic; } /** * find the maximally allowed pt acc to the hard process. */ void setupMaximumScales(const vector &,XCPtr); /** * find the relevant hard scales for profile scales. */ void setupHardScales(const vector &,XCPtr); /** * Convert the HardTree into an extra shower emission */ void convertHardTree(bool hard,ShowerInteraction type); protected: /** * Find the parton extracted from the incoming particle after ISR */ PPtr findFirstParton(tPPtr seed) const; /** * Fix Remnant connections after ISR */ tPPair remakeRemnant(tPPair oldp); protected: /** * Start the shower of a timelike particle */ virtual bool startTimeLikeShower(ShowerInteraction); /** * Update of the time-like stuff */ void updateHistory(tShowerParticlePtr particle); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeShower(PPtr,ShowerInteraction); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction); /** * Select the branching for the next time-like emission */ Branching selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch); /** * Select the branching for the next space-like emission in a decay */ Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch); /** * Create the timelike child of a branching */ ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle, IdList ids); /** * Vetos for the timelike shower */ virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); /** * Only generate the hard emission, for testing only. */ bool hardOnly() const {return _limitEmissions==3;} /** * Check the flags */ void checkFlags(); /** * */ void addFSRUsingDecayPOWHEG(HardTreePtr ISRTree); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); /** * Decay a ShowerTree */ void decay(ShowerTreePtr tree, ShowerDecayMap & decay); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeShowerHandler & operator=(const QTildeShowerHandler &); private: /** * Stuff from the ShowerHandler */ //@{ /** * The ShowerTree for the hard process */ ShowerTreePtr hard_; /** * The ShowerTree for the decays */ ShowerDecayMap decay_; /** * The ShowerTrees for which the initial shower */ vector done_; //@} private : /** * Pointer to the splitting generator */ SplittingGeneratorPtr _splittingGenerator; /** * Maximum number of tries to generate the shower of a particular tree */ unsigned int _maxtry; /** * Matrix element correction switch */ unsigned int _meCorrMode; /** * Control of the reconstruction option */ unsigned int _reconOpt; /** * If hard veto pT scale is being read-in this determines * whether the read-in value is applied to primary and * secondary (MPI) scatters or just the primary one, with * the usual computation of the veto being performed for * the secondary (MPI) scatters. */ bool _hardVetoReadOption; /** * rms intrinsic pT of Gaussian distribution */ Energy _iptrms; /** * Proportion of inverse quadratic intrinsic pT distribution */ double _beta; /** * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) */ Energy _gamma; /** * Upper bound on intrinsic pT for inverse quadratic */ Energy _iptmax; /** * Limit the number of emissions for testing */ unsigned int _limitEmissions; /** * The progenitor of the current shower */ ShowerProgenitorPtr _progenitor; /** * Matrix element */ HwMEBasePtr _hardme; /** * Decayer */ HwDecayerBasePtr _decayme; /** * The ShowerTree currently being showered */ ShowerTreePtr _currenttree; /** * The HardTree currently being showered */ HardTreePtr _hardtree; /** * Radiation enhancement factors for use with the veto algorithm * if needed by the soft matrix element correction */ //@{ /** * Enhancement factor for initial-state radiation */ double _initialenhance; /** * Enhancement factor for final-state radiation */ double _finalenhance; //@} /** * The beam particle data for the current initial-state shower */ Ptr::const_pointer _beam; /** * Storage of the intrinsic \f$p_t\f$ of the particles */ map > _intrinsic; /** * Vetoes */ vector _vetoes; /** * Full Shower Vetoes */ vector _fullShowerVetoes; /** * Number of iterations for reweighting */ unsigned int _nReWeight; /** * Whether or not we are reweighting */ bool _reWeight; /** * number of IS emissions */ unsigned int _nis; /** * Number of FS emissions */ unsigned int _nfs; /** * The option for wqhich interactions to use */ ShowerInteraction interaction_; /** * Truncated shower switch */ bool _trunc_Mode; /** * Count of the number of truncated emissions */ unsigned int _truncEmissions; /** * Mode for the hard emissions */ int _hardEmission; /** * Option to include spin correlations */ unsigned int _spinOpt; /** * Option for the kernal for soft correlations */ unsigned int _softOpt; /** * Option for hard radiation in POWHEG events */ bool _hardPOWHEG; /** * True if no warnings about incorrect hard emission * mode setting have been issued yet */ static bool _hardEmissionWarn; /** * True if no warnings about missing truncated shower * have been issued yet */ static bool _missingTruncWarn; /** * The relevant hard scale to be used in the profile scales */ Energy muPt; /** * Maximum number of emission attempts for FSR */ unsigned int _maxTryFSR; /** * Maximum number of failures for FSR generation */ unsigned int _maxFailFSR; /** * Failure fraction for FSR generation */ double _fracFSR; /** * Counter for number of FSR emissions */ unsigned int _nFSR; /** * Counter for the number of failed events due to FSR emissions */ unsigned int _nFailedFSR; private: /** * Pointer to the various objects */ //@{ /** * Pointer to the KinematicsReconstructor object */ KinematicsReconstructorPtr _reconstructor; /** * Pointer to the PartnerFinder object */ PartnerFinderPtr _partnerfinder; //@} }; } #endif /* HERWIG_QTildeShowerHandler_H */ diff --git a/Shower/QTilde/ShowerConfig.cc b/Shower/QTilde/ShowerConfig.cc --- a/Shower/QTilde/ShowerConfig.cc +++ b/Shower/QTilde/ShowerConfig.cc @@ -1,47 +1,47 @@ // -*- C++ -*- // // ShowerConfig.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerConfig class. // #include "ShowerConfig.h" -#include "Base/SudakovFormFactor.h" +#include "SplittingFunctions/SudakovFormFactor.h" using namespace Herwig; BranchingElement::~BranchingElement() {} BranchingElement::BranchingElement() {} BranchingElement::BranchingElement(SudakovPtr sud, IdList part) : sudakov(sud), particles(part) { for(unsigned int ix=0;ixCC() ? tcPDPtr(part[ix]->CC()) : part[ix]); } namespace ThePEG { /** * Output operator to allow the structure */ PersistentOStream & operator << (PersistentOStream & os, const Herwig::BranchingElement & x) { os << x.sudakov << x.particles << x.conjugateParticles; return os; } /** * Input operator to allow the structure */ PersistentIStream & operator >> (PersistentIStream & is, Herwig::BranchingElement & x) { is >> x.sudakov >> x.particles >> x.conjugateParticles; return is; } } diff --git a/Shower/QTilde/ShowerConfig.h b/Shower/QTilde/ShowerConfig.h --- a/Shower/QTilde/ShowerConfig.h +++ b/Shower/QTilde/ShowerConfig.h @@ -1,151 +1,151 @@ // -*- C++ -*- // // ShowerConfig.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerConfig_H #define HERWIG_ShowerConfig_H // // This is the declaration of the ShowerConfig class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDT/ParticleData.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.fh" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.fh" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/ShowerInteraction.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * Handy header file to be included in all Shower classes. * It contains only some useful typedefs. */ /** * Pointer to a ColourLine */ typedef Ptr::pointer ColinePtr; /** * Transient Pointer to a ColourLine */ typedef Ptr::transient_pointer tColinePtr; /** * A pair of ColourLine pointers */ typedef pair ColinePair; /** * A pair of transient ColourLine pointers */ typedef pair tColinePair; /** * A Vector of ShowerParticle pointers */ typedef vector ShowerParticleVector; /** * A Vector of transient ShowerParticle pointers */ typedef vector tShowerParticleVector; /** * Definition of the IdList for branchings */ typedef vector IdList; inline ShowerInteraction convertInteraction(ShowerPartnerType partner) { if (partner==ShowerPartnerType::QCDColourLine || partner==ShowerPartnerType::QCDAntiColourLine) return ShowerInteraction::QCD; else if (partner==ShowerPartnerType::QED) return ShowerInteraction::QED; else return ShowerInteraction::UNDEFINED; } /** * typedef to pair the SudakovFormFactor and the particles in a branching */ struct BranchingElement { /** * Constructor */ BranchingElement(); /** * Constructor */ BranchingElement(SudakovPtr sud, IdList part); /** * Destructor */ ~BranchingElement(); /** * Access to the Sudakov */ SudakovPtr sudakov; /** * Access to the particles */ IdList particles; /** * Access to the charge conjugate particles */ IdList conjugateParticles; /** * Compare two BranchingElements **/ bool operator == (const BranchingElement& x) const{ return sudakov == x.sudakov && particles == x.particles && conjugateParticles == x.conjugateParticles; } }; /** * typedef to pair the PDG code of the particle and the BranchingElement */ typedef multimap BranchingList; /** * typedef to create a structure which can be inserted into a BranchingList */ typedef pair BranchingInsert; } namespace ThePEG { /** * Output operator to allow the structure */ PersistentOStream & operator << (PersistentOStream & os, const Herwig::BranchingElement & x); /** * Input operator to allow the structure */ PersistentIStream & operator >> (PersistentIStream & is, Herwig::BranchingElement & x); } #endif // HERWIG_ShowerConfig_H diff --git a/Shower/QTilde/SplittingFunctions/SplittingFunction.h b/Shower/QTilde/SplittingFunctions/SplittingFunction.h --- a/Shower/QTilde/SplittingFunctions/SplittingFunction.h +++ b/Shower/QTilde/SplittingFunctions/SplittingFunction.h @@ -1,377 +1,377 @@ // -*- C++ -*- // // SplittingFunction.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SplittingFunction_H #define HERWIG_SplittingFunction_H // // This is the declaration of the SplittingFunction class. // #include "ThePEG/Interface/Interfaced.h" #include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "Herwig/Decay/DecayMatrixElement.h" -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.fh" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.fh" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/PDT/ParticleData.h" #include "SplittingFunction.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * Enum to define the possible types of colour structure which can occur in * the branching. */ enum ColourStructure {Undefined=0, TripletTripletOctet = 1,OctetOctetOctet =2, OctetTripletTriplet = 3,TripletOctetTriplet=4, SextetSextetOctet = 5, ChargedChargedNeutral=-1,ChargedNeutralCharged=-2, NeutralChargedCharged=-3}; /** \ingroup Shower * * This is an abstract class which defines the common interface * for all \f$1\to2\f$ splitting functions, for both initial-state * and final-state radiation. * * The SplittingFunction class contains a number of purely virtual members * which must be implemented in the inheriting classes. The class also stores * the interaction type of the spltting function. * * The inheriting classes need to specific the splitting function * \f$P(z,2p_j\cdot p_k)\f$, in terms of the energy fraction \f$z\f$ and * the evolution scale. In order to allow the splitting functions to be used * with different choices of evolution functions the scale is given by * \f[2p_j\cdot p_k=(p_j+p_k)^2-m_{jk}^2=Q^2-(p_j+p_k)^2=z(1-z)\tilde{q}^2= * \frac{p_T^2}{z(1-z)}-m_{jk}^2+\frac{m_j^2}{z}+\frac{m_k^2}{1-z},\f] * where \f$Q^2\f$ is the virtuality of the branching particle, * $p_T$ is the relative transverse momentum of the branching products and * \f$\tilde{q}^2\f$ is the angular variable described in hep-ph/0310083. * * In addition an overestimate of the * splitting function, \f$P_{\rm over}(z)\f$ which only depends upon \f$z\f$, * the integral, inverse of the integral for this overestimate and * ratio of the true splitting function to the overestimate must be provided * as they are necessary for the veto alogrithm used to implement the evolution. * * @see \ref SplittingFunctionInterfaces "The interfaces" * defined for SplittingFunction. */ class SplittingFunction: public Interfaced { public: /** * The default constructor. * @param b All splitting functions must have an interaction order */ SplittingFunction() : Interfaced(), _interactionType(ShowerInteraction::UNDEFINED), _colourStructure(Undefined), _colourFactor(-1.), angularOrdered_(true), scaleChoice_(2) {} public: /** * Methods to return the interaction type and order for the splitting function */ //@{ /** * Return the type of the interaction */ ShowerInteraction interactionType() const {return _interactionType;} /** * Return the colour structure */ ColourStructure colourStructure() const {return _colourStructure;} /** * Return the colour factor */ double colourFactor(const IdList &ids) const { if(_colourStructure>0) return _colourFactor; else if(_colourStructure<0) { if(_colourStructure==ChargedChargedNeutral || _colourStructure==ChargedNeutralCharged) { return sqr(double(ids[0]->iCharge())/3.); } else if(_colourStructure==NeutralChargedCharged) { double fact = sqr(double(ids[1]->iCharge())/3.); if(ids[1]->coloured()) fact *= abs(double(ids[1]->iColour())); return fact; } else assert(false); } else assert(false); } //@} /** * Purely virtual method which should determine whether this splitting * function can be used for a given set of particles. * @param ids The PDG codes for the particles in the splitting. */ virtual bool accept(const IdList & ids) const = 0; /** * Method to check the colours are correct */ virtual bool checkColours(const IdList & ids) const; /** * Methods to return the splitting function. */ //@{ /** * Purely virtual method which should return the exact value of the splitting function, * \f$P\f$ evaluated in terms of the energy fraction, \f$z\f$, and the evolution scale \f$\tilde{q}^2\f$. * @param z The energy fraction. * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms */ virtual double P(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const = 0; /** * Purely virtual method which should return * an overestimate of the splitting function, * \f$P_{\rm over}\f$ such that the result \f$P_{\rm over}\geq P\f$. This function * should be simple enough that it does not depend on the evolution scale. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. */ virtual double overestimateP(const double z, const IdList & ids) const = 0; /** * Purely virtual method which should return * the ratio of the splitting function to the overestimate, i.e. * \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$. * @param z The energy fraction. * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms */ virtual double ratioP(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const = 0; /** * Purely virtual method which should return the indefinite integral of the * overestimated splitting function, \f$P_{\rm over}\f$. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ * */ virtual double integOverP(const double z, const IdList & ids, unsigned int PDFfactor=0) const = 0; /** * Purely virtual method which should return the inverse of the * indefinite integral of the * overestimated splitting function, \f$P_{\rm over}\f$ which is used to * generate the value of \f$z\f$. * @param r Value of the splitting function to be inverted * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ */ virtual double invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor=0) const = 0; //@} /** * Purely virtual method which should make the proper colour connection * between the emitting parent and the branching products. * @param parent The parent for the branching * @param first The first branching product * @param second The second branching product * @param partnerType The type of evolution partner * @param back Whether this is foward or backward evolution. */ virtual void colourConnection(tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second, ShowerPartnerType partnerType, const bool back) const; /** * Method to calculate the azimuthal angle for forward evolution * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param The azimuthal angle, \f$\phi\f$. * @return The weight */ virtual vector > generatePhiForward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &) = 0; /** * Method to calculate the azimuthal angle for backward evolution * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @return The weight */ virtual vector > generatePhiBackward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &) = 0; /** * Calculate the matrix element for the splitting * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param phi The azimuthal angle, \f$\phi\f$. * @param timeLike Whether timelike or spacelike, affects inclusive of mass terms */ virtual DecayMEPtr matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) = 0; /** * Whether or not the interaction is angular ordered */ bool angularOrdered() const {return angularOrdered_;} /** * Scale choice */ bool pTScale() const { return scaleChoice_ == 2 ? angularOrdered_ : scaleChoice_ == 0; } /** * Functions to state scales after branching happens */ //@{ /** * Sort out scales for final-state emission */ void evaluateFinalStateScales(ShowerPartnerType type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); /** * Sort out scales for initial-state emission */ void evaluateInitialStateScales(ShowerPartnerType type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); /** * Sort out scales for decay emission */ void evaluateDecayScales(ShowerPartnerType type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Set the colour factor */ void colourFactor(double in) {_colourFactor=in;} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SplittingFunction & operator=(const SplittingFunction &); private: /** * The interaction type for the splitting function. */ ShowerInteraction _interactionType; /** * The colour structure */ ColourStructure _colourStructure; /** * The colour factor */ double _colourFactor; /** * Whether or not this interaction is angular-ordered */ bool angularOrdered_; /** * The choice of scale */ unsigned int scaleChoice_; }; } #endif /* HERWIG_SplittingFunction_H */ diff --git a/Shower/QTilde/SplittingFunctions/SplittingGenerator.h b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h --- a/Shower/QTilde/SplittingFunctions/SplittingGenerator.h +++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h @@ -1,321 +1,321 @@ // -*- C++ -*- // // SplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SplittingGenerator_H #define HERWIG_SplittingGenerator_H // // This is the declaration of the SplittingGenerator class. // #include "ThePEG/Interface/Interfaced.h" #include "Herwig/Shower/QTilde/Base/Branching.h" -#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h" #include "SplittingGenerator.fh" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" -#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This class is responsible for creating, at the beginning of the Run, * all the SplittingFunction objects and the corresponding * SudakovFormFactor objects, and then of the generation of splittings * (radiation emissions) during the event. * Many switches are defined in this class which allowed the user to turn on/off: * - each type of interaction (QCD, QED, EWK,...); * - initial- and final-state radiation for all type of interactions; * - initial- and final-state radiation for each type of interaction; * - each type of splitting (\f$u\to ug\f$, \f$d\to dg\f$, \f$\ldots\f$, * \f$g\to gg\f$, \f$g\to u\bar{u}\f$, \f$\ldots\f$). * * These switches are useful mainly for debugging, but eventually can * also be used for a "quick and dirty" estimation of systematic errors. * * In the future it should be possible to implement in this class * * - the \f$1\to2\f$ azimuthal correlations for soft emission due to QCD coherence * using the ShowerParticle object provided in the input. * - Similarly having the \f$\rho-D\f$ matrix and the SplittingFunction pointer * it should be possible to implement the spin correlations. * * @see SudakovFormFactor * @see SplitFun * * @see \ref SplittingGeneratorInterfaces "The interfaces" * defined for SplittingGenerator. */ class SplittingGenerator: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ SplittingGenerator() : _deTuning(1.) {} //@} public: /** * Methods to select the next branching and reconstruct the kinematics */ //@{ /** * Choose a new forward branching for a time-like particle * The method returns: * - a pointer to a ShowerKinematics object, which * contains the information about the new scale and all other * kinematics variables that need to be generated simultaneously; * - a pointer to the SudakovFormFactor object associated * with the chosen emission. * - The PDG codes of the particles in the branching, * as a Branching struct. * * In the case no branching has been generated, both the returned * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). * * @param particle The particle to be evolved * @param enhance The factor by which to ehnace the emission of radiation * @param type The type of interaction to generate * @return The Branching struct for the branching */ Branching chooseForwardBranching(ShowerParticle & particle, double enhance, ShowerInteraction type) const; /** * Select the next branching of a particles for the initial-state shower * in the particle's decay. * @param particle The particle being showerwed * @param maxscale The maximum scale * @param minmass Minimum mass of the particle after the branching * @param enhance The factor by which to ehnace the emission of radiation * @param type The type of interaction to generate * @return The Branching struct for the branching */ Branching chooseDecayBranching(ShowerParticle & particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,double enhance, ShowerInteraction type) const; /** * Choose a new backward branching for a space-like particle. * The method returns: * - a pointer to a ShowerKinematics object, which * contains the information about the new scale and all other * kinematics variables that need to be generated simultaneously; * - a pointer to the SudakovFormFactor object associated * with the chosen emission. * - The PDG codes of the particles in the branching, * as a Branching struct. * * In the case no branching has been generated, both the returned * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). * * @param particle The particle to be evolved * @param enhance The factor by which to ehnace the emission of radiation * @param beamparticle The beam particle * @param beam The BeamParticleData object * @param type The type of interaction to generate * @return The Branching struct for the branching */ Branching chooseBackwardBranching(ShowerParticle & particle, PPtr beamparticle, double enhance, Ptr::transient_const_pointer beam, ShowerInteraction type, tcPDFPtr , Energy ) const; //@} public: /** * Methods to parse the information from the input files to create the * branchings */ //@{ /** * Add a final-state splitting */ string addFinalSplitting(string arg) { return addSplitting(arg,true); } /** * Add an initial-state splitting */ string addInitialSplitting(string arg) { return addSplitting(arg,false); } /** * Add a final-state splitting */ string deleteFinalSplitting(string arg) { return deleteSplitting(arg,true); } /** * Add an initial-state splitting */ string deleteInitialSplitting(string arg) { return deleteSplitting(arg,false); } //@} /** * Access to the splittings */ //@{ /** * Access the final-state branchings */ const BranchingList & finalStateBranchings() const { return _fbranchings; } /** * Access the initial-state branchings */ const BranchingList & initialStateBranchings() const { return _bbranchings; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); //@} private: /** * Add a branching to the map * @param ids PDG coeds of the particles in the branching * @param sudakov The SudakovFormFactor for the branching * @param final Whether this is an initial- or final-state branching */ void addToMap(const IdList & ids, const SudakovPtr & sudakov, bool final); /** * Remove a branching to the map * @param ids PDG coeds of the particles in the branching * @param sudakov The SudakovFormFactor for the branching * @param final Whether this is an initial- or final-state branching */ void deleteFromMap(const IdList & ids, const SudakovPtr & sudakov, bool final); /** * Obtain the reference vectors for a final-state particle * @param particle The particle * @param p The p reference vector * @param n The n reference vector */ void finalStateBasisVectors(ShowerParticle particle, Lorentz5Momentum & p, Lorentz5Momentum & n) const; /** * Add a splitting * @param in string to be parsed * @param final Whether this is an initial- or final-state branching */ string addSplitting(string in ,bool final); /** * Delete a splitting * @param in string to be parsed * @param final Whether this is an initial- or final-state branching */ string deleteSplitting(string in ,bool final); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SplittingGenerator & operator=(const SplittingGenerator &); private: /** * List of the branchings and the appropriate Sudakovs for forward branchings */ BranchingList _fbranchings; /** * Lists of the branchings and the appropriate Sudakovs for backward branchings. */ BranchingList _bbranchings; /** * The detuning parameter */ double _deTuning; }; } #endif /* HERWIG_SplittingGenerator_H */ diff --git a/Shower/QTilde/Base/SudakovFormFactor.cc b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc rename from Shower/QTilde/Base/SudakovFormFactor.cc rename to Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc --- a/Shower/QTilde/Base/SudakovFormFactor.cc +++ b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.cc @@ -1,1371 +1,1371 @@ // -*- C++ -*- // // SudakovFormFactor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SudakovFormFactor class. // #include "SudakovFormFactor.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" -#include "ShowerKinematics.h" -#include "ShowerParticle.h" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include "Herwig/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h" #include using std::array; using namespace Herwig; DescribeClass describeSudakovFormFactor ("Herwig::SudakovFormFactor",""); void SudakovFormFactor::persistentOutput(PersistentOStream & os) const { os << splittingFn_ << alpha_ << pdfmax_ << particles_ << pdffactor_ << a_ << b_ << ounit(c_,GeV) << ounit(kinCutoffScale_,GeV) << cutOffOption_ << ounit(vgcut_,GeV) << ounit(vqcut_,GeV) << ounit(pTmin_,GeV) << ounit(pT2min_,GeV2); } void SudakovFormFactor::persistentInput(PersistentIStream & is, int) { is >> splittingFn_ >> alpha_ >> pdfmax_ >> particles_ >> pdffactor_ >> a_ >> b_ >> iunit(c_,GeV) >> iunit(kinCutoffScale_,GeV) >> cutOffOption_ >> iunit(vgcut_,GeV) >> iunit(vqcut_,GeV) >> iunit(pTmin_,GeV) >> iunit(pT2min_,GeV2); } void SudakovFormFactor::Init() { static ClassDocumentation documentation ("The SudakovFormFactor class is the base class for the implementation of Sudakov" " form factors in Herwig"); static Reference interfaceSplittingFunction("SplittingFunction", "A reference to the SplittingFunction object", &Herwig::SudakovFormFactor::splittingFn_, false, false, true, false); static Reference interfaceAlpha("Alpha", "A reference to the Alpha object", &Herwig::SudakovFormFactor::alpha_, false, false, true, false); static Parameter interfacePDFmax ("PDFmax", "Maximum value of PDF weight. ", &SudakovFormFactor::pdfmax_, 35.0, 1.0, 1000000.0, false, false, Interface::limited); static Switch interfacePDFFactor ("PDFFactor", "Include additional factors in the overestimate for the PDFs", &SudakovFormFactor::pdffactor_, 0, false, false); static SwitchOption interfacePDFFactorNo (interfacePDFFactor, "No", "Don't include any factors", 0); static SwitchOption interfacePDFFactorOverZ (interfacePDFFactor, "OverZ", "Include an additional factor of 1/z", 1); static SwitchOption interfacePDFFactorOverOneMinusZ (interfacePDFFactor, "OverOneMinusZ", "Include an additional factor of 1/(1-z)", 2); static SwitchOption interfacePDFFactorOverZOneMinusZ (interfacePDFFactor, "OverZOneMinusZ", "Include an additional factor of 1/z/(1-z)", 3); static SwitchOption interfacePDFFactorOverRootZ (interfacePDFFactor, "OverRootZ", "Include an additional factor of 1/sqrt(z)", 4); static SwitchOption interfacePDFFactorRootZ (interfacePDFFactor, "RootZ", "Include an additional factor of sqrt(z)", 5); static Switch interfaceCutOffOption ("CutOffOption", "The type of cut-off to use to end the shower", &SudakovFormFactor::cutOffOption_, 0, false, false); static SwitchOption interfaceCutOffOptionDefault (interfaceCutOffOption, "Default", "Use the standard Herwig cut-off on virtualities with the minimum" " virtuality depending on the mass of the branching particle", 0); static SwitchOption interfaceCutOffOptionFORTRAN (interfaceCutOffOption, "FORTRAN", "Use a FORTRAN-like cut-off on virtualities", 1); static SwitchOption interfaceCutOffOptionpT (interfaceCutOffOption, "pT", "Use a cut on the minimum allowed pT", 2); static Parameter interfaceaParameter ("aParameter", "The a parameter for the kinematic cut-off", &SudakovFormFactor::a_, 0.3, -10.0, 10.0, false, false, Interface::limited); static Parameter interfacebParameter ("bParameter", "The b parameter for the kinematic cut-off", &SudakovFormFactor::b_, 2.3, -10.0, 10.0, false, false, Interface::limited); static Parameter interfacecParameter ("cParameter", "The c parameter for the kinematic cut-off", &SudakovFormFactor::c_, GeV, 0.3*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceKinScale ("cutoffKinScale", "kinematic cutoff scale for the parton shower phase" " space (unit [GeV])", &SudakovFormFactor::kinCutoffScale_, GeV, 2.3*GeV, 0.001*GeV, 10.0*GeV,false,false,false); static Parameter interfaceGluonVirtualityCut ("GluonVirtualityCut", "For the FORTRAN cut-off option the minimum virtuality of the gluon", &SudakovFormFactor::vgcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceQuarkVirtualityCut ("QuarkVirtualityCut", "For the FORTRAN cut-off option the minimum virtuality added to" " the mass for particles other than the gluon", &SudakovFormFactor::vqcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacepTmin ("pTmin", "The minimum pT if using a cut-off on the pT", &SudakovFormFactor::pTmin_, GeV, 1.0*GeV, ZERO, 10.0*GeV, false, false, Interface::limited); } bool SudakovFormFactor::alphaSVeto(Energy2 pt2) const { double ratio=alphaSVetoRatio(pt2,1.); return UseRandom::rnd() > ratio; } double SudakovFormFactor::alphaSVetoRatio(Energy2 pt2, double factor) const { factor *= ShowerHandler::currentHandler()->renormalizationScaleFactor(); return alpha_->ratio(pt2, factor); } bool SudakovFormFactor::PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::transient_const_pointer beam) const { double ratio=PDFVetoRatio(t,x,parton0,parton1,beam,1.); return UseRandom::rnd() > ratio; } double SudakovFormFactor::PDFVetoRatio(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::transient_const_pointer beam,double factor) const { assert(pdf_); Energy2 theScale = t * sqr(ShowerHandler::currentHandler()->factorizationScaleFactor()*factor); if (theScale < sqr(freeze_)) theScale = sqr(freeze_); const double newpdf=pdf_->xfx(beam,parton0,theScale,x/z()); if(newpdf<=0.) return 0.; const double oldpdf=pdf_->xfx(beam,parton1,theScale,x); if(oldpdf<=0.) return 1.; const double ratio = newpdf/oldpdf; double maxpdf = pdfmax_; switch (pdffactor_) { case 0: break; case 1: maxpdf /= z(); break; case 2: maxpdf /= 1.-z(); break; case 3: maxpdf /= (z()*(1.-z())); break; case 4: maxpdf /= sqrt(z()); break; case 5: maxpdf *= sqrt(z()); break; default : throw Exception() << "SudakovFormFactor::PDFVetoRatio invalid PDFfactor = " << pdffactor_ << Exception::runerror; } if (ratio > maxpdf) { generator()->log() << "PDFVeto warning: Ratio > " << name() << ":PDFmax (by a factor of " << ratio/maxpdf <<") for " << parton0->PDGName() << " to " << parton1->PDGName() << "\n"; } return ratio/maxpdf ; } void SudakovFormFactor::addSplitting(const IdList & in) { bool add=true; for(unsigned int ix=0;ix::iterator it=particles_.begin(); it!=particles_.end();++it) { if(it->size()==in.size()) { bool match=true; for(unsigned int iy=0;iy::iterator itemp=it; --itemp; particles_.erase(it); it = itemp; } } } } Energy2 SudakovFormFactor::guesst(Energy2 t1,unsigned int iopt, const IdList &ids, double enhance,bool ident, double detune) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double c = 1./((splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - splittingFn_->integOverP(zlimits_.first ,ids,pdfopt))* alpha_->overestimateValue()/Constants::twopi*enhance*detune); assert(iopt<=2); if(iopt==1) { c/=pdfmax_; //symmetry of FS gluon splitting if(ident) c*=0.5; } else if(iopt==2) c*=-1.; double r = UseRandom::rnd(); if(iopt!=2 || c*log(r)integOverP(zlimits_.first,ids,pdfopt); return splittingFn_->invIntegOverP (lower + UseRandom::rnd()*(splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - lower),ids,pdfopt); } void SudakovFormFactor::doinit() { Interfaced::doinit(); pT2min_ = cutOffOption()==2 ? sqr(pTmin_) : ZERO; } const vector & SudakovFormFactor::virtualMasses(const IdList & ids) { static vector output; output.clear(); if(cutOffOption() == 0) { for(unsigned int ix=0;ixmass()); Energy kinCutoff= kinematicCutOff(kinScale(),*std::max_element(output.begin(),output.end())); for(unsigned int ix=0;ixmass()); output.back() += ids[ix]->id()==ParticleID::g ? vgCut() : vqCut(); } } else if(cutOffOption() == 2) { for(unsigned int ix=0;ixmass()); } else { throw Exception() << "Unknown option for the cut-off" << " in SudakovFormFactor::virtualMasses()" << Exception::runerror; } return output; } bool SudakovFormFactor::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance, double detune) { Energy2 told = t; // calculate limits on z and if lower>upper return if(!computeTimeLikeLimits(t)) return false; // guess values of t and z t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2],detune); z_ = guessz(0,ids_); // actual values for z-limits if(!computeTimeLikeLimits(t)) return false; if(tupper return if(!computeSpaceLikeLimits(t,x)) return false; // guess values of t and z t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2],detune); z_ = guessz(1,ids_); // actual values for z-limits if(!computeSpaceLikeLimits(t,x)) return false; if(t zlimits_.second) return true; Energy2 q2 = z()*(1.-z())*t; if(ids_[0]->id()!=ParticleID::g && ids_[0]->id()!=ParticleID::gamma ) q2 += masssquared_[0]; if(q2>maxQ2) return true; // compute the pts Energy2 pt2 = z()*(1.-z())*q2 - masssquared_[1]*(1.-z()) - masssquared_[2]*z(); // if pt2<0 veto if(pt2 min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax); // no shower variations to calculate if(ShowerHandler::currentHandler()->showerVariations().empty()){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; } while(PSVeto(t,maxQ2) || SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning) || alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); } else { bool alphaRew(true),PSRew(true),SplitRew(true); do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; PSRew=PSVeto(t,maxQ2); if (PSRew) continue; SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning); alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t); double factor=alphaSVetoRatio(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)* SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning); tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map::const_iterator var = ch->showerVariations().begin(); var != ch->showerVariations().end(); ++var ) { if ( ( ch->firstInteraction() && var->second.firstInteraction ) || ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { double newfactor = alphaSVetoRatio(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,var->second.renormalizationScaleFactor) * SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning); double varied; if ( SplitRew || alphaRew ) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) wi->second *= varied; else { assert(false); //ch->currentWeights()[var->first] = varied; } } } } while(PSRew || SplitRew || alphaRew); } q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if(q_ < ZERO) return ShoKinPtr(); // return the ShowerKinematics object return createFinalStateBranching(q_,z(),phi(),pT()); } ShoKinPtr SudakovFormFactor:: generateNextSpaceBranching(const Energy startingQ, const IdList &ids, double x, const RhoDMatrix & rho, double enhance, Ptr::transient_const_pointer beam, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to the method. q_ = ZERO; z_ = 0.; phi_ = 0.; // perform the initialization Energy2 tmax(sqr(startingQ)),tmin; initialize(ids,tmin); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax),pt2(ZERO); // no shower variations if(ShowerHandler::currentHandler()->showerVariations().empty()){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2=sqr(1.-z())*t-z()*masssquared_[2]; } while(pt2 < pT2min()|| z() > zlimits_.second|| SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning)|| alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t)|| PDFVeto(t,x,ids[0],ids[1],beam)); } // shower variations else { bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true); do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2=sqr(1.-z())*t-z()*masssquared_[2]; ptRew=pt2 < pT2min(); zRew=z() > zlimits_.second; if (ptRew||zRew) continue; SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning); alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t); PDFRew=PDFVeto(t,x,ids[0],ids[1],beam); double factor=PDFVetoRatio(t,x,ids[0],ids[1],beam,1.)* alphaSVetoRatio(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t,1.)* SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(PDFRew || SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map::const_iterator var = ch->showerVariations().begin(); var != ch->showerVariations().end(); ++var ) { if ( ( ch->firstInteraction() && var->second.firstInteraction ) || ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { double newfactor = PDFVetoRatio(t,x,ids[0],ids[1],beam,var->second.factorizationScaleFactor)* alphaSVetoRatio(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t,var->second.renormalizationScaleFactor) *SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); double varied; if( PDFRew || SplitRew || alphaRew) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) wi->second *= varied; else { assert(false); //ch->currentWeights()[var->first] = varied; } } } } while( PDFRew || SplitRew || alphaRew); } if(t > ZERO && zlimits_.first < zlimits_.second) q_ = sqrt(t); else return ShoKinPtr(); pT_ = sqrt(pt2); // create the ShowerKinematics and return it return createInitialStateBranching(q_,z(),phi(),pT()); } void SudakovFormFactor::initialize(const IdList & ids, Energy2 & tmin) { ids_=ids; tmin = cutOffOption() != 2 ? ZERO : 4.*pT2min(); masses_ = virtualMasses(ids); masssquared_.clear(); for(unsigned int ix=0;ix0) tmin=max(masssquared_[ix],tmin); } } ShoKinPtr SudakovFormFactor::generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to this method. q_ = Constants::MaxEnergy; z_ = 0.; phi_ = 0.; // perform initialisation Energy2 tmax(sqr(stoppingScale)),tmin; initialize(ids,tmin); tmin=sqr(startingScale); // check some branching possible if(tmax<=tmin) return ShoKinPtr(); // perform the evolution Energy2 t(tmin),pt2(-MeV2); do { if(!guessDecay(t,tmax,minmass,enhance,detuning)) break; pt2 = sqr(1.-z())*(t-masssquared_[0])-z()*masssquared_[2]; } while(SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning)|| alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t ) || pt2masssquared_[0]-sqr(minmass)); if(t > ZERO) { q_ = sqrt(t); pT_ = sqrt(pt2); } else return ShoKinPtr(); phi_ = 0.; // create the ShowerKinematics object return createDecayBranching(q_,z(),phi(),pT()); } bool SudakovFormFactor::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass, double enhance, double detune) { // previous scale Energy2 told = t; // overestimated limits on z if(tmaxtmax||zlimits_.secondid()==ParticleID::g||ids_[0]->id()==ParticleID::gamma) { // no emission possible if(t<16.*(masssquared_[1]+pT2min())) { t=-1.*GeV2; return false; } // overestimate of the limits zlimits_.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min())/t))); zlimits_.second = 1.-zlimits_.first; } // special case for radiated particle is gluon else if(ids_[2]->id()==ParticleID::g||ids_[2]->id()==ParticleID::gamma) { zlimits_.first = sqrt((masssquared_[1]+pT2min())/t); zlimits_.second = 1.-sqrt((masssquared_[2]+pT2min())/t); } else if(ids_[1]->id()==ParticleID::g||ids_[1]->id()==ParticleID::gamma) { zlimits_.second = sqrt((masssquared_[2]+pT2min())/t); zlimits_.first = 1.-sqrt((masssquared_[1]+pT2min())/t); } else { zlimits_.first = (masssquared_[1]+pT2min())/t; zlimits_.second = 1.-(masssquared_[2]+pT2min())/t; } if(zlimits_.first>=zlimits_.second) { t=-1.*GeV2; return false; } return true; } bool SudakovFormFactor::computeSpaceLikeLimits(Energy2 & t, double x) { if (t < 1e-20 * GeV2) { t=-1.*GeV2; return false; } // compute the limits zlimits_.first = x; double yy = 1.+0.5*masssquared_[2]/t; zlimits_.second = yy - sqrt(sqr(yy)-1.+pT2min()/t); // return false if lower>upper if(zlimits_.second(particle.parents()[0]) : tShowerParticlePtr(); } else { mother = particle.children().size()==2 ? dynamic_ptr_cast(&particle) : tShowerParticlePtr(); } tShowerParticlePtr partner; while(mother) { tPPtr otherChild; if(forward) { for (unsigned int ix=0;ixchildren().size();++ix) { if(mother->children()[ix]!=child) { otherChild = mother->children()[ix]; break; } } } else { otherChild = mother->children()[1]; } tShowerParticlePtr other = dynamic_ptr_cast(otherChild); if((inter==ShowerInteraction::QCD && otherChild->dataPtr()->coloured()) || (inter==ShowerInteraction::QED && otherChild->dataPtr()->charged())) { partner = other; break; } if(forward && !other->isFinalState()) { partner = dynamic_ptr_cast(mother); break; } child = mother; if(forward) { mother = ! mother->parents().empty() ? dynamic_ptr_cast(mother->parents()[0]) : tShowerParticlePtr(); } else { if(mother->children()[0]->children().size()!=2) break; tShowerParticlePtr mtemp = dynamic_ptr_cast(mother->children()[0]); if(!mtemp) break; else mother=mtemp; } } if(!partner) { if(forward) { partner = dynamic_ptr_cast( child)->partner(); } else { if(mother) { tShowerParticlePtr parent; if(!mother->children().empty()) { parent = dynamic_ptr_cast(mother->children()[0]); } if(!parent) { parent = dynamic_ptr_cast(mother); } partner = parent->partner(); } else { partner = dynamic_ptr_cast(&particle)->partner(); } } } return partner; } pair softPhiMin(double phi0, double phi1, double A, double B, double C, double D) { double c01 = cos(phi0 - phi1); double s01 = sin(phi0 - phi1); double s012(sqr(s01)), c012(sqr(c01)); double A2(A*A), B2(B*B), C2(C*C), D2(D*D); if(abs(B/A)<1e-10 && abs(D/C)<1e-10) return make_pair(phi0,phi0+Constants::pi); double root = sqr(B2)*C2*D2*sqr(s012) + 2.*A*B2*B*C2*C*D*c01*s012 + 2.*A*B2*B*C*D2*D*c01*s012 + 4.*A2*B2*C2*D2*c012 - A2*B2*C2*D2*s012 - A2*B2*sqr(D2)*s012 - sqr(B2)*sqr(C2)*s012 - sqr(B2)*C2*D2*s012 - 4.*A2*A*B*C*D2*D*c01 - 4.*A*B2*B*C2*C*D*c01 + sqr(A2)*sqr(D2) + 2.*A2*B2*C2*D2 + sqr(B2)*sqr(C2); if(root<0.) return make_pair(phi0,phi0+Constants::pi); root = sqrt(root); double denom = (-2.*A*B*C*D*c01 + A2*D2 + B2*C2); double denom2 = (-B*C*c01 + A*D); if(denom==ZERO || denom2==0) return make_pair(phi0,phi0+Constants::pi); double num = B2*C*D*s012; return make_pair(atan2(B*s01*(-C*(num + root) / denom + D) / denom2, -(num + root ) / denom) + phi0, atan2(B*s01*(-C*(num - root) / denom + D) / denom2, -(num - root ) / denom) + phi0); } } double SudakovFormFactor::generatePhiForward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = z*(1.-z)*sqr(kinematics->scale()); Energy pT = kinematics->pT(); // if soft correlations Energy2 pipj,pik; bool canBeSoft[2] = {ids[1]->id()==ParticleID::g || ids[1]->id()==ParticleID::gamma, ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma }; array pjk; array Ek; Energy Ei,Ej; Energy2 m12(ZERO),m22(ZERO); InvEnergy2 aziMax(ZERO); bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()&& (canBeSoft[0] || canBeSoft[1]); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,true,splittingFn()->interactionType()); // remember we want the softer gluon bool swapOrder = !canBeSoft[1] || (canBeSoft[0] && canBeSoft[1] && z < 0.5); double zFact = !swapOrder ? (1.-z) : z; // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); Boost beta_bb; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { beta_bb = -(pVect + nVect).boostVector(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { beta_bb = -pVect.boostVector(); } else assert(false); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { axis = pVect.vect().unit(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { axis = nVect.vect().unit(); } else assert(false); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect, m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); assert(partner); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; m12 = sqr(particle.dataPtr()->mass()); m22 = sqr(partner->dataPtr()->mass()); if(swapOrder) { pjk[1] *= -1.; pjk[2] *= -1.; } Ek[0] = zFact*(alpha0*pVect.t()-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; if(swapOrder) { Ek[1] *= -1.; Ek[2] *= -1.; } Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); double phi0 = atan2(-pjk[2],-pjk[1]); if(phi0<0.) phi0 += Constants::twopi; double phi1 = atan2(-Ek[2],-Ek[1]); if(phi1<0.) phi1 += Constants::twopi; double xi_min = pik/Ei/(Ek[0]+mag2), xi_max = pik/Ei/(Ek[0]-mag2), xi_ij = pipj/Ei/Ej; if(xi_min>xi_max) swap(xi_min,xi_max); if(xi_min>xi_ij) softAllowed = false; Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { double A = (pipj*Ek[0]- Ej*pik)/Ej/sqr(Ej); double B = -sqrt(sqr(pipj)*(sqr(Ek[1])+sqr(Ek[2])))/Ej/sqr(Ej); double C = pjk[0]/sqr(Ej); double D = -sqrt(sqr(pjk[1])+sqr(pjk[2]))/sqr(Ej); pair minima = softPhiMin(phi0,phi1,A,B,C,D); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + max(Ej*(A+B*cos(minima.first -phi1))/(C+D*cos(minima.first -phi0)), Ej*(A+B*cos(minima.second-phi1))/(C+D*cos(minima.second-phi0)))); } else assert(false); } // if spin correlations vector > wgts; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // calculate the weights wgts = splittingFn()->generatePhiForward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); // first the spin correlations bit (gives 1 if correlations off) Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); if(pipj*Eg>pik*Ej) { if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Forward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } else { aziWgt = 0.; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in forward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double SudakovFormFactor::generatePhiBackward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = (1.-z)*sqr(kinematics->scale())/z; Energy pT = kinematics->pT(); // if soft correlations bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma); Energy2 pipj,pik,m12(ZERO),m22(ZERO); array pjk; Energy Ei,Ej,Ek; InvEnergy2 aziMax(ZERO); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,false,splittingFn()->interactionType()); double zFact = (1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::BackToBack); Boost beta_bb = -(pVect + nVect).boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = pVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.x(); double beta0 = -0.5/alpha0/pn*sqr(alpha0)*m2; Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; double beta2 = 0.5*(1.-zFact)*(sqr(alpha0*zFact/(1.-zFact))*m2+sqr(pT))/alpha0/zFact/pn; // compute the two phi independent dot products Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; pipj = alpha0*dot1+beta0*dot2; pik = alpha0*(alpha0*zFact/(1.-zFact)*m2+pn*(beta2+zFact/(1.-zFact)*beta0)); // compute the constants for the phi dependent dot product pjk[0] = alpha0*zFact/(1.-zFact)*dot1+beta2*dot2; pjk[1] = pj.x()*pT; pjk[2] = pj.y()*pT; m12 = ZERO; m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek = alpha0*zFact/(1.-zFact)*pVect.t()+beta2*nVect.t(); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); if(pipj*Ek> Ej*pik) { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik + (pipj*Ek- Ej*pik)/(pjk[0]-mag)); } else { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik); } } else { assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); } } // if spin correlations vector > wgts; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // get the weights wgts = splittingFn()->generatePhiBackward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Backward weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << z << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Ek*(Ei-m12*Ek/pik + pipj*Ek/dot - Ej*pik/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Backward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in backward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double SudakovFormFactor::generatePhiDecay(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix &) { // only soft correlations in this case // no correlations, return flat phi if( !(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma ))) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy pT = kinematics->pT(); // if soft correlations // find the partner for the soft correlations tShowerParticlePtr partner = findCorrelationPartner(particle,true,splittingFn()->interactionType()); double zFact(1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::Rest); Boost beta_bb = -pVect.boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = nVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products Energy2 pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; Energy2 pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product array pjk; pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; Energy2 m12 = sqr(particle.dataPtr()->mass()); Energy2 m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); InvEnergy2 aziMax; array Ek; Energy Ei,Ej; if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek[0] = zFact*(alpha0*pVect.t()+-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + pipj*(Ek[0]+mag2)/(pjk[0]-mag) - Ej*pik/(pjk[0]-mag) ); } else assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); // generate the azimuthal angle double phi,wgt(0.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { if(qperp0.m2()==ZERO) { wgt = 1.; } else { Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); wgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } } if(wgt-1.>1e-10||wgt<-1e-10) { generator()->log() << "Decay soft weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi\n"; } // return the azimuthal angle return phi; } Energy SudakovFormFactor::calculateScale(double zin, Energy pt, IdList ids, unsigned int iopt) { Energy2 tmin; initialize(ids,tmin); // final-state branching if(iopt==0) { Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin); if(ids[0]->id()!=ParticleID::g) scale -= zin*(1.-zin)*masssquared_[0]; scale /= sqr(zin*(1-zin)); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==1) { Energy2 scale=(sqr(pt)+zin*masssquared_[2])/sqr(1.-zin); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==2) { Energy2 scale = (sqr(pt)+zin*masssquared_[2])/sqr(1.-zin)+masssquared_[0]; return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else { throw Exception() << "Unknown option in SudakovFormFactor::calculateScale() " << "iopt = " << iopt << Exception::runerror; } } ShoKinPtr SudakovFormFactor::createFinalStateBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } ShoKinPtr SudakovFormFactor::createInitialStateBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(IS_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } ShoKinPtr SudakovFormFactor::createDecayBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } diff --git a/Shower/QTilde/Base/SudakovFormFactor.fh b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh rename from Shower/QTilde/Base/SudakovFormFactor.fh rename to Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh diff --git a/Shower/QTilde/Base/SudakovFormFactor.h b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h rename from Shower/QTilde/Base/SudakovFormFactor.h rename to Shower/QTilde/SplittingFunctions/SudakovFormFactor.h --- a/Shower/QTilde/Base/SudakovFormFactor.h +++ b/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h @@ -1,758 +1,758 @@ // -*- C++ -*- // // SudakovFormFactor.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SudakovFormFactor_H #define HERWIG_SudakovFormFactor_H // // This is the declaration of the SudakovFormFactor class. // #include "ThePEG/Interface/Interfaced.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" #include "Herwig/Shower/ShowerAlpha.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.fh" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "ThePEG/EventRecord/SpinInfo.h" -#include "ShowerKinematics.fh" +#include "Herwig/Shower/QTilde/Kinematics/ShowerKinematics.fh" #include "SudakovFormFactor.fh" namespace Herwig { using namespace ThePEG; /** * A typedef for the BeamParticleData */ typedef Ptr::transient_const_pointer tcBeamPtr; /** \ingroup Shower * * This is the definition of the Sudakov form factor class. In general this * is the base class for the implementation of Sudakov form factors in Herwig. * The methods generateNextTimeBranching(), generateNextDecayBranching() and * generateNextSpaceBranching need to be implemented in classes inheriting from this * one. * * In addition a number of methods are implemented to assist with the calculation * of the form factor using the veto algorithm in classes inheriting from this one. * * In general the Sudakov form-factor, for final-state radiation, is given * by * \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)= * \exp\left\{ * -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}} * \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2} * \int\frac{\alpha_S(z,\tilde{q})}{2\pi} * P_{ba}(z,\tilde{q})\Theta(p_T) * \right\}. * \f] * We can solve this to obtain the next value of the scale \f$\tilde{q}_{i+1}\f$ * given the previous value \f$\tilde{q}_i\f$ * in the following way. First we obtain a simplified form of the integrand * which is greater than or equal to the true integrand for all values of * \f$\tilde{q}\f$. * * In practice it is easiest to obtain this over estimate in pieces. The ShowerAlpha * object contains an over estimate for \f$\alpha_S\f$, the splitting function * contains both an over estimate of the spltting function and its integral * which is needed to compute the over estimate of the \f$\tilde{q}\f$ integrand, * together with an over estimate of the limit of the \f$z\f$ integral. * * This gives an overestimate of the integrand * \f[g(\tilde{q}^2) = \frac{c}{\tilde{q}^2}, \f] * where because the over estimates are chosen to be independent of \f$\tilde{q}\f$ the * parameter * \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z),\f] * is a constant independent of \f$\tilde{q}\f$. * * The guesst() member can then be used to generate generate the value of * \f$\tilde{q}^2\f$ according to this result. This is done by solving the Sudakov * form factor, with the over estimates, is equal to a random number * \f$r\f$ in the interval \f$[0,1]\f$. This gives * \f[\tilde{q}^2_{i+1}=G^{-1}\left[G(\tilde{q}^2_i)+\ln r\right],\f] * where \f$G(\tilde{q}^2)=c\ln(\tilde{q}^2)\f$ is the infinite integral * of \f$g(\tilde{q}^2)\f$ and \f$G^{-1}(x)=\exp\left(\frac{x}c\right)\f$ * is its inverse. * It this case we therefore obtain * \f[\tilde{q}^2_{i+1}=\tilde{q}^2_ir^{\frac1c}.\f] * The value of \f$z\f$ can then be calculated in a similar way * \f[z = I^{-1}\left[I(z_0)+r\left(I(z_1)-I(z_0)\right)\right],\f] * using the guessz() member, * where \f$I=\int P(z){\rm d}z\f$ and \f$I^{-1}\f$ is its inverse. * * The veto algorithm then uses rejection using the ratio of the * true value to the overestimated one to obtain the original distribution. * This is accomplished using the * - alphaSVeto() member for the \f$\alpha_S\f$ veto * - SplittingFnVeto() member for the veto on the value of the splitting function. * in general there must also be a chech that the emission is in the allowed * phase space but this is left to the inheriting classes as it will depend * on the ordering variable. * * The Sudakov form factor for the initial-scale shower is different because * it must include the PDF which guides the backward evolution. * It is given by * \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)= * \exp\left\{ * -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}} * \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2} * \int\frac{\alpha_S(z,\tilde{q})}{2\pi} * P_{ba}(z,\tilde{q})\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})} * \right\}, * \f] * where \f$x\f$ is the fraction of the beam momentum the parton \f$b\f$ had before * the backward evolution. * This can be solve in the same way as for the final-state branching but the constant * becomes * \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z)PDF_{\rm max},\f] * where * \f[PDF_{\rm max}=\max\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})},\f] * which can be set using an interface. * In addition the PDFVeto() member then is needed to implement the relevant veto. * * @see SplittingGenerator * @see SplittingFunction * @see ShowerAlpha * @see \ref SudakovFormFactorInterfaces "The interfaces" * defined for SudakovFormFactor. */ class SudakovFormFactor: public Interfaced { /** * The SplittingGenerator is a friend to insert the particles in the * branchings at initialisation */ friend class SplittingGenerator; public: /** * The default constructor. */ SudakovFormFactor() : pdfmax_(35.0), pdffactor_(0), cutOffOption_(0), a_(0.3), b_(2.3), c_(0.3*GeV), kinCutoffScale_( 2.3*GeV ), vgcut_(0.85*GeV), vqcut_(0.85*GeV), pTmin_(1.*GeV), pT2min_(ZERO), z_( 0.0 ),phi_(0.0), pT_(){} /** * Members to generate the scale of the next branching */ //@{ /** * Return the scale of the next time-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param enhance The radiation enhancement factor * defined. */ virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning, Energy2 maxQ2); /** * Return the scale of the next space-like decay branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param stoppingScale stopping scale for the evolution * @param minmass The minimum mass allowed for the spake-like particle. * @param ids The PDG codes of the particles in the splitting * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning); /** * Return the scale of the next space-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param x The fraction of the beam momentum * defined. * @param beam The beam particle * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale, const IdList &ids,double x, const RhoDMatrix & rho, double enhance, tcBeamPtr beam, double detuning); //@} /** * Generate the azimuthal angle of the branching for forward evolution * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiForward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Generate the azimuthal angle of the branching for backward evolution * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiBackward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Generate the azimuthal angle of the branching for ISR in decays * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiDecay(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Methods to provide public access to the private member variables */ //@{ /** * Return the pointer to the SplittingFunction object. */ tSplittingFnPtr splittingFn() const { return splittingFn_; } /** * Return the pointer to the ShowerAlpha object. */ tShowerAlphaPtr alpha() const { return alpha_; } /** * The type of interaction */ inline ShowerInteraction interactionType() const {return splittingFn_->interactionType();} //@} public: /** * Methods to access the kinematic variables for the branching */ //@{ /** * The energy fraction */ double z() const { return z_; } /** * The azimuthal angle */ double phi() const { return phi_; } /** * The transverse momentum */ Energy pT() const { return pT_; } //@} /** * Access the maximum weight for the PDF veto */ double pdfMax() const { return pdfmax_;} /** * Method to return the evolution scale given the * transverse momentum, \f$p_T\f$ and \f$z\f$. */ virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt); /** * Method to create the ShowerKinematics object for a final-state branching */ virtual ShoKinPtr createFinalStateBranching(Energy scale,double z, double phi, Energy pt); /** * Method to create the ShowerKinematics object for an initial-state branching */ virtual ShoKinPtr createInitialStateBranching(Energy scale,double z, double phi, Energy pt); /** * Method to create the ShowerKinematics object for a decay branching */ virtual ShoKinPtr createDecayBranching(Energy scale,double z, double phi, Energy pt); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Methods to provide the next value of the scale before the vetos * are applied. */ //@{ /** * Value of the energy fraction and scale for time-like branching * @param t The scale * @param tmin The minimum scale * @param enhance The radiation enhancement factor * @return False if scale less than minimum, true otherwise */ bool guessTimeLike(Energy2 &t, Energy2 tmin, double enhance, double detune); /** * Value of the energy fraction and scale for time-like branching * @param t The scale * @param tmax The maximum scale * @param minmass The minimum mass of the particle after the branching * @param enhance The radiation enhancement factor */ bool guessDecay(Energy2 &t, Energy2 tmax,Energy minmass, double enhance, double detune); /** * Value of the energy fraction and scale for space-like branching * @param t The scale * @param tmin The minimum scale * @param x Fraction of the beam momentum. * @param enhance The radiation enhancement factor */ bool guessSpaceLike(Energy2 &t, Energy2 tmin, const double x, double enhance, double detune); //@} /** * Initialize the values of the cut-offs and scales * @param tmin The minimum scale * @param ids The ids of the partics in the branching */ void initialize(const IdList & ids,Energy2 &tmin); /** * Phase Space veto member to implement the \f$\Theta\f$ function as a veto * so that the emission is within the allowed phase space. * @param t The scale * @param maxQ2 The maximum virtuality * @return true if vetoed */ bool PSVeto(const Energy2 t,const Energy2 maxQ2); /** * Compute the limits on \f$z\f$ for time-like branching * @param scale The scale of the particle * @return True if lower limit less than upper, otherwise false */ bool computeTimeLikeLimits(Energy2 & scale); /** * Compute the limits on \f$z\f$ for space-like branching * @param scale The scale of the particle * @param x The energy fraction of the parton * @return True if lower limit less than upper, otherwise false */ bool computeSpaceLikeLimits(Energy2 & scale, double x); protected: /** * Methods to implement the veto algorithm to generate the scale of * the next branching */ //@{ /** * Value of the energy fraction for the veto algorithm * @param iopt The option for calculating z * @param ids The PDG codes of the particles in the splitting * - 0 is final-state * - 1 is initial-state for the hard process * - 2 is initial-state for particle decays */ double guessz (unsigned int iopt, const IdList &ids) const; /** * Value of the scale for the veto algorithm * @param t1 The starting valoe of the scale * @param iopt The option for calculating t * @param ids The PDG codes of the particles in the splitting * - 0 is final-state * - 1 is initial-state for the hard process * - 2 is initial-state for particle decays * @param enhance The radiation enhancement factor * @param identical Whether or not the outgoing particles are identical */ Energy2 guesst (Energy2 t1,unsigned int iopt, const IdList &ids, double enhance, bool identical, double detune) const; /** * Veto on the PDF for the initial-state shower * @param t The scale * @param x The fraction of the beam momentum * @param parton0 Pointer to the particleData for the * new parent (this is the particle we evolved back to) * @param parton1 Pointer to the particleData for the * original particle * @param beam The BeamParticleData object */ bool PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, tcBeamPtr beam) const; /** * The PDF veto ratio */ double PDFVetoRatio(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, tcBeamPtr beam,double factor) const; /** * The veto on the splitting function. * @param t The scale * @param ids The PDG codes of the particles in the splitting * @param mass Whether or not to use the massive splitting functions * @return true if vetoed */ bool SplittingFnVeto(const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & rho, double detune) const { return UseRandom::rnd()>SplittingFnVetoRatio(t,ids,mass,rho,detune); } /** * The Splitting function veto ratio */ double SplittingFnVetoRatio(const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & rho, double detune) const { return splittingFn_->ratioP(z_, t, ids,mass,rho)/detune; } /** * The veto on the coupling constant * @param pt2 The value of ther transverse momentum squared, \f$p_T^2\f$. * @return true if vetoed */ bool alphaSVeto(Energy2 pt2) const; /** * The alpha S veto ratio */ double alphaSVetoRatio(Energy2 pt2,double factor) const; //@} /** * Set the particles in the splittings */ void addSplitting(const IdList &); /** * Delete the particles in the splittings */ void removeSplitting(const IdList &); /** * Access the potential branchings */ const vector & particles() const { return particles_; } public: /** * @name Methods for the cut-off */ //@{ /** * The option being used */ unsigned int cutOffOption() const { return cutOffOption_; } /** * The kinematic scale */ Energy kinScale() const {return kinCutoffScale_;} /** * The virtuality cut-off on the gluon \f$Q_g=\frac{\delta-am_q}{b}\f$ * @param scale The scale \f$\delta\f$ * @param mq The quark mass \f$m_q\f$. */ Energy kinematicCutOff(Energy scale, Energy mq) const {return max((scale -a_*mq)/b_,c_);} /** * The virtualilty cut-off for gluons */ Energy vgCut() const { return vgcut_; } /** * The virtuality cut-off for everything else */ Energy vqCut() const { return vqcut_; } /** * The minimum \f$p_T\f$ for the branching */ Energy pTmin() const { return pTmin_; } /** * The square of the minimum \f$p_T\f$ */ Energy2 pT2min() const { return pT2min_; } /** * Calculate the virtual masses for a branchings */ const vector & virtualMasses(const IdList & ids); //@} /** * Set the PDF */ void setPDF(tcPDFPtr pdf, Energy scale) { pdf_ = pdf; freeze_ = scale; } protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SudakovFormFactor & operator=(const SudakovFormFactor &) = delete; private: /** * Pointer to the splitting function for this Sudakov form factor */ SplittingFnPtr splittingFn_; /** * Pointer to the coupling for this Sudakov form factor */ ShowerAlphaPtr alpha_; /** * Maximum value of the PDF weight */ double pdfmax_; /** * List of the particles this Sudakov is used for to aid in setting up * interpolation tables if needed */ vector particles_; /** * Option for the inclusion of a factor \f$1/(1-z)\f$ in the PDF estimate */ unsigned pdffactor_; private: /** * Option for the type of cut-off to be applied */ unsigned int cutOffOption_; /** * Parameters for the default Herwig cut-off option, i.e. the parameters for * the \f$Q_g=\max(\frac{\delta-am_q}{b},c)\f$ kinematic cut-off */ //@{ /** * The \f$a\f$ parameter */ double a_; /** * The \f$b\f$ parameter */ double b_; /** * The \f$c\f$ parameter */ Energy c_; /** * Kinematic cutoff used in the parton shower phase space. */ Energy kinCutoffScale_; //@} /** * Parameters for the FORTRAN-like cut-off */ //@{ /** * The virtualilty cut-off for gluons */ Energy vgcut_; /** * The virtuality cut-off for everything else */ Energy vqcut_; //@} /** * Parameters for the \f$p_T\f$ cut-off */ //@{ /** * The minimum \f$p_T\f$ for the branching */ Energy pTmin_; /** * The square of the minimum \f$p_T\f$ */ Energy2 pT2min_; //@} private: /** * Member variables to keep the shower kinematics information * generated by a call to generateNextTimeBranching or generateNextSpaceBranching */ //@{ /** * The energy fraction */ double z_; /** * The azimuthal angle */ double phi_; /** * The transverse momentum */ Energy pT_; //@} /** * The limits of \f$z\f$ in the splitting */ pair zlimits_; /** * Stuff for the PDFs */ //@{ /** * PDf */ tcPDFPtr pdf_; /** * Freezing scale */ Energy freeze_; //@} private: /** * The evolution scale, \f$\tilde{q}\f$. */ Energy q_; /** * The Ids of the particles in the current branching */ IdList ids_; /** * The masses of the particles in the current branching */ vector masses_; /** * The mass squared of the particles in the current branching */ vector masssquared_; }; } #endif /* HERWIG_SudakovFormFactor_H */