diff --git a/Analysis/LeptonsJetsAnalysis.h b/Analysis/LeptonsJetsAnalysis.h --- a/Analysis/LeptonsJetsAnalysis.h +++ b/Analysis/LeptonsJetsAnalysis.h @@ -1,1123 +1,1140 @@ // -*- C++ -*- #ifndef Herwig_LeptonsJetsAnalysis_H #define Herwig_LeptonsJetsAnalysis_H // // This is the declaration of the LeptonsJetsAnalysis class. // #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Cuts/JetFinder.h" #include "ThePEG/Cuts/JetRegion.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Utilities/Statistics/Histogram.h" #include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple_comparison.hpp> namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the LeptonsJetsAnalysis class. * * @see \ref LeptonsJetsAnalysisInterfaces "The interfaces" * defined for LeptonsJetsAnalysis. */ class LeptonsJetsAnalysis: public AnalysisHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ LeptonsJetsAnalysis(); /** * The destructor. */ virtual ~LeptonsJetsAnalysis(); //@} public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event * may be presented several times, if it has been manipulated in * between. The default version of this function will call transform * to make a lorentz transformation of the whole event, then extract * all final state particles and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the event has been * manipulated in some way since it was last presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); //@} protected: /** * Analyze one subprocess, given the event number it belongs to */ void analyze(ParticleVector&, long, double); /** * Clear the electroweak objects and jets for the next event */ void clear() { theJets.clear(); theEWIDs.clear(); theChargedLeptons.clear(); theNeutrinos.clear(); theHiggs.clear(); } /** * Reconstruct the jets and fill the respective momenta. */ virtual void reconstructJets(const ParticleVector&); /** * The jet finder to use */ Ptr<JetFinder>::tptr jetFinder() const { return theJetFinder; } /** * The jet regions to match. */ const vector<Ptr<JetRegion>::ptr>& jetRegions() const { return theJetRegions; } /** * Return the number of matched jets */ unsigned int nJets() const { return theJets.size(); } /** * Set the momentum of the indicated jet. */ LorentzMomentum& jetMomentum(const unsigned int id) { return theJets[id]; } /** * Reconstruct all the variables for EW particles and fill the respective momenta. */ virtual void reconstructEWParticles(ParticleVector&); /** * Set the momentum of the indicated electroweak particle. */ LorentzMomentum& eWIDMomentum(const unsigned int id) { return theEWIDs[id]; } /** * Set the momentum of the indicated charged lepton. */ LorentzMomentum& chargedLeptonMomentum(const unsigned int id) { return theChargedLeptons[id]; } /** * Set the momentum of the indicated neutrino. */ LorentzMomentum& neutrinoMomentum(const unsigned int id) { return theNeutrinos[id]; } /** * Set the missing pT momentum. */ LorentzMomentum& pTmissMomentum() { return thePTmiss; } /** * Set the momentum of the indicated Higgs. */ LorentzMomentum& higgsMomentum(const unsigned int id) { return theHiggs[id]; } protected: /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); 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: /** * Collection of object histograms; ranges are adjusted to the * maximum, so range constraints and rebinning can be applied later. */ struct ObjectProperties { /** * Transverse momentum */ Statistics::Histogram pt; Statistics::Histogram ptlow; Statistics::Histogram pt_logx; /** * Rapidity */ Statistics::Histogram y; /** * Azimuth */ Statistics::Histogram phi; /** * Mass */ Statistics::Histogram mass; Statistics::Histogram masslow; /** * Default constructor */ ObjectProperties() {} /** * Construct given Ecm */ ObjectProperties(const string& name, Energy) : pt(name + "Pt",Statistics::Histogram::regularBinEdges(0,1000,200),true,false), ptlow(name + "Ptlow",Statistics::Histogram::regularBinEdges(0,200,100),true,false), pt_logx(name + "PtLogX",Statistics::Histogram::logBinEdges(0.1,1000,100),true,false), y(name + "Y",Statistics::Histogram::regularBinEdges(-6,6,120),false,false), phi(name + "Phi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,62), make_pair(-Constants::pi,Constants::pi)), mass(name + "Mass",Statistics::Histogram::regularBinEdges(0,5000,500),true,false), masslow(name + "Masslow",Statistics::Histogram::regularBinEdges(0,250,100),true,false) {} /** * Count given momentum, weight and id */ void count(const LorentzMomentum& p, double weight, unsigned int id) { pt.count(Statistics::EventContribution(p.perp()/GeV,weight,5.),id); ptlow.count(Statistics::EventContribution(p.perp()/GeV,weight,2.),id); pt_logx.count(Statistics::EventContribution(p.perp()/GeV,weight,1.),id); y.count(Statistics::EventContribution(p.rapidity(),weight,0.1),id); phi.count(Statistics::EventContribution(p.phi(),weight,0.1),id); mass.count(Statistics::EventContribution(p.m()/GeV,weight,10.),id); masslow.count(Statistics::EventContribution(p.m()/GeV,weight,2.5),id); } /** * Count given momentum components, weight and id */ void count(Energy perp, double rapidity, double xphi, Energy m, double weight, unsigned int id) { pt.count(Statistics::EventContribution(perp/GeV,weight,5.),id); ptlow.count(Statistics::EventContribution(perp/GeV,weight,1.),id); pt_logx.count(Statistics::EventContribution(perp/GeV,weight,1.),id); y.count(Statistics::EventContribution(rapidity,weight,0.1),id); phi.count(Statistics::EventContribution(xphi,weight,0.1),id); mass.count(Statistics::EventContribution(m/GeV,weight,5.),id); masslow.count(Statistics::EventContribution(m/GeV,weight,1.25),id); } /** * Convert to XML */ void finalize(XML::Element& elem) { pt.finalize(); elem.append(pt.toXML()); ptlow.finalize(); elem.append(ptlow.toXML()); pt_logx.finalize(); elem.append(pt_logx.toXML()); y.finalize(); elem.append(y.toXML()); phi.finalize(); elem.append(phi.toXML()); mass.finalize(); elem.append(mass.toXML()); masslow.finalize(); elem.append(masslow.toXML()); } }; /** * Collection of pair histograms; ranges are adjusted to the * maximum, so range constraints and rebinning can be applied later. */ struct PairProperties : public ObjectProperties { /** * Calculate deltaPhi */ static double dPhi(const LorentzMomentum& a, const LorentzMomentum& b){ double phi1 = a.phi(); double phi2 = b.phi(); double diff=phi1-phi2; if(diff<-Constants::pi){ diff+=(2.0*Constants::pi); } else if (diff>Constants::pi){ diff-=(2.0*Constants::pi); } return diff; } /** * Calculate deltaY */ static double dY(const LorentzMomentum& a, const LorentzMomentum& b){ return abs(a.rapidity()-b.rapidity()); } /** * Calculate deltaR */ static double dR(const LorentzMomentum& a, const LorentzMomentum& b){ return sqrt(sqr(dPhi(a,b))+sqr(dY(a,b))); } /** * Calculate ydoty */ static double yy(const LorentzMomentum& a, const LorentzMomentum& b){ double ya = a.rapidity(); double yb = b.rapidity(); double yres = sqrt(abs(ya*yb)); return ya*yb < 0. ? -yres : yres; } /** * Delta y */ Statistics::Histogram deltaY; /** * Delta phi */ Statistics::Histogram deltaPhi; /** * Delta phi */ Statistics::Histogram deltaR; /** * Product of the rapidities */ Statistics::Histogram yDotY; /** * Default constructor */ PairProperties() : ObjectProperties() {} /** * Construct given Ecm */ PairProperties(const string& name, Energy ecm) : ObjectProperties(name,ecm), deltaY(name + "DeltaY",Statistics::Histogram::regularBinEdges(0,6,60),true,false), deltaPhi(name + "DeltaPhi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32), make_pair(-Constants::pi,Constants::pi)), deltaR(name + "DeltaR",Statistics::Histogram::regularBinEdges(0,10,100),true,false), yDotY(name + "YDotY",Statistics::Histogram::regularBinEdges(-6,6,120),false,false) {} /** * Count given momentum, weight and id */ void count(const LorentzMomentum& p, const LorentzMomentum& q, double weight, unsigned int id) { ObjectProperties::count(p+q,weight,id); deltaY.count(Statistics::EventContribution(dY(p,q),weight,0.1),id); deltaPhi.count(Statistics::EventContribution(dPhi(p,q),weight,0.1),id); deltaR.count(Statistics::EventContribution(dR(p,q),weight,0.1),id); yDotY.count(Statistics::EventContribution(yy(p,q),weight,0.1),id); } /** * Convert to XML */ void finalize(XML::Element& elem) { ObjectProperties::finalize(elem); deltaY.finalize(); elem.append(deltaY.toXML()); deltaPhi.finalize(); elem.append(deltaPhi.toXML()); deltaR.finalize(); elem.append(deltaR.toXML()); yDotY.finalize(); elem.append(yDotY.toXML()); } }; /** * Collection of triple histograms; ranges are adjusted to the * maximum, so range constraints and rebinning can be applied later. */ struct TripleProperties : public ObjectProperties { /** * Calculate deltaY^* */ static double dYstar(const LorentzMomentum& a, const LorentzMomentum& b, const LorentzMomentum& c){ return c.rapidity()-(a.rapidity()+b.rapidity())/2.; } /** + * Calculate deltaZ^* -- normalized deltaY^* + */ + static double dZstar(const LorentzMomentum& a, + const LorentzMomentum& b, + const LorentzMomentum& c){ + return dYstar(a,b,c)*2./abs(a.rapidity()-b.rapidity()); + } + + /** * Delta y^* */ Statistics::Histogram deltaYstar; /** + * Delta z^* + */ + Statistics::Histogram deltaZstar; + + /** * Default constructor */ TripleProperties() : ObjectProperties() {} /** * Construct given Ecm */ TripleProperties(const string& name, Energy ecm) : ObjectProperties(name,ecm), - deltaYstar(name + "DeltaYstar",Statistics::Histogram::regularBinEdges(-6,6,120),true,false) {} + deltaYstar(name + "DeltaYstar",Statistics::Histogram::regularBinEdges(-6,6,120),true,false), + deltaZstar(name + "DeltaZstar",Statistics::Histogram::regularBinEdges(-3,3,120),true,false) {} /** * Count given momentum, weight and id */ void count(const LorentzMomentum& p, const LorentzMomentum& q, const LorentzMomentum& r, double weight, unsigned int id) { ObjectProperties::count(p+q+r,weight,id); deltaYstar.count(Statistics::EventContribution(dYstar(p,q,r),weight,0.1),id); + deltaZstar.count(Statistics::EventContribution(dZstar(p,q,r),weight,0.05),id); } /** * Convert to XML */ void finalize(XML::Element& elem) { ObjectProperties::finalize(elem); deltaYstar.finalize(); elem.append(deltaYstar.toXML()); + deltaZstar.finalize(); elem.append(deltaZstar.toXML()); } }; private: /** * Switch between fixed order and showered */ bool theIsShowered; /** * Switch whether to apply extra analysis cuts */ bool theApplyCuts; /** * The jet finder to use */ Ptr<JetFinder>::ptr theJetFinder; /** * The jet regions to match. */ vector<Ptr<JetRegion>::ptr> theJetRegions; /** * The reconstructed jets */ map<unsigned int,LorentzMomentum> theJets; /** * The reconstructed electroweak particles */ map<unsigned int,LorentzMomentum> theEWIDs; /** * The reconstructed charged leptons */ map<unsigned int,LorentzMomentum> theChargedLeptons; /** * The reconstructed neutrinos */ map<unsigned int,LorentzMomentum> theNeutrinos; /** * The reconstructed missing pT */ LorentzMomentum thePTmiss; /** * The reconstructed Higgs */ map<unsigned int,LorentzMomentum> theHiggs; /** * Jet properties */ map<unsigned int,ObjectProperties> theJetProperties; /** * Exclusive jet properties */ map<unsigned int,ObjectProperties> theExclusiveJetProperties; /** * Jet-inclusive properties */ ObjectProperties theJetInclusiveProperties; /** * Jet-summed properties */ ObjectProperties theJetSummedProperties; /** * Jet-average properties */ ObjectProperties theJetAverageProperties; /** * Inclusive jet multiplicities */ Statistics::Histogram theNJetsInclusive; /** * Exclusive jet multiplicities */ Statistics::Histogram theNJetsExclusive; /** * Electroweak properties */ map<unsigned int,ObjectProperties> theEWIDProperties; /** * Charged lepton properties */ map<unsigned int,ObjectProperties> theChargedLeptonProperties; /** * Neutrino properties */ map<unsigned int,ObjectProperties> theNeutrinoProperties; /** * missing pT properties */ ObjectProperties thePTmissProperties; /** * Higgs properties */ map<unsigned int,ObjectProperties> theHiggsProperties; /** * Jet pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theJetPairProperties; /** * Jet/electroweak pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theJetEWIDPairProperties; /** * Jet/charged lepton pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theJetChargedLeptonPairProperties; /** * Jet/neutrino pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theJetNeutrinoPairProperties; /** * Jet/missing pT pair properties */ map<unsigned int,PairProperties> theJetPTmissPairProperties; /** * Jet/Higgs pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theJetHiggsPairProperties; /** * Electroweak pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theEWIDPairProperties; /** * Charged lepton pair properties */ map<pair<unsigned int,unsigned int>,PairProperties> theChargedLeptonPairProperties; /** * Trijet properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeJetProperties; /** * Jet-pair/electroweak triple properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairEWIDTripleProperties; /** * Jet-pair/charged lepton triple properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairChargedLeptonTripleProperties; /** * Jet-pair/neutrino triple properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairNeutrinoTripleProperties; /** * Jet-pair/missing pT triple properties */ map<pair<unsigned int,unsigned int>,TripleProperties> theJetPairPTmissTripleProperties; /** * Jet-pair/Higgs triple properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairHiggsTripleProperties; /** * Triple electroweak properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeEWIDProperties; /** * Triple charged lepton properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeChargedLeptonProperties; /** * Fourjet properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourJetProperties; /** * Four electroweak properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourEWIDProperties; /** * Four charged lepton properties */ map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourChargedLeptonProperties; protected: /** * Jet properties */ ObjectProperties& jetProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theJetProperties.find(id); if ( h != theJetProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id; return theJetProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Exclusive jet properties */ ObjectProperties& exclusiveJetProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theExclusiveJetProperties.find(id); if ( h != theExclusiveJetProperties.end() ) return h->second; ostringstream ids; ids << "ExclusiveJet" << id; return theExclusiveJetProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-inclusive properties */ ObjectProperties& jetInclusiveProperties() { if ( !theJetInclusiveProperties.pt.bins().empty() ) return theJetInclusiveProperties; return theJetInclusiveProperties = ObjectProperties("JetInclusive",generator()->maximumCMEnergy()); } /** * Jet-summed properties */ ObjectProperties& jetSummedProperties() { if ( !theJetSummedProperties.pt.bins().empty() ) return theJetSummedProperties; return theJetSummedProperties = ObjectProperties("JetSummed",generator()->maximumCMEnergy()); } /** * Jet-average properties */ ObjectProperties& jetAverageProperties() { if ( !theJetAverageProperties.pt.bins().empty() ) return theJetAverageProperties; return theJetAverageProperties = ObjectProperties("JetAverage",generator()->maximumCMEnergy()); } /** * Inclusive jet multiplicities */ Statistics::Histogram& nJetsInclusive() { if ( !theNJetsInclusive.bins().empty() ) return theNJetsInclusive; return theNJetsInclusive = Statistics::Histogram("NJetsInclusive", Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5, theJetRegions.size()+1), true,true); } /** * Exclusive jet multiplicities */ Statistics::Histogram& nJetsExclusive() { if ( !theNJetsExclusive.bins().empty() ) return theNJetsExclusive; return theNJetsExclusive = Statistics::Histogram("NJetsExclusive", Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5, theJetRegions.size()+1), true,true); } /** * Lepton properties -- all sorted by ID */ ObjectProperties& eWIDProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theEWIDProperties.find(id); if ( h != theEWIDProperties.end() ) return h->second; ostringstream ids; ids << "EWID" << id; return theEWIDProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Charged lepton properties */ ObjectProperties& chargedLeptonProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theChargedLeptonProperties.find(id); if ( h != theChargedLeptonProperties.end() ) return h->second; ostringstream ids; ids << "ChargedLepton" << id; return theChargedLeptonProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Neutrino properties */ ObjectProperties& neutrinoProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theNeutrinoProperties.find(id); if ( h != theNeutrinoProperties.end() ) return h->second; ostringstream ids; ids << "Neutrino" << id; return theNeutrinoProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Missing pT properties */ ObjectProperties& pTmissProperties() { if ( !thePTmissProperties.pt.bins().empty() ) return thePTmissProperties; return thePTmissProperties = ObjectProperties("PTmiss",generator()->maximumCMEnergy()); } /** * Higgs properties */ ObjectProperties& higgsProperties(const unsigned int id) { map<unsigned int,ObjectProperties>::iterator h = theHiggsProperties.find(id); if ( h != theHiggsProperties.end() ) return h->second; ostringstream ids; ids << "Higgs" << id; return theHiggsProperties[id] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet pair properties */ PairProperties& jetPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetPairProperties.find(make_pair(id,jd)); if ( h != theJetPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << jd; return theJetPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet/lepton(all sorted by ID) pair properties */ PairProperties& jetEWIDPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetEWIDPairProperties.find(make_pair(id,jd)); if ( h != theJetEWIDPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << "EWID" << jd; return theJetEWIDPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet/charged lepton pair properties */ PairProperties& jetChargedLeptonPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetChargedLeptonPairProperties.find(make_pair(id,jd)); if ( h != theJetChargedLeptonPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << "ChargedLepton" << jd; return theJetChargedLeptonPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet/neutrino pair properties */ PairProperties& jetNeutrinoPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetNeutrinoPairProperties.find(make_pair(id,jd)); if ( h != theJetNeutrinoPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << "Neutrino" << jd; return theJetNeutrinoPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet/missing pT pair properties */ PairProperties& jetPTmissPairProperties(const unsigned int id) { map<unsigned int,PairProperties>::iterator h = theJetPTmissPairProperties.find(id); if ( h != theJetPTmissPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << "PTmiss"; return theJetPTmissPairProperties[id] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet/Higgs pair properties */ PairProperties& jetHiggsPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetHiggsPairProperties.find(make_pair(id,jd)); if ( h != theJetHiggsPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << "Higgs" << jd; return theJetHiggsPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Electroweak pair properties */ PairProperties& eWIDPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theEWIDPairProperties.find(make_pair(id,jd)); if ( h != theEWIDPairProperties.end() ) return h->second; ostringstream ids; ids << "EWID" << id << jd; return theEWIDPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Charged lepton pair properties */ PairProperties& chargedLeptonPairProperties(const unsigned int id, const unsigned int jd) { map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theChargedLeptonPairProperties.find(make_pair(id,jd)); if ( h != theChargedLeptonPairProperties.end() ) return h->second; ostringstream ids; ids << "ChargedLepton" << id << jd; return theChargedLeptonPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Trijet properties */ TripleProperties& threeJetProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theThreeJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theThreeJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3; return theThreeJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-pair/electroweak triple properties */ TripleProperties& jetPairEWIDTripleProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theJetPairEWIDTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theJetPairEWIDTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "EWID" << id3; return theJetPairEWIDTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-pair/charged lepton triple properties */ TripleProperties& jetPairChargedLeptonTripleProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theJetPairChargedLeptonTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theJetPairChargedLeptonTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "ChargedLepton" << id3; return theJetPairChargedLeptonTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-pair/neutrino triple properties */ TripleProperties& jetPairNeutrinoTripleProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theJetPairNeutrinoTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theJetPairNeutrinoTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "Neutrino" << id3; return theJetPairNeutrinoTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-pair/missing pT triple properties */ TripleProperties& jetPairPTmissTripleProperties(const unsigned int id1, const unsigned int id2) { map<pair<unsigned int,unsigned int>,TripleProperties>::iterator it = theJetPairPTmissTripleProperties.find(pair<unsigned int,unsigned int>(id1,id2)); if ( it != theJetPairPTmissTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "PTmiss"; return theJetPairPTmissTripleProperties[pair<unsigned int,unsigned int>(id1,id2)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Jet-pair/Higgs triple properties */ TripleProperties& jetPairHiggsTripleProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theJetPairHiggsTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theJetPairHiggsTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "Higgs" << id3; return theJetPairHiggsTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Triple electroweak properties -- all sorted by ID */ TripleProperties& threeEWIDProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theThreeEWIDProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theThreeEWIDProperties.end() ) return it->second; ostringstream ids; ids << "EWID" << id1 << id2 << id3; return theThreeEWIDProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Triple charged lepton properties */ TripleProperties& threeChargedLeptonProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it = theThreeChargedLeptonProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)); if ( it != theThreeChargedLeptonProperties.end() ) return it->second; ostringstream ids; ids << "ChargedLepton" << id1 << id2 << id3; return theThreeChargedLeptonProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] = TripleProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Fourjet properties */ ObjectProperties& fourJetProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3, const unsigned int id4) { map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it = theFourJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)); if ( it != theFourJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3 << id4; return theFourJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Four electroweak properties */ ObjectProperties& fourEWIDProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3, const unsigned int id4) { map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it = theFourEWIDProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)); if ( it != theFourEWIDProperties.end() ) return it->second; ostringstream ids; ids << "EWID" << id1 << id2 << id3 << id4; return theFourEWIDProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Four charged lepton properties */ ObjectProperties& fourChargedLeptonProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3, const unsigned int id4) { map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it = theFourChargedLeptonProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)); if ( it != theFourChargedLeptonProperties.end() ) return it->second; ostringstream ids; ids << "ChargedLepton" << id1 << id2 << id3 << id4; return theFourChargedLeptonProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] = ObjectProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Perform any additional analysis required */ virtual void analyzeSpecial(long, double) {} /** * Append any additional histograms to the given histogram element */ virtual void finalize(XML::Element&) {} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ LeptonsJetsAnalysis & operator=(const LeptonsJetsAnalysis &); }; } #endif /* Herwig_LeptonsJetsAnalysis_H */ diff --git a/DipoleShower/Base/DipoleSplittingGenerator.cc b/DipoleShower/Base/DipoleSplittingGenerator.cc --- a/DipoleShower/Base/DipoleSplittingGenerator.cc +++ b/DipoleShower/Base/DipoleSplittingGenerator.cc @@ -1,611 +1,600 @@ // -*- C++ -*- // // DipoleSplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 DipoleSplittingGenerator class. // #include <config.h> #include "DipoleSplittingGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/DipoleShower/DipoleShowerHandler.h" using namespace Herwig; DipoleSplittingGenerator::DipoleSplittingGenerator() : HandlerBase(), theExponentialGenerator(0), prepared(false), presampling(false), - theDoCompensate(false) { + theDoCompensate(false), theSplittingWeight(1.) { if ( ShowerHandler::currentHandler() ) setGenerator(ShowerHandler::currentHandler()->generator()); } DipoleSplittingGenerator::~DipoleSplittingGenerator() { if ( theExponentialGenerator ) { delete theExponentialGenerator; theExponentialGenerator = 0; } } IBPtr DipoleSplittingGenerator::clone() const { return new_ptr(*this); } IBPtr DipoleSplittingGenerator::fullclone() const { return new_ptr(*this); } void DipoleSplittingGenerator::wrap(Ptr<DipoleSplittingGenerator>::ptr other) { assert(!prepared); theOtherGenerator = other; } void DipoleSplittingGenerator::resetVariations() { for ( map<string,double>::iterator w = currentWeights.begin(); w != currentWeights.end(); ++w ) w->second = 1.; } +void DipoleSplittingGenerator::veto(const vector<double>&, double p, double r) { + double factor = 1.; + if ( splittingReweight() ) { + factor = splittingReweight()->evaluate(generatedSplitting); + theSplittingWeight *= (r-factor*p)/(r-p); + } + splittingKernel()->veto(generatedSplitting, factor*p, r, currentWeights); +} + +void DipoleSplittingGenerator::accept(const vector<double>&, double p, double r) { + double factor = 1.; + if ( splittingReweight() ) { + factor = splittingReweight()->evaluate(generatedSplitting); + theSplittingWeight *= factor; + } + splittingKernel()->accept(generatedSplitting, factor*p, r, currentWeights); +} + void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) { generatedSplitting = sp; generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics()); generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional()); if ( wrapping() ) { generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index())); generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index())); generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index())); parameters.resize(theOtherGenerator->nDim()); prepared = true; return; } generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index())); generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index())); generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index())); presampledSplitting = generatedSplitting; prepared = true; parameters.resize(nDim()); theExponentialGenerator = new exsample::exponential_generator<DipoleSplittingGenerator,UseRandom>(); theExponentialGenerator->sampling_parameters().maxtry = maxtry(); theExponentialGenerator->sampling_parameters().presampling_points = presamplingPoints(); theExponentialGenerator->sampling_parameters().freeze_grid = freezeGrid(); theExponentialGenerator->detuning(detuning()); theExponentialGenerator->docompensate(theDoCompensate); theExponentialGenerator->function(this); theExponentialGenerator->initialize(); } void DipoleSplittingGenerator::fixParameters(const DipoleSplittingInfo& sp, Energy optHardPt) { assert(generator()); assert(!presampling); assert(prepared); assert(sp.index() == generatedSplitting.index()); generatedSplitting.scale(sp.scale()); parameters[3] = sp.scale()/generator()->maximumCMEnergy(); generatedSplitting.hardPt(sp.hardPt()); parameters[0] = splittingKinematics()->ptToRandom(optHardPt == ZERO ? generatedSplitting.hardPt() : min(generatedSplitting.hardPt(),optHardPt), sp.scale(), sp.emitterX(), sp.spectatorX(), generatedSplitting.index(), *splittingKernel()); size_t shift = 4; if ( generatedSplitting.index().emitterPDF().pdf() && generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.emitterX(sp.emitterX()); generatedSplitting.spectatorX(sp.spectatorX()); parameters[4] = sp.emitterX(); parameters[5] = sp.spectatorX(); shift += 2; } if ( generatedSplitting.index().emitterPDF().pdf() && !generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.emitterX(sp.emitterX()); parameters[4] = sp.emitterX(); ++shift; } if ( !generatedSplitting.index().emitterPDF().pdf() && generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.spectatorX(sp.spectatorX()); parameters[4] = sp.spectatorX(); ++shift; } - if ( splittingReweight() ) { - parameters[shift] = splittingReweight()->evaluate(sp); - ++shift; - } - if ( splittingKernel()->nDimAdditional() ) copy(sp.lastSplittingParameters().begin(),sp.lastSplittingParameters().end(),parameters.begin()+shift); if ( sp.emitter() ) generatedSplitting.emitter(sp.emitter()); if ( sp.spectator() ) generatedSplitting.spectator(sp.spectator()); } int DipoleSplittingGenerator::nDim() const { assert(!wrapping()); assert(prepared); int ret = 4; // 0 pt, 1 z, 2 phi, 3 scale, 4/5 xs + parameters if ( generatedSplitting.index().emitterPDF().pdf() ) { ++ret; } if ( generatedSplitting.index().spectatorPDF().pdf() ) { ++ret; } - if ( splittingReweight() ) - ++ret; - ret += splittingKernel()->nDimAdditional(); return ret; } const vector<bool>& DipoleSplittingGenerator::sampleFlags() { assert(!wrapping()); if ( !theFlags.empty() ) return theFlags; theFlags.resize(nDim(),false); theFlags[0] = true; theFlags[1] = true; theFlags[2] = true; // 0 pt, 1 z, 2 phi return theFlags; } const pair<vector<double>,vector<double> >& DipoleSplittingGenerator::support() { assert(!wrapping()); if ( !theSupport.first.empty() ) return theSupport; vector<double> lower(nDim(),0.); vector<double> upper(nDim(),1.); pair<double,double> kSupport = generatedSplitting.splittingKinematics()->kappaSupport(generatedSplitting); pair<double,double> xSupport = generatedSplitting.splittingKinematics()->xiSupport(generatedSplitting); lower[0] = kSupport.first; lower[1] = xSupport.first; upper[0] = kSupport.second; upper[1] = xSupport.second; - if ( splittingReweight() ) { - pair<double,double> bounds = splittingReweight()->reweightBounds(generatedSplitting.index()); - int pos = 4; - if ( generatedSplitting.index().emitterPDF().pdf() ) { - ++pos; - } - if ( generatedSplitting.index().spectatorPDF().pdf() ) { - ++pos; - } - lower[pos] = bounds.first; - upper[pos] = bounds.second; - } - theSupport.first = lower; theSupport.second = upper; return theSupport; } void DipoleSplittingGenerator::startPresampling() { assert(!wrapping()); splittingKernel()->startPresampling(generatedSplitting.index()); presampling = true; } void DipoleSplittingGenerator::stopPresampling() { assert(!wrapping()); splittingKernel()->stopPresampling(generatedSplitting.index()); presampling = false; } bool DipoleSplittingGenerator::haveOverestimate() const { assert(!wrapping()); assert(prepared); return generatedSplitting.splittingKinematics()->haveOverestimate() && splittingKernel()->haveOverestimate(generatedSplitting); } bool DipoleSplittingGenerator::overestimate(const vector<double>& point) { assert(!wrapping()); assert(prepared); assert(!presampling); assert(haveOverestimate()); if ( ! generatedSplitting.splittingKinematics()->generateSplitting(point[0],point[1],point[2], generatedSplitting, *splittingKernel()) ) return 0.; generatedSplitting.splittingKinematics()->prepareSplitting(generatedSplitting); return ( generatedSplitting.splittingKinematics()->jacobianOverestimate() * - splittingKernel()->overestimate(generatedSplitting) * - (splittingReweight() ? splittingReweight()->evaluate(generatedSplitting) : 1.) ); + splittingKernel()->overestimate(generatedSplitting) ); } double DipoleSplittingGenerator::invertOverestimateIntegral(double value) const { assert(!wrapping()); assert(prepared); assert(!presampling); assert(haveOverestimate()); return splittingKernel()->invertOverestimateIntegral(generatedSplitting,value); } double DipoleSplittingGenerator::evaluate(const vector<double>& point) { assert(!wrapping()); assert(prepared); assert(generator()); DipoleSplittingInfo& split = ( !presampling ? generatedSplitting : presampledSplitting ); split.continuesEvolving(); size_t shift = 4; if ( presampling ) { split.scale(point[3] * generator()->maximumCMEnergy()); if ( split.index().emitterPDF().pdf() && split.index().spectatorPDF().pdf() ) { split.emitterX(point[4]); split.spectatorX(point[5]); shift += 2; } if ( split.index().emitterPDF().pdf() && !split.index().spectatorPDF().pdf() ) { split.emitterX(point[4]); ++shift; } if ( !split.index().emitterPDF().pdf() && split.index().spectatorPDF().pdf() ) { split.spectatorX(point[4]); ++shift; } - if ( splittingReweight() ) - ++shift; - if ( splittingKernel()->nDimAdditional() ) copy(point.begin()+shift,point.end(),split.splittingParameters().begin()); split.hardPt(split.splittingKinematics()->ptMax(split.scale(), split.emitterX(), split.spectatorX(), split.index(), *splittingKernel())); } if ( ! split.splittingKinematics()->generateSplitting(point[0],point[1],point[2],split,*splittingKernel()) ) { split.lastValue(0.); return 0.; } split.splittingKinematics()->prepareSplitting(split); if ( split.stoppedEvolving() ) { split.lastValue(0.); return 0.; } if ( !presampling ) splittingKernel()->clearAlphaPDFCache(); double kernel = splittingKernel()->evaluate(split); - if ( splittingReweight() ) { - if ( !presampling ) - kernel *= splittingReweight()->evaluate(split); - else - kernel *= point[shift-1]; - } double jac = split.splittingKinematics()->jacobian(); // multiply in the profile scales when relevant assert(ShowerHandler::currentHandler()); if ( ShowerHandler::currentHandler()->firstInteraction() && ShowerHandler::currentHandler()->profileScales() && !presampling ) { Energy hard = ShowerHandler::currentHandler()->hardScale(); if ( hard > ZERO ) kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt()); } split.lastValue( abs(jac) * kernel ); if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) { generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for " << splittingKernel()->name() << "\n" << flush; split.lastValue(0.0); } if ( kernel < 0. ) return 0.; return split.lastValue(); } void DipoleSplittingGenerator::doGenerate(map<string,double>& variations, Energy optCutoff) { assert(!wrapping()); double res = 0.; Energy startPt = generatedSplitting.hardPt(); double optKappaCutoff = 0.0; if ( optCutoff > splittingKinematics()->IRCutoff() ) { optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff, generatedSplitting.scale(), generatedSplitting.emitterX(), generatedSplitting.spectatorX(), generatedSplitting.index(), *splittingKernel()); } resetVariations(); + theSplittingWeight = 1.; while (true) { try { if ( optKappaCutoff == 0.0 ) { res = theExponentialGenerator->generate(); } else { res = theExponentialGenerator->generate(optKappaCutoff); } } catch (exsample::exponential_regenerate&) { resetVariations(); + theSplittingWeight = 1.; generatedSplitting.hardPt(startPt); continue; } catch (exsample::hit_and_miss_maxtry&) { throw DipoleShowerHandler::RedoShower(); } catch (exsample::selection_maxtry&) { throw DipoleShowerHandler::RedoShower(); } break; } for ( map<string,double>::const_iterator w = currentWeights.begin(); w != currentWeights.end(); ++w ) { map<string,double>::iterator v = variations.find(w->first); if ( v != variations.end() ) v->second *= w->second; else variations[w->first] = w->second; } if ( res == 0. ) { generatedSplitting.lastPt(0.0*GeV); generatedSplitting.didStopEvolving(); } else { generatedSplitting.continuesEvolving(); if ( theMCCheck ) theMCCheck->book(generatedSplitting.emitterX(), generatedSplitting.spectatorX(), generatedSplitting.scale(), startPt, generatedSplitting.lastPt(), generatedSplitting.lastZ(), 1.); } } Energy DipoleSplittingGenerator::generate(const DipoleSplittingInfo& split, map<string,double>& variations, Energy optHardPt, Energy optCutoff) { fixParameters(split,optHardPt); if ( wrapping() ) { return theOtherGenerator->generateWrapped(generatedSplitting,variations,optHardPt,optCutoff); } doGenerate(variations,optCutoff); return generatedSplitting.lastPt(); } Energy DipoleSplittingGenerator::generateWrapped(DipoleSplittingInfo& split, map<string,double>& variations, Energy optHardPt, Energy optCutoff) { assert(!wrapping()); DipoleSplittingInfo backup = generatedSplitting; generatedSplitting = split; fixParameters(split,optHardPt); try { doGenerate(variations,optCutoff); } catch (...) { split = generatedSplitting; generatedSplitting = backup; throw; } Energy pt = generatedSplitting.lastPt(); split = generatedSplitting; generatedSplitting = backup; return pt; } void DipoleSplittingGenerator::completeSplitting(DipoleSplittingInfo& sp) const { pair<bool,bool> conf = sp.configuration(); sp = generatedSplitting; sp.configuration(conf); } Ptr<DipoleSplittingKernel>::tptr DipoleSplittingGenerator::splittingKernel() const { if ( wrapping() ) return theOtherGenerator->splittingKernel(); return theSplittingKernel; } Ptr<DipoleSplittingReweight>::tptr DipoleSplittingGenerator::splittingReweight() const { if ( wrapping() ) return theOtherGenerator->splittingReweight(); return theSplittingReweight; } Ptr<DipoleSplittingKinematics>::tptr DipoleSplittingGenerator::splittingKinematics() const { if ( wrapping() ) return theOtherGenerator->splittingKinematics(); return theSplittingKernel->splittingKinematics(); } void DipoleSplittingGenerator::splittingKernel(Ptr<DipoleSplittingKernel>::tptr sp) { theSplittingKernel = sp; if ( theSplittingKernel->mcCheck() ) theMCCheck = theSplittingKernel->mcCheck(); } void DipoleSplittingGenerator::splittingReweight(Ptr<DipoleSplittingReweight>::tptr sp) { theSplittingReweight = sp; } void DipoleSplittingGenerator::debugGenerator(ostream& os) const { os << "--- DipoleSplittingGenerator ---------------------------------------------------\n"; os << " generating splittings using\n" << " splittingKernel = " << splittingKernel()->name() << " splittingKinematics = " << generatedSplitting.splittingKinematics()->name() << "\n" << " to sample splittings of type:\n"; os << generatedSplitting; os << "--------------------------------------------------------------------------------\n"; } void DipoleSplittingGenerator::debugLastEvent(ostream& os) const { os << "--- DipoleSplittingGenerator ---------------------------------------------------\n"; os << " last generated event:\n"; os << generatedSplitting; os << "--------------------------------------------------------------------------------\n"; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleSplittingGenerator::persistentOutput(PersistentOStream & os) const { os << theOtherGenerator << theSplittingKernel << theSplittingReweight << theMCCheck << theDoCompensate; } void DipoleSplittingGenerator::persistentInput(PersistentIStream & is, int) { is >> theOtherGenerator >> theSplittingKernel >> theSplittingReweight >> theMCCheck >> theDoCompensate; } ClassDescription<DipoleSplittingGenerator> DipoleSplittingGenerator::initDipoleSplittingGenerator; // Definition of the static class description member. void DipoleSplittingGenerator::Init() { static ClassDocumentation<DipoleSplittingGenerator> documentation ("DipoleSplittingGenerator is used by the dipole shower " "to sample splittings from a given dipole splitting kernel."); static Reference<DipoleSplittingGenerator,DipoleSplittingKernel> interfaceSplittingKernel ("SplittingKernel", "Set the splitting kernel to sample from.", &DipoleSplittingGenerator::theSplittingKernel, false, false, true, false, false); static Reference<DipoleSplittingGenerator,DipoleSplittingReweight> interfaceSplittingReweight ("SplittingReweight", "Set the splitting reweight.", &DipoleSplittingGenerator::theSplittingReweight, false, false, true, true, false); static Reference<DipoleSplittingGenerator,DipoleMCCheck> interfaceMCCheck ("MCCheck", "[debug option] MCCheck", &DipoleSplittingGenerator::theMCCheck, false, false, true, true, false); interfaceMCCheck.rank(-1); } diff --git a/DipoleShower/Base/DipoleSplittingGenerator.h b/DipoleShower/Base/DipoleSplittingGenerator.h --- a/DipoleShower/Base/DipoleSplittingGenerator.h +++ b/DipoleShower/Base/DipoleSplittingGenerator.h @@ -1,481 +1,491 @@ // -*- C++ -*- // // DipoleSplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleSplittingGenerator_H #define HERWIG_DipoleSplittingGenerator_H // // This is the declaration of the DipoleSplittingGenerator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" #include "DipoleSplittingReweight.h" #include "Herwig/DipoleShower/Utility/DipoleMCCheck.h" #include "Herwig/Sampling/exsample/exponential_generator.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingGenerator is used by the dipole shower * to sample splittings from a given dipole splitting kernel. * * @see \ref DipoleSplittingGeneratorInterfaces "The interfaces" * defined for DipoleSplittingGenerator. */ class DipoleSplittingGenerator: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleSplittingGenerator(); /** * The destructor. */ virtual ~DipoleSplittingGenerator(); //@} public: /** * Return the dipole splitting kernel. */ Ptr<DipoleSplittingKernel>::tptr splittingKernel() const; /** * Return the dipole splitting reweight. */ Ptr<DipoleSplittingReweight>::tptr splittingReweight() const; /** * Return the dipole splitting kinematics. */ Ptr<DipoleSplittingKinematics>::tptr splittingKinematics() const; /** * Set the dipole splitting kernel. */ void splittingKernel(Ptr<DipoleSplittingKernel>::tptr sp); /** * Set the dipole splitting reweight. */ void splittingReweight(Ptr<DipoleSplittingReweight>::tptr sp); /** * Make a wrapper around another generator. */ void wrap(Ptr<DipoleSplittingGenerator>::ptr other); /** * Return true, if this is actually a wrapper around * another splitting generator. */ bool wrapping() const { return theOtherGenerator; } public: /** * Reset the current variations to one */ void resetVariations(); /** * Prepare to fill the given splitting. */ void prepare(const DipoleSplittingInfo&); /** * Fix parameters from the fiven DipoleSplittingInfo * and generate the next splitting. Return the * pt selected for the next splitting. */ Energy generate(const DipoleSplittingInfo&, map<string,double>& variations, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Fix parameters from the fiven DipoleSplittingInfo * and generate the next splitting. Return the * pt selected for the next splitting when called * from a wrapping generator. */ Energy generateWrapped(DipoleSplittingInfo&, map<string,double>& variations, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Complete the given splitting. */ void completeSplitting(DipoleSplittingInfo&) const; /** * Return the last generated splitting */ const DipoleSplittingInfo& lastSplitting() const { return generatedSplitting; } public: /** * Print debug information on the splitting * handled. */ void debugGenerator(ostream&) const; /** * Print debug information on the last * generated event. */ void debugLastEvent(ostream&) const; protected: /** * Update parameters given a splitting. */ void fixParameters(const DipoleSplittingInfo&, Energy optHardPt = ZERO); /** * With the parameters previuosly supplied * through fixParameters generate the next * splitting. */ void doGenerate(map<string,double>& variations, Energy optCutoff = ZERO); public: /** * Return the number of random numbers * needed to sample this kernel. */ int nDim() const; /** * Flag, which variables are free variables. */ const vector<bool>& sampleFlags(); /** * Return the support of the splitting kernel. * The lower bound on the first variable is * assumed to correspond to the cutoff on the * evolution variable. */ const pair<vector<double>,vector<double> >& support(); /** * Return the parameter point associated to the splitting * previously supplied through fixParameters. */ const vector<double>& parameterPoint() const { return parameters; } /** * Indicate that presampling of this kernel * will be performed in the next calls to * evaluate until stopPresampling() is called. */ void startPresampling(); /** * Indicate that presampling of this kernel * is done until startPresampling() is called. */ void stopPresampling(); /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return splittingKernel()->presamplingPoints(); } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return splittingKernel()->maxtry(); } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return splittingKernel()->freezeGrid(); } /** * Return the detuning factor applied to the sampling overestimate kernel */ double detuning() const { return splittingKernel()->detuning(); } /** * Return true, if this splitting generator * is able to deliver an overestimate to the sampled * kernel. */ bool haveOverestimate() const; /** * Return an overestimate to the sampled kernel. */ bool overestimate(const vector<double>&); /** * Invert the integral over the overestimate to equal * the given value. */ double invertOverestimateIntegral(double) const; /** * Evalute the splitting kernel. */ double evaluate(const vector<double>&); /** * Indicate that a veto with the given kernel value and overestimate has occured. */ - void veto(const vector<double>&, double p, double r) { - splittingKernel()->veto(generatedSplitting, p, r, currentWeights); - } + void veto(const vector<double>&, double p, double r); /** * Indicate that an accept with the given kernel value and overestimate has occured. */ - void accept(const vector<double>&, double p, double r) { - splittingKernel()->accept(generatedSplitting, p, r, currentWeights); + void accept(const vector<double>&, double p, double r); + + /** + * Return the weight associated to the currently generated splitting + */ + double splittingWeight() const { + if ( wrapping() ) + return theOtherGenerator->splittingWeight(); + return theSplittingWeight; } /** * True, if sampler should apply compensation */ void doCompensate(bool yes = true) { theDoCompensate = yes; } public: /**@name Wrap to the exsample2 interface until this is finally cleaned up. */ //@{ inline const vector<bool>& variable_flags () { return sampleFlags(); } inline size_t evolution_variable () const { return 0; } inline double evolution_cutoff () { return support().first[0]; } inline const vector<double>& parameter_point () const { return parameterPoint(); } inline void start_presampling () { startPresampling(); } inline void stop_presampling () { stopPresampling(); } inline size_t dimension () const { return nDim(); } inline unsigned long presampling_points () const { return presamplingPoints(); } //@} 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). private: /** * Pointer to another generator to wrap around. */ Ptr<DipoleSplittingGenerator>::ptr theOtherGenerator; /** * The dipole splitting kernel to sample * splitting from. */ Ptr<DipoleSplittingKernel>::ptr theSplittingKernel; /** * The dipole splitting reweight. */ Ptr<DipoleSplittingReweight>::ptr theSplittingReweight; /** * Pointer to the exponential generator */ exsample::exponential_generator<DipoleSplittingGenerator,UseRandom>* theExponentialGenerator; /** * The dipole splitting to be completed. */ DipoleSplittingInfo generatedSplitting; /** * A backup of the dipole splitting to be * completed, if this generator is presampled. */ DipoleSplittingInfo presampledSplitting; /** * True, if prepared to sample splittings * of a given kind. */ bool prepared; /** * Wether or not the kernel is currently * being presampled. */ bool presampling; /** * The parameter point. */ vector<double> parameters; /** * The sampling flags */ vector<bool> theFlags; /** * The support. */ pair<vector<double>,vector<double> > theSupport; /** * Pointer to a check histogram object */ Ptr<DipoleMCCheck>::ptr theMCCheck; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * The currently used weight map */ map<string,double> currentWeights; + /** + * The weight associated to the currently generated splitting + */ + double theSplittingWeight; + private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription<DipoleSplittingGenerator> initDipoleSplittingGenerator; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingGenerator & operator=(const DipoleSplittingGenerator &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingGenerator. */ template <> struct BaseClassTrait<Herwig::DipoleSplittingGenerator,1> { /** Typedef of the first base class of DipoleSplittingGenerator. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingGenerator class and the shared object where it is defined. */ template <> struct ClassTraits<Herwig::DipoleSplittingGenerator> : public ClassTraitsBase<Herwig::DipoleSplittingGenerator> { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingGenerator"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingGenerator is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingGenerator depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_DipoleSplittingGenerator_H */ diff --git a/DipoleShower/Base/DipoleSplittingReweight.h b/DipoleShower/Base/DipoleSplittingReweight.h --- a/DipoleShower/Base/DipoleSplittingReweight.h +++ b/DipoleShower/Base/DipoleSplittingReweight.h @@ -1,143 +1,138 @@ // -*- C++ -*- // // DipoleSplittingReweight.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleSplittingReweight_H #define HERWIG_DipoleSplittingReweight_H // // This is the declaration of the DipoleSplittingReweight class. // #include "ThePEG/Handlers/HandlerBase.h" #include "DipoleSplittingInfo.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingReweight is used by the dipole shower * to reweight splittings from a given dipole splitting kernel. * * @see \ref DipoleSplittingReweightInterfaces "The interfaces" * defined for DipoleSplittingReweight. */ class DipoleSplittingReweight: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleSplittingReweight(); /** * The destructor. */ virtual ~DipoleSplittingReweight(); //@} public: /** - * Return the range of reweight factors for the given dipole type. - */ - virtual pair<double,double> reweightBounds(const DipoleIndex&) const = 0; - - /** - * Return the reweight factor for the given splitting type. + * Return the reweighting factor for the given splitting type. */ virtual double evaluate(const DipoleSplittingInfo&) const = 0; 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(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static AbstractClassDescription<DipoleSplittingReweight> initDipoleSplittingReweight; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingReweight & operator=(const DipoleSplittingReweight &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingReweight. */ template <> struct BaseClassTrait<Herwig::DipoleSplittingReweight,1> { /** Typedef of the first base class of DipoleSplittingReweight. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingReweight class and the shared object where it is defined. */ template <> struct ClassTraits<Herwig::DipoleSplittingReweight> : public ClassTraitsBase<Herwig::DipoleSplittingReweight> { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingReweight"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingReweight is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingReweight depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_DipoleSplittingReweight_H */ diff --git a/DipoleShower/DipoleShowerHandler.cc b/DipoleShower/DipoleShowerHandler.cc --- a/DipoleShower/DipoleShowerHandler.cc +++ b/DipoleShower/DipoleShowerHandler.cc @@ -1,1106 +1,1108 @@ // -*- C++ -*- // // DipoleShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 DipoleShowerHandler class. // #include <config.h> #include "DipoleShowerHandler.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 theses to have complete types #include "Herwig/Shower/Base/Evolver.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/Shower/Base/ShowerTree.h" #include "Herwig/Shower/Base/KinematicsReconstructor.h" #include "Herwig/Shower/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" using namespace Herwig; bool DipoleShowerHandler::firstWarn = true; DipoleShowerHandler::DipoleShowerHandler() : ShowerHandler(), chainOrderVetoScales(true), nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false), doFSR(true), doISR(true), realignmentScheme(0), verbosity(0), printEvent(0), nTries(0), didRadiate(false), didRealign(false), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(2.*GeV), isMCatNLOSEvent(false), isMCatNLOHEvent(false), theDoCompensate(false), theFreezeGrid(500000), theDetuning(1.0), maxPt(ZERO), muPt(ZERO) {} DipoleShowerHandler::~DipoleShowerHandler() {} IBPtr DipoleShowerHandler::clone() const { return new_ptr(*this); } IBPtr DipoleShowerHandler::fullclone() const { return new_ptr(*this); } tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCPtr, Energy optHardPt, Energy optCutoff) { useMe(); prepareCascade(sub); resetWeights(); if ( !doFSR && ! doISR ) return sub->incoming(); eventRecord().clear(); eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs()); if ( eventRecord().outgoing().empty() && !doISR ) return sub->incoming(); if ( !eventRecord().incoming().first->coloured() && !eventRecord().incoming().second->coloured() && !doFSR ) return sub->incoming(); nTries = 0; while ( true ) { try { didRadiate = false; didRealign = false; isMCatNLOSEvent = false; isMCatNLOHEvent = false; if ( eventRecord().xcombPtr() ) { Ptr<SubtractedME>::tptr subme = dynamic_ptr_cast<Ptr<SubtractedME>::tptr>(eventRecord().xcombPtr()->matrixElement()); Ptr<MatchboxMEBase>::tptr me = dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(eventRecord().xcombPtr()->matrixElement()); Ptr<SubtractionDipole>::tptr dipme = dynamic_ptr_cast<Ptr<SubtractionDipole>::tptr>(eventRecord().xcombPtr()->matrixElement()); if ( subme ) { if ( subme->showerApproximation() ) { // don't do this for POWHEG-type corrections if ( !subme->showerApproximation()->needsSplittingGenerator() ) { theShowerApproximation = subme->showerApproximation(); if ( subme->realShowerSubtraction() ) isMCatNLOHEvent = true; else if ( subme->virtualShowerSubtraction() ) isMCatNLOSEvent = true; } } } else if ( me ) { if ( me->factory()->showerApproximation() ) { if ( !me->factory()->showerApproximation()->needsSplittingGenerator() ) { theShowerApproximation = me->factory()->showerApproximation(); isMCatNLOSEvent = true; } } } string error = "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. "; if (evolver()->hardEmissionMode()==1 || evolver()->hardEmissionMode()==3 ) throw Exception() << error << "Cannot generate POWHEG corrections " << "for particle decays using DipoleShowerHandler. " << "Check value of Evolver:HardEmissionMode." << Exception::runerror; if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==2) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower approximation. " << "Add 'set Evolver:HardEmissionMode 0' to input file." << Exception::runerror; if (me && me->factory()->showerApproximation()){ if(me->factory()->showerApproximation()->needsTruncatedShower()) throw Exception() << error << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to input file." << Exception::runerror; if (!( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } } else if (subme && subme->factory()->showerApproximation()){ if(subme->factory()->showerApproximation()->needsTruncatedShower()) throw Exception() << error << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to input file." << Exception::runerror; if (!( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } } else if (dipme && evolver()->hardEmissionMode() == 0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } else if (!dipme && evolver()->hardEmissionMode()==2 && ShowerHandler::currentHandler()->firstInteraction()) throw Exception() << error << "POWHEG matching requested for LO events. Include " << "'set Factory:ShowerApproximation MEMatching' in input file." << Exception::runerror; } hardScales(lastXCombPtr()->lastShowerScale()); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler starting off:\n"; eventRecord().debugLastEvent(generator()->log()); generator()->log() << flush; } unsigned int nEmitted = 0; if ( firstMCatNLOEmission ) { if ( !isMCatNLOHEvent ) nEmissions = 1; else nEmissions = 0; } if ( !firstMCatNLOEmission ) { doCascade(nEmitted,optHardPt,optCutoff); if ( discardNoEmissions ) { if ( !didRadiate ) throw Veto(); if ( nEmissions ) if ( nEmissions < nEmitted ) throw Veto(); } } else { if ( nEmissions == 1 ) doCascade(nEmitted,optHardPt,optCutoff); } if ( intrinsicPtGenerator ) { if ( eventRecord().incoming().first->coloured() && eventRecord().incoming().second->coloured() ) { SpinOneLorentzRotation rot = intrinsicPtGenerator->kick(eventRecord().incoming(), eventRecord().intermediates()); eventRecord().transform(rot); } } didRealign = realign(); constituentReshuffle(); break; } catch (RedoShower&) { resetWeights(); if ( ++nTries > maxtry() ) throw ShowerTriesVeto(maxtry()); eventRecord().clear(); eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs()); continue; } catch (...) { throw; } } return eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign); } void DipoleShowerHandler::constituentReshuffle() { if ( constituentReshuffler ) { constituentReshuffler->reshuffle(eventRecord().outgoing(), eventRecord().incoming(), eventRecord().intermediates()); } } void DipoleShowerHandler::hardScales(Energy2 muf) { maxPt = generator()->maximumCMEnergy(); if ( restrictPhasespace() ) { if ( !hardScaleIsMuF() || !firstInteraction() ) { if ( !eventRecord().outgoing().empty() ) { for ( PList::const_iterator p = eventRecord().outgoing().begin(); p != eventRecord().outgoing().end(); ++p ) maxPt = min(maxPt,(**p).momentum().mt()); } else { assert(!eventRecord().hard().empty()); Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO); for ( PList::const_iterator p = eventRecord().hard().begin(); p != eventRecord().hard().end(); ++p ) phard += (**p).momentum(); Energy mhard = phard.m(); maxPt = mhard; } maxPt *= hardScaleFactor(); } else { maxPt = hardScaleFactor()*sqrt(muf); } muPt = maxPt; } else { muPt = hardScaleFactor()*sqrt(muf); } for ( list<DipoleChain>::iterator ch = eventRecord().chains().begin(); ch != eventRecord().chains().end(); ++ch ) { Energy minVetoScale = -1.*GeV; for ( list<Dipole>::iterator dip = ch->dipoles().begin(); dip != ch->dipoles().end(); ++dip ) { // max scale per config Energy maxFirst = 0.0*GeV; Energy maxSecond = 0.0*GeV; for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { pair<bool,bool> conf = make_pair(true,false); if ( (**k).canHandle(dip->index(conf)) ) { Energy scale = evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf), dip->emitterX(conf),dip->spectatorX(conf), **k,dip->index(conf)); maxFirst = max(maxFirst,scale); } conf = make_pair(false,true); if ( (**k).canHandle(dip->index(conf)) ) { Energy scale = evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf), dip->emitterX(conf),dip->spectatorX(conf), **k,dip->index(conf)); maxSecond = max(maxSecond,scale); } } if ( dip->leftParticle()->vetoScale() >= ZERO ) { maxFirst = min(maxFirst,sqrt(dip->leftParticle()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip->leftParticle()->vetoScale())); else minVetoScale = sqrt(dip->leftParticle()->vetoScale()); } if ( dip->rightParticle()->vetoScale() >= ZERO ) { maxSecond = min(maxSecond,sqrt(dip->rightParticle()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip->rightParticle()->vetoScale())); else minVetoScale = sqrt(dip->rightParticle()->vetoScale()); } maxFirst = min(maxPt,maxFirst); dip->emitterScale(make_pair(true,false),maxFirst); maxSecond = min(maxPt,maxSecond); dip->emitterScale(make_pair(false,true),maxSecond); } if ( !evolutionOrdering()->independentDipoles() && chainOrderVetoScales && minVetoScale >= ZERO ) { for ( list<Dipole>::iterator dip = ch->dipoles().begin(); dip != ch->dipoles().end(); ++dip ) { dip->leftScale(min(dip->leftScale(),minVetoScale)); dip->rightScale(min(dip->rightScale(),minVetoScale)); } } } } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair<bool,bool> conf, Energy optHardPt, Energy optCutoff) { return getWinner(winner,dip.index(conf), dip.emitterX(conf),dip.spectatorX(conf), conf,dip.emitter(conf),dip.spectator(conf), dip.emitterScale(conf),optHardPt,optCutoff); } Energy DipoleShowerHandler::getWinner(SubleadingSplittingInfo& winner, Energy optHardPt, Energy optCutoff) { return getWinner(winner,winner.index(), winner.emitterX(),winner.spectatorX(), winner.configuration(), winner.emitter(),winner.spectator(), winner.startScale(),optHardPt,optCutoff); } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const DipoleIndex& index, double emitterX, double spectatorX, pair<bool,bool> conf, tPPtr emitter, tPPtr spectator, Energy startScale, Energy optHardPt, Energy optCutoff) { if ( !index.initialStateEmitter() && !doFSR ) { winner.didStopEvolving(); return 0.0*GeV; } if ( index.initialStateEmitter() && !doISR ) { winner.didStopEvolving(); return 0.0*GeV; } DipoleSplittingInfo candidate; candidate.index(index); candidate.configuration(conf); candidate.emitterX(emitterX); candidate.spectatorX(spectatorX); if ( generators().find(candidate.index()) == generators().end() ) getGenerators(candidate.index()); // // NOTE -- needs proper fixing at some point // // For some very strange reason, equal_range gives back // key ranges it hasn't been asked for. This particularly // happens e.g. for FI dipoles of the same kind, but different // PDF (hard vs MPI PDF). I can't see a reason for this, // as DipoleIndex properly implements comparison for equality // and (lexicographic) ordering; for the time being, we // use equal_range, extented by an explicit check for wether // the key is indeed what we wanted. See line after (*) comment // below. // pair<GeneratorMap::iterator,GeneratorMap::iterator> gens = generators().equal_range(candidate.index()); Energy winnerScale = 0.0*GeV; GeneratorMap::iterator winnerGen = generators().end(); for ( GeneratorMap::iterator gen = gens.first; gen != gens.second; ++gen ) { // (*) see NOTE above if ( !(gen->first == candidate.index()) ) continue; if ( startScale <= gen->second->splittingKinematics()->IRCutoff() ) continue; Energy dScale = gen->second->splittingKinematics()->dipoleScale(emitter->momentum(), spectator->momentum()); // in very exceptional cases happening in DIS if ( isnan(dScale/GeV ) ) throw RedoShower(); candidate.scale(dScale); candidate.continuesEvolving(); Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel())); Energy maxPossible = gen->second->splittingKinematics()->ptMax(candidate.scale(), candidate.emitterX(), candidate.spectatorX(), candidate.index(), *gen->second->splittingKernel()); Energy ircutoff = optCutoff < gen->second->splittingKinematics()->IRCutoff() ? gen->second->splittingKinematics()->IRCutoff() : optCutoff; if ( maxPossible <= ircutoff ) { continue; } if ( maxPossible >= hardScale ) candidate.hardPt(hardScale); else { hardScale = maxPossible; candidate.hardPt(maxPossible); } gen->second->generate(candidate,currentWeights_,optHardPt,optCutoff); Energy nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel())); if ( nextScale > winnerScale ) { winner.fill(candidate); gen->second->completeSplitting(winner); winnerGen = gen; winnerScale = nextScale; } + reweight_ *= gen->second->splittingWeight(); + } if ( winnerGen == generators().end() ) { winner.didStopEvolving(); return 0.0*GeV; } if ( winner.stoppedEvolving() ) return 0.0*GeV; return winnerScale; } void DipoleShowerHandler::doCascade(unsigned int& emDone, Energy optHardPt, Energy optCutoff) { if ( nEmissions ) if ( emDone == nEmissions ) return; DipoleSplittingInfo winner; DipoleSplittingInfo dipoleWinner; while ( eventRecord().haveChain() ) { if ( verbosity > 2 ) { generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" << eventRecord().currentChain() << flush; } list<Dipole>::iterator winnerDip = eventRecord().currentChain().dipoles().end(); Energy winnerScale = 0.0*GeV; Energy nextLeftScale = 0.0*GeV; Energy nextRightScale = 0.0*GeV; for ( list<Dipole>::iterator dip = eventRecord().currentChain().dipoles().begin(); dip != eventRecord().currentChain().dipoles().end(); ++dip ) { nextLeftScale = getWinner(dipoleWinner,*dip,make_pair(true,false),optHardPt,optCutoff); if ( nextLeftScale > winnerScale ) { winnerScale = nextLeftScale; winner = dipoleWinner; winnerDip = dip; } nextRightScale = getWinner(dipoleWinner,*dip,make_pair(false,true),optHardPt,optCutoff); if ( nextRightScale > winnerScale ) { winnerScale = nextRightScale; winner = dipoleWinner; winnerDip = dip; } if ( evolutionOrdering()->independentDipoles() ) { Energy dipScale = max(nextLeftScale,nextRightScale); if ( dip->leftScale() > dipScale ) dip->leftScale(dipScale); if ( dip->rightScale() > dipScale ) dip->rightScale(dipScale); } } if ( verbosity > 1 ) { if ( winnerDip != eventRecord().currentChain().dipoles().end() ) generator()->log() << "DipoleShowerHandler selected the splitting:\n" << winner << " for the dipole\n" << (*winnerDip) << flush; else generator()->log() << "DipoleShowerHandler could not select a splitting above the IR cutoff\n" << flush; } // pop the chain if no dipole did radiate if ( winnerDip == eventRecord().currentChain().dipoles().end() ) { eventRecord().popChain(); if ( theEventReweight && eventRecord().chains().empty() ) if ( (theEventReweight->firstInteraction() && firstInteraction()) || (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { double w = theEventReweight->weightCascade(eventRecord().incoming(), eventRecord().outgoing(), eventRecord().hard(),theGlobalAlphaS); reweight_ *= w; } continue; } // otherwise perform the splitting didRadiate = true; isMCatNLOSEvent = false; isMCatNLOHEvent = false; pair<list<Dipole>::iterator,list<Dipole>::iterator> children; DipoleChain* firstChain = 0; DipoleChain* secondChain = 0; eventRecord().split(winnerDip,winner,children,firstChain,secondChain); assert(firstChain && secondChain); evolutionOrdering()->setEvolutionScale(winnerScale,winner,*firstChain,children); if ( !secondChain->dipoles().empty() ) evolutionOrdering()->setEvolutionScale(winnerScale,winner,*secondChain,children); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler did split the last selected dipole into:\n" << (*children.first) << (*children.second) << flush; } if ( verbosity > 2 ) { generator()->log() << "After splitting the last selected dipole, " << "DipoleShowerHandler encountered the following chains:\n" << (*firstChain) << (*secondChain) << flush; } if ( theEventReweight ) if ( (theEventReweight->firstInteraction() && firstInteraction()) || (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { double w = theEventReweight->weight(eventRecord().incoming(), eventRecord().outgoing(), eventRecord().hard(),theGlobalAlphaS); reweight_ *= w; } if ( nEmissions ) if ( ++emDone == nEmissions ) return; } } bool DipoleShowerHandler::realign() { if ( !didRadiate && !intrinsicPtGenerator ) return false; if ( eventRecord().incoming().first->coloured() || eventRecord().incoming().second->coloured() ) { if ( eventRecord().incoming().first->momentum().perp2()/GeV2 < 1e-10 && eventRecord().incoming().second->momentum().perp2()/GeV2 < 1e-10 ) return false; pair<Lorentz5Momentum,Lorentz5Momentum> inMomenta (eventRecord().incoming().first->momentum(), eventRecord().incoming().second->momentum()); SpinOneLorentzRotation transform((inMomenta.first+inMomenta.second).findBoostToCM()); Axis dir = (transform * inMomenta.first).vect().unit(); Axis rot (-dir.y(),dir.x(),0); double theta = dir.theta(); if ( lastParticles().first->momentum().z() < ZERO ) theta = -theta; transform.rotate(-theta,rot); inMomenta.first = transform*inMomenta.first; inMomenta.second = transform*inMomenta.second; assert(inMomenta.first.z() > ZERO && inMomenta.second.z() < ZERO); Energy2 sHat = (eventRecord().incoming().first->momentum() + eventRecord().incoming().second->momentum()).m2(); pair<Energy,Energy> masses(eventRecord().incoming().first->mass(), eventRecord().incoming().second->mass()); pair<Energy,Energy> qs; if ( !eventRecord().incoming().first->coloured() ) { assert(masses.second == ZERO); qs.first = eventRecord().incoming().first->momentum().z(); qs.second = (sHat-sqr(masses.first))/(2.*(qs.first+sqrt(sqr(masses.first)+sqr(qs.first)))); } else if ( !eventRecord().incoming().second->coloured() ) { assert(masses.first == ZERO); qs.second = eventRecord().incoming().second->momentum().z(); qs.first = (sHat-sqr(masses.second))/(2.*(qs.second+sqrt(sqr(masses.second)+sqr(qs.second)))); } else { assert(masses.first == ZERO && masses.second == ZERO); if ( realignmentScheme == 0 ) { double yX = eventRecord().pX().rapidity(); double yInt = (transform*eventRecord().pX()).rapidity(); double dy = yX-yInt; qs.first = (sqrt(sHat)/2.)*exp(dy); qs.second = (sqrt(sHat)/2.)*exp(-dy); } else if ( realignmentScheme == 1 ) { Energy sS = sqrt((lastParticles().first->momentum() + lastParticles().second->momentum()).m2()); qs.first = eventRecord().fractions().first * sS / 2.; qs.second = eventRecord().fractions().second * sS / 2.; } } double beta = (qs.first-qs.second) / ( sqrt(sqr(masses.first)+sqr(qs.first)) + sqrt(sqr(masses.second)+sqr(qs.second)) ); transform.boostZ(beta); Lorentz5Momentum tmp; if ( eventRecord().incoming().first->coloured() ) { tmp = eventRecord().incoming().first->momentum(); tmp = transform * tmp; eventRecord().incoming().first->set5Momentum(tmp); } if ( eventRecord().incoming().second->coloured() ) { tmp = eventRecord().incoming().second->momentum(); tmp = transform * tmp; eventRecord().incoming().second->set5Momentum(tmp); } eventRecord().transform(transform); return true; } return false; } void DipoleShowerHandler::resetAlphaS(Ptr<AlphaSBase>::tptr as) { for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { (**k).alphaS(as); (**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze); (**k).factorizationScaleFreeze(theFactorizationScaleFreeze); } // clear the generators to be rebuild // actually, there shouldn't be any generators // when this happens. generators().clear(); } void DipoleShowerHandler::resetReweight(Ptr<DipoleSplittingReweight>::tptr rw) { for ( GeneratorMap::iterator k = generators().begin(); k != generators().end(); ++k ) k->second->splittingReweight(rw); } void DipoleShowerHandler::getGenerators(const DipoleIndex& ind, Ptr<DipoleSplittingReweight>::tptr rw) { bool gotone = false; for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { if ( (**k).canHandle(ind) ) { if ( verbosity > 0 ) { generator()->log() << "DipoleShowerHandler encountered the dipole configuration\n" << ind << " in event number " << eventHandler()->currentEvent()->number() << "\nwhich can be handled by the splitting kernel '" << (**k).name() << "'.\n" << flush; } gotone = true; Ptr<DipoleSplittingGenerator>::ptr nGenerator = new_ptr(DipoleSplittingGenerator()); nGenerator->doCompensate(theDoCompensate); nGenerator->splittingKernel(*k); nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); nGenerator->splittingKernel()->freezeGrid(theFreezeGrid); nGenerator->splittingKernel()->detuning(theDetuning); GeneratorMap::const_iterator equivalent = generators().end(); for ( GeneratorMap::const_iterator eq = generators().begin(); eq != generators().end(); ++eq ) { if ( !eq->second->wrapping() ) if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) { equivalent = eq; if ( verbosity > 0 ) { generator()->log() << "The dipole configuration " << ind << " can equivalently be handled by the existing\n" << "generator for configuration " << eq->first << " using the kernel '" << eq->second->splittingKernel()->name() << "'\n" << flush; } break; } } if ( equivalent != generators().end() ) { nGenerator->wrap(equivalent->second); } DipoleSplittingInfo dummy; dummy.index(ind); nGenerator->splittingReweight(rw); nGenerator->prepare(dummy); generators().insert(make_pair(ind,nGenerator)); } } if ( !gotone ) { generator()->logWarning(Exception() << "DipoleShowerHandler could not " << "find a splitting kernel which is able " << "to handle splittings off the dipole " << ind << ".\n" << "Please check the input files." << Exception::warning); } } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleShowerHandler::doinit() { ShowerHandler::doinit(); if ( theGlobalAlphaS ) resetAlphaS(theGlobalAlphaS); } void DipoleShowerHandler::dofinish() { ShowerHandler::dofinish(); } void DipoleShowerHandler::doinitrun() { ShowerHandler::doinitrun(); } void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const { os << kernels << theEvolutionOrdering << constituentReshuffler << intrinsicPtGenerator << theGlobalAlphaS << chainOrderVetoScales << nEmissions << discardNoEmissions << firstMCatNLOEmission << doFSR << doISR << realignmentScheme << verbosity << printEvent << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << isMCatNLOSEvent << isMCatNLOHEvent << theShowerApproximation << theDoCompensate << theFreezeGrid << theDetuning << theEventReweight << ounit(maxPt,GeV) << ounit(muPt,GeV); } void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { is >> kernels >> theEvolutionOrdering >> constituentReshuffler >> intrinsicPtGenerator >> theGlobalAlphaS >> chainOrderVetoScales >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> doFSR >> doISR >> realignmentScheme >> verbosity >> printEvent >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> isMCatNLOSEvent >> isMCatNLOHEvent >> theShowerApproximation >> theDoCompensate >> theFreezeGrid >> theDetuning >> theEventReweight >> iunit(maxPt,GeV) >> iunit(muPt,GeV); } ClassDescription<DipoleShowerHandler> DipoleShowerHandler::initDipoleShowerHandler; // Definition of the static class description member. void DipoleShowerHandler::Init() { static ClassDocumentation<DipoleShowerHandler> documentation ("The DipoleShowerHandler class manages the showering using " "the dipole shower algorithm.", "The shower evolution was performed using the algorithm described in " "\\cite{Platzer:2009jq} and \\cite{Platzer:2011bc}.", "%\\cite{Platzer:2009jq}\n" "\\bibitem{Platzer:2009jq}\n" "S.~Platzer and S.~Gieseke,\n" "``Coherent Parton Showers with Local Recoils,''\n" " JHEP {\\bf 1101}, 024 (2011)\n" "arXiv:0909.5593 [hep-ph].\n" "%%CITATION = ARXIV:0909.5593;%%\n" "%\\cite{Platzer:2011bc}\n" "\\bibitem{Platzer:2011bc}\n" "S.~Platzer and S.~Gieseke,\n" "``Dipole Showers and Automated NLO Matching in Herwig,''\n" "arXiv:1109.6256 [hep-ph].\n" "%%CITATION = ARXIV:1109.6256;%%"); static RefVector<DipoleShowerHandler,DipoleSplittingKernel> interfaceKernels ("Kernels", "Set the splitting kernels to be used by the dipole shower.", &DipoleShowerHandler::kernels, -1, false, false, true, false, false); static Reference<DipoleShowerHandler,DipoleEvolutionOrdering> interfaceEvolutionOrdering ("EvolutionOrdering", "Set the evolution ordering to be used.", &DipoleShowerHandler::theEvolutionOrdering, false, false, true, false, false); static Reference<DipoleShowerHandler,ConstituentReshuffler> interfaceConstituentReshuffler ("ConstituentReshuffler", "The object to be used to reshuffle partons to their constitutent mass shells.", &DipoleShowerHandler::constituentReshuffler, false, false, true, true, false); static Reference<DipoleShowerHandler,IntrinsicPtGenerator> interfaceIntrinsicPtGenerator ("IntrinsicPtGenerator", "Set the object in charge to generate intrinsic pt for incoming partons.", &DipoleShowerHandler::intrinsicPtGenerator, false, false, true, true, false); static Reference<DipoleShowerHandler,AlphaSBase> interfaceGlobalAlphaS ("GlobalAlphaS", "Set a global strong coupling for all splitting kernels.", &DipoleShowerHandler::theGlobalAlphaS, false, false, true, true, false); static Switch<DipoleShowerHandler,bool> interfaceDoFSR ("DoFSR", "Switch on or off final state radiation.", &DipoleShowerHandler::doFSR, true, false, false); static SwitchOption interfaceDoFSROn (interfaceDoFSR, "On", "Switch on final state radiation.", true); static SwitchOption interfaceDoFSROff (interfaceDoFSR, "Off", "Switch off final state radiation.", false); static Switch<DipoleShowerHandler,bool> interfaceDoISR ("DoISR", "Switch on or off initial state radiation.", &DipoleShowerHandler::doISR, true, false, false); static SwitchOption interfaceDoISROn (interfaceDoISR, "On", "Switch on initial state radiation.", true); static SwitchOption interfaceDoISROff (interfaceDoISR, "Off", "Switch off initial state radiation.", false); static Switch<DipoleShowerHandler,int> interfaceRealignmentScheme ("RealignmentScheme", "The realignment scheme to use.", &DipoleShowerHandler::realignmentScheme, 0, false, false); static SwitchOption interfaceRealignmentSchemePreserveRapidity (interfaceRealignmentScheme, "PreserveRapidity", "Preserve the rapidity of non-coloured outgoing system.", 0); static SwitchOption interfaceRealignmentSchemeEvolutionFractions (interfaceRealignmentScheme, "EvolutionFractions", "Use momentum fractions as generated by the evolution.", 1); static SwitchOption interfaceRealignmentSchemeCollisionFrame (interfaceRealignmentScheme, "CollisionFrame", "Determine realignment from collision frame.", 2); static Switch<DipoleShowerHandler,bool> interfaceChainOrderVetoScales ("ChainOrderVetoScales", "[experimental] Switch on or off the chain ordering for veto scales.", &DipoleShowerHandler::chainOrderVetoScales, true, false, false); static SwitchOption interfaceChainOrderVetoScalesOn (interfaceChainOrderVetoScales, "On", "Switch on chain ordering for veto scales.", true); static SwitchOption interfaceChainOrderVetoScalesOff (interfaceChainOrderVetoScales, "Off", "Switch off chain ordering for veto scales.", false); interfaceChainOrderVetoScales.rank(-1); static Parameter<DipoleShowerHandler,unsigned int> interfaceNEmissions ("NEmissions", "[debug option] Limit the number of emissions to be generated. Zero does not limit the number of emissions.", &DipoleShowerHandler::nEmissions, 0, 0, 0, false, false, Interface::lowerlim); interfaceNEmissions.rank(-1); static Switch<DipoleShowerHandler,bool> interfaceDiscardNoEmissions ("DiscardNoEmissions", "[debug option] Discard events without radiation.", &DipoleShowerHandler::discardNoEmissions, false, false, false); static SwitchOption interfaceDiscardNoEmissionsOn (interfaceDiscardNoEmissions, "On", "Discard events without radiation.", true); static SwitchOption interfaceDiscardNoEmissionsOff (interfaceDiscardNoEmissions, "Off", "Do not discard events without radiation.", false); interfaceDiscardNoEmissions.rank(-1); static Switch<DipoleShowerHandler,bool> interfaceFirstMCatNLOEmission ("FirstMCatNLOEmission", "[debug option] Only perform the first MC@NLO emission.", &DipoleShowerHandler::firstMCatNLOEmission, false, false, false); static SwitchOption interfaceFirstMCatNLOEmissionOn (interfaceFirstMCatNLOEmission, "On", "", true); static SwitchOption interfaceFirstMCatNLOEmissionOff (interfaceFirstMCatNLOEmission, "Off", "", false); interfaceFirstMCatNLOEmission.rank(-1); static Parameter<DipoleShowerHandler,int> interfaceVerbosity ("Verbosity", "[debug option] Set the level of debug information provided.", &DipoleShowerHandler::verbosity, 0, 0, 0, false, false, Interface::lowerlim); interfaceVerbosity.rank(-1); static Parameter<DipoleShowerHandler,int> interfacePrintEvent ("PrintEvent", "[debug option] The number of events for which debugging information should be provided.", &DipoleShowerHandler::printEvent, 0, 0, 0, false, false, Interface::lowerlim); interfacePrintEvent.rank(-1); static Parameter<DipoleShowerHandler,Energy> interfaceRenormalizationScaleFreeze ("RenormalizationScaleFreeze", "The freezing scale for the renormalization scale.", &DipoleShowerHandler::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter<DipoleShowerHandler,Energy> interfaceFactorizationScaleFreeze ("FactorizationScaleFreeze", "The freezing scale for the factorization scale.", &DipoleShowerHandler::theFactorizationScaleFreeze, GeV, 2.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch<DipoleShowerHandler,bool> interfaceDoCompensate ("DoCompensate", "", &DipoleShowerHandler::theDoCompensate, false, false, false); static SwitchOption interfaceDoCompensateYes (interfaceDoCompensate, "Yes", "", true); static SwitchOption interfaceDoCompensateNo (interfaceDoCompensate, "No", "", false); static Parameter<DipoleShowerHandler,unsigned long> interfaceFreezeGrid ("FreezeGrid", "", &DipoleShowerHandler::theFreezeGrid, 500000, 1, 0, false, false, Interface::lowerlim); static Parameter<DipoleShowerHandler,double> interfaceDetuning ("Detuning", "A value to detune the overestimate kernel.", &DipoleShowerHandler::theDetuning, 1.0, 1.0, 0, false, false, Interface::lowerlim); static Reference<DipoleShowerHandler,DipoleEventReweight> interfaceEventReweight ("EventReweight", "", &DipoleShowerHandler::theEventReweight, false, false, true, true, false); } diff --git a/DipoleShower/Kinematics/IFLightKinematics.cc b/DipoleShower/Kinematics/IFLightKinematics.cc --- a/DipoleShower/Kinematics/IFLightKinematics.cc +++ b/DipoleShower/Kinematics/IFLightKinematics.cc @@ -1,253 +1,256 @@ // -*- C++ -*- // // IFLightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 IFLightKinematics class. // #include "IFLightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" using namespace Herwig; IFLightKinematics::IFLightKinematics() - : DipoleSplittingKinematics(), theCollinearScheme(false) {} + : DipoleSplittingKinematics(), theCollinearScheme(true) {} IFLightKinematics::~IFLightKinematics() {} IBPtr IFLightKinematics::clone() const { return new_ptr(*this); } IBPtr IFLightKinematics::fullclone() const { return new_ptr(*this); } Energy IFLightKinematics::ptMax(Energy dScale, double emX, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-emX)/emX) /2.; } Energy IFLightKinematics::QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { assert(false && "add this"); return 0.0*GeV; } Energy IFLightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(1.-z); } Energy IFLightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(1.-z); } pair<double,double> IFLightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double x = dInfo.emitterX(); double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } bool IFLightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { if ( info.emitterX() < xMin() ) { jacobian(0.0); return false; } double weight = 1.0; Energy pt = generatePt(kappa,info.scale(), info.emitterX(),info.spectatorX(), info.index(),split, weight); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emitterData()->id() == ParticleID::g ) { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZ, info,split,weight); } } if ( info.index().emitterData()->id() != ParticleID::g ) { if ( info.emitterData()->id() != ParticleID::g ) { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,FlatZ, info,split,weight); } } if ( weight == 0. && z == -1. ) { jacobian(0.0); return false; } double ratio = sqr(pt/info.scale()); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); if ( rho < 0.0 ) { jacobian(0.0); return false; } double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); if ( x < info.emitterX() || x > 1. || u < 0. || u > 1. ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1./z)); lastPt(pt); lastZ(z); lastPhi(phi); lastEmitterZ(x); if ( theMCCheck ) theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void IFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double ratio = sqr(pt)/(2.*pEmitter*pSpectator); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); Lorentz5Momentum kt = getKt (pEmitter, pSpectator, pt, dInfo.lastPhi(),true); Lorentz5Momentum em; Lorentz5Momentum emm; Lorentz5Momentum spe; if ( !theCollinearScheme && x > u && (1.-x)/(x-u) < 1. ) { + assert(false); + em = ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); em.setMass(0.*GeV); em.rescaleEnergy(); emm = ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); emm.setMass(0.*GeV); emm.rescaleEnergy(); spe = (1.-u/x)*pSpectator; spe.setMass(0.*GeV); spe.rescaleEnergy(); } else { em = (1./x)*pEmitter; emm = ((1.-x)*(1.-u)/x)*pEmitter + u*pSpectator + kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); spe = ((1.-x)*u/x)*pEmitter + (1.-u)*pSpectator - kt; spe.setMass(0.*GeV); spe.rescaleEnergy(); } emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). -void IFLightKinematics::persistentOutput(PersistentOStream & os) const { - os << theCollinearScheme; +void IFLightKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; } -void IFLightKinematics::persistentInput(PersistentIStream & is, int) { - is >> theCollinearScheme; +void IFLightKinematics::persistentInput(PersistentIStream &, int) { + //is >> theCollinearScheme; } ClassDescription<IFLightKinematics> IFLightKinematics::initIFLightKinematics; // Definition of the static class description member. void IFLightKinematics::Init() { static ClassDocumentation<IFLightKinematics> documentation ("IFLightKinematics implements massless splittings " "off a initial-final dipole."); - + /* static Switch<IFLightKinematics,bool> interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IFLightKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeOn (interfaceCollinearScheme, "On", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeOff (interfaceCollinearScheme, "Off", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); + */ } diff --git a/DipoleShower/Kinematics/IFMassiveKinematics.cc b/DipoleShower/Kinematics/IFMassiveKinematics.cc --- a/DipoleShower/Kinematics/IFMassiveKinematics.cc +++ b/DipoleShower/Kinematics/IFMassiveKinematics.cc @@ -1,314 +1,315 @@ // -*- C++ -*- // // IFMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 IFMassiveKinematics class. // #include "IFMassiveKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" using namespace Herwig; IFMassiveKinematics::IFMassiveKinematics() : DipoleSplittingKinematics(), theCollinearScheme(true) {} IFMassiveKinematics::~IFMassiveKinematics() {} IBPtr IFMassiveKinematics::clone() const { return new_ptr(*this); } IBPtr IFMassiveKinematics::fullclone() const { return new_ptr(*this); } pair<double,double> IFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return make_pair(0.0,1.0); } pair<double,double> IFMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emitterData()->id() == ParticleID::g ) { double b = log((1.+c)/(1.-c)); return make_pair(-b,b); } else { return make_pair(log(0.5*(1.-c)),log(0.5*(1.+c))); } } if ( split.index().emitterData()->id() != ParticleID::g && split.emitterData()->id() != ParticleID::g ) { return make_pair(-log(0.5*(1.+c)),-log(0.5*(1.-c))); } return make_pair(0.5*(1.-c),0.5*(1.+c)); } // sbar Energy IFMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return sqrt(2.*(pEmitter*pSpectator)); } Energy IFMassiveKinematics::ptMax(Energy dScale, double emX, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt(1.-emX) /2.; } Energy IFMassiveKinematics::QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { assert(false && "add this"); return 0.0*GeV; } Energy IFMassiveKinematics::PtFromQ(Energy, const DipoleSplittingInfo&) const { assert(false && "add this"); return 0.0*GeV; } Energy IFMassiveKinematics::QFromPt(Energy, const DipoleSplittingInfo&) const { assert(false && "add this"); return 0.0*GeV; } double IFMassiveKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } bool IFMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { if ( info.emitterX() < xMin() ) { jacobian(0.0); return false; } Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); if ( sqr(pt) > sqr(info.hardPt())/(1.+4.*sqr(info.hardPt()/info.scale())) ) { jacobian(0.0); return false; } double z = 0.; double mapZJacobian = 0.; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emitterData()->id() == ParticleID::g ) { z = exp(xi)/(1.+exp(xi)); mapZJacobian = z*(1.-z); } else { z = exp(xi); mapZJacobian = z; } } if ( info.index().emitterData()->id() != ParticleID::g ) { if ( info.emitterData()->id() != ParticleID::g ) { z = 1.-exp(-xi); mapZJacobian = 1.-z; } else { z = xi; mapZJacobian = 1.; } } double ratio = sqr(pt/info.scale()); double x = ( z*(1.-z) - ratio ) / ( 1. - z - ratio ); double u = ratio/(1.-z); double up = (1.-x) / ( 1.-x + x*sqr(info.spectatorData()->mass()/info.scale()) ); if ( x < 0. || x > 1. || u > up ) { jacobian(0.0); return false; } double xe = info.emitterX(); double zmx = 0.5*(1.+xe-(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); double zpx = 0.5*(1.+xe+(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); double xq = sqr(pt/info.hardPt()); double zpq = 0.5*( 1.+ xq + (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); double zmq = 0.5*( 1.+ xq - (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); double zp = min(zpx,zpq); double zm = max(zmx,zmq); if ( pt < IRCutoff() || pt > info.hardPt() || z > zp || z < zm || x < xe ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(2. * mapZJacobian * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) * (1.-z-ratio)/sqr(z*(1.-z)-ratio) ); lastPt(pt); lastZ(z); lastPhi(phi); lastEmitterZ(x); if ( theMCCheck ) theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void IFMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy2 sbar = 2.*pEmitter*pSpectator; Energy pt = dInfo.lastPt(); double ratio = pt*pt/sbar; double z = dInfo.lastZ(); double x = (z*(1.-z)-ratio)/(1.-z-ratio); double u = ratio / (1.-z); pt = sqrt(sbar*u*(1.-u)*(1.-x)); Energy magKt = sqrt(sbar*u*(1.-u)*(1.-x)/x - sqr(u*dInfo.spectatorData()->mass())); Lorentz5Momentum kt = getKt (pEmitter, pSpectator, magKt, dInfo.lastPhi(),true); Lorentz5Momentum em; Lorentz5Momentum emm; Lorentz5Momentum spe; Energy2 mj2 = dInfo.spectatorData()->mass()*dInfo.spectatorData()->mass(); double alpha = 1. - 2.*mj2/sbar; // TODO: adjust phasespace boundary condition if (!theCollinearScheme) assert(false); if ( !theCollinearScheme && x > u && (1.-x)/(x-u) < 1. ) { double fkt = sqrt(sqr(x-u)+4.*x*u*mj2/sbar); // em = // ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); Energy2 fa = (sbar*(x+u-2.*x*z)+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); double a = (-sbar+fa) / (2.*x*(sbar-mj2)); double ap = (sbar+alpha*fa) / (2.*x*(sbar-mj2)); em = ap*pEmitter + a*pSpectator - fkt*kt; em.setMass(ZERO); em.rescaleEnergy(); // emm = // ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); Energy2 fb = abs(sbar*(u*(1.-u)-x*(1.-x))+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); double b = (-sbar*(1.-x-u)+fb) / (2.*x*(sbar-mj2)); double bp = (sbar*(1.-x-u)+alpha*fb) / (2.*x*(sbar-mj2)); emm = bp*pEmitter + b*pSpectator + fkt*kt; emm.setMass(ZERO); emm.rescaleEnergy(); // spe = // (1.-u/x)*pSpectator; Energy2 fc = sqrt(sqr(sbar*(x-u))+4.*sbar*mj2*x*u); double c = (sbar*(x-u)-2.*x*mj2+fc) / (2.*x*(sbar-mj2)); double cp = (-sbar*(x-u)+2.*x*mj2+alpha*fc) / (2.*x*(sbar-mj2)); spe = cp*pEmitter + c*pSpectator; spe.setMass(dInfo.spectatorData()->mass()); spe.rescaleEnergy(); } else { em = (1./x)*pEmitter; em.setMass(ZERO); em.rescaleEnergy(); emm = (-kt*kt-u*u*mj2)/(u*sbar)*pEmitter + u*pSpectator - kt; emm.setMass(ZERO); emm.rescaleEnergy(); spe = (-kt*kt + mj2*u*(2.-u))/((1.-u)*sbar)*pEmitter + (1.-u)*pSpectator + kt; spe.setMass(dInfo.spectatorData()->mass()); spe.rescaleEnergy(); } emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). -void IFMassiveKinematics::persistentOutput(PersistentOStream & os) const { - os << theCollinearScheme; +void IFMassiveKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; } -void IFMassiveKinematics::persistentInput(PersistentIStream & is, int) { - is >> theCollinearScheme; +void IFMassiveKinematics::persistentInput(PersistentIStream &, int) { + //is >> theCollinearScheme; } ClassDescription<IFMassiveKinematics> IFMassiveKinematics::initIFMassiveKinematics; // Definition of the static class description member. void IFMassiveKinematics::Init() { static ClassDocumentation<IFMassiveKinematics> documentation ("IFMassiveKinematics implements massless splittings " "off a initial-final dipole."); - + /* static Switch<IFMassiveKinematics,bool> interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IFMassiveKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeOn (interfaceCollinearScheme, "On", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeOff (interfaceCollinearScheme, "Off", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); + */ } diff --git a/DipoleShower/Kinematics/IILightKinematics.cc b/DipoleShower/Kinematics/IILightKinematics.cc --- a/DipoleShower/Kinematics/IILightKinematics.cc +++ b/DipoleShower/Kinematics/IILightKinematics.cc @@ -1,287 +1,290 @@ // -*- C++ -*- // // IILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 IILightKinematics class. // #include "IILightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" using namespace Herwig; IILightKinematics::IILightKinematics() - : DipoleSplittingKinematics(), theCollinearScheme(false), didCollinear(false) {} + : DipoleSplittingKinematics(), theCollinearScheme(true), didCollinear(false) {} IILightKinematics::~IILightKinematics() {} IBPtr IILightKinematics::clone() const { return new_ptr(*this); } IBPtr IILightKinematics::fullclone() const { return new_ptr(*this); } Energy IILightKinematics::ptMax(Energy dScale, double emX, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { double tau = !theCollinearScheme ? emX*specX : emX; return (1.-tau) * dScale / (2.*sqrt(tau)); } Energy IILightKinematics::QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { assert(false && "add this"); return 0.0*GeV; } Energy IILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(1.-z); } Energy IILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(1.-z); } pair<double,double> IILightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double x = !theCollinearScheme ? dInfo.emitterX()*dInfo.spectatorX() : dInfo.emitterX(); double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } bool IILightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { if ( info.emitterX() < xMin() || info.spectatorX() < xMin() ) { jacobian(0.0); return false; } double weight = 1.0; Energy pt = generatePt(kappa,info.scale(), info.emitterX(),info.spectatorX(), info.index(),split, weight); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emitterData()->id() == ParticleID::g ) { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZ, info,split,weight); } } if ( info.index().emitterData()->id() != ParticleID::g ) { if ( info.emitterData()->id() != ParticleID::g ) { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,FlatZ, info,split,weight); } } if ( weight == 0. && z == -1. ) { jacobian(0.0); return false; } double ratio = sqr(pt/info.scale()); double x = z*(1.-z)/(1.-z+ratio); double v = ratio*z /(1.-z+ratio); if ( x < 0. || x > 1. || v < 0. || v > 1.-x ) { jacobian(0.0); return false; } if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { if ( (x+v) < info.emitterX() || x/(x+v) < info.spectatorX() ) { jacobian(0.0); return false; } } else { if ( x < info.emitterX() ) { jacobian(0.0); return false; } } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1./z)); lastPt(pt); lastZ(z); lastPhi(phi); if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { lastEmitterZ(x+v); lastSpectatorZ(x/(x+v)); } else { lastEmitterZ(x); lastSpectatorZ(1.); } if ( theMCCheck ) theMCCheck->book(info.emitterX(),info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void IILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double ratio = sqr(pt)/(2.*pEmitter*pSpectator); double x = z*(1.-z)/(1.-z+ratio); double v = ratio*z /(1.-z+ratio); Lorentz5Momentum kt = getKt (pEmitter, pSpectator, pt, dInfo.lastPhi()); if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { + assert(false); + Lorentz5Momentum em = (1./(v+x))*pEmitter+(v*(1.-v-x)/(x*(x+v)))*pSpectator+kt/(x+v); em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = ((1.-v-x)/(v+x))*pEmitter+(v/(x*(x+v)))*pSpectator+kt/(x+v); emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = (1.+v/x)*pSpectator; spe.setMass(0.*GeV); spe.rescaleEnergy(); emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); didCollinear = false; } else { Lorentz5Momentum em = (1./x)*pEmitter; em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = ((1.-x-v)/x)*pEmitter+v*pSpectator+kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = pSpectator; emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); K = em + spe - emm; K2 = K.m2(); Ktilde = pEmitter + pSpectator; KplusKtilde = K + Ktilde; KplusKtilde2 = KplusKtilde.m2(); didCollinear = true; } } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). -void IILightKinematics::persistentOutput(PersistentOStream & os) const { - os << theCollinearScheme; +void IILightKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; } -void IILightKinematics::persistentInput(PersistentIStream & is, int) { - is >> theCollinearScheme; +void IILightKinematics::persistentInput(PersistentIStream &, int) { + //is >> theCollinearScheme; } ClassDescription<IILightKinematics> IILightKinematics::initIILightKinematics; // Definition of the static class description member. void IILightKinematics::Init() { static ClassDocumentation<IILightKinematics> documentation ("IILightKinematics implements massless splittings " "off an initial-initial dipole."); - + /* static Switch<IILightKinematics,bool> interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IILightKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeOn (interfaceCollinearScheme, "On", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeOff (interfaceCollinearScheme, "Off", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); + */ } diff --git a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc --- a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc +++ b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc @@ -1,843 +1,844 @@ // -*- C++ -*- // // MadGraphAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 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 MadGraphAmplitude class. // #include "MadGraphAmplitude.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" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include <boost/lexical_cast.hpp> #include <boost/filesystem.hpp> #include <cstdlib> #include <dlfcn.h> #include <errno.h> #include <sstream> using namespace Herwig; #ifndef HERWIG_BINDIR #error Makefile.am needs to define HERWIG_BINDIR #endif #ifndef HERWIG_PKGDATADIR #error Makefile.am needs to define HERWIG_PKGDATADIR #endif #ifndef MADGRAPH_PREFIX #error Makefile.am needs to define MADGRAPH_PREFIX #endif extern "C" void mginitproc_(char *i,int); extern "C" void MG_Calculate_wavefunctions_virt(int* proc,double*,double*); extern "C" void MG_Calculate_wavefunctions_born(int* proc,double*, int*); extern "C" void MG_Jamp (int* proc,int*, double*); extern "C" void MG_LNJamp (int* proc,int*, double*); extern "C" void MG_Virt (int* proc,double*); extern "C" void MG_NCol (int* proc,int*); extern "C" void MG_vxxxxx (double* p,double* n,int* inc,double* ); extern "C" void MG_Colour (int* proc,int* i,int* j ,int* color); MadGraphAmplitude::MadGraphAmplitude() : theMGmodel("loop_sm"),keepinputtopmass(false), bindir_(HERWIG_BINDIR), includedir_(HERWIG_INCLUDEDIR), pkgdatadir_(HERWIG_PKGDATADIR), madgraphPrefix_(MADGRAPH_PREFIX) {} MadGraphAmplitude::~MadGraphAmplitude() { } IBPtr MadGraphAmplitude::clone() const { return new_ptr(*this); } IBPtr MadGraphAmplitude::fullclone() const { return new_ptr(*this); } bool MadGraphAmplitude::initializedMad=false; vector<string> MadGraphAmplitude::BornAmplitudes=vector<string>(); vector<string> MadGraphAmplitude::VirtAmplitudes=vector<string>(); void MadGraphAmplitude::initProcess(const cPDVector& ) { if ( lastMatchboxXComb()->initialized() ) return; if ( !DynamicLoader::load(mgProcLibPath()+"InterfaceMadGraph.so") ) throw Exception() << "MadGraphAmplitude: Failed to load MadGraph amplitudes\n" << DynamicLoader::lastErrorMessage << Exception::runerror; if (!initializedMad){ string mstr=(factory()->runStorage()+"MadGraphAmplitudes"+"/param_card"+((theMGmodel=="loop_sm")?"":("_"+theMGmodel))+".dat"); if( theMGmodel[0]=='/')mstr="param_card.dat"; size_t len = mstr.size(); mginitproc_(const_cast<char*>(mstr.c_str()),len); initializedMad=true; } lastMatchboxXComb()->isInitialized(); } bool MadGraphAmplitude::writeAmplitudesDat(){ bool res=false; string born= mgProcLibPath()+"BornAmplitudes.dat"; if ( !boost::filesystem::exists(born) ) { ofstream borns(born.c_str()); for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++) borns<<*amps<<endl; borns.close(); res=true; } string virt= mgProcLibPath()+"VirtAmplitudes.dat"; if ( !boost::filesystem::exists(virt) ) { ofstream virts(virt.c_str()); for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++) virts<<*amps<<endl; virts.flush(); virts.close(); res=true; } return res; } bool MadGraphAmplitude::checkAmplitudes(){ string born= mgProcLibPath()+"BornAmplitudes.dat"; string virt= mgProcLibPath()+"VirtAmplitudes.dat"; assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt)); bool foundallborns=true; for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++){ ifstream borns(born.c_str()); string line; bool foundthisborn=false; while (std::getline(borns, line)) { if(line==*amps)foundthisborn=true; } foundallborns&=foundthisborn; } bool foundallvirts=true; for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++){ ifstream virts(virt.c_str()); string line; bool foundthisvirt=false; while (std::getline(virts, line)) { if(line==*amps)foundthisvirt=true; } foundallvirts&=foundthisvirt; } if (!foundallborns||!foundallvirts) throw Exception() << "MadGraphAmplitude: One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::runerror; return foundallborns && foundallvirts; } string MadGraphAmplitude::mgProcLibPath(){ string res=theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath; if (res.at(res.length()-1) != '/') res.append("/"); return res; } bool MadGraphAmplitude::initializeExternal() { if ( boost::filesystem::exists(mgProcLibPath()) ) { if ( !boost::filesystem::is_directory(mgProcLibPath()) ) throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '" << mgProcLibPath() << "' existing but not a directory." << Exception::runerror; } else { boost::filesystem::create_directories(mgProcLibPath()); } string runAmplitudes = factory()->runStorage() + "/MadGraphAmplitudes"; if ( boost::filesystem::exists(runAmplitudes) ) { if ( !boost::filesystem::is_directory(runAmplitudes) ) throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '" << runAmplitudes << "' existing but not a directory." << Exception::runerror; } else { boost::filesystem::create_directories(runAmplitudes); } //EW-consistency check: Energy MW=getParticleData(ParticleID::Wplus)->hardProcessMass(); Energy MZ=getParticleData(ParticleID::Z0)->hardProcessMass(); if( MW!= sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))){ generator()->log()<<"\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----"; generator()->log() << "\nYou are using a EW scheme which is inconsistent with the MadGraph parametisation:\n\n" <<MW/GeV<< " GeV==MW!= sqrt(MZ^2/2+sqrt(MZ^4/4.0-pi*alphaEMMZ*MZ^2/ sqrt(2)/G_f))=="<< sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))/GeV <<" GeV\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----\n"; } string para= factory()->runStorage()+"/MadGraphAmplitudes"+"/MG-Parameter.dat"; ofstream params(para.c_str()); params<<"$WZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessWidth() /GeV; params<<"\n$WW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV; params<<"\n$alphas$ " <<std::setiosflags(ios::scientific) <<SM().alphaS(); params<<"\n$GF$ " <<std::setiosflags(ios::scientific) <<SM().fermiConstant()*GeV2 ; params<<"\n$alphaMZ$ " <<std::setiosflags(ios::scientific) <<1/SM().alphaEMMZ(); params<<"\n$MZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessMass() /GeV<<flush; params<<"\n$MW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessMass() /GeV<<flush; params<<"\n$sw2$ " <<std::setiosflags(ios::scientific) << SM().sin2ThetaW() <<flush; if(theMGmodel=="heft"&&!keepinputtopmass){ if ( factory()->initVerbose() ) { generator()->log()<<"\n---------------------------------------------------------------"; generator()->log()<<"\n---------------------------------------------------------------"; generator()->log()<<"\nNote: You are using the Higgs Effective model (heft) in "; generator()->log()<<"\n Madgraph. We assume you try to calculate NLO with "; generator()->log()<<"\n the GoSam virtual amplitudes. To match the models we "; generator()->log()<<"\n therefore set the topmass to 10000000 GeV."; generator()->log()<<"\n\n For more information see the \\tau parameter in:"; generator()->log()<<"\n https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Models/HiggsEffective"; generator()->log()<<"\n\n The Effective Higgs model in Gosam is using mT=infinity"; generator()->log()<<"\n\n\n If you want to use the LO matrixelements of MadGraph with finite' topmass you need to add: "; generator()->log()<<"\n\n set Madgraph:KeepInputTopMass True"; generator()->log()<<"\n\n to your input file."; generator()->log()<<"\n---------------------------------------------------------------"; generator()->log()<<"\n---------------------------------------------------------------\n"; } params<<"\n$MT$ 10000000." <<flush; }else{ params<<"\n$MT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessMass() /GeV <<flush; } params<<"\n$WT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessWidth() /GeV <<flush; params<<"\n$MB$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::b)->hardProcessMass() /GeV <<flush; params<<"\n$MH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessMass() /GeV <<flush; params<<"\n$WH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessWidth() /GeV <<flush; params<<"\n$MTA$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::tauplus)->hardProcessMass() /GeV <<flush; string cmd = "python " + bindir_ + "/mg2herwig "; cmd +=" --buildpath "+mgProcLibPath(); + cmd += !theProcessPath.empty() ? " --absolute-links" : ""; cmd +=" --model "+theMGmodel; cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes "; cmd +=" --datadir "+pkgdatadir_; cmd +=" --includedir "+includedir_; std::stringstream as,aem; as << factory()->orderInAlphaS(); cmd +=" --orderas "+as.str() ; aem <<factory()->orderInAlphaEW(); cmd +=" --orderew "+aem.str(); // TODO move to boost::system writeAmplitudesDat(); if (boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so") ){ //set the parameters checkAmplitudes(); std::system(cmd.c_str()); ranMadGraphInitializeExternal = true; return true; } char cwd[1024]; if ( !getcwd(cwd,sizeof(cwd)) ) throw Exception() << "MadGraphAmplitude: failed to determine current working directory\n" << Exception::runerror; cmd +=" --madgraph " + madgraphPrefix_ + "/bin " ; cmd +="--build > "; cmd += mgProcLibPath()+"MG.log 2>&1"; generator()->log() << "\n>>> Compiling MadGraph amplitudes. This may take some time -- please be patient.\n" << ">>> In case of problems see " << mgProcLibPath() << "MG.log for details.\n\n" << flush; std::system(cmd.c_str()); cmd = "python " + bindir_ + "/mg2herwig "; cmd +=" --buildpath "+mgProcLibPath(); cmd +=" --model "+theMGmodel; cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes "; cmd +=" --datadir "+pkgdatadir_; as.clear(); aem.clear(); as << factory()->orderInAlphaS(); cmd +=" --orderas "+as.str() ; aem <<factory()->orderInAlphaEW(); cmd +=" --orderew "+aem.str(); std::system(cmd.c_str()); ranMadGraphInitializeExternal = true; return boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so"); } int MadGraphAmplitude::externalId(const cPDVector& proc) { for (int i=0;i<100;i++){ colourindex.push_back(-2); } assert(!BornAmplitudes.empty()||!VirtAmplitudes.empty()); writeAmplitudesDat(); int res=0; string amp=""; int k=0; for (cPDVector::const_iterator it=proc.begin();it!=proc.end();it++,k++){ amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > "; } string born= mgProcLibPath()+"BornAmplitudes.dat"; string virt= mgProcLibPath()+"VirtAmplitudes.dat"; assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt)); ifstream borns(born.c_str()); string line; while (std::getline(borns, line)) { res+=1; if(line==amp)return res; } ifstream virts(virt.c_str()); while (std::getline(virts, line)) { res+=1; if(line==amp)return res; } throw Exception() << "MadGraphAmplitude: One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::runerror; return res; } bool MadGraphAmplitude::ranMadGraphInitializeExternal = false; void MadGraphAmplitude::doinit() { if ( !ranMadGraphInitializeExternal ) { initializeExternal(); } MatchboxAmplitude::doinit(); } void MadGraphAmplitude::doinitrun() { if ( !ranMadGraphInitializeExternal ) { initializeExternal(); } MatchboxAmplitude::doinitrun(); } bool MadGraphAmplitude::canHandle(const PDVector& p, Ptr<MatchboxFactory>::tptr factory, bool virt) const { if ( factory->processData()->diagramMap().find(p) != factory->processData()->diagramMap().end() ) return true; vector<Ptr<Tree2toNDiagram>::ptr> diags = factory->diagramGenerator()->generate(p,orderInGs(),orderInGem()); if ( diags.empty() ) return false; factory->processData()->diagramMap()[p] = diags; string amp=""; int k=0; for (PDVector::const_iterator it=p.begin();it!=p.end();it++,k++){ amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > "; } if (virt && factory->highestVirt()>=p.size()){ VirtAmplitudes.push_back(amp); }else{ BornAmplitudes.push_back(amp); } return true; } void MadGraphAmplitude::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr me) { useMe(); if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } if (colourindex.empty()) { for (int i=0;i<100;i++){ colourindex.push_back(-2); } } lastMatchboxXComb()->clearheljamp(); lastMatchboxXComb()->clearhelLNjamp(); initProcess(mePartonData()); MatchboxAmplitude::prepareAmplitudes(me); } Complex MadGraphAmplitude::evaluate(size_t i, const vector<int>& hel, Complex& largeN) { //find the colourline: int ii = -1; int xx=lastMatchboxXComb()->externalId(); if (colourindex.size()<=i) { colourindex.clear(); for (size_t l=0;l<=i+10;l++){ colourindex.push_back(-2); } } if(colourindex[i]!=-2){ ii = colourindex[i]; if (ii==-1) { largeN = Complex(0.0); return Complex(0.0); } } else { set<vector<size_t> > a = colourOrdering(i); int ncol=-1; MG_NCol(&xx,&ncol); assert(ncol!=-1); for( int it = 0; it < ncol; it++ ){ int n = 0; for ( cPDVector::const_iterator nx = mePartonData().begin(); nx != mePartonData().end(); nx++ ) if ( (*nx)->coloured() ) n++; set<vector<size_t> > tmpset; vector<size_t> tmpvek; for ( int it2 = 0; it2 < n; it2++ ) { int ret=-2; MG_Colour(&xx,&it,&it2,&ret); assert(ret !=-2); if (ret== -1) break; if ( ret == 0 ) { n++; tmpset.insert(tmpvek); tmpvek.clear(); } else { tmpvek.push_back(ret-1); } if( it2 == n-1 ) tmpset.insert(tmpvek); } bool found_all = true; for ( set<vector<size_t> >::iterator it3 = a.begin(); it3 != a.end(); it3++ ) { bool found_it3=false; for ( set<vector<size_t> >::iterator it4 = tmpset.begin(); it4 != tmpset.end(); it4++ ) { vector<size_t> it3tmp = gluonsFirst(*it3); vector<size_t> it4tmp = (*it4); if ( it3tmp.size() != it4tmp.size() ) continue; if ( it3tmp == it4tmp ) found_it3 = true; } found_all = found_all && found_it3; } if ( found_all ) { colourindex[i]=it; ii=it; } } } if ( ii == -1 ){ colourindex[i]=ii; largeN = Complex(0.0); return Complex(0.0); } const map<vector<int>,vector < complex<double> > >& tmp = lastMatchboxXComb()->heljamp(); const map<vector<int>,vector < complex<double> > >& tmpLN = lastMatchboxXComb()->helLNjamp(); if( tmp.find(hel) != tmp.end()) { largeN = tmpLN.find(hel)->second[ii]; return tmp.find(hel)->second[ii];; } double units = pow(sqrt(lastSHat())/GeV,int(hel.size())-4); int heltmp[10]; for(size_t j=0;j<hel.size();j++){ int cross=crossingMap()[j]; if( (cross>1&&j<=1)||(cross<=1&&j>1)){ heltmp[cross]=-1*hel[j];} else{heltmp[cross]=hel[j];} } vector<Lorentz5Momentum> reshuffled = meMomenta(); if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) { const cPDVector& pdata = mePartonData(); const map<long,Energy>& masses = reshuffleMasses(); lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses); } double momenta[50]; size_t j=0; for (size_t i=0;i<mePartonData().size();i++){ momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV); momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV); momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV); momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV); if(momenta[j ] == 0. && momenta[j+1] == 0. && momenta[j+2] == 0. && momenta[j+3] == 0. ) return 0.; j+=4; } MG_Calculate_wavefunctions_born(&xx, &momenta[0], &heltmp[0]); int ncol=-1; MG_NCol(&xx,&ncol); Complex res; Complex resLN; for( int it = 0; it < ncol; it++ ){ double dd[2]; MG_Jamp(&xx,&it,&dd[0]); Complex d(dd[0],dd[1]); if(it==ii)res=d*units; lastMatchboxXComb()->pushheljamp(hel,d*units); double ddLN[2]; MG_LNJamp(&xx,&it,&ddLN[0]); Complex dLN(ddLN[0],ddLN[1]); if(it==ii)resLN=dLN*units; lastMatchboxXComb()->pushhelLNjamp(hel,dLN*units); } largeN = resLN; return res; } vector<unsigned int> MadGraphAmplitude::physicalHelicities(const vector<int>& hel) const { vector<unsigned int> res(hel.size(),0); for ( size_t j = 0; j < hel.size(); ++j ) { int cross = crossingMap()[j]; int xhel = 0; if ( (cross > 1 && j <= 1) || (cross <= 1 && j > 1) ) xhel = -1*hel[j]; else xhel = hel[j]; if ( mePartonData()[cross]->iSpin() == PDT::Spin1Half ) res[cross] = (xhel == -1 ? 0 : 1); else if ( mePartonData()[cross]->iSpin() == PDT::Spin1 ) res[cross] = (unsigned int)(xhel + 1); else if ( mePartonData()[cross]->iSpin() == PDT::Spin0 ) res[cross] = 0; else assert(false); } return res; } LorentzVector<Complex> MadGraphAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int i) const { int tmp=i; double pg[4],ng[4],poltmp[8]; pg[0]=p.e()/GeV;pg[1]=p.x()/GeV;pg[2]=p.y()/GeV;pg[3]=p.z()/GeV; ng[0]=n.e()/GeV;ng[1]=n.x()/GeV;ng[2]=n.y()/GeV;ng[3]=n.z()/GeV; MG_vxxxxx(&pg[0],&ng[0],&tmp,&poltmp[0]); complex<double> pol[6]; pol[0]=Complex(poltmp[0],poltmp[1]); pol[1]=Complex(poltmp[2],poltmp[3]); pol[2]=Complex(poltmp[4],poltmp[5]); pol[3]=Complex(poltmp[6],poltmp[7]); LorentzVector<Complex> polarization(pol[1],pol[2],pol[3],pol[0]); return polarization; } bool equalsModulo(unsigned int i, const vector<int>& a, const vector<int>& b) { assert(a.size()==b.size()); if ( a[i] == b[i] ) return false; for ( unsigned int k = 0; k < a.size(); ++k ) { if ( k == i ) continue; if ( a[k] != b[k] ) return false; } return true; } vector<size_t> MadGraphAmplitude::gluonsFirst(vector<size_t> vec) { vector<size_t> vecout; for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it) if ( mePartonData()[crossingMap()[*it]]->id()==21) vecout.push_back(crossingMap()[*it]); for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it) if ( mePartonData()[crossingMap()[*it]]->id()!=21) vecout.push_back(crossingMap()[*it]); return vecout; } double MadGraphAmplitude::spinColourCorrelatedME2(pair<int,int> ij, const SpinCorrelationTensor& c) const { vector<Lorentz5Momentum> reshuffled = meMomenta(); if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) { const cPDVector& pdata = mePartonData(); const map<long,Energy>& masses = reshuffleMasses(); lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses); } Lorentz5Momentum p = reshuffled[ij.first]; Lorentz5Momentum n = reshuffled[ij.second]; LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first<2?-1:1); int iCrossed = -1; for ( unsigned int k = 0; k < crossingMap().size(); ++k ) if ( crossingMap()[k] == ij.first ) { iCrossed = k; break; } assert(iCrossed!=-1); if(ij.first>1) polarization =polarization.conjugate(); if(iCrossed<2) polarization =polarization.conjugate(); Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale())); double avg = colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor)); Complex csCorr = 0.0; if ( calculateColourSpinCorrelator(ij) ) { set<const CVector*> done; for ( AmplitudeConstIterator a = lastAmplitudes().begin(); a != lastAmplitudes().end(); ++a ) { if ( done.find(&(a->second)) != done.end() ) continue; AmplitudeConstIterator b = lastAmplitudes().begin(); while ( !equalsModulo(iCrossed,a->first,b->first) ) if ( ++b == lastAmplitudes().end() ) break; if ( b == lastAmplitudes().end() || done.find(&(b->second)) != done.end() ) continue; done.insert(&(a->second)); done.insert(&(b->second)); if ( a->first[iCrossed] == 1 ) swap(a,b); csCorr -= colourBasis()->colourCorrelatedInterference(ij,mePartonData(),a->second,b->second); } lastColourSpinCorrelator(ij,csCorr); } else { csCorr = lastColourSpinCorrelator(ij); } double corr = 2.*real(csCorr*sqr(pFactor)); double Nc = generator()->standardModel()->Nc(); double cfac = 1.; if ( mePartonData()[ij.first]->iColour() == PDT::Colour8 ) { cfac = Nc; } else if ( mePartonData()[ij.first]->iColour() == PDT::Colour3 || mePartonData()[ij.first]->iColour() == PDT::Colour3bar ) { cfac = (sqr(Nc)-1.)/(2.*Nc); } else assert(false); return ( avg +(c.scale() > ZERO ? 1. : -1.)*corr/cfac); } void MadGraphAmplitude::prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr ){ assert(false); } double MadGraphAmplitude::oneLoopInterference() const { if ( !calculateOneLoopInterference() ) return lastOneLoopInterference(); evaloneLoopInterference(); return lastOneLoopInterference(); } void MadGraphAmplitude::evaloneLoopInterference() const { double units = pow(lastSHat()/GeV2,int(mePartonData().size())-4); vector<Lorentz5Momentum> reshuffled = meMomenta(); if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) { const cPDVector& pdata = mePartonData(); const map<long,Energy>& masses = reshuffleMasses(); lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses); } double virt[20]; double momenta[50]; size_t j=0; for (size_t i=0;i<mePartonData().size();i++){ momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV); momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV); momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV); momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV); j+=4; } int xx=lastMatchboxXComb()->externalId(); MG_Calculate_wavefunctions_virt(&xx,&momenta[0],&virt[0]); double ifact = 1.; ifact = 1./4.; if (lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3 || lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3bar ) ifact /= SM().Nc(); else if ( lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour8 ) ifact /= (SM().Nc()*SM().Nc()-1.); if ( lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3 || lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3bar ) ifact /= SM().Nc(); else if ( mePartonData()[1]->iColour() == PDT::Colour8 ) ifact /= (SM().Nc()*SM().Nc()-1.); ifact *= lastMatchboxXComb()->matchboxME()->finalStateSymmetry(); lastOneLoopInterference(virt[1]/ifact*units); lastOneLoopPoles(pair<double, double>(virt[2]/ifact*units,virt[3]/ifact*units)); } void MadGraphAmplitude::persistentOutput(PersistentOStream & os) const { os << theOrderInGs << theOrderInGem << BornAmplitudes << VirtAmplitudes << colourindex<<crossing << theProcessPath << theMGmodel << bindir_ << pkgdatadir_ << madgraphPrefix_; } void MadGraphAmplitude::persistentInput(PersistentIStream & is, int) { is >> theOrderInGs >> theOrderInGem >> BornAmplitudes >> VirtAmplitudes >> colourindex>>crossing >> theProcessPath >> theMGmodel >> bindir_ >> pkgdatadir_ >> madgraphPrefix_; } // *** 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<MadGraphAmplitude,MatchboxAmplitude> describeHerwigMadGraphAmplitude("Herwig::MadGraphAmplitude", "HwMatchboxMadGraph.so"); void MadGraphAmplitude::Init() { static ClassDocumentation<MadGraphAmplitude> documentation("MadGraphAmplitude", "Matrix elements have been calculated using MadGraph5 \\cite{Alwall:2011uj}", "%\\cite{Alwall:2011uj}\n" "\\bibitem{Alwall:2011uj}\n" "J. Alwall et al.,\n" "``MadGraph 5 : Going Beyond,''\n" "arXiv:1106.0522 [hep-ph].\n" "%%CITATION = ARXIV:1106.0522;%%"); static Parameter<MadGraphAmplitude,string> interfaceProcessPath ("ProcessPath", "The Process Path.", &MadGraphAmplitude::theProcessPath, "",false, false); static Parameter<MadGraphAmplitude,string> interfaceModel ("Model", "The MadGraph-Model.", &MadGraphAmplitude::theMGmodel, "loop_sm",false, false); static Switch<MadGraphAmplitude,bool> interfacekeepinputtopmass ("KeepInputTopMass", "Switch On/Off formopt", &MadGraphAmplitude::keepinputtopmass, false, false, false); static SwitchOption interfacekeepinputtopmassTrue (interfacekeepinputtopmass, "On", "On", true); static SwitchOption interfacekeepinputtopmassFalse (interfacekeepinputtopmass, "Off", "Off", false); static Parameter<MadGraphAmplitude,string> interfaceBinDir ("BinDir", "The location for the installed executable", &MadGraphAmplitude::bindir_, string(HERWIG_BINDIR), false, false); static Parameter<MadGraphAmplitude,string> interfacePKGDATADIR ("DataDir", "The location for the installed Herwig data files", &MadGraphAmplitude::pkgdatadir_, string(HERWIG_PKGDATADIR), false, false); static Parameter<MadGraphAmplitude,string> interfaceMadgraphPrefix ("MadgraphPrefix", "The prefix for the location of MadGraph", &MadGraphAmplitude::madgraphPrefix_, string(MADGRAPH_PREFIX), false, false); } diff --git a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in --- a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in +++ b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in @@ -1,382 +1,387 @@ #! /usr/bin/env python import os,sys,glob,errno,shutil,time,fnmatch #argparse from optparse import OptionParser # helper to replace all sourceText in fileName with replaceText def replacetext(fileName, sourceText, replaceText): file = open(fileName, "r") text = file.read() file.close() file = open(fileName, "w") file.write(text.replace(sourceText, replaceText)) file.close() # helper to build recursivly path def mkdir_p(path): try: os.makedirs(path) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise # helper to find all files of with name in path def find(name, path): for root, dirs, files in os.walk(path): if name in files: return os.path.join(root, name) # helper to find all file paths which contain file names matching filepattern def finddirs(filepattern, path): founddirs = [] for root, dirs, files in os.walk(path): if fnmatch.filter(files, filepattern): founddirs.append(root) return founddirs # fill the proc.dat file from BornAmplitudes.dat and VirtAmplitudes.dat. def fillprocs(model,oras,orew): bornlist=[] virtlist=[] fileproc=open("proc.dat","w") fileproc.write("set fortran_compiler @FC@ --no_save\n") fileproc.write("import model "+model+"\n") borns="BornAmplitudes.dat" virts="VirtAmplitudes.dat" first=True procnr=0 virtlines="" bornlines="" minlegs=100 legs=0 for i in [borns, virts]: file = open(i, "r") for line in file: if (len(line.split(" "))<minlegs): minlegs=len(line.split(" ")) for it in line.split(" "): if it.replace("-","").isdigit(): legs+=1 file.close() #conversion for heft model to go from (2QCD+1QED)->1HIG for each FS HIGGS. HIG=0 if (model=="heft"): HIG=(int(oras)+int(orew)-legs+2)/2 if (int(oras)+int(orew)-legs+2)%2!=0: print "Warning: No possible coupling power:(int(oras)+int(orew)-legs+2)%2!=0 " exit() return file = open(borns, "r") for line in file: #this assumes extra QCD emmissions addalphas=len(line.split(" "))-minlegs linetmp=line.rstrip() procnr+=1 bornlist+=[str(procnr)] if first: if HIG ==0 : bornlines+="generate "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n" else: bornlines+="generate "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n" first=False else: if HIG ==0 : bornlines+="add process "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n" else: bornlines+="add process "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n" file.close() first=True file = open(virts, "r") for line in file: addalphas=len(line.split(" "))-minlegs linetmp=line.rstrip()+" QCD="+str(int(oras)+addalphas)+" QED="+str(int(orew))+" [ virt=QCD ]" procnr+=1 virtlist+=[str(procnr)] if first: virtlines+="generate "+linetmp+" @"+str(procnr)+"\n" first=False else: virtlines+="add process "+linetmp+" @"+str(procnr)+"\n" file.close() fileproc.write(bornlines) if virtlines!="" and bornlines!="": fileproc.write("output matchbox MG5 --postpone_model\n") fileproc.write(virtlines) fileproc.write("output matchbox MG5 -f\n") fileproc.close() return bornlist,virtlist -def build_matchbox_tmp(pwd,buildpath): +def build_matchbox_tmp(pwd,buildpath,absolute_links): cwd=os.getcwd() os.chdir(pwd) mkdir_p(pwd+"/Herwig-scratch/MG_tmp/") if not buildpath.startswith("/"): buildpath=pwd+"/"+buildpath.lstrip("./") - resources=glob.glob(buildpath +"/MG5/SubProcesses/MadLoop5_resources/*") - resources+=glob.glob(buildpath +"/MG5/Cards/*") - resources+=glob.glob(buildpath +"/MG5/Cards/SubProcesses/*") + if not buildpath.endswith("/"): + buildpath=buildpath + "/" + resources=glob.glob(buildpath +"MG5/SubProcesses/MadLoop5_resources/*") + resources+=glob.glob(buildpath +"MG5/Cards/*") + resources+=glob.glob(buildpath +"MG5/Cards/SubProcesses/*") for i in resources: if not os.path.isfile( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)) \ and not os.path.islink( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)): - os.symlink(i, pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)) + if not absolute_links: + source=os.path.dirname(i) + dest=pwd+"/Herwig-scratch/MG_tmp/" + os.chdir(dest) + os.symlink(os.path.relpath(source,dest)+"/"+os.path.basename(i),"./" + os.path.basename(i)) + else: + os.symlink(i, pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)) os.chdir(cwd) - - - - - parser = OptionParser() parser.add_option("-a", "--buildpath", dest="buildpath",help="Do not use this script. Only for Herwig internal use. ") parser.add_option("-b", "--build", action="store_true", dest="build", default=True,help="Do not use this script. Only for Herwig internal use.") parser.add_option("-c", "--madgraph", dest="madgraph",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-d", "--runpath", dest="runpath",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-e", "--model", dest="model",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-f", "--orderas", dest="orderas",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-g", "--orderew", dest="orderew",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-i", "--datadir",dest="datadir",help="Do not use this script. Only for Herwig internal use.") parser.add_option("-I", "--includedir",dest="includedir",help="Do not use this script. Only for Herwig internal use.") +parser.add_option("-l", "--absolute-links",action="store_true", dest="absolute_links", default=False,\ + help="Do not use this script. Only for Herwig internal use.") (options, args) = parser.parse_args() #parser = argparse.ArgumentParser() #parser.add_argument('--buildpath', help='installpath') #parser.add_argument('--build', help='build', action="store_true") #parser.add_argument('--madgraph', help='madgraph_installpath') #parser.add_argument('--runpath', help='runpath') #parser.add_argument('--model', help='model') #parser.add_argument('--orderas', help='orderas') #parser.add_argument('--orderew', help='orderew') #parser.add_argument('--datadir', help='datadir') #args = parser.parse_args() pwd=os.getcwd() param_card="" mkdir_p(pwd+"/Herwig-scratch/MG_tmp/") if options.model=="loop_sm" or options.model=="heft": if options.model=="loop_sm": param_card="param_card.dat" else: param_card="param_card_"+options.model+".dat" file = open("%s/MadGraphInterface/%s.in" % (options.datadir,param_card) , "r") paramcard = file.read() file.close() file = open(options.runpath+"/"+param_card, "w") params=open(options.runpath+"/MG-Parameter.dat", "r") for line in params: a=line.split() paramcard=paramcard.replace(a[0],a[1]) params.close() file.write(paramcard) file.close() elif options.model.startswith("/"): os.system("python %s/write_param_card.py " % options.model) else: print "---------------------------------------------------------------" print "---------------------------------------------------------------" print "Warning: The model set for the MadGraph Interface " print " needs a parameter setting by hand." print " Please fill the param_card_"+options.model+".dat" print " with your favourite assumptions." print " And make sure Herwig uses the same parameters." print "---------------------------------------------------------------" print "---------------------------------------------------------------" if os.path.isfile(options.buildpath +"/MG5/Cards/param_card.dat") and not os.path.isfile(options.runpath+"/"+"param_card_"+options.model+".dat"): shutil.copyfile(options.buildpath +"/MG5/Cards/param_card.dat", options.runpath+"/"+"param_card_"+options.model+".dat") time.sleep(1) if not os.path.isdir(options.buildpath): print "The MadGraph Install path was not existend. It has been created for you." print "Just start Herwig read again.." mkdir_p(options.buildpath) exit() os.chdir(options.buildpath) if os.path.isfile("InterfaceMadGraph.so"): - build_matchbox_tmp(pwd,options.buildpath) + build_matchbox_tmp(pwd,options.buildpath,options.absolute_links) exit() Bornlist,Virtlist=fillprocs(options.model,options.orderas,options.orderew) if not options.madgraph and not os.path.isfile("InterfaceMadGraph.so"): print "*** warning *** MadGraph build failed, check logfile for details" exit() os.system("python "+options.madgraph+"/mg5_aMC proc.dat") routines=[["","BORN(momenta,hel)"], ["","SLOOPMATRIX(momenta,virt)"], ["","GET_JAMP(color,Jamp)"], ["","GET_LNJAMP(color,Jamp)"], ["","GET_NCOL(color)"], ["","GET_NCOLOR(i,j,color)"]] for routine in routines: for i in Bornlist + list(set(Virtlist) - set(Bornlist)): if routine[1]=="Virt(amp)" or routine[1]=="SLOOPMATRIX(momenta,virt)" and i not in Virtlist: continue if routine[0]=="": routine[0]+=" SELECT CASE (proc) \n" routine[0]+=" CASE("+i+") \n CALL " routine[0]+= "MG5_"+i+"_"+routine[1]+"\n" else: routine[0]+=" CASE("+i+") \n"\ " CALL " routine[0]+= "MG5_"+i+"_"+routine[1]+"\n" if routine[0]!="": routine[0]+=" CASE DEFAULT\n" routine[0]+=" WRITE(*,*) '##W02A WARNING No id found '\n" routine[0]+=" END SELECT \n" shutil.copyfile("%s/MadGraphInterface/InterfaceMadGraph.f.in" % options.datadir, "InterfaceMadGraph.f") replacetext("InterfaceMadGraph.f","MG_CalculateBORNtxt",routines[0][0]) replacetext("InterfaceMadGraph.f","MG_CalculateVIRTtxt",routines[1][0]) replacetext("InterfaceMadGraph.f","MG_Jamptxt", routines[2][0]) replacetext("InterfaceMadGraph.f","MG_LNJamptxt", routines[3][0]) replacetext("InterfaceMadGraph.f","MG_NColtxt", routines[4][0]) replacetext("InterfaceMadGraph.f","MG_ColourMattxt",routines[5][0]) MG_vxxxxxtxt="" if routines[1][0]!="": MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC) $ bind(c, name='MG_vxxxxx') IMPLICIT NONE double precision p(0:3) double precision n(0:3) INTEGER inc double precision VC(0:7) double complex VCtmp(8) call vxxxxx(p, 0d0,1,inc ,VCtmp) VC(0)= real(VCtmp(5)) VC(1)=aimag(VCtmp(5)) VC(2)= real(VCtmp(6)) VC(3)=aimag(VCtmp(6)) VC(4)= real(VCtmp(7)) VC(5)=aimag(VCtmp(7)) VC(6)= real(VCtmp(8)) VC(7)=aimag(VCtmp(8)) END""" else: MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC) $ bind(c, name='MG_vxxxxx') IMPLICIT NONE double precision p(0:3) double precision n(0:3) INTEGER inc double precision VC(0:7) double complex VCtmp(6) call vxxxxx(p, 0d0,1,inc ,VCtmp) VC(0)= real(VCtmp(3)) VC(1)=aimag(VCtmp(3)) VC(2)= real(VCtmp(4)) VC(3)=aimag(VCtmp(4)) VC(4)= real(VCtmp(5)) VC(5)=aimag(VCtmp(5)) VC(6)= real(VCtmp(6)) VC(7)=aimag(VCtmp(6)) END""" replacetext("InterfaceMadGraph.f","MG_vxxxxxtxt",MG_vxxxxxtxt) make=" " fortanfiles=glob.glob('*/*/*.f')+glob.glob('*/*/*/*.f') for i in fortanfiles: if "check_sa" not in i: if not os.path.islink(i): make += " "+i+"\\\n " incfiles=glob.glob('*/*/*.inc')+glob.glob('*/*/*/*.inc') coefdir="" for i in incfiles: if "nexternal.inc" in i: coefdir+=" -I"+i.replace("nexternal.inc"," ") file=open("makefile","w") file.write("include MG5/Source/make_opts ") if Virtlist!=[]: file.write("\nLIBDIR = MG5/lib\nLINKLIBS = -L$(LIBDIR) -lcts -liregi -L$(LIBDIR)/golem95_lib -lgolem") file.write("\nLIBS = $(LIBDIR)libcts.$(libext) $(LIBDIR)libgolem.$(libext) $(LIBDIR)libiregi.$(libext)") file.write("\nPROCESS= InterfaceMadGraph.f "+make+"\n\nall: \n\t @FC@ @FFLAGS@ -w -fbounds-check -ffixed-line-length-132 -fPIC -fno-f2c -shared -s -o InterfaceMadGraph.so -IMG5/SubProcesses/" ) if Virtlist!=[]: file.write(" -IMG5/lib/golem95_include ") # Find all .mod files also in /usr/include if golem was build there. # There can be an error message in the MadGraph output to add the golem include path to the makefiles. # Usually MadGraph finds the path if its Golem was build in an separate dictionary. # Our bootstrap script installs golem with gosam beside boost. Here MadGraph creates a link (->errormessage). # If we can find the modfiles easily the user doesn't need to change the makefiles. moddirs=finddirs('*.mod',options.includedir) for moddir in moddirs: file.write(" -I%s " % moddir) if os.path.isdir("/usr/include"): moddirs=finddirs('*.mod',"/usr/include") for moddir in moddirs: file.write(" -I%s " % moddir) if coefdir != "": file.write(coefdir) file.write(" $(PROCESS) $(LINKLIBS) ") file.close() os.chdir(pwd) os.chdir(options.buildpath) replacetext("MG5/Source/MODEL/lha_read.f", "ident_card.dat","Herwig-scratch/MG_tmp/ident_card.dat") replacetext("MG5/Source/MODEL/lha_read.f", "param.log","Herwig-scratch/MG_tmp/param.log") if Virtlist!=[]: replacetext("MG5/SubProcesses/MadLoopCommons.f", "PREFIX='./'","PREFIX='./Herwig-scratch/MG_tmp/'") os.system("make") -build_matchbox_tmp(pwd,options.buildpath) +build_matchbox_tmp(pwd,options.buildpath,options.absolute_links) diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc --- a/MatrixElement/Matchbox/MatchboxFactory.cc +++ b/MatrixElement/Matchbox/MatchboxFactory.cc @@ -1,2109 +1,2109 @@ // -*- C++ -*- // // MatchboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 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 MatchboxFactory class. // #include "MatchboxFactory.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/SamplerBase.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" #include "Herwig/Utilities/RunDirectories.h" #include <boost/progress.hpp> #include <boost/filesystem.hpp> #include <iterator> using std::ostream_iterator; using namespace Herwig; using std::ostream_iterator; MatchboxFactory::MatchboxFactory() : SubProcessHandler(), theNLight(0), theOrderInAlphaS(0), theOrderInAlphaEW(0), theBornContributions(true), theVirtualContributions(true), theRealContributions(true), theIndependentVirtuals(false), theIndependentPKs(false), theSubProcessGroups(false), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theFixedCouplings(false), theFixedQEDCouplings(false), theVetoScales(false), theDipoleSet(0), theVerbose(false), theDiagramWeightVerbose(false), theDiagramWeightVerboseNBins(200), theInitVerbose(false), theSubtractionData(""), theSubtractionPlotType(1), theSubtractionScatterPlot(false), thePoleData(""), theRealEmissionScales(false), theAllProcesses(false), theMECorrectionsOnly(false), theLoopSimCorrections(false), ranSetup(false), theFirstPerturbativePDF(true), theSecondPerturbativePDF(true), inProductionMode(false), theSpinCorrelations(false),theAlphaParameter(1.), - theEnforceChargeConservation(true), theEnforceColourConservation(true), - theEnforceLeptonNumberConservation(true), theEnforceQuarkNumberConservation(true), - theLeptonFlavourDiagonal(true), theQuarkFlavourDiagonal(true) {} + theEnforceChargeConservation(true), theEnforceColourConservation(false), + theEnforceLeptonNumberConservation(false), theEnforceQuarkNumberConservation(false), + theLeptonFlavourDiagonal(false), theQuarkFlavourDiagonal(false) {} MatchboxFactory::~MatchboxFactory() {} bool& MatchboxFactory::theIsMatchboxRun() { static bool flag = false; return flag; } IBPtr MatchboxFactory::clone() const { return new_ptr(*this); } IBPtr MatchboxFactory::fullclone() const { return new_ptr(*this); } void MatchboxFactory::prepareME(Ptr<MatchboxMEBase>::ptr me) { Ptr<MatchboxAmplitude>::ptr amp = dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>((*me).amplitude()); me->matchboxAmplitude(amp); me->factory(this); if ( phasespace() && !me->phasespace() ) me->phasespace(phasespace()); if ( scaleChoice() && !me->scaleChoice() ) me->scaleChoice(scaleChoice()); if ( !reweighters().empty() ) { for ( vector<ReweightPtr>::const_iterator rw = reweighters().begin(); rw != reweighters().end(); ++rw ) me->addReweighter(*rw); } if ( !preweighters().empty() ) { for ( vector<ReweightPtr>::const_iterator rw = preweighters().begin(); rw != preweighters().end(); ++rw ) me->addPreweighter(*rw); } } string pid(const PDVector& key) { ostringstream res; res << "[" << key[0]->PDGName() << "," << key[1]->PDGName() << "->"; for ( PDVector::const_iterator k = key.begin() + 2; k != key.end(); ++k ) res << (**k).PDGName() << (k != --key.end() ? "," : ""); res << "]"; return res.str(); } vector<Ptr<MatchboxMEBase>::ptr> MatchboxFactory:: makeMEs(const vector<string>& proc, unsigned int orderas, bool virt) { generator()->log() << "determining subprocesses for "; copy(proc.begin(),proc.end(),ostream_iterator<string>(generator()->log()," ")); generator()->log() << "\n" << flush; map<Ptr<MatchboxAmplitude>::ptr,set<Process> > ampProcs; map<Process,set<Ptr<MatchboxAmplitude>::ptr> > procAmps; set<PDVector> processes = makeSubProcesses(proc); // TODO Fix me for 3.0.x // At the moment we got troubles with processes with no coloured // legs so they will not be supported set<PDVector> colouredProcesses; for ( set<PDVector>::const_iterator pr = processes.begin(); pr != processes.end(); ++pr ) { for ( PDVector::const_iterator pp = pr->begin(); pp != pr->end(); ++pp ) { if ( (**pp).coloured() ) { colouredProcesses.insert(*pr); break; } } } if ( colouredProcesses.size() != processes.size() ) { generator()->log() << "Some or all of the generated subprocesses do not contain coloured legs.\n" << "Processes of this kind are currently not supported.\n" << flush; } if ( colouredProcesses.empty() ) { throw Exception() << "MatchboxFactory::makeMEs(): No processes with coloured legs have been found. " << "This run will be aborted." << Exception::runerror; } processes = colouredProcesses; // end unsupported processes // detect external particles with non-zero width for the hard process bool trouble = false; string troubleMaker; for ( set<PDVector>::const_iterator pr = processes.begin(); pr != processes.end(); ++pr ) { for ( PDVector::const_iterator pp = pr->begin(); pp != pr->end(); ++pp ) { if ( (**pp).hardProcessWidth() != ZERO ) { trouble = true; troubleMaker = (**pp).PDGName(); break; } } } if ( trouble ) { throw Exception() << "MatchboxFactory::makeMEs(): Particle '" << troubleMaker << "' appears as external\nprocess leg with non-zero " << "width to be used in the hard process calculation.\n" << "Please check your setup and consider setting HardProcessWidth to zero." << Exception::runerror; } vector<Ptr<MatchboxAmplitude>::ptr> matchAmplitudes; unsigned int lowestAsOrder = allProcesses() ? 0 : orderas; unsigned int highestAsOrder = orderas; unsigned int lowestAeOrder = allProcesses() ? 0 : orderInAlphaEW(); unsigned int highestAeOrder = orderInAlphaEW(); for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) { for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) { for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { if ( !theSelectedAmplitudes.empty() ) { if ( find(theSelectedAmplitudes.begin(),theSelectedAmplitudes.end(),*amp) == theSelectedAmplitudes.end() ) continue; } if ( !theDeselectedAmplitudes.empty() ) { if ( find(theDeselectedAmplitudes.begin(),theDeselectedAmplitudes.end(),*amp) != theDeselectedAmplitudes.end() ) continue; } (**amp).orderInGs(oas); (**amp).orderInGem(oae); if ( (**amp).orderInGs() != oas || (**amp).orderInGem() != oae ) { continue; } matchAmplitudes.push_back(*amp); } } } size_t combinations = processes.size()*matchAmplitudes.size(); size_t procCount = 0; generator()->log() << "building matrix elements." << flush; boost::progress_display * progressBar = new boost::progress_display(combinations,generator()->log()); for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) { for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) { for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp = matchAmplitudes.begin(); amp != matchAmplitudes.end(); ++amp ) { (**amp).orderInGs(oas); (**amp).orderInGem(oae); for ( set<PDVector>::const_iterator p = processes.begin(); p != processes.end(); ++p ) { ++(*progressBar); if ( !(**amp).canHandle(*p,this,virt) ) continue; if ( (**amp).isExternal() ) externalAmplitudes().insert(*amp); ++procCount; Process proc(*p,oas,oae); ampProcs[*amp].insert(proc); procAmps[proc].insert(*amp); } } } } delete progressBar; generator()->log() << flush; bool clash = false; for ( map<Process,set<Ptr<MatchboxAmplitude>::ptr> >::const_iterator check = procAmps.begin(); check != procAmps.end(); ++check ) { if ( check->second.size() > 1 ) { clash = true; generator()->log() << "Several different amplitudes have been found for: " << check->first.legs[0]->PDGName() << " " << check->first.legs[1]->PDGName() << " -> "; for ( PDVector::const_iterator p = check->first.legs.begin() + 2; p != check->first.legs.end(); ++p ) generator()->log() << (**p).PDGName() << " "; generator()->log() << "at alpha_s^" << check->first.orderInAlphaS << " and alpha_ew^" << check->first.orderInAlphaEW << "\n"; generator()->log() << "The following amplitudes claim responsibility:\n"; for ( set<Ptr<MatchboxAmplitude>::ptr>::const_iterator a = check->second.begin(); a != check->second.end(); ++a ) { generator()->log() << (**a).name() << " "; } generator()->log() << "\n"; } } if ( clash ) { throw Exception() << "MatchboxFactory: Ambiguous amplitude setup - please check your input files.\n" << "To avoid this problem use the SelectAmplitudes or DeselectAmplitudes interfaces.\n" << Exception::runerror; } bool canDoSpinCorrelations = true; vector<Ptr<MatchboxMEBase>::ptr> res; for ( map<Ptr<MatchboxAmplitude>::ptr,set<Process> >::const_iterator ap = ampProcs.begin(); ap != ampProcs.end(); ++ap ) { canDoSpinCorrelations &= ap->first->canFillRhoMatrix(); for ( set<Process>::const_iterator m = ap->second.begin(); m != ap->second.end(); ++m ) { Ptr<MatchboxMEBase>::ptr me = ap->first->makeME(m->legs); me->subProcess() = *m; me->amplitude(ap->first); me->matchboxAmplitude(ap->first); prepareME(me); string pname = "ME" + ap->first->name() + pid(m->legs); if ( ! (generator()->preinitRegister(me,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( me->diagrams().empty() )continue; res.push_back(me); if ( theFirstPerturbativePDF ) theIncoming.insert(m->legs[0]->id()); if ( theSecondPerturbativePDF ) theIncoming.insert(m->legs[1]->id()); } } if ( spinCorrelations() && !canDoSpinCorrelations ) { generator()->log() << "Warning: Spin correlations have been requested, but no amplitude is " << "capable of performing these.\n"; theSpinCorrelations = false; } generator()->log() << "created " << procCount << " subprocesses.\n"; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; return res; } int MatchboxFactory::orderOLPProcess(const Process& proc, Ptr<MatchboxAmplitude>::tptr amp, int type) { map<pair<Process,int>,int>& procs = olpProcesses()[amp]; map<pair<Process,int>,int>::const_iterator it = procs.find(make_pair(proc,type)); if ( it != procs.end() ) return it->second; int id = procs.size(); procs[make_pair(proc,type)] = id + 1; return id + 1; } void MatchboxFactory::productionMode() { if ( inProductionMode ) return; if ( !bornContributions() && !virtualContributions() && !realContributions() ) throw Exception() << "MatchboxFactory: At least one cross section contribution needs to be enabled.\n" << "Please check your setup.\n" << Exception::runerror; bool needTrueVirtuals = virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections(); for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { if ( !needTrueVirtuals && (**amp).oneLoopAmplitude() ) { Repository::clog() << "One-loop contributions from '" << (**amp).name() << "' are not required and will be disabled.\n" << flush; (**amp).disableOneLoop(); } } if ( subtractionData() != "" && !subProcessGroups() ) { throw Exception() << "MatchboxFactory: Plain NLO settings are required for subtraction checks.\n" << "Please check your setup.\n" << Exception::runerror; } if ( showerApproximation() && !virtualContributions() && !realContributions() ) { Repository::clog() << "Warning: Matching requested for LO run. Matching disabled.\n" << flush; showerApproximation(Ptr<ShowerApproximation>::tptr()); } if ( showerApproximation() && (subtractionData() != "" || subProcessGroups()) ) { Repository::clog() << "Warning: Matching requested for plain NLO run. Matching disabled.\n" << flush; showerApproximation(Ptr<ShowerApproximation>::tptr()); } if ( showerApproximation() ) { if ( spinCorrelations() && !showerApproximation()->hasSpinCorrelations() ) { Repository::clog() << "Warning: Spin correlations have been requested but the matching " << "object is not capable of these. Spin correlations will be turned of.\n" << flush; theSpinCorrelations = false; } } inProductionMode = true; } void MatchboxFactory::setup() { useMe(); if ( !ranSetup ) { if ( !inProductionMode ) throw Exception() << "MatchboxFactory: The MatchboxFactory object '" << name() << "' has not been switched to production mode.\n" << "Did you use 'do " << name() << ":ProductionMode' before isolating the event generator?\n" << Exception::runerror; olpProcesses().clear(); externalAmplitudes().clear(); theHighestVirtualsize = 0; theIncoming.clear(); bool needTrueVirtuals = virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections(); for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) (**amp).factory(this); if ( bornMEs().empty() ) { if ( particleGroups().find("j") == particleGroups().end() ) throw Exception() << "MatchboxFactory: Could not find a jet particle group named 'j'" << Exception::runerror; // rebind the particle data objects for ( map<string,PDVector>::iterator g = particleGroups().begin(); g != particleGroups().end(); ++g ) for ( PDVector::iterator p = g->second.begin(); p != g->second.end(); ++p ) { #ifndef NDEBUG long checkid = (**p).id(); #endif *p = getParticleData((**p).id()); assert((**p).id() == checkid); } const PDVector& partons = particleGroups()["j"]; unsigned int nl = 0; for ( PDVector::const_iterator p = partons.begin(); p != partons.end(); ++p ) { if ( abs((**p).id()) < 7 && (**p).hardProcessMass() == ZERO ) ++nl; if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() == ZERO ) nLightJetVec( (**p).id() ); if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() != ZERO ) nHeavyJetVec( (**p).id() ); } nLight(nl/2); if ( particleGroups().find("p") == particleGroups().end() ) throw Exception() << "MatchboxFactory: Could not find a hadron particle group named 'p'" << Exception::runerror; const PDVector& partonsInP = particleGroups()["p"]; for ( PDVector::const_iterator pip = partonsInP.begin(); pip != partonsInP.end(); ++pip ) { if ( (**pip).id() > 0 && (**pip).id() < 7 && (**pip).hardProcessMass() == ZERO ) nLightProtonVec( (**pip).id() ); } vector<Ptr<MatchboxMEBase>::ptr> mes; for ( vector<vector<string> >::const_iterator p = processes.begin(); p != processes.end(); ++p ) { if( needTrueVirtuals ) { theHighestVirtualsize = max(theHighestVirtualsize,(int((*p).size()))); } mes = makeMEs(*p,orderInAlphaS(),needTrueVirtuals); copy(mes.begin(),mes.end(),back_inserter(bornMEs())); if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { if ( realEmissionProcesses.empty() ) { vector<string> rproc = *p; rproc.push_back("j"); mes = makeMEs(rproc,orderInAlphaS()+1,false); copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs())); } } } if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { if ( !realEmissionProcesses.empty() ) { for ( vector<vector<string> >::const_iterator q = realEmissionProcesses.begin(); q != realEmissionProcesses.end(); ++q ) { mes = makeMEs(*q,orderInAlphaS()+1,false); copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs())); } } } } if ( loopInducedMEs().empty() ) { for ( vector<vector<string> >::const_iterator p = loopInducedProcesses.begin(); p != loopInducedProcesses.end(); ++p ) { vector<Ptr<MatchboxMEBase>::ptr> mes = makeMEs(*p,orderInAlphaS(),false); copy(mes.begin(),mes.end(),back_inserter(loopInducedMEs())); } } if( bornMEs().empty() && realEmissionMEs().empty() && loopInducedMEs().empty() ) throw Exception() << "MatchboxFactory: No matrix elements have been found.\n\ Please check if your order of Alpha_s and Alpha_ew have the right value.\n" << Exception::runerror; // check if we have virtual contributions bool haveVirtuals = true; // check DR conventions of virtual contributions bool virtualsAreDR = false; bool virtualsAreCDR = false; // check finite term conventions of virtual contributions bool virtualsAreCS = false; bool virtualsAreBDK = false; bool virtualsAreExpanded = false; // renormalization scheme bool virtualsAreDRbar = false; // check and prepare the Born and virtual matrix elements for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { prepareME(*born); haveVirtuals &= (**born).haveOneLoop(); if ( needTrueVirtuals ) { if ( (**born).haveOneLoop() ) { virtualsAreDRbar |= (**born).isDRbar(); virtualsAreDR |= (**born).isDR(); virtualsAreCDR |= !(**born).isDR(); virtualsAreCS |= (**born).isCS(); virtualsAreBDK |= (**born).isBDK(); virtualsAreExpanded |= (**born).isExpanded(); } } } // prepare the loop induced matrix elements for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped = loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) { prepareME(*looped); } if ( needTrueVirtuals ) { // check the additional insertion operators if ( !virtuals().empty() ) haveVirtuals = true; for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = virtuals().begin(); virt != virtuals().end(); ++virt ) { virtualsAreDRbar |= (**virt).isDRbar(); virtualsAreDR |= (**virt).isDR(); virtualsAreCDR |= !(**virt).isDR(); virtualsAreCS |= (**virt).isCS(); virtualsAreBDK |= (**virt).isBDK(); virtualsAreExpanded |= (**virt).isExpanded(); } // check for consistent conventions on virtuals, if we are to include them if ( virtualContributions() ) { if ( !haveVirtuals ) { throw Exception() << "MatchboxFactory: Could not find amplitudes for all virtual contributions needed.\n" << Exception::runerror; } if ( virtualsAreDR && virtualsAreCDR ) { throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent regularization schemes.\n" << Exception::runerror; } if ( (virtualsAreCS && virtualsAreBDK) || (virtualsAreCS && virtualsAreExpanded) || (virtualsAreBDK && virtualsAreExpanded) || (!virtualsAreCS && !virtualsAreBDK && !virtualsAreExpanded) ) { throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent conventions on finite terms.\n" << Exception::runerror; } } // prepare dipole insertion operators if ( virtualContributions() ) { for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = DipoleRepository::insertionIOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) { (**virt).factory(this); if ( virtualsAreDRbar ) (**virt).useDRbar(); if ( virtualsAreDR ) (**virt).useDR(); else (**virt).useCDR(); if ( virtualsAreCS ) (**virt).useCS(); if ( virtualsAreBDK ) (**virt).useBDK(); if ( virtualsAreExpanded ) (**virt).useExpanded(); } for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { (**virt).factory(this); if ( virtualsAreDRbar ) (**virt).useDRbar(); if ( virtualsAreDR ) (**virt).useDR(); else (**virt).useCDR(); if ( virtualsAreCS ) (**virt).useCS(); if ( virtualsAreBDK ) (**virt).useBDK(); if ( virtualsAreExpanded ) (**virt).useExpanded(); } } } // prepare the real emission matrix elements if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real = realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) { prepareME(*real); } } // start creating matrix elements MEs().clear(); // setup born and virtual contributions if ( bornContributions() || virtualContributions() ) { generator()->log() << "preparing Born" << (virtualContributions() ? " and virtual" : "") << " matrix elements.\n" << flush; } if ( (bornContributions() && !virtualContributions()) || (bornContributions() && meCorrectionsOnly()) || (bornContributions() && virtualContributions() && independentVirtuals()) ) { for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { if ( (**born).onlyOneLoop() ) continue; Ptr<MatchboxMEBase>::ptr bornme = (**born).cloneMe(); string pname = fullName() + "/" + (**born).name(); if ( virtualContributions() && independentVirtuals() ) pname += ".Born"; if ( ! (generator()->preinitRegister(bornme,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( bornme->isOLPTree() ) { int id = orderOLPProcess(bornme->subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); bornme->olpProcess(ProcessType::treeME2,id); } bornme->needsNoCorrelations(); bornme->cloneDependencies(); MEs().push_back(bornme); } } if ( bornContributions() && !loopInducedMEs().empty() ) { for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped = loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) { Ptr<MatchboxMEBase>::ptr loopme = (**looped).cloneMe(); string pname = fullName() + "/" + (**looped).name() + ".LoopInduced"; if ( ! (generator()->preinitRegister(loopme,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( loopme->isOLPTree() ) { int id = orderOLPProcess(loopme->subProcess(), (**looped).matchboxAmplitude(), ProcessType::loopInducedME2); loopme->olpProcess(ProcessType::loopInducedME2,id); } loopme->needsNoCorrelations(); loopme->cloneDependencies(); MEs().push_back(loopme); } } if ( needTrueVirtuals ) { bornVirtualMEs().clear(); boost::progress_display * progressBar = new boost::progress_display(bornMEs().size(),generator()->log()); if ( thePoleData != "" ) if ( thePoleData[thePoleData.size()-1] != '/' ) thePoleData += "/"; for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { Ptr<MatchboxMEBase>::ptr nlo = (**born).cloneMe(); string pname = fullName() + "/" + (**born).name(); if ( !independentVirtuals() && !(!bornContributions() && virtualContributions()) ) pname += ".BornVirtual"; else if ( independentPKs() && !nlo->onlyOneLoop() ) pname += ".VirtualVI"; else pname += ".Virtual"; if ( ! (generator()->preinitRegister(nlo,pname) ) ) throw Exception() << "MatchboxFactory: NLO ME " << pname << " already existing." << Exception::runerror; nlo->virtuals().clear(); if ( !nlo->onlyOneLoop() ) { for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = virtuals().begin(); virt != virtuals().end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = DipoleRepository::insertionIOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } if ( !independentVirtuals() || ( independentVirtuals() && !independentPKs() ) ) { for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } } if ( nlo->virtuals().empty() ) throw Exception() << "MatchboxFactory: No insertion operators have been found for " << (**born).name() << "\n" << Exception::runerror; if ( checkPoles() ) { if ( !virtualsAreExpanded ) { throw Exception() << "MatchboxFactory: Cannot check epsilon poles if virtuals are not in `expanded' convention.\n" << Exception::runerror; } } } if ( !bornContributions() || independentVirtuals() ) { nlo->doOneLoopNoBorn(); } else { nlo->doOneLoop(); } if ( nlo->isOLPLoop() ) { int id = orderOLPProcess(nlo->subProcess(), (**born).matchboxAmplitude(), ProcessType::oneLoopInterference); nlo->olpProcess(ProcessType::oneLoopInterference,id); if ( !nlo->onlyOneLoop() && nlo->needsOLPCorrelators() ) { id = orderOLPProcess(nlo->subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); nlo->olpProcess(ProcessType::colourCorrelatedME2,id); } } nlo->needsCorrelations(); nlo->cloneDependencies(); bornVirtualMEs().push_back(nlo); MEs().push_back(nlo); if ( independentVirtuals() && independentPKs() && !nlo->onlyOneLoop() ) { Ptr<MatchboxMEBase>::ptr nlopk = (**born).cloneMe(); string pnamepk = fullName() + "/" + (**born).name(); pnamepk += ".VirtualPK"; if ( ! (generator()->preinitRegister(nlopk,pnamepk) ) ) throw Exception() << "MatchboxFactory: NLO ME " << pnamepk << " already existing." << Exception::runerror; nlopk->virtuals().clear(); for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlopk->virtuals().push_back(*virt); } if ( !nlopk->virtuals().empty() ) { nlopk->doOneLoopNoBorn(); nlopk->doOneLoopNoLoops(); if ( nlopk->isOLPLoop() ) { int id = orderOLPProcess(nlopk->subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); nlopk->olpProcess(ProcessType::treeME2,id); if ( nlopk->needsOLPCorrelators() ) { id = orderOLPProcess(nlopk->subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); nlopk->olpProcess(ProcessType::colourCorrelatedME2,id); } } nlopk->needsCorrelations(); nlopk->cloneDependencies(); bornVirtualMEs().push_back(nlopk); MEs().push_back(nlopk); } } ++(*progressBar); } delete progressBar; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } theSplittingDipoles.clear(); set<cPDVector> bornProcs; if ( showerApproximation() ) { if ( showerApproximation()->needsSplittingGenerator() ) { for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) for ( MEBase::DiagramVector::const_iterator d = (**born).diagrams().begin(); d != (**born).diagrams().end(); ++d ) bornProcs.insert((**d).partons()); } } if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { generator()->log() << "preparing subtracted matrix elements.\n" << flush; if ( theSubtractionData != "" ) if ( theSubtractionData[theSubtractionData.size()-1] != '/' ) theSubtractionData += "/"; subtractedMEs().clear(); for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { if ( (**born).onlyOneLoop() ) continue; (**born).needsCorrelations(); if ( (**born).isOLPTree() ) { int id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); (**born).olpProcess(ProcessType::colourCorrelatedME2,id); bool haveGluon = false; for ( PDVector::const_iterator p = (**born).subProcess().legs.begin(); p != (**born).subProcess().legs.end(); ++p ) if ( (**p).id() == 21 ) { haveGluon = true; break; } if ( haveGluon ) { id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::spinColourCorrelatedME2); (**born).olpProcess(ProcessType::spinColourCorrelatedME2,id); } if ( showerApproximation() ) { id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); (**born).olpProcess(ProcessType::treeME2,id); } } } boost::progress_display * progressBar = new boost::progress_display(realEmissionMEs().size(),generator()->log()); for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real = realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) { Ptr<SubtractedME>::ptr sub = new_ptr(SubtractedME()); string pname = fullName() + "/" + (**real).name() + ".SubtractedReal"; if ( ! (generator()->preinitRegister(sub,pname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << pname << " already existing." << Exception::runerror; sub->factory(this); (**real).needsNoCorrelations(); if ( (**real).isOLPTree() ) { int id = orderOLPProcess((**real).subProcess(), (**real).matchboxAmplitude(), ProcessType::treeME2); (**real).olpProcess(ProcessType::treeME2,id); } sub->head(*real); sub->dependent().clear(); sub->getDipoles(); if ( sub->dependent().empty() ) { // finite real contribution if ( realContributions() ) { Ptr<MatchboxMEBase>::ptr fme = dynamic_ptr_cast<Ptr<MatchboxMEBase>::ptr>(sub->head())->cloneMe(); string qname = fullName() + "/" + (**real).name() + ".FiniteReal"; if ( ! (generator()->preinitRegister(fme,qname) ) ) throw Exception() << "MatchboxFactory: ME " << qname << " already existing." << Exception::runerror; MEs().push_back(fme); finiteRealMEs().push_back(fme); } sub->head(tMEPtr()); ++(*progressBar); continue; } if ( realEmissionScales() ) sub->doRealEmissionScales(); subtractedMEs().push_back(sub); if ( realContributions() ) if ( !showerApproximation() || (showerApproximation() && showerApproximation()->hasHEvents()) ) MEs().push_back(sub); if ( showerApproximation() ) { if ( virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections() ) { Ptr<SubtractedME>::ptr subv = new_ptr(*sub); string vname = sub->fullName() + ".SubtractionIntegral"; if ( ! (generator()->preinitRegister(subv,vname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing." << Exception::runerror; subv->cloneDependencies(vname); subv->doVirtualShowerSubtraction(); subtractedMEs().push_back(subv); MEs().push_back(subv); } if ( loopSimCorrections() ) { Ptr<SubtractedME>::ptr subv = new_ptr(*sub); string vname = sub->fullName() + ".SubtractionIntegral"; if ( ! (generator()->preinitRegister(subv,vname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing." << Exception::runerror; subv->cloneDependencies(vname); subv->doLoopSimSubtraction(); subtractedMEs().push_back(subv); MEs().push_back(subv); } sub->doRealShowerSubtraction(); if ( showerApproximation()->needsSplittingGenerator() ) for ( set<cPDVector>::const_iterator p = bornProcs.begin(); p != bornProcs.end(); ++p ) { vector<Ptr<SubtractionDipole>::ptr> sdip = sub->splitDipoles(*p); set<Ptr<SubtractionDipole>::ptr>& dips = theSplittingDipoles[*p]; copy(sdip.begin(),sdip.end(),inserter(dips,dips.begin())); } } ++(*progressBar); } delete progressBar; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } if ( !theSplittingDipoles.empty() ) { map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr> cloneMap; for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator d = sd->second.begin(); d != sd->second.end(); ++d ) { cloneMap[*d] = Ptr<SubtractionDipole>::ptr(); } } for ( map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr>::iterator cd = cloneMap.begin(); cd != cloneMap.end(); ++cd ) { Ptr<SubtractionDipole>::ptr cloned = cd->first->cloneMe(); string dname = cd->first->fullName() + ".splitting"; if ( ! (generator()->preinitRegister(cloned,dname)) ) throw Exception() << "MatchboxFactory: Dipole '" << dname << "' already existing." << Exception::runerror; cloned->cloneDependencies(); cloned->showerApproximation(Ptr<ShowerApproximation>::tptr()); cloned->doSplitting(); cd->second = cloned; } for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { set<Ptr<SubtractionDipole>::ptr> cloned; for ( set<Ptr<SubtractionDipole>::ptr>::iterator d = sd->second.begin(); d != sd->second.end(); ++d ) { cloned.insert(cloneMap[*d]); } sd->second = cloned; } } if ( !externalAmplitudes().empty() ) { generator()->log() << "Initializing external amplitudes.\n" << flush; for ( set<Ptr<MatchboxAmplitude>::tptr>::const_iterator ext = externalAmplitudes().begin(); ext != externalAmplitudes().end(); ++ext ) { if ( !(**ext).initializeExternal() ) { throw Exception() << "Failed to initialize amplitude '" << (**ext).name() << "'\n" << Exception::runerror; } } generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } if ( !olpProcesses().empty() ) { generator()->log() << "Initializing one-loop provider(s).\n" << flush; map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> > olps; for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator oit = olpProcesses().begin(); oit != olpProcesses().end(); ++oit ) { olps[oit->first] = oit->second; } for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator olpit = olps.begin(); olpit != olps.end(); ++olpit ) { if ( !olpit->first->startOLP(olpit->second) ) { throw Exception() << "MatchboxFactory: Failed to start OLP for amplitude '" << olpit->first->name() << "'\n" << Exception::runerror; } } generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } generator()->log() << "Process setup finished.\n" << flush; ranSetup = true; } } void MatchboxFactory::SplittingChannel::print(ostream& os) const { os << "--- SplittingChannel setup -----------------------------------------------------\n"; os << " Born process "; const StandardXComb& bxc = *bornXComb; os << bxc.mePartonData()[0]->PDGName() << " " << bxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2; p != bxc.mePartonData().end(); ++p ) { os << (**p).PDGName() << " "; } os << "\n"; os << " to real emission process "; const StandardXComb& rxc = *realXComb; os << rxc.mePartonData()[0]->PDGName() << " " << rxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = rxc.mePartonData().begin() + 2; p != rxc.mePartonData().end(); ++p ) { os << (**p).PDGName() << " "; } os << "\n"; os << " with dipole:\n"; dipole->print(os); os << "--------------------------------------------------------------------------------\n"; os << flush; } list<MatchboxFactory::SplittingChannel> MatchboxFactory::getSplittingChannels(tStdXCombPtr xcptr) const { if ( xcptr->lastProjector() ) xcptr = xcptr->lastProjector(); const StandardXComb& xc = *xcptr; cPDVector proc = xc.mePartonData(); map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator splitEntries = splittingDipoles().find(proc); list<SplittingChannel> res; if ( splitEntries == splittingDipoles().end() ) return res; const set<Ptr<SubtractionDipole>::ptr>& splitDipoles = splitEntries->second; SplittingChannel channel; if ( !splitDipoles.empty() ) { Ptr<MatchboxMEBase>::tptr bornME = const_ptr_cast<Ptr<MatchboxMEBase>::tptr>((**splitDipoles.begin()).underlyingBornME()); channel.bornXComb = bornME->makeXComb(xc.maxEnergy(),xc.particles(),xc.eventHandlerPtr(), const_ptr_cast<tSubHdlPtr>(xc.subProcessHandler()), xc.pExtractor(),xc.CKKWHandler(), xc.partonBins(),xc.cuts(),xc.diagrams(),xc.mirror(), PartonPairVec()); } for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator sd = splitDipoles.begin(); sd != splitDipoles.end(); ++sd ) { channel.dipole = *sd; vector<StdXCombPtr> realXCombs = (**sd).makeRealXCombs(channel.bornXComb); for ( vector<StdXCombPtr>::const_iterator rxc = realXCombs.begin(); rxc != realXCombs.end(); ++rxc ) { channel.realXComb = *rxc; if ( showerApproximation()->needsTildeXCombs() ) { channel.tildeXCombs.clear(); assert(!channel.dipole->partnerDipoles().empty()); for ( vector<Ptr<SubtractionDipole>::tptr>::const_iterator p = channel.dipole->partnerDipoles().begin(); p != channel.dipole->partnerDipoles().end(); ++p ) { StdXCombPtr txc = channel.dipole->makeBornXComb(channel.realXComb); if ( txc ) channel.tildeXCombs.push_back(txc); } } res.push_back(channel); } } if ( initVerbose() ) { generator()->log() << "--- MatchboxFactory splitting channels ----------------------------------------------\n"; const StandardXComb& bxc = *xcptr; generator()->log() << " hard process handled is: "; generator()->log() << bxc.mePartonData()[0]->PDGName() << " " << bxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2; p != bxc.mePartonData().end(); ++p ) { generator()->log() << (**p).PDGName() << " "; } generator()->log() << "\n"; for ( list<MatchboxFactory::SplittingChannel>::const_iterator sp = res.begin(); sp != res.end(); ++sp ) { sp->print(generator()->log()); } generator()->log() << "-------------------------------------------------------------------------------------\n" << flush; } return res; } void MatchboxFactory::print(ostream& os) const { os << "--- MatchboxFactory setup -----------------------------------------------------------\n"; if ( !amplitudes().empty() ) { os << " generated Born matrix elements:\n"; for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = bornMEs().begin(); m != bornMEs().end(); ++m ) { (**m).print(os); } os << flush; os << " generated real emission matrix elements:\n"; for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = realEmissionMEs().begin(); m != realEmissionMEs().end(); ++m ) { (**m).print(os); } os << flush; } os << " generated Born+virtual matrix elements:\n"; for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator bv = bornVirtualMEs().begin(); bv != bornVirtualMEs().end(); ++bv ) { (**bv).print(os); } os << " generated subtracted matrix elements:\n"; for ( vector<Ptr<SubtractedME>::ptr>::const_iterator sub = subtractedMEs().begin(); sub != subtractedMEs().end(); ++sub ) { os << " '" << (**sub).name() << "'\n"; } os << "--------------------------------------------------------------------------------\n"; os << flush; } void MatchboxFactory::doinit() { theIsMatchboxRun() = true; if ( RunDirectories::empty() ) RunDirectories::pushRunId(generator()->runName()); setup(); if ( theShowerApproximation ) theShowerApproximation->init(); if ( initVerbose() && !ranSetup ) print(Repository::clog()); Ptr<StandardEventHandler>::tptr eh = dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler()); assert(eh); SubProcessHandler::doinit(); } void MatchboxFactory::doinitrun() { theIsMatchboxRun() = true; if ( theShowerApproximation ) theShowerApproximation->initrun(); Ptr<StandardEventHandler>::tptr eh = dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler()); assert(eh); SubProcessHandler::doinitrun(); } const string& MatchboxFactory::buildStorage() { return RunDirectories::buildStorage(); } const string& MatchboxFactory::runStorage() { return RunDirectories::runStorage(); } void MatchboxFactory::persistentOutput(PersistentOStream & os) const { os << theDiagramGenerator << theProcessData << theNLight << theNLightJetVec << theNHeavyJetVec << theNLightProtonVec << theOrderInAlphaS << theOrderInAlphaEW << theBornContributions << theVirtualContributions << theRealContributions << theIndependentVirtuals << theIndependentPKs << theSubProcessGroups << thePhasespace << theScaleChoice << theFactorizationScaleFactor << theRenormalizationScaleFactor << theFixedCouplings << theFixedQEDCouplings << theVetoScales << theAmplitudes << theBornMEs << theVirtuals << theRealEmissionMEs << theLoopInducedMEs << theBornVirtualMEs << theSubtractedMEs << theFiniteRealMEs << theVerbose<<theDiagramWeightVerbose <<theDiagramWeightVerboseNBins << theInitVerbose << theSubtractionData << theSubtractionPlotType << theSubtractionScatterPlot << thePoleData << theParticleGroups << processes << loopInducedProcesses << realEmissionProcesses << theShowerApproximation << theSplittingDipoles << theRealEmissionScales << theAllProcesses << theOLPProcesses << theExternalAmplitudes << theSelectedAmplitudes << theDeselectedAmplitudes << theDipoleSet << theReweighters << thePreweighters << theMECorrectionsOnly<< theLoopSimCorrections<<theHighestVirtualsize << ranSetup << theIncoming << theFirstPerturbativePDF << theSecondPerturbativePDF << inProductionMode << theSpinCorrelations << theAlphaParameter << theEnforceChargeConservation << theEnforceColourConservation << theEnforceLeptonNumberConservation << theEnforceQuarkNumberConservation << theLeptonFlavourDiagonal << theQuarkFlavourDiagonal; } void MatchboxFactory::persistentInput(PersistentIStream & is, int) { is >> theDiagramGenerator >> theProcessData >> theNLight >> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec >> theOrderInAlphaS >> theOrderInAlphaEW >> theBornContributions >> theVirtualContributions >> theRealContributions >> theIndependentVirtuals >> theIndependentPKs >> theSubProcessGroups >> thePhasespace >> theScaleChoice >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> theFixedCouplings >> theFixedQEDCouplings >> theVetoScales >> theAmplitudes >> theBornMEs >> theVirtuals >> theRealEmissionMEs >> theLoopInducedMEs >> theBornVirtualMEs >> theSubtractedMEs >> theFiniteRealMEs >> theVerbose >> theDiagramWeightVerbose >> theDiagramWeightVerboseNBins >> theInitVerbose >> theSubtractionData >> theSubtractionPlotType >> theSubtractionScatterPlot >> thePoleData >> theParticleGroups >> processes >> loopInducedProcesses >> realEmissionProcesses >> theShowerApproximation >> theSplittingDipoles >> theRealEmissionScales >> theAllProcesses >> theOLPProcesses >> theExternalAmplitudes >> theSelectedAmplitudes >> theDeselectedAmplitudes >> theDipoleSet >> theReweighters >> thePreweighters >> theMECorrectionsOnly>> theLoopSimCorrections>>theHighestVirtualsize >> ranSetup >> theIncoming >> theFirstPerturbativePDF >> theSecondPerturbativePDF >> inProductionMode >> theSpinCorrelations >> theAlphaParameter >> theEnforceChargeConservation >> theEnforceColourConservation >> theEnforceLeptonNumberConservation >> theEnforceQuarkNumberConservation >> theLeptonFlavourDiagonal >> theQuarkFlavourDiagonal; } string MatchboxFactory::startParticleGroup(string name) { particleGroupName = StringUtils::stripws(name); particleGroup.clear(); return ""; } string MatchboxFactory::endParticleGroup(string) { if ( particleGroup.empty() ) throw Exception() << "MatchboxFactory: Empty particle group." << Exception::runerror; particleGroups()[particleGroupName] = particleGroup; particleGroup.clear(); return ""; } vector<string> MatchboxFactory::parseProcess(string in) { vector<string> process = StringUtils::split(in); if ( process.size() < 3 ) throw Exception() << "MatchboxFactory: Invalid process." << Exception::runerror; for ( vector<string>::iterator p = process.begin(); p != process.end(); ++p ) { *p = StringUtils::stripws(*p); } vector<string> pprocess; for ( vector<string>::const_iterator p = process.begin(); p != process.end(); ++p ) { if ( *p == "->" ) continue; pprocess.push_back(*p); } return pprocess; } string MatchboxFactory::doProcess(string in) { processes.push_back(parseProcess(in)); return ""; } string MatchboxFactory::doLoopInducedProcess(string in) { loopInducedProcesses.push_back(parseProcess(in)); return ""; } string MatchboxFactory::doSingleRealProcess(string in) { realEmissionProcesses.push_back(parseProcess(in)); return ""; } struct SortPID { inline bool operator()(PDPtr a, PDPtr b) const { return a->id() < b->id(); } }; // // @TODO // // SP: After improving this for standard model process building this should // actually got into a separate process builder class or something along these // lines to have it better factored for use with BSM models. // // set<PDVector> MatchboxFactory:: makeSubProcesses(const vector<string>& proc) const { if ( proc.empty() ) throw Exception() << "MatchboxFactory: No process specified." << Exception::runerror; vector<PDVector> groups; typedef map<string,PDVector>::const_iterator GroupIterator; for ( vector<string>::const_iterator gr = proc.begin(); gr != proc.end(); ++gr ) { GroupIterator git = particleGroups().find(*gr); if ( git == particleGroups().end() ) { throw Exception() << "MatchboxFactory: Particle group '" << *gr << "' not defined." << Exception::runerror; } groups.push_back(git->second); } vector<size_t> counts(groups.size(),0); PDVector proto(groups.size()); set<PDVector> allProcs; while ( true ) { for ( size_t k = 0; k < groups.size(); ++k ) proto[k] = groups[k][counts[k]]; int charge = 0; int colour = 0; int nleptons = 0; int nquarks = 0; int ncolour = 0; int nleptonsGen[4]; int nquarksGen[4]; for ( size_t i = 0; i < 4; ++i ) { nleptonsGen[i] = 0; nquarksGen[i] = 0; } for ( size_t k = 0; k < proto.size(); ++k ) { int sign = k > 1 ? 1 : -1; charge += sign * proto[k]->iCharge(); colour += sign * proto[k]->iColour(); if ( abs(proto[k]->id()) <= 8 ) { int generation = (abs(proto[k]->id()) - 1)/2; nquarks += sign * ( proto[k]->id() < 0 ? -1 : 1); nquarksGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1); } if ( abs(proto[k]->id()) > 10 && abs(proto[k]->id()) <= 18 ) { int generation = (abs(proto[k]->id()) - 11)/2; nleptons += sign * ( proto[k]->id() < 0 ? -1 : 1); nleptonsGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1); } if ( proto[k]->coloured() ) ++ncolour; } bool pass = true; if ( theEnforceChargeConservation ) pass &= (charge == 0); if ( theEnforceColourConservation ) pass &= (colour % 8 == 0) && (ncolour > 1); if ( theEnforceLeptonNumberConservation ) { pass &= (nleptons == 0); if ( theLeptonFlavourDiagonal ) { for ( size_t i = 0; i < 4; ++i ) pass &= (nleptonsGen[i] == 0); } } if ( theEnforceQuarkNumberConservation ) { pass &= (nquarks == 0); if ( theQuarkFlavourDiagonal ) { for ( size_t i = 0; i < 4; ++i ) pass &= (nquarksGen[i] == 0); } } if ( pass ) { for ( int i = 0; i < 2; ++i ) { if ( proto[i]->coloured() && proto[i]->hardProcessMass() != ZERO ) throw Exception() << "Inconsistent flavour scheme detected with massive incoming " << proto[i]->PDGName() << ". Check your setup." << Exception::runerror; } sort(proto.begin()+2,proto.end(),SortPID()); allProcs.insert(proto); } vector<size_t>::reverse_iterator c = counts.rbegin(); vector<PDVector>::const_reverse_iterator g = groups.rbegin(); while ( c != counts.rend() ) { if ( ++(*c) == g->size() ) { *c = 0; ++c; ++g; } else { break; } } if ( c == counts.rend() ) break; } return allProcs; } void MatchboxFactory::Init() { static ClassDocumentation<MatchboxFactory> documentation ("MatchboxFactory", "NLO QCD corrections have been calculated " "using Matchbox \\cite{Platzer:2011bc}, \\cite{Matchbox:2015}", "%\\cite{Platzer:2011bc}\n" "\\bibitem{Platzer:2011bc}\n" "S.~Platzer and S.~Gieseke,\n" "``Dipole Showers and Automated NLO Matching in Herwig,''\n" "arXiv:1109.6256 [hep-ph].\n" "%%CITATION = ARXIV:1109.6256;%%\n" "%\\cite{Matchbox:2015}\n" "\\bibitem{Matchbox:2015}\n" "Herwig collaboration,\n" "``Precision LHC Event Generation with Herwig,''\n" "in preparation."); static Reference<MatchboxFactory,Tree2toNGenerator> interfaceDiagramGenerator ("DiagramGenerator", "Set the diagram generator.", &MatchboxFactory::theDiagramGenerator, false, false, true, true, false); static Reference<MatchboxFactory,ProcessData> interfaceProcessData ("ProcessData", "Set the process data object to be used.", &MatchboxFactory::theProcessData, false, false, true, true, false); static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaS ("OrderInAlphaS", "The order in alpha_s to consider.", &MatchboxFactory::theOrderInAlphaS, 0, 0, 0, false, false, Interface::lowerlim); static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaEW ("OrderInAlphaEW", "The order in alpha_EW", &MatchboxFactory::theOrderInAlphaEW, 2, 0, 0, false, false, Interface::lowerlim); static Switch<MatchboxFactory,bool> interfaceBornContributions ("BornContributions", "Switch on or off the Born contributions.", &MatchboxFactory::theBornContributions, true, false, false); static SwitchOption interfaceBornContributionsOn (interfaceBornContributions, "On", "Switch on Born contributions.", true); static SwitchOption interfaceBornContributionsOff (interfaceBornContributions, "Off", "Switch off Born contributions.", false); static Switch<MatchboxFactory,bool> interfaceVirtualContributions ("VirtualContributions", "Switch on or off the virtual contributions.", &MatchboxFactory::theVirtualContributions, true, false, false); static SwitchOption interfaceVirtualContributionsOn (interfaceVirtualContributions, "On", "Switch on virtual contributions.", true); static SwitchOption interfaceVirtualContributionsOff (interfaceVirtualContributions, "Off", "Switch off virtual contributions.", false); static Switch<MatchboxFactory,bool> interfaceRealContributions ("RealContributions", "Switch on or off the real contributions.", &MatchboxFactory::theRealContributions, true, false, false); static SwitchOption interfaceRealContributionsOn (interfaceRealContributions, "On", "Switch on real contributions.", true); static SwitchOption interfaceRealContributionsOff (interfaceRealContributions, "Off", "Switch off real contributions.", false); static Switch<MatchboxFactory,bool> interfaceIndependentVirtuals ("IndependentVirtuals", "Switch on or off virtual contributions as separate subprocesses.", &MatchboxFactory::theIndependentVirtuals, true, false, false); static SwitchOption interfaceIndependentVirtualsOn (interfaceIndependentVirtuals, "On", "Switch on virtual contributions as separate subprocesses.", true); static SwitchOption interfaceIndependentVirtualsOff (interfaceIndependentVirtuals, "Off", "Switch off virtual contributions as separate subprocesses.", false); static Switch<MatchboxFactory,bool> interfaceIndependentPKs ("IndependentPKOperators", "Switch on or off PK oeprators as separate subprocesses.", &MatchboxFactory::theIndependentPKs, true, false, false); static SwitchOption interfaceIndependentPKsOn (interfaceIndependentPKs, "On", "Switch on PK operators as separate subprocesses.", true); static SwitchOption interfaceIndependentPKsOff (interfaceIndependentPKs, "Off", "Switch off PK operators as separate subprocesses.", false); static Switch<MatchboxFactory,bool> interfaceSubProcessGroups ("SubProcessGroups", "Switch on or off production of sub-process groups.", &MatchboxFactory::theSubProcessGroups, false, false, false); static SwitchOption interfaceSubProcessGroupsOn (interfaceSubProcessGroups, "On", "On", true); static SwitchOption interfaceSubProcessGroupsOff (interfaceSubProcessGroups, "Off", "Off", false); static Reference<MatchboxFactory,MatchboxPhasespace> interfacePhasespace ("Phasespace", "Set the phasespace generator.", &MatchboxFactory::thePhasespace, false, false, true, true, false); static Reference<MatchboxFactory,MatchboxScaleChoice> interfaceScaleChoice ("ScaleChoice", "Set the scale choice object.", &MatchboxFactory::theScaleChoice, false, false, true, true, false); static Parameter<MatchboxFactory,double> interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The factorization scale factor.", &MatchboxFactory::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter<MatchboxFactory,double> interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The renormalization scale factor.", &MatchboxFactory::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Switch<MatchboxFactory,bool> interfaceFixedCouplings ("FixedCouplings", "Switch on or off fixed couplings.", &MatchboxFactory::theFixedCouplings, true, false, false); static SwitchOption interfaceFixedCouplingsOn (interfaceFixedCouplings, "On", "On", true); static SwitchOption interfaceFixedCouplingsOff (interfaceFixedCouplings, "Off", "Off", false); static Switch<MatchboxFactory,bool> interfaceFixedQEDCouplings ("FixedQEDCouplings", "Switch on or off fixed QED couplings.", &MatchboxFactory::theFixedQEDCouplings, true, false, false); static SwitchOption interfaceFixedQEDCouplingsOn (interfaceFixedQEDCouplings, "On", "On", true); static SwitchOption interfaceFixedQEDCouplingsOff (interfaceFixedQEDCouplings, "Off", "Off", false); static Switch<MatchboxFactory,bool> interfaceVetoScales ("VetoScales", "Switch on or setting veto scales.", &MatchboxFactory::theVetoScales, false, false, false); static SwitchOption interfaceVetoScalesOn (interfaceVetoScales, "On", "On", true); static SwitchOption interfaceVetoScalesOff (interfaceVetoScales, "Off", "Off", false); static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceAmplitudes ("Amplitudes", "The amplitude objects.", &MatchboxFactory::theAmplitudes, -1, false, false, true, true, false); static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornMEs ("BornMEs", "The Born matrix elements to be used", &MatchboxFactory::theBornMEs, -1, false, false, true, true, false); static RefVector<MatchboxFactory,MatchboxInsertionOperator> interfaceVirtuals ("Virtuals", "The virtual corrections to include", &MatchboxFactory::theVirtuals, -1, false, false, true, true, false); static RefVector<MatchboxFactory,MatchboxMEBase> interfaceRealEmissionMEs ("RealEmissionMEs", "The RealEmission matrix elements to be used", &MatchboxFactory::theRealEmissionMEs, -1, false, false, true, true, false); static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornVirtuals ("BornVirtualMEs", "The generated Born/virtual contributions", &MatchboxFactory::theBornVirtualMEs, -1, false, true, true, true, false); static RefVector<MatchboxFactory,SubtractedME> interfaceSubtractedMEs ("SubtractedMEs", "The generated subtracted real emission contributions", &MatchboxFactory::theSubtractedMEs, -1, false, true, true, true, false); static RefVector<MatchboxFactory,MatchboxMEBase> interfaceFiniteRealMEs ("FiniteRealMEs", "The generated finite real contributions", &MatchboxFactory::theFiniteRealMEs, -1, false, true, true, true, false); static Switch<MatchboxFactory,bool> interfaceVerbose ("Verbose", "Print full infomation on each evaluated phase space point.", &MatchboxFactory::theVerbose, false, false, false); static SwitchOption interfaceVerboseOn (interfaceVerbose, "On", "On", true); static SwitchOption interfaceVerboseOff (interfaceVerbose, "Off", "Off", false); static Switch<MatchboxFactory,bool> interfaceVerboseDia ("DiagramWeightVerbose", "Print full infomation on each evaluated phase space point.", &MatchboxFactory::theDiagramWeightVerbose, false, false, false); static SwitchOption interfaceVerboseDiaOn (interfaceVerboseDia, "On", "On", true); static SwitchOption interfaceVerboseDiaOff (interfaceVerboseDia, "Off", "Off", false); static Parameter<MatchboxFactory,int> interfaceVerboseDiaNbins ("DiagramWeightVerboseNBins", "No. of Bins for DiagramWeightVerbose Diagrams.", &MatchboxFactory::theDiagramWeightVerboseNBins, 200, 0, 0, false, false, Interface::lowerlim); static Switch<MatchboxFactory,bool> interfaceInitVerbose ("InitVerbose", "Print setup information.", &MatchboxFactory::theInitVerbose, false, false, false); static SwitchOption interfaceInitVerboseOn (interfaceInitVerbose, "On", "On", true); static SwitchOption interfaceInitVerboseOff (interfaceInitVerbose, "Off", "Off", false); static Parameter<MatchboxFactory,string> interfaceSubtractionData ("SubtractionData", "Prefix for subtraction check data.", &MatchboxFactory::theSubtractionData, "", false, false); static Switch<MatchboxFactory,int> interfaceSubtractionPlotType ("SubtractionPlotType", "Switch for controlling what kind of plot is generated for checking the subtraction", &MatchboxFactory::theSubtractionPlotType, 1, false, false); static SwitchOption interfaceSubtractionPlotTypeLinearRatio (interfaceSubtractionPlotType, "LinRatio", "Switch on the linear plot of the ratio", 1); static SwitchOption interfaceSubtractionPlotTypeLogRelDiff (interfaceSubtractionPlotType, "LogRelDiff", "Switch on the logarithmic plot of the relative difference", 2); static Switch<MatchboxFactory,bool> interfaceSubtractionScatterPlot ("SubtractionScatterPlot", "Switch for controlling whether subtraction data should be plotted for each phase space point individually", &MatchboxFactory::theSubtractionScatterPlot, false, false, false); static SwitchOption interfaceSubtractionScatterPlotOff (interfaceSubtractionScatterPlot, "Off", "Switch off the scatter plot", false); static SwitchOption interfaceSubtractionScatterPlotOn (interfaceSubtractionScatterPlot, "On", "Switch on the scatter plot", true); static Parameter<MatchboxFactory,string> interfacePoleData ("PoleData", "Prefix for subtraction check data.", &MatchboxFactory::thePoleData, "", false, false); static RefVector<MatchboxFactory,ParticleData> interfaceParticleGroup ("ParticleGroup", "The particle group just started.", &MatchboxFactory::particleGroup, -1, false, false, true, false, false); static Command<MatchboxFactory> interfaceStartParticleGroup ("StartParticleGroup", "Start a particle group.", &MatchboxFactory::startParticleGroup, false); static Command<MatchboxFactory> interfaceEndParticleGroup ("EndParticleGroup", "End a particle group.", &MatchboxFactory::endParticleGroup, false); static Command<MatchboxFactory> interfaceProcess ("Process", "Set the process(es) to consider.", &MatchboxFactory::doProcess, false); static Command<MatchboxFactory> interfaceLoopInducedProcess ("LoopInducedProcess", "Set the loop induced process(es) to consider.", &MatchboxFactory::doLoopInducedProcess, false); static Command<MatchboxFactory> interfaceSingleRealProcess ("SingleRealProcess", "Set the real emission process(es) to consider.", &MatchboxFactory::doSingleRealProcess, false); static Reference<MatchboxFactory,ShowerApproximation> interfaceShowerApproximation ("ShowerApproximation", "Set the shower approximation to be considered.", &MatchboxFactory::theShowerApproximation, false, false, true, true, false); static Switch<MatchboxFactory,bool> interfaceRealEmissionScales ("RealEmissionScales", "Switch on or off calculation of subtraction scales from real emission kinematics.", &MatchboxFactory::theRealEmissionScales, false, false, false); static SwitchOption interfaceRealEmissionScalesOn (interfaceRealEmissionScales, "On", "On", true); static SwitchOption interfaceRealEmissionScalesOff (interfaceRealEmissionScales, "Off", "Off", false); static Switch<MatchboxFactory,bool> interfaceAllProcesses ("AllProcesses", "Consider all processes up to a maximum coupling order specified by the coupling order interfaces.", &MatchboxFactory::theAllProcesses, false, false, false); static SwitchOption interfaceAllProcessesYes (interfaceAllProcesses, "Yes", "Include all processes.", true); static SwitchOption interfaceAllProcessesNo (interfaceAllProcesses, "No", "Only consider processes matching the exact order in the couplings.", false); static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceSelectAmplitudes ("SelectAmplitudes", "The amplitude objects to be favoured in clashing responsibilities.", &MatchboxFactory::theSelectedAmplitudes, -1, false, false, true, true, false); static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceDeselectAmplitudes ("DeselectAmplitudes", "The amplitude objects to be disfavoured in clashing responsibilities.", &MatchboxFactory::theDeselectedAmplitudes, -1, false, false, true, true, false); static Switch<MatchboxFactory,int> interfaceDipoleSet ("DipoleSet", "The set of subtraction terms to be considered.", &MatchboxFactory::theDipoleSet, 0, false, false); static SwitchOption interfaceDipoleSetCataniSeymour (interfaceDipoleSet, "CataniSeymour", "Use default Catani-Seymour dipoles.", 0); static RefVector<MatchboxFactory,ReweightBase> interfaceReweighters ("Reweighters", "Reweight objects for matrix elements.", &MatchboxFactory::theReweighters, -1, false, false, true, false, false); static RefVector<MatchboxFactory,ReweightBase> interfacePreweighters ("Preweighters", "Preweight objects for matrix elements.", &MatchboxFactory::thePreweighters, -1, false, false, true, false, false); static Switch<MatchboxFactory,bool> interfaceMECorrectionsOnly ("MECorrectionsOnly", "Prepare only ME corrections, but no NLO calculation.", &MatchboxFactory::theMECorrectionsOnly, false, false, false); static SwitchOption interfaceMECorrectionsOnlyYes (interfaceMECorrectionsOnly, "Yes", "Produce only ME corrections.", true); static SwitchOption interfaceMECorrectionsOnlyNo (interfaceMECorrectionsOnly, "No", "Produce full NLO.", false); static Switch<MatchboxFactory,bool> interfaceLoopSimCorrections ("LoopSimCorrections", "Prepare LoopSim corrections.", &MatchboxFactory::theLoopSimCorrections, false, false, false); static SwitchOption interfaceLoopSimCorrectionsYes (interfaceLoopSimCorrections, "Yes", "Produce loopsim corrections.", true); static SwitchOption interfaceLoopSimCorrectionsNo (interfaceLoopSimCorrections, "No", "Produce full NLO.", false); static Switch<MatchboxFactory,bool> interfaceFirstPerturbativePDF ("FirstPerturbativePDF", "", &MatchboxFactory::theFirstPerturbativePDF, true, false, false); static SwitchOption interfaceFirstPerturbativePDFYes (interfaceFirstPerturbativePDF, "Yes", "", true); static SwitchOption interfaceFirstPerturbativePDFNo (interfaceFirstPerturbativePDF, "No", "", false); static Switch<MatchboxFactory,bool> interfaceSecondPerturbativePDF ("SecondPerturbativePDF", "", &MatchboxFactory::theSecondPerturbativePDF, true, false, false); static SwitchOption interfaceSecondPerturbativePDFYes (interfaceSecondPerturbativePDF, "Yes", "", true); static SwitchOption interfaceSecondPerturbativePDFNo (interfaceSecondPerturbativePDF, "No", "", false); static Command<MatchboxFactory> interfaceProductionMode ("ProductionMode", "Switch this factory to production mode.", &MatchboxFactory::doProductionMode, false); static Switch<MatchboxFactory,bool> interfaceSpinCorrelations ("SpinCorrelations", "Fill information for the spin correlations, if possible.", &MatchboxFactory::theSpinCorrelations, false, false, false); static SwitchOption interfaceSpinCorrelationsYes (interfaceSpinCorrelations, "Yes", "", true); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "", false); static Parameter<MatchboxFactory,double> interfaceAlphaParameter ("AlphaParameter", "Nagy-AlphaParameter.", &MatchboxFactory::theAlphaParameter, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Switch<MatchboxFactory,bool> interfaceEnforceChargeConservation ("EnforceChargeConservation", "Enforce charge conservation while generating the hard process.", &MatchboxFactory::theEnforceChargeConservation, true, false, false); static SwitchOption interfaceEnforceChargeConservationYes (interfaceEnforceChargeConservation, "Yes", "Enforce charge conservation.", true); static SwitchOption interfaceEnforceChargeConservationNo (interfaceEnforceChargeConservation, "No", "Do not enforce charge conservation.", false); static Switch<MatchboxFactory,bool> interfaceEnforceColourConservation ("EnforceColourConservation", "Enforce colour conservation while generating the hard process.", - &MatchboxFactory::theEnforceColourConservation, true, false, false); + &MatchboxFactory::theEnforceColourConservation, false, false, false); static SwitchOption interfaceEnforceColourConservationYes (interfaceEnforceColourConservation, "Yes", "Enforce colour conservation.", true); static SwitchOption interfaceEnforceColourConservationNo (interfaceEnforceColourConservation, "No", "Do not enforce colour conservation.", false); static Switch<MatchboxFactory,bool> interfaceEnforceLeptonNumberConservation ("EnforceLeptonNumberConservation", "Enforce lepton number conservation while generating the hard process.", - &MatchboxFactory::theEnforceLeptonNumberConservation, true, false, false); + &MatchboxFactory::theEnforceLeptonNumberConservation, false, false, false); static SwitchOption interfaceEnforceLeptonNumberConservationYes (interfaceEnforceLeptonNumberConservation, "Yes", "Enforce lepton number conservation.", true); static SwitchOption interfaceEnforceLeptonNumberConservationNo (interfaceEnforceLeptonNumberConservation, "No", "Do not enforce lepton number conservation.", false); static Switch<MatchboxFactory,bool> interfaceEnforceQuarkNumberConservation ("EnforceQuarkNumberConservation", "Enforce quark number conservation while generating the hard process.", - &MatchboxFactory::theEnforceQuarkNumberConservation, true, false, false); + &MatchboxFactory::theEnforceQuarkNumberConservation, false, false, false); static SwitchOption interfaceEnforceQuarkNumberConservationYes (interfaceEnforceQuarkNumberConservation, "Yes", "Enforce quark number conservation.", true); static SwitchOption interfaceEnforceQuarkNumberConservationNo (interfaceEnforceQuarkNumberConservation, "No", "Do not enforce quark number conservation.", false); static Switch<MatchboxFactory,bool> interfaceLeptonFlavourDiagonal ("LeptonFlavourDiagonal", "Assume that lepton interactions are flavour diagonal while generating the hard process.", - &MatchboxFactory::theLeptonFlavourDiagonal, true, false, false); + &MatchboxFactory::theLeptonFlavourDiagonal, false, false, false); static SwitchOption interfaceLeptonFlavourDiagonalYes (interfaceLeptonFlavourDiagonal, "Yes", "Assume that lepton interactions are flavour diagonal.", true); static SwitchOption interfaceLeptonFlavourDiagonalNo (interfaceLeptonFlavourDiagonal, "No", "Do not assume that lepton interactions are flavour diagonal.", false); static Switch<MatchboxFactory,bool> interfaceQuarkFlavourDiagonal ("QuarkFlavourDiagonal", "Assume that quark interactions are flavour diagonal while generating the hard process.", - &MatchboxFactory::theQuarkFlavourDiagonal, true, false, false); + &MatchboxFactory::theQuarkFlavourDiagonal, false, false, false); static SwitchOption interfaceQuarkFlavourDiagonalYes (interfaceQuarkFlavourDiagonal, "Yes", "Assume that quark interactions are flavour diagonal.", true); static SwitchOption interfaceQuarkFlavourDiagonalNo (interfaceQuarkFlavourDiagonal, "No", "Do not assume that quark interactions are flavour diagonal.", false); } // *** 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<MatchboxFactory,SubProcessHandler> describeHerwigMatchboxFactory("Herwig::MatchboxFactory", "Herwig.so"); diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,1526 +1,1565 @@ Herwig News -*- outline -*- ================================================================================ +* Herwig 7.0.3 release: 2016-xx-xx + +** fix for relocating MadGraph generated amplitudes + The directory and symbolic link structure for MadGraph-built amplitudes has + been changed to allow for relocation of a run directory to a different file + system hierarchy. + +** z* variable added to LeptonsJetsAnalysis + The builtin LeptonsJetsAnalysis has been extented to include the normalized + relative rapidity z* + +** fix to directory hierarchy + A bug in the Herwig-scratch directory hierarchy when integrating with + different seeds has been fixed. + +** detuning parameter for shower reweighting + An efficiency tweak when using the shower reweighting facilities has been + introduced for the veto algorithms in both the QTilde and the Dipole + shower. See the documentation for more details. + +** subprocess generation filters + A number of filters has been implemented to speed up process and diagram + generation for the case of Standard Model like processes; this is + particularly helpful for processes involving a large number of electroweak + combinatorics. See the documentation for more details. + * Herwig 7.0.2 release: 2016-04-29 ** Event reweighting - New option of calculating the weights for the effect of varying the scale used in both the default and dipole showers. This will be described in a forthcoming publication. + New option of calculating the weights for the effect of varying the scale + used in both the default and dipole showers. The method is described in + arXiv:1605.08256 ** mergegrids mode - A main mode for the Herwig executable has been added which merges the integration grids from parallel runs. + A main mode for the Herwig executable has been added which merges the + integration grids from parallel runs. ** NLO Diphoton production - The NLO matrix elements in the POWHEG approach for diphoton production as described in JHEP 1202 (2012) 130, arXiv:1106.3939 have been included as MEPP2GammaGammaPowheg. + The NLO matrix elements in the POWHEG approach for diphoton production as + described in JHEP 1202 (2012) 130, arXiv:1106.3939 have been included as + MEPP2GammaGammaPowheg. ** BSM Hard process constructor - A missing Feynman diagram with a t-channel vector boson has been added to the matrix element for vv2ss + A missing Feynman diagram with a t-channel vector boson has been added to + the matrix element for vv2ss ** BSM Decay Modes calculation - The behaviour of the option to disable decay modes in BSM Models has been changed so that the partial width for the ignored modes is now calculated and included in the total width, but the branching ratio is set to zero. This is more physical than the previous option where the mode was totally ignored and hence not included in the calculation of the width. + The behaviour of the option to disable decay modes in BSM Models has been + changed so that the partial width for the ignored modes is now calculated + and included in the total width, but the branching ratio is set to + zero. This is more physical than the previous option where the mode was + totally ignored and hence not included in the calculation of the width. ** Mass Generation - The behaviour of the GenericMassGenerator has been changed so that modes which have been disabled are only included in the calculation of the total width and not in the partial width used in the numerator of the weight used to select the off-shell mass. + The behaviour of the GenericMassGenerator has been changed so that modes + which have been disabled are only included in the calculation of the total + width and not in the partial width used in the numerator of the weight used + to select the off-shell mass. ** Boost detection Boost could not detect the compiler version for gcc-5.3 and gcc-6.1 * Herwig 7.0.1 release: 2016-01-17 ** Version number written to log file The Herwig version number is now included in addition to ThePEG's version. ** Tau lifetimes A bug with lifetimes for hard process Taus is fixed. Thanks to ATLAS for the report! ** Shower FSR retries Rare events could take a long time due to an extremely large number of FSR retries. These are now capped at a configurable number. ** Dipole shower Reweighting for non-radiating events; fixes for shower profile handling; option to downgrade large-Q expansion for alphaS ** Matchbox builtins Added massive currents for q-qbar ** ShowerAlphaQCD can now use user-defined thresholds ** Input snippets W/Z/H on-shell now split into three files; 4-flavour scheme added ** UFO converter The converter now has experimental support for writing out param cards of its current settings. ** LEPJetAnalysis loading fixed ** Contrib HJets++ has moved to a stand-alone project, FxFx has been added * Herwig 7.0.0 (Herwig++ 3.0.0) release: 2015-12-04 ** Major new release A major new release of the Monte Carlo event generator Herwig++ (version 3.0) is now available. This release marks the end of distinguishing Herwig++ and HERWIG development and therefore constitutes the first major release of version 7 of the Herwig event generator family. The new version features a number of significant improvements to the event simulation, including: built-in NLO hard process calculation for all Standard Model processes, with matching to both angular ordered and dipole shower modules via variants of both subtractive (MC@NLO-type) and multiplicative (Powheg-type) algorithms; QED radiation and spin correlations in the angular ordered shower; a consistent treatment of perturbative uncertainties within the hard process and parton showering, as well as a vastly improved documentation. This version includes (for a more detailed overview and further references please see the release note arXiv:1512.01178): ** A long list of improvements and fixes for the Matchbox module *** includes MC@NLO and Powheg matching to both showers with truncated showering ** A long list of improvements and fixes for both of the shower modules *** includes improvements of numerics issues relevant to 100 TeV pp collisions ** NLO event simulation and Matchbox development *** Interfaces to a number of external libraries *** A new workflow for event generation *** Electroweak corrections to VV production ** Parton shower development *** QED radiation in the angular ordered shower *** Spin correlations in the angular ordered shower *** New scale choices in gluon branchings ** Improvements to event generation workflow *** Re-organized and streamlined input files for the new NLO development *** A unified treatment of shower and matching uncertainties *** New integrator modules featuring parallel integration ** New default tunes for both shower modules ** New contrib modules *** Electroweak Higgs plus jets production *** FxFx merging support *** Higgs boson pair production * Herwig++-2.7.1 release: 2014-07-07 ** New shower switches to select schemes for momentum reconstruction *** QTildeReconstructor:FinalStateReconOption has the following options: *** Default All momenta are rescaled in the rest frame. *** MostOffShell Put all particles on the new-mass shell and the most off-shell and recoiling system are rescaled to ensure 4-momentum is conserved. *** Recursive Recursively put the most off-shell particle which hasn't yet been rescaled on-shell by rescaling the particles and the recoiling system. *** RestMostOffShell The most off-shell is put on shell by rescaling it and the recoiling system, the recoiling system is then put on-shell in its rest frame. *** RestRecursive As above, but recursively treat the currently most-off shell (only makes a difference for more than 3 partons) ** Ticket #378: Hadronization of baryon number violating clusters involving diquarks Fixed by only considering non-diquarks to be combined in the ClusterFinder. ** UFO converter can now parse SLHA files for parameter settings The UFO converter code can now use SLHA files for modifying parameters. The first pass "ufo2herwig" produces the model to be compiled. For each parameter card, run "slha2herwig" to get the matching input file. ** Fix for systems using lib64 The repository is now initialized correctly on systems using lib64 as the library location. ** Efficiency optimization Better allocation of internal vector variables for a noticeable speed increase of 10-20% with LHC events. * Herwig++-2.7.0 release: 2013-10-28 ** UFO interface to Feynman rules generators Herwig++ now includes "ufo2herwig", a tool that automatically creates all required files to run a BSM model from a UFO directory. The conversion has been extensively tested against Feynrules models MSSM, NMSSM, RS, Technicolor, and less extensively with most of the other models in the Feynrules model database. We expect that following this release there will be no further hard-coded new physics models added to Herwig++ and that future models will be included using the UFO interface. ** Shower uncertainties A first set of scaling parameters to estimate shower uncertainties is provided for both the angular ordered as well as the dipole shower; they are Evolver:HardScaleFactor and ShowerAlphaQCD: RenormalizationScaleFactor. ** Rewrite of Matchbox NLO matching The NLO matching implementation has been rewritten and is now more flexible and consistent. Profile scales are provided for the hardest emission both for the dipole shower and matrix element correction matching. ** BLHA2 Interface and new processes Matchbox now features a generic BLHA2 interface to one-loop amplitude codes and now also includes W and W+jet production as well as Higss production in gluon fusion as builtin processes. ** Impoved dipole shower kinematics parametrization The kinematics parametrization for emissions in the dipole shower has been made more efficient. ** W and Z Powheg decays Decays of W and Z bosons now use the Powheg decayers by default. ** Improved treatment of beam remnants The handling of beam remnants has been improved in multiple contexts, leading to a much lower error rate at p+/p- collisions. An additional value "VeryHard" for ClusterFissioner:RemnantOption can be used to disable any special treatment of beam remnant clusters. ** New underlying event tune Herwig++ now uses tune UE-EE-5-MRST by default. Other related tunes can be obtained from the Herwig++ tunes page ** Improvements in BSM code The UFO development identified many sign fixes in rarely used BSM vertices; many improvements were made to general decayers, allowing four-body decays in BSM for the first time; Powheg is enabled in General two-body decayers; and the handling of colour sextets has been improved. ** A new HiggsPair matrix element in Contrib. ** A new matrix element for single top production. ** The Higgs mass is now set to 125.9 GeV (from PDG 2013 update). ** C++-11 testing To help with the coming transition to C++-11, we provide the new --enable-stdcxx11 configure flag. Please try to test builds with this flag enabled and let us know any problems, but do not use this in production code yet. In future releases, this flag will be on by default. ** Other changes *** Many new Rivet analyses have been included in the Tests directory. *** Cleaned Shower header structure; grouped shower parameters into one struct. *** The boolean Powheg flag in HwMEBase changed to an enumeration. * Herwig++-2.6.3 release: 2013-02-22 ** Decay vertex positioning in HepMC output Pseudo-vertices that Herwig++ inserts for technical reasons will now not contribute to the Lorentz positions of downstream vertices. Thanks to ATLAS for the bug report! ** Updated Rivet tests Herwig's library of Rivet test runs has been brought up-to-date with new analyses that were recently published by the Rivet collaboration. * Herwig++-2.6.2 release: 2013-01-30 ** Fixes for PDF and scale choices in POWHEG events Scale settings for MPI and the regular shower are now correct in POWHEG events. This should fix reported anomalies in POWHEG jet rates. NLO PDFs are now also set consistently in the example input files. ** Ticket #373: Branching ratio factors in cross-section If any decay modes are selectively disabled, setting the following post-handler will cause all reported cross-sections to include the branching ratio factor(s) from the previous stages correctly: create Herwig::BranchingRatioReweighter BRreweight insert LHCGenerator:EventHandler:PostDecayHandlers 0 BRreweight ** Anomalous vertices now possible in MEfftoVH ** Interactive shell does not quit on error ** Better warning messages for events from inconsistent LHEF files ** Possible division by zero error fixed in BSM branching ratio calculations ** Decayer and ME changes to improve checkpointing The checkpointing changes in ThePEG 1.8.2 are implemented here, too. Regular dump files are consistent now. * Herwig++-2.6.1 release: 2012-10-16 ** Configure switches The various switches to turn off compilation of BSM models have been unified into a single '--disable-models'. A new flag '--disable-dipole' can be used to turn off the compilation of the Dipole and Matchbox codes. ** Ticket #348: Search path for repository 'read' command The search path for the 'read' command is configurable on the command line with the -i and -I switches. By default, the installation location is now included in the search path, so that 'Herwig++ read LEP.in' will work in an empty directory. The current working directory will always be searched first. The rarely used "Herwig++ init" command has been made consistent with 'read' and 'run' and should now be used without the '-i' flag. ** Width treatment in BSM The width treatment in BSM decay chains has been greatly improved and is now switched on by default in the .model files. To get the old behaviour, use set /Herwig/NewPhysics/NewModel:WhichOffshell Selected ** New BSM models Little Higgs models with and without T-parity are now available. ** Resonance photon lifetime A lifetime bug affecting decays of pi0 to e+e-X was fixed. The virtual photon is not part of the event record anymore. ** Ticket #371: Hard diffraction FPE Herwig++ 2.6.0 introduced a bug into the diffraction code which would abort any runs. This is now fixed. ** O2AlphaS Support for setting quark masses different from the particle data objects as introduced in ThePEG 1.8.1 has been enabled. ** Matchbox Several improvements and bug fixes are included for Matchbox. Amplitudes relevant to pp -> Z+jet and crossed processes at NLO are now available, and various scale choices have been added in a more flexible way. All subtraction dipoles for massive quarks are now included. ** Dipole shower Parameters to perform scale variations in the shower have been added to estimate uncertainties. A bug in showering off gg -> h has been fixed. ** Minor fixes *** Two broken colour structures in GeneralHardME *** Susy Higgs mixing matrix *** BaryonFactorizedDecayer out-of-bounds access *** Mass values in SimpleLHCAnalysis * Herwig++-2.6.0 release: 2012-05-21 (tagged at SVN r7407) ** New NLO framework Matchbox, a flexible and very general framework for performing NLO calculations at fixed order or matched to parton showers is provided with this release. ** Dipole shower algorithm A first implementation of the coherent dipole shower algorithm by Plätzer and Gieseke (arXiv:0909.5593 and arXiv:1109.6256) is available. ** Alternative samplers and the ExSample library The ExSample library by Plätzer (arXiv:1108.6182) is shipped along with Herwig++ in an extended version. The extended version provides SamplerBase objects which can be used alternatively to the default ACDCSampler. ** New BSM models *** New colour sextet diquark model A colour sextet diquark model has been included, as described in Richardson and Winn (arXiv:1108.6154). *** Models reproducing the CDF t-tbar asymmetry Four models that can reproduce the reported t-tbar asymmetry have been included. *** Zprime A simple standard model extension by one additional heavy neutral vector boson. ** Interface to AlpGen, with MLM merging The Contrib directory contains a new interface to the AlpGen matrix element generator. AlpGen events must be preprocessed with the provided AlpGenToLH.exe tool before they can be used. More information can be found in the Herwig++ 2.6 release note. ** HiggsVBF Powheg Higgs boson production by vector boson fusion is available at NLO in the POWHEG scheme, as described in d'Errico, Richardson (arXiv:1106.2983). The Powheg DIS processes were available in Herwig++-2.5.2 already. ** Statistical colour reconnection Alternative mechanisms to minimize the colour length Sum(m_clu) before the hadronization stage, based on Metropolis and annealing algorithms. ** Energy extrapolation of underlying-event tunes To describe underlying-event data at different c.m. energies, the energy-dependent parameter pT_min will now be adjusted automatically, following a power-law. The new tune parameters are the value at 7000 GeV "MPIHandler:pTmin0", and MPIHandler:Power. ** Ticket #239: Reporting of minimum-bias cross-section When simulating minimum-bias events using the MEMinBias matrix element, the correct unitarized cross section can now be reported via the standard facilities; it is no longer necessary to extract it from the .log file of the run. The corresponding functionality is enabled by inserting a MPIXSecReweighter object as a post-subprocess handler: create Herwig::MPIXSecReweighter MPIXSecReweighter insert LHCHandler:PostSubProcessHandlers 0 MPIXSecReweighter ** Dependency on 'boost' Herwig++ now requires the boost headers to build; if not detected in standard locations, specify with the --with-boost configure option. ** Tests directory The Tests directory now contains input cards for almost all Rivet analyses. A full comparison run can be initiated with 'make tests'. ** Minor changes *** Default LHC energy now 8 TeV All LHC-based defaults have now been updated to use 8 TeV as the center-of-mass energy. *** Herwig::ExtraParticleID -> ThePEG::ParticleID The namespace for additional particles has been unified into ThePEG::ParticleID *** MEee2VectorMeson The e+e- -> vector meson matrix element has moved from Contrib into HwMELepton.so *** SUSY numerics fixes Better handling of rare numerical instabilities. *** YODA output for Rivet The built-in histogramming handler can now output data in the YODA format used by Rivet. *** Consistency checks in SLHA file reader Better warnings for inconsistent SusyLHA files *** better colour flow checking for development ** Bug fixes *** Extremely offshell W from top decay Numerical improvements for very off-shell W bosons coming from top decays. *** Ticket #367: problems in using SUSY + LHE Susy events from Les Houches event files are now handled better. *** Infinite loop in remnant decayer The remnant decayer will now abort after 100 tries. *** Fix to HiggsVBF LO diagrams The diagram structure of HiggsVBF LO matrix elements has been fixed. *** LEP thrust fix The calculation of the transverse momentum of a branching from the evolution variable in final-state radiation can now be changed. While formally a sub-leading choice this enables a better description of the thrust distribution in e+e- collisions at small values of the thrust. Currently the default behaviour, where the cut-off masses are used in the calculation, remains the same as previous versions. * Herwig++-2.5.2 release: 2011-11-01 (tagged at SVN r6928) ** Optional new jet vetoing model The jet vetoing model by Schofield and Seymour (arXiv:1103.4811) is available via Evolver:ColourEvolutionMethod, PartnerFinder:PartnerMethod and SplittingFunction:SplittingColourMethod. The default behaviour is unchanged. ** MPI tune Version 3 of the MPI tunes is now the default. Please note that the pT parameter is energy-dependent and needs to be modified when an LHC run is not at 7 TeV. The latest tunes are always available at http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes ** MPI PDFs MPI PDFs can now be controlled independently. ** Initialization time speedup A new BSMModel base class was introduced between StandardModel and the BSM model classes. Together with a restructured decay mode initialization, this offers significantly faster startup times for BSM runs. ThreeBodyDecays can now always be switched on without a large speed penalty. ** Decay mode file Decay mode files in the SLHA format can now be read separately in any BSM model with 'set Model:DecayFileName filename' ** Powheg DIS Charged- and neutral-current DIS processes implementing the POWHEG method are now available. ** Diffraction models Xi cut implemented in PomeronFlux ** Ticket #352: Colour reconnection fixed in DIS ** Ticket #353: Improved numerical stability in chargino decays ** Ticket #358: Infinite loop in top events with pT cut in shower ** Ticket #361: Problem with duplicate 2-body modes in BSM ** Tickets #362 / #363: Crashes with baryon number violating models Particle decays in SUSY models with RPV now work correctly in the colour 8 -> 3,3,3 case. Colour reshuffling now works for RPV clusters. ** Improved Fastjet detection The configure step uses fastjet-config to make sure all header file paths are seen. ** Darwin 11 / OS X Lion A configure bug was fixed which prevented 'make check' from succeeding on OS X Lion. ** Vertex classes The specification of QED / QCD orders has been moved to the vertex constructors, to allow ThePEG consistency checks. WWHH vertices in MSSM and NMSSM were fixed. Some Leptoquark and UED vertices fixed. ** Hadronization Cleanup of obsolete code. * Herwig++-2.5.1 release: 2011-06-24 (tagged at SVN r6609) ** Example input files at 7 TeV All our example input files for LHC now have their beam energy set to 7 TeV instead of 14 TeV. ** Colour reconnection on by default The colour reconnection tunes are now the default setup. Version 2 of the tunes replaces the *-1 tunes, which had a problem with LEP event shapes. ** Run name tags Aded possibility to add a tag to the run name when running with the '-t' option. One run file can thus be run with different seeds and results stored in different output files. ** Floating point exceptions The new command line option -D enables floating point error checking. ** General improvements to WeakCurrent decays ** Remnant decayer Hardwired gluon mass was removed. ** WeakCurrentDecayConstructor Instead of specifying separate Particle1...Particle5 vectors for the decay modes, the new interface DecayModes can be filled with decay tags in the standard syntax. ** BSM: improvements to handling of vertex and model initialisation ** Powheg Higgs Option to use pT or mT as the scale in alphaS and for the factorization scale in the PDFs ** Ticket #337: Tau polarization wrong in charged Higgs decay ** Ticket #339: Colour flows in GeneralThreeBody Decayers for 3bar -> 8 3bar 1 ** Ticket #340: Crash for resonant zero-width particles ** Ticket #341: Varying scale for BSM processes The scale used is now ResonantProcessConstructor:ScaleFactor or TwoToTwoProcessConstructor:ScaleFactor multiplied by sHat. ** Ticket #346: Chargino decays Chargino decayers now automatically switch between the mesonic decays for mass differences less than 2 GeV and the normal partonic decays above 2 GeV. ** Ticket #349: Stop by default on input file errors The '--exitonerror' flag is now the default behaviour for the Herwig++ binary. To switch back to the old behaviour, '--noexitonerror' is required. ** Ticket #351: Four-body stop decays ** Tested with gcc-4.6 * Herwig++-2.5.0 release: 2011-02-08 (tagged at SVN r6274) ** Uses ThePEG-1.7.0 Herwig++ 2.5.0 requires ThePEG 1.7.0 to benefit from various improvements, particularly: handling of diffractive processes; respecting LD_LIBRARY_PATH when loading dynamic libraries, including LHAPDF; improvements to repository commands for decay modes. See ThePEG's NEWS file for more details. ** POWHEG improvements *** New POWHEG processes Simulation at NLO accuracy using the POWHEG method is now available for hadronic diboson production (pp to WW,WZ,ZZ), Higgs decays to heavy quarks, and e+e- to two jets or ttbar, including full mass dependence. *** Input file changes The input files for setting up POWHEG process simulation have been simplified. See the example files LHC-Powheg.in and TVT-Powheg.in for the improved command list. *** Structural changes The POWHEG backend in the shower code has been restructured to make future additions easier: PowhegEvolver has merged with Evolver; both the matrix element corrections and real corrections in the POWHEG scheme are implemented directly in the ME or Decayer classes. ** New processes at leading order *** Photon initiated processes We have added a matrix element for dijet production in gamma hadron collisions. *** Bottom and charm in heavy quark ME The option of bottom and charm quarks is now supported for heavy quark production in MEHeavyQuark. ** Colour reconnection The cluster hadronization model has been extended by an option to reconnect coloured constituents between clusters with a given probability. This new model is different from the colour reconnection model used in FORTRAN HERWIG, and improves the description of minimum bias and underlying event data. ** Diffractive Processes Both single and double diffractive processes are now supported in Herwig++. The Pomeron PDF is implemented using a fit to HERA data, and a pion PDF can be used to model reggeon flux. ** BSM physics *** New models We have added new BSM models, particularly ADD-type extra dimension models and the next-to-minimal supersymmetric standard model (NMSSM). Effects of leptoquarks can as well be simulated. *** Vertex additions We have added flavour changing stop interactions (stop - neutralino - charm) and gravitino interactions with particular emphasis on numerical stability for very light gravitinos. Tri-linear Higgs and Higgs-Higgs/Vector-Vector four-vertices are available as well. *** Input file changes The SUSY model can now also extract the SLHA information from the header of a Les Houches event file: replace the SLHA file name in the example input files with the LH file name. *** Structure The backend structure of the HardProcessConstructor has changed, to allow easier inclusion of new process constructors. Some 2->3 BSM scattering processes involving neutral higgs bosons are now included. The spin handling has been improved in the background. ** Shower splitting code reorganized The selection of spin structures has been decoupled from the choice of colour structure. This gives more flexibility in implementing new splittings. Selected splittings can be disabled in the input files. ** B mixing B mixing, and indirect CP violation in the B meson system are included now. ** Looptools The Looptools directory has been updated to reflect T.Hahn's Looptools 2.6. ** Contrib changes The ROOT interface has been removed as deprecated. The MCPWNLO code has temporarily been removed from the Contrib directory as a major review of this code is required. Additionally, there are various fixes to all other codes shipped in Contrib. ** DIS improvements The momentum reshuffling in DIS events has been improved. ** mu and nu beams mu, nu_e and nu_mu and their antiparticles are now available as beam particles. They are all supported in the DIS matrix elements. mu+ mu- collisions are supported in the general matrix element code for BSM models, but not yet in the hard-coded matrix elements for lepton-lepton scattering. ** Structural changes *** Inline code Inline code has been merged into the header files, .icc files were removed. *** Silent build By default, Herwig++ now builds with silent build rules. To get the old behaviour, run 'make V=1'. *** Debug level The debug level on the command line will now always have priority. *** Event counter The event counter has been simplified. *** Interpolator persistency Interpolators can now be written persistently. ** Ticket #307: Momentum violation check in BasicConsistency Added parameters AbsoluteMomentumTolerance and RelativeMomentumTolerance ** Example POWHEG input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** Truncated shower A problem which lead to the truncated shower not being applied in some cases has been fixed. ** Fixes to numerical problems Minor problems with values close to zero were fixed in several locations. ** Remove duplicated calculation of event shapes An accidental duplication in the calculation of event shapes was removed, they are now only calculated once per event. Several other minor issues in the event shape calculations have also been fixed. ** MRST PDFs fixed An initialization problem in the internal MRST PDFs was fixed. ** Vertex scale choice The scale in the Vertex classes can now be zero where possible. ** Treatment of -N flag The Herwig++ main program now correctly treats the -N flag as optional. ** Numerical stability improved The numerical stability in the 'RunningMass' and 'QTildeReconstructor' classes has been improved. The stability of the boosts in the SOPTHY code for the simulation of QED radiation has been improved. The accuracy of boosts in the z-direction has been improved to fix problems with extremely high p_T partons. ** Bugfix in initial state splittings A bug in the implementation of the PDF weight in initial-state qbar -> qbar g splittings has been fixed. ** Bugfix in chargino neutralino vertices A bug in the 'chi+- chi0 W-+' and charged Higgs-sfermions vertices has been fixed. ** Remove uninitialized variables written to repository A number of uninitialised variables which were written to the repository have been initialised to zero to avoid problems on some systems. ** Fix to QED radiation in hadronic collisions The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now in the generation of QED radiation. ** Fix to numerical problems in two-body decays Numerical problems have been fixed, which appeared in the rare case that the three-momenta of the decay products in two-body decays are zero in the rest frame of the decay particle. ** A problem with forced splittings in the Remnant was fixed. ** ME correction for W+- decays applied properly The matrix element correction for QCD radiation in W+- decays which was not being applied is now correctly used. ** Top quark decays from SLHA file The presence of top quark decay modes in SLHA files is now handled correctly. ** Exceptional shower reconstruction kinematics Additional protection against problems due to the shower reconstruction leading to partons with x>1 has been added. ** Ordering of particles in BSM processes Changes have been made to allow arbitrary ordering of the outgoing particles in BSM processes. ** Bugfixes in tau decays Two bugs involving tau decays have been fixed. The wrong masses were used in the 'KPiCurrent' class for the scalar form factors and a mistake in the selection of decay products lead to tau- --> pi0 K- being generated instead of tau- --> eta K-. ** Avoid crashes in baryon number violating processes. To avoid crashes, better protection has been introduced for the case where diquarks cannot be formed from the quarks in a baryon-number violating process. In addition, the parents of the baryon-number violating clusters have been changed to avoid problems with the conversion of the events to HepMC. ** QED radiation in W- decays A bug in the 'QEDRadiationHandler' class which resulted in no QED radiation being generated in W- decays has been fixed. ** A number of minor fixes to the SUSY models have been made. ** Partial width calculations in BSM models A fix for the direction of the incoming particle in the calculation of two-body partial widths in BSM models has been made. ** LoopTools improvements The LoopTools cache is now cleared more frequently to reduce the amount of memory used by the particle. ** Negative gluino masses are now correctly handled. ** A problem with mixing matrices which are not square has been fixed. ** Removed duplicate diagram The 'MEee2gZ2ll' class has been fixed to only include the photon exchange diagram once rather than twice as previously. ** Fix for duplicate particles in DecayConstructor A problem has been fixed which occurred if the same particle was included in the list of DecayConstructor:DecayParticles. ** Fixes for UED model vertices A number of minor problems in the vertices for the UED model have been fixed. ** Include missing symmetry factor The missing identical-particle symmetry factor in 'MEPP2GammaGamma' has been included. ** Fix floating point problem in top decays A floating point problem in the matrix element correction for top decays has been fixed. * Herwig++-2.4.2 release: 2009-12-11 (tagged at SVN r5022) ** Ticket #292: Tau decay numerical instability The momentum assignment in tau decays contained numerical instabilities which have been fixed by postponing the tau decay until after the parton shower. A new interface setting DecayHandler:Excluded is available to prevent decays in the shower step. This is enabled by default for tau only. ** Ticket #290: Missing MSSM colour structure The missing colour structure for gluino -> gluon neutralino was added. ** Ticket #294: Zero momentum in some decays Some rare phase space points lead to zero momentum in two-body decays. This has been fixed. ** Ticket #295: Stability of QED radiation for lepton collider processes The numerical stability of QED radiation momenta was improved further. ** Ticket #296: K0 oscillation vertex was wrong The oscillation from K0 to K0_L/S now takes place at the production vertex of K0. ** Ticket #289: Undefined variables in repository On some system configurations, undefined variables were written to the repository. These have been fixed. ** Fixed QED radiation for hadron processes The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now. ** Numerical stability fixes Small fixes in RunningMass and QTildeReconstructor. ** Powheg example input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** OS X builds for Snow Leopard Snow Leopard machines will now be recognized as a 64bit architecture. * Herwig++-2.4.1 release: 2009-11-19 (tagged at SVN r4932) ** Uses ThePEG-1.6.0 Herwig++ now requires ThePEG-1.6.0 to benefit from the improved helicity code there. If you have self-written vertex classes, see ThePEG's NEWS file for conversion instructions. ** Vertex improvements ThePEG's new helicity code allowed major simplification of the vertex implementations for all Standard Model and BSM physics models. ** New Transplanckian scattering model An example configuration is in LHC-TRP.in ** BSM ModelGenerator as branching ratio calculator The BSM ModelGenerator has a new switch to output the branching ratios for a given SLHA file in SLHA format, which can then be used elsewhere. ** BSM debugging: HardProcessConstructor New interface 'Excluded' to exclude certain particles from intermediate lines. ** Chargino-Neutralino-W vertex fixed ** Spin correlations are now switched on by default for all perturbative decays. ** Ticket #276: Scale choice in BSM models' HardProcessConstructor New interface 'ScaleChoice' to choose process scale between - sHat (default for colour neutral intermediates) and - transverse mass (default for all other processes). ** Ticket #287: Powheg process scale choice The default choice is now the mass of the colour-singlet system. ** Ticket #278: QED radiation for BSM Soft QED radiation is now enabled in BSM decays and all perturbative decays by default. ** Ticket #279: Full 1-loop QED radiation for Z decays Soft QED radiation in Z decays is now fully 1-loop by default. ** Ticket #280: Redirect all files to stdout This is now implemented globally. The files previously ending in -UE.out and -BSMinfo.out are now appended to the log file. They now also obey the EventGenerator:UseStdout flag. ** Ticket #270: LaTeX output updated After each run, a LaTeX file is produced that contains the full list of citations. Please include the relevant ones in publications. ** Ticket #256: Mac OS X problems An initialization problem that affected only some configurations has been identified and fixed. ** Tests directory added This contains many .in files, to exercise most matrix elements. ** Minor fixes *** Prevent rare x>1 partons in shower reconstruction. *** SUSY-LHA parameter EXTPAR can be used to set tan beta *** Improved Fastjet detection at configure time * Herwig++-2.4.0 release: 2009-09-01 (tagged at SVN r4616) ** New matrix elements We have added a built-in implementation of several new matrix elements: PP --> WW / WZ / ZZ PP --> W gamma / Z gamma PP --> VBF Higgs PP --> Higgs tt / Higgs bb e+e- --> WW / ZZ gamma gamma --> ff / WW ** Base code improvements *** Ticket #257: Remnant handling A problem with forced splittings in the Remnant was fixed. *** Ticket #264: Soft matrix element correction A problem with emissions form antiquarks was fixed. ** PDF sets *** New default set MRST LO** is the new default PDF set. LO* is also available built-in. *** Shower PDFs can be set separately from the hard process Use the 'ShowerHandler:PDF' interface. ** Parameter tunes Shower, hadronization and underlying event parameters were retuned against LEP and Tevatron data respectively. ** BSM module improvements *** Ticket #259: read error for some UED models Arbitrary ordering of outgoing lines in the process description is now possible. *** Ticket #266: branching ratio sums The warning threshold for branching ratios not summing to 1 has been relaxed. It is now a user interface parameter. *** Ticket #267: Top decay modes Top decay modes listed in SLHA files are now handled correctly. ** QED radiation *** Ticket #241: Soft QED radiation is now enabled by default *** Ticket #265: Radiation off W+ and W- is now handled correctly ** Interfaces *** Ticket #243: Fastjet Fastjet is now the only supported jet finder code. All example analyses have been converted to use Fastjet. *** KtJet and CLHEP interfaces have been removed. *** New interfaces to AcerDet and PGS available in Contrib *** MCPWnlo distributed in Contrib *** HepMC and Rivet interfaces moved to ThePEG ** Ticket #239: Inelastic cross-section for MinBias This information is now available in the ...-UE.out files. ** Technical changes *** Ticket #186 Configure now looks for ThePEG in the --prefix location first. *** Configure information Important configuration information is listed at the end of the 'configure' run and in the file 'config.thepeg'. Please provide this file in any bug reports. *** New ZERO object The ZERO object can be used to set any dimensionful quantity to zero. This avoids explicit constructs like 0.0*GeV. *** Exception specifiers removed Client code changes are needed in doinit() etc., simply remove the exception specifier after the function name. *** Ticket #263: Tau polarizations can be forced in TauDecayer * Herwig++-2.3.2 release: 2009-05-08 (tagged at SVN r4249) ** SUSY enhancements *** Ticket #245: Select inclusive / exclusive production Using the new 'HardProcessConstructor:Processes' switch options 'SingleParticleInclusive', 'TwoParticleInclusive' or 'Exclusive' *** Improved three-body decay generation Several problems were fixed, incl. tickets #249 #250 #251 Thanks to J.Tattersall and K.Rolbiecki for the stress-testing! *** Looptools fix Release 2.3.1 had broken the Looptools initialization. *** Improved warning message texts ** Ticket #237: Values of q2last can now be zero where possible. ** Ticket #240: The Herwig++ main program now correctly treats the -N flag as optional. ** Ticket #246: Extreme pT partons fixed by improving accuracy of z boosts. ** DIS Improved parton shower momentum reshuffling. ** Minimum Bias events The zero-momentum interacting particle used for bookkeeping is now labelled as a pomeron. ** User Makefile Makefile-UserModules does not enable -pedantic anymore. User's ROOT code will not compile otherwise. ** Build system Small fixes in the build system. * Herwig++-2.3.1 release: 2009-03-31 (tagged at SVN r4140) ** Initial state showers The PDF veto was wrongly applied to qbar->qbar g splittings. ** User interaction The Makefile-UserModules now includes the Herwig version number. The -N flag to 'Herwig++ run' is optional now, as was always intended. ** Contrib The contrib directory is now included in the tarball. The omission was accidental. ** Numerical accuracy Minor problems with values close to zero were fixed in several locations. ** LEP event shapes An accidental duplication was removed, they are now only calculated once per event. ** MRST PDF code Initialization problem fixed. ** Mac OS X The configure script was improved to detect libraries better. ** Libtool Updated to version 2.2.6 * Herwig++-2.3.0 release: 2008-12-02 (tagged at SVN r3939) ** Major release, with many new features and bug fixes ** Extension to lepton-hadron collisions ** Inclusion of several processes accurate at next-to-leading order in the POsitive Weight Hardest Emission Generator (POWHEG) scheme ** Inclusion of three-body decays and finite-width effects in BSM processes ** New procedure for reconstructing kinematics of the parton shower based on the colour structure of the hard scattering process ** New model for baryon decays including excited baryon multiplets ** Addition of a soft component to the multiple scattering model of the underlying event and the option to choose more than one hard scattering explicitly ** New matrix elements for DIS and e+e- processes ** New /Contrib directory added containing external modules that will hopefully be of use to some users but are not expected to be needed by most users and are not supported at the same level as the main Herwig++ code ** Minor changes to improve the physics simulation: *** IncomingPhotonEvolver added to allow the simulation of partonic processes with incoming photons in hadron collisions *** KTRapidityCut added to allow cuts on the p_T and rapidity, rather than just the p_T and pseudorapidity used in SimpleKTCut. This is now used by default for cuts on massive particles such as the $W^\pm$, $Z^0$ and Higgs bosons and the top quark *** Several changes to the decayers of B mesons both to resolve problems with the modelling of partonic decays and improve agreement with $\Upsilon(4s)$ data *** Changes to allow values other than transverse mass of final-state particles as maximum transverse momentum for radiation in parton shower either SCALUP for Les Houches events or the scale of the hard process for internally generated hard processes *** Changed defaults for intrinsic transverse momentum in hadron collisions to 1.9GeV, 2.1GeV and 2.2GeV for the Tevatron and LHC at 10 TeV and 14 TeV, respectively *** Pdfinfo object is now created in the HepMC interface However in order to support all versions of HepMC containing this feature the PDF set is not specified as not all versions contain this information *** New option of only decaying particles with lifetimes below user specified value *** New options for the cut-off in the shower and some obsolete parameters removed *** Added option of switching off certain decay modes in BSM models *** Added a Matcher for Higgs boson to allow cuts to be placed on it *** Diffractive particles deleted from default input files they were not previously used ** Technical changes: *** Some AnalysisHandler classes comparing to LEP data have been renamed e.g. MultiplicityCount becomes LEPMultiplicityCount to avoid confusion with those supplied in /Contrib for observables at the Upsilon(4s) resonance *** Reorganisation to remove the majority of the .icc files by moving inlined functions to headers in an effort to improve compile time *** Restructured the decay libraries to reduce the amount of memory allocation and de-allocation which improves run-time performance *** The switch to turn off LoopTools has been removed because LoopTools is now used by several core modules. As LoopTools does not work on 64-bit platforms with g77 this build option is not supported *** Removed support for obsolete version of HepMC supplied with CLHEP and improved the support for different units options with HepMC *** EvtGen interface has been removed until it is more stable *** Support for ROOT has been removed it was not previously used *** CKKW infrastructure has been removed from the release until a concrete implementation is available *** Default optimisation has been increased from -O2 to -O3 *** Handling of the fortran compiler has been improved mainly due to improvements in the autotools *** Use of FixedAllocator for Particle objects in ThePEG has been removed as it had no performance benefits ** Bugs fixed: *** Problems with the mother/daughter relations in the hard process and diagram selection in W+- and Z0 production in association with a hard jet *** In general matrix element code for fermion-vector to fermion-scalar where the outgoing fermion is coloured and the scalar neutral *** In the selection of diagrams in some associated squark gaugino processes *** h0->mu+mu- was being generated when h0->tau+tau- *** Normalisation in the Histogram class for non unit-weight events *** Protection against negative PDF values has been improved these can occur when using NLO PDF sets *** Lifetime for BSM particles is now automatically calculated at the same time as the width *** Hadrons containing a top quark now treated like hadrons containing BSM particles in order to support this possibility *** Several ambiguous uses of unsigned int *** Several variables that may have been used undefined *** Several memory leaks at initialisation *** The configuration now aborts if no fortran compiler is found as this is required to compile Looptools *** Several minor floating point errors that did not affect results * Herwig++-2.2.1 release: 2008-07-09 (tagged at SVN r3434) ** Ticket #181: BSM shower with a decay close to threshold Now fixed. ** Ticket #191: Split SUSY crash Improved error message. ** Ticket #192: using SCALUP as the pT veto in the shower Now implemented. ** Ticket #194: production processes of ~chi_1(2)- Fixed bug in the diagram creation. ** Removed unused particles DiffractiveParticles.in was removed, they were never produced. ** Hadronization Top quark clusters now possible, handled as 'exotic' clusters. ** Improved handling of decay modes See ThePEG-1.3.0. 'defaultparticle' command is now obsolete. ** Multi-Parton interactions Increased phase space sampling to have less than 1% uncertainty on average multiplicity. ** New libtool version gfortran is now used as default if it is available. Set FC=g77 to override this. ** Fixed several memory leaks ** Memory allocation Now using plain 'new' and 'delete'. * Herwig++-2.2.0 release: 2008-04-18 (tagged at SVN r3195) ** Major release: now as stand-alone library Herwig++ is now a stand-alone dlopen() plugin to ThePEG. No compile-time linking to Herwig code is required. The Herwig++ binary is a simple executable steering ThePEG, which can be replaced by other frontends (such as setupThePEG / runThePEG). ** New matrix elements p p -> W + jet / Z + jet / W + higgs / Z + higgs e+ e- -> Z + higgs ** Looptools Updated to version 2.2. ** Ticket #141: segfault from using 'run' command Fixed by using default allocators in Herwig++, and the Repository::cleanup() method in ThePEG 1.2.0. ** Ticket #157: broken gsl library path on some 64bit systems Paths with lib64 are correctly identified now. ** Ticket #159: p_t spectrum of ttbar pair Fixed identical particle multiplier in Sudakov form factor. ** Ticket #161: glibc segfault Rare segfault in MPI handler fixed. ** Ticket #165: rare infinite loop in four-body decay All 4-body decays without dedicated decayers now use the Mambo algorithm. A loop guard has been introduced to 3-body decays to avoid infinite retries. ** Ticket #166: rare infinite loop in top ME correction These very rare events (O(1) in 10^7) close to mass threshold now are discarded. ** Higgs width fixes ** SatPDF Optionally, the PDF extrapolation behaviour outside a given range can now be specified. ** gcc 4.3 Herwig++-2.2 compiles cleanly with the new gcc 4.3 series. * Herwig++-2.1.4 release: 2008-03-03 (tagged at SVN r3024) ** Ticket #152: Vertex positions All vertex positions of unphysical particles are set to zero until a fix for the previous nonsensical values can be implemented. * Herwig++-2.1.3 release: 2008-02-25 (tagged at SVN r2957) ** Ticket #129: Baryon decays Fix for baryon decay modes. ** Ticket #131: HepMC Check if IO_GenEvent exists ** Ticket #134: Hadronization Smearing of hadron directions in cluster decay fixed. ** Ticket #137: HepMC HepMC conversion allows specification of energy and length units to be used. ** Ticket #139: Neutral kaons Ratio K_L / K_S corrected. ** Ticket #140 / #141: Crash on shutdown Event generation from the 'read' stage or an interface now shuts down cleanly. Fixes a crash bug introduced in 2.1.1 which affected external APIs to ThePEG / Herwig. ** Ticket #146: BSM models can be disabled To save build time, some or all of the BSM models can be disabled using the '--enable-models' configure switch. ** Reorganised .model files The .model files now include the model-specific particles, too. ** Re-tune Re-tuned hadronization parameters to LEP data. ** Other fixes in QSPAC implementation in Shower; Multi-parton interaction tuning; MRST initialization * Herwig++-2.1.2 release: 2008-01-05 (tagged at SVN r2694) ** Ticket #127 Thanks to a patch submitted by Fred Stober, HepMCFile now can output event files in all supported formats. ** Ticket #128 Fixed incorrect value of pi in histogram limits. ** Other fixes in CKKW Qtilde clusterers, BSM width cut, SUSY mixing matrices. * Herwig++-2.1.1 release: 2007-12-08 (tagged at SVN r2589) ** Bug #123 Fixed a bug with particle lifetimes which resulted in nan for some vertex positions. ** Secondary scatters Fixed bug which gave intrinsic pT to secondary scatters. ** gcc abs bug detection configure now checks for and works around http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 ** CKKW reweighting Fixed wrong check for top quarks. ** MPIHandler Fixed call order ambiguity. * Herwig++-2.1.0 release: 2007-11-20 (tagged at SVN r2542) ** Major new release Herwig++-2.1 includes significant improvements, including multi-parton interactions, BSM physics and a new hadronic decay model, tuned to LEP data. For an overview of the changes, please see the release note arXiv:0711.3137 * Herwig++-2.0.3 release: 2007-08-21 (tagged at SVN r2101) ** Bug #90 nan in top decay ME corrections fixed. ** unlisted Colour flow fix in LightClusterDecayer ** unlisted Updated version of MultiplicityCount analysis handler. * Herwig++-2.0.2 release: 2007-07-06 (tagged at SVN r1716) ** Bug #80 Separation of HepMC from CLHEP is handled properly now. ** Bug #83 Workaround for OS X header problem ** unlisted Veto on very hard emissions from Shower. ** unlisted Detailed documentation in .in files * Herwig++-2.0.1 release: 2006-12-05 (tagged at SVN r1195) ** Bug #54 ClusterFissioner vertex calculation fixed. ** Bug #57 Crash when showering W+jet events supplied by Les Houches interface. ** Bug #59 Fix for #57 applied to LHC events. ** Bug #60 Segfault when PDF is set to NoPDF. ** Bug #61 Missing weight factor for I=0 mesons ** Bug #62 Spinor vertex calculations broken when spinor rep is not default rep. ** Bug #63 Top decay never produces tau. ** Bug #69 TTbar and HiggsJet analysis handlers fixed. ** unlisted Reorganization of Hadronization module gives 30% speedup. Thanks to Vincenzo Innocente at CMS for his profiling work! ** unlisted cleaner automake files in include/ and src/ ** unlisted Hw64 hadron selection algorithm 'abortnow' fixed. ** unlisted Top/LeptonDalitzAnalysis removed (only worked with modified code). ** unlisted removed f'_0 from particle list, decays were not handled * Herwig++-2.0.0 release: 2006-09-28 (tagged at SVN r1066) ** Full simulation of hadron collisions diff --git a/Shower/Base/SudakovFormFactor.cc b/Shower/Base/SudakovFormFactor.cc --- a/Shower/Base/SudakovFormFactor.cc +++ b/Shower/Base/SudakovFormFactor.cc @@ -1,703 +1,704 @@ // -*- C++ -*- // // SudakovFormFactor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 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 "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/ShowerHandler.h" using namespace Herwig; DescribeAbstractClass<SudakovFormFactor,Interfaced> 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) << theFactorizationScaleFactor << theRenormalizationScaleFactor; } 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) >> theFactorizationScaleFactor >> theRenormalizationScaleFactor; } void SudakovFormFactor::Init() { static ClassDocumentation<SudakovFormFactor> documentation ("The SudakovFormFactor class is the base class for the implementation of Sudakov" " form factors in Herwig"); static Reference<SudakovFormFactor,SplittingFunction> interfaceSplittingFunction("SplittingFunction", "A reference to the SplittingFunction object", &Herwig::SudakovFormFactor::splittingFn_, false, false, true, false); static Reference<SudakovFormFactor,ShowerAlpha> interfaceAlpha("Alpha", "A reference to the Alpha object", &Herwig::SudakovFormFactor::alpha_, false, false, true, false); static Parameter<SudakovFormFactor,double> interfacePDFmax ("PDFmax", "Maximum value of PDF weight. ", &SudakovFormFactor::pdfmax_, 35.0, 1.0, 100000.0, false, false, Interface::limited); static Switch<SudakovFormFactor,unsigned int> interfacePDFFactor ("PDFFactor", "Include additional factors in the overestimate for the PDFs", &SudakovFormFactor::pdffactor_, 0, false, false); static SwitchOption interfacePDFFactorOff (interfacePDFFactor, "Off", "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 Switch<SudakovFormFactor,unsigned int> 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<SudakovFormFactor,double> interfaceaParameter ("aParameter", "The a parameter for the kinematic cut-off", &SudakovFormFactor::a_, 0.3, -10.0, 10.0, false, false, Interface::limited); static Parameter<SudakovFormFactor,double> interfacebParameter ("bParameter", "The b parameter for the kinematic cut-off", &SudakovFormFactor::b_, 2.3, -10.0, 10.0, false, false, Interface::limited); static Parameter<SudakovFormFactor,Energy> 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<SudakovFormFactor,Energy> 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<SudakovFormFactor,Energy> 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<SudakovFormFactor,Energy> 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<SudakovFormFactor,Energy> 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 *= renormalizationScaleFactor(); return ThePEG::Math::powi(alpha_->ratio(pt2, factor), splittingFn_->interactionOrder()); } bool SudakovFormFactor::PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr<BeamParticleData>::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<BeamParticleData>::transient_const_pointer beam,double factor) const { assert(pdf_); Energy2 theScale = t * sqr(factorizationScaleFactor()*factor); if (theScale < sqr(freeze_)) theScale = sqr(freeze_); double newpdf(0.0), oldpdf(0.0); newpdf=pdf_->xfx(beam,parton0,theScale,x/z()); oldpdf=pdf_->xfx(beam,parton1,theScale,x); if(newpdf<=0.) return 0.; if(oldpdf<=0.) return 1.; double ratio = newpdf/oldpdf; double maxpdf = pdfmax_; switch (pdffactor_) { case 1: maxpdf /= z(); break; case 2: maxpdf /= 1.-z(); break; case 3: maxpdf /= (z()*(1.-z())); break; } 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<particles_.size();++ix) { if(particles_[ix].size()==in.size()) { bool match=true; for(unsigned int iy=0;iy<in.size();++iy) { if(particles_[ix][iy]!=in[iy]) { match=false; break; } } if(match) { add=false; break; } } } if(add) particles_.push_back(in); } namespace { LorentzRotation boostToShower(const vector<Lorentz5Momentum> & basis, ShowerKinematics::Frame frame, Lorentz5Momentum & porig) { LorentzRotation output; if(frame==ShowerKinematics::BackToBack) { // we are doing the evolution in the back-to-back frame // work out the boostvector Boost boostv(-(basis[0]+basis[1]).boostVector()); // momentum of the parton Lorentz5Momentum ptest(basis[0]); // construct the Lorentz boost output = LorentzRotation(boostv); ptest *= output; Axis axis(ptest.vect().unit()); // now rotate so along the z axis as needed for the splitting functions if(axis.perp2()>1e-10) { double sinth(sqrt(1.-sqr(axis.z()))); output.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { output.rotate(Constants::pi,Axis(1.,0.,0.)); } porig = output*basis[0]; porig.setX(ZERO); porig.setY(ZERO); } else { output = LorentzRotation(-basis[0].boostVector()); porig = output*basis[0]; porig.setX(ZERO); porig.setY(ZERO); porig.setZ(ZERO); } return output; } RhoDMatrix bosonMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, VectorSpinPtr vspin, const LorentzRotation & rot) { // rotate the original basis vector<LorentzPolarizationVector> sbasis; for(unsigned int ix=0;ix<3;++ix) { sbasis.push_back(vspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // splitting basis vector<LorentzPolarizationVector> fbasis; bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),outgoing); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { fbasis.push_back(LorentzPolarizationVector()); } else { wave.reset(ix); fbasis.push_back(wave.wave()); } } // work out the mapping RhoDMatrix mapping=RhoDMatrix(PDT::Spin1,false); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { mapping(ix,iy)= sbasis[iy].dot(fbasis[ix].conjugate()); if(particle.id()<0) mapping(ix,iy)=conj(mapping(ix,iy)); } } // \todo need to fix this mapping = RhoDMatrix(PDT::Spin1,false); if(massless) { mapping(0,0) = 1.; mapping(2,2) = 1.; } else { mapping(0,0) = 1.; mapping(1,1) = 1.; mapping(2,2) = 1.; } return mapping; } RhoDMatrix fermionMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, FermionSpinPtr fspin, const LorentzRotation & rot) { // extract the original basis states vector<LorentzSpinor<SqrtEnergy> > sbasis; for(unsigned int ix=0;ix<2;++ix) { sbasis.push_back(fspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // calculate the states in the splitting basis vector<LorentzSpinor<SqrtEnergy> > fbasis; SpinorWaveFunction wave(porig,particle.dataPtr(), particle.id()>0 ? incoming : outgoing); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); fbasis.push_back(wave.dimensionedWave()); } RhoDMatrix mapping=RhoDMatrix(PDT::Spin1Half,false); for(unsigned int ix=0;ix<2;++ix) { if(fbasis[0].s2()==complex<SqrtEnergy>()) { mapping(ix,0) = sbasis[ix].s3()/fbasis[0].s3(); mapping(ix,1) = sbasis[ix].s2()/fbasis[1].s2(); } else { mapping(ix,0) = sbasis[ix].s2()/fbasis[0].s2(); mapping(ix,1) = sbasis[ix].s3()/fbasis[1].s3(); } } return mapping; } FermionSpinPtr createFermionSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); SpinorWaveFunction wave; if(particle.id()>0) wave=SpinorWaveFunction(porig,particle.dataPtr(),incoming); else wave=SpinorWaveFunction(porig,particle.dataPtr(),outgoing); FermionSpinPtr fspin = new_ptr(FermionSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); LorentzSpinor<SqrtEnergy> basis = wave.dimensionedWave(); basis.transform(rinv); fspin->setBasisState(ix,basis); fspin->setDecayState(ix,basis); } particle.spinInfo(fspin); return fspin; } VectorSpinPtr createVectorSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),dir); VectorSpinPtr vspin = new_ptr(VectorSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<3;++ix) { LorentzPolarizationVector basis; if(massless&&ix==1) { basis = LorentzPolarizationVector(); } else { wave.reset(ix); basis = wave.wave(); } basis *= rinv; vspin->setBasisState(ix,basis); vspin->setDecayState(ix,basis); } particle.spinInfo(vspin); vspin-> DMatrix() = RhoDMatrix(PDT::Spin1); vspin->rhoMatrix() = RhoDMatrix(PDT::Spin1); if(massless) { vspin-> DMatrix()(0,0) = 0.5; vspin->rhoMatrix()(0,0) = 0.5; vspin-> DMatrix()(2,2) = 0.5; vspin->rhoMatrix()(2,2) = 0.5; } return vspin; } } bool SudakovFormFactor::getMapping(SpinPtr & output, RhoDMatrix & mapping, ShowerParticle & particle,ShoKinPtr showerkin) { // if the particle is not from the hard process if(!particle.perturbative()) { // mapping is the identity output=particle.spinInfo(); mapping=RhoDMatrix(particle.dataPtr()->iSpin()); if(output) { return false; } else { Lorentz5Momentum porig; LorentzRotation rot = boostToShower(showerkin->getBasis(),showerkin->frame(),porig); Helicity::Direction dir = particle.isFinalState() ? outgoing : incoming; if(particle.dataPtr()->iSpin()==PDT::Spin0) { assert(false); } else if(particle.dataPtr()->iSpin()==PDT::Spin1Half) { output = createFermionSpinInfo(particle,porig,rot,dir); } else if(particle.dataPtr()->iSpin()==PDT::Spin1) { output = createVectorSpinInfo(particle,porig,rot,dir); } else { assert(false); } return false; } } // if particle is final-state and is from the hard process else if(particle.isFinalState()) { assert(particle.perturbative()==1 || particle.perturbative()==2); // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(showerkin->getBasis(),showerkin->frame(),porig); // the rest depends on the spin of the particle PDT::Spin spin(particle.dataPtr()->iSpin()); mapping=RhoDMatrix(spin,false); // do the spin dependent bit if(spin==PDT::Spin0) { ScalarSpinPtr sspin=dynamic_ptr_cast<ScalarSpinPtr>(particle.spinInfo()); if(!sspin) { ScalarWaveFunction::constructSpinInfo(&particle,outgoing,true); } output=particle.spinInfo(); return false; } else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(particle.spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(particle,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(particle,porig,rot,outgoing); return false; } } else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(particle.spinInfo()); // spin info exists get information from it if(vspin) { output=vspin; mapping = bosonMapping(particle,porig,vspin,rot); return true; } else { output = createVectorSpinInfo(particle,porig,rot,outgoing); return false; } } // not scalar/fermion/vector else assert(false); } // incoming to hard process else if(particle.perturbative()==1 && !particle.isFinalState()) { // get the basis vectors // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(showerkin->getBasis(),showerkin->frame(),porig); porig *= particle.x(); // the rest depends on the spin of the particle PDT::Spin spin(particle.dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(particle.spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(particle,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(particle,porig,rot,incoming); return false; } } // spin-1 else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(particle.spinInfo()); // spinInfo exists map it if(vspin) { output=vspin; mapping = bosonMapping(particle,porig,vspin,rot); return true; } // create the spininfo else { output = createVectorSpinInfo(particle,porig,rot,incoming); return false; } } assert(false); } // incoming to decay else if(particle.perturbative() == 2 && !particle.isFinalState()) { // get the basis vectors Lorentz5Momentum porig; LorentzRotation rot=boostToShower(showerkin->getBasis(), showerkin->frame(),porig); // the rest depends on the spin of the particle PDT::Spin spin(particle.dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { // FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(particle.spinInfo()); // // spin info exists get information from it // if(fspin) { // output=fspin; // mapping = fermionMapping(particle,porig,fspin,rot); // return true; // // spin info does not exist create it // else { // output = createFermionSpinInfo(particle,porig,rot,incoming); // return false; // } // } assert(false); } // // spin-1 // else if(spin==PDT::Spin1) { // VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(particle.spinInfo()); // // spinInfo exists map it // if(vspin) { // output=vspin; // mapping = bosonMapping(particle,porig,vspin,rot); // return true; // } // // create the spininfo // else { // output = createVectorSpinInfo(particle,porig,rot,incoming); // return false; // } // } // assert(false); assert(false); } else assert(false); return true; } void SudakovFormFactor::removeSplitting(const IdList & in) { for(vector<IdList>::iterator it=particles_.begin(); it!=particles_.end();++it) { if(it->size()==in.size()) { bool match=true; for(unsigned int iy=0;iy<in.size();++iy) { if((*it)[iy]!=in[iy]) { match=false; break; } } if(match) { vector<IdList>::iterator itemp=it; --itemp; particles_.erase(it); it = itemp; } } } } Energy2 SudakovFormFactor::guesst(Energy2 t1,unsigned int iopt, - const IdList &ids, - double enhance,bool ident) const { + const IdList &ids, + double enhance,bool ident, + const 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); + 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.; if(splittingFn_->interactionOrder()==1) { double r = UseRandom::rnd(); if(iopt!=2 || c*log(r)<log(Constants::MaxEnergy2/t1)) { return t1*pow(r,c); } else return Constants::MaxEnergy2; } else { assert(false && "Units are dubious here."); int nm(splittingFn()->interactionOrder()-1); c/=Math::powi(alpha_->overestimateValue()/Constants::twopi,nm); return t1 / pow (1. - nm*c*log(UseRandom::rnd()) * Math::powi(t1*UnitRemoval::InvE2,nm) ,1./double(nm)); } } double SudakovFormFactor::guessz (unsigned int iopt, const IdList &ids) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double lower = splittingFn_->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<Energy> & SudakovFormFactor::virtualMasses(const IdList & ids) { static vector<Energy> output; output.clear(); if(cutOffOption() == 0) { for(unsigned int ix=0;ix<ids.size();++ix) output.push_back(getParticleData(ids[ix])->mass()); Energy kinCutoff= kinematicCutOff(kinScale(),*std::max_element(output.begin(),output.end())); for(unsigned int ix=0;ix<output.size();++ix) output[ix]=max(kinCutoff,output[ix]); } else if(cutOffOption() == 1) { for(unsigned int ix=0;ix<ids.size();++ix) { output.push_back(getParticleData(ids[ix])->mass()); output.back() += ids[ix]==ParticleID::g ? vgCut() : vqCut(); } } else if(cutOffOption() == 2) { for(unsigned int ix=0;ix<ids.size();++ix) output.push_back(getParticleData(ids[ix])->mass()); } else { throw Exception() << "Unknown option for the cut-off" << " in SudakovFormFactor::virtualMasses()" << Exception::runerror; } return output; } diff --git a/Shower/Base/SudakovFormFactor.h b/Shower/Base/SudakovFormFactor.h --- a/Shower/Base/SudakovFormFactor.h +++ b/Shower/Base/SudakovFormFactor.h @@ -1,725 +1,730 @@ // -*- C++ -*- // // SudakovFormFactor.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 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/SplittingFunctions/SplittingFunction.h" #include "Herwig/Shower/Couplings/ShowerAlpha.h" #include "Herwig/Shower/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 "SudakovFormFactor.fh" namespace Herwig { using namespace ThePEG; /** * A typedef for the BeamParticleData */ typedef Ptr<BeamParticleData>::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_(), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0) {} /** * 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 cc Whether this is the charge conjugate of the branching * @param enhance The radiation enhancement factor - * @param maxQ2 The maximum \f$Q^2\f$ for the emission + * defined. */ virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale, const IdList &ids,const bool cc, - double enhance, Energy2 maxQ2)=0; + double enhance, double detuning, + Energy2 maxQ2)=0; /** * 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 * @param cc Whether this is the charge conjugate of the branching * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const bool cc, - double enhance)=0; + double enhance, + double detuning)=0; /** * 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 * @param cc Whether this is the charge conjugate of the branching * defined. * @param beam The beam particle * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale, const IdList &ids,double x, const bool cc,double enhance, - tcBeamPtr beam)=0; + tcBeamPtr beam, + double detuning)=0; //@} /** * 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)=0; /** * 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)=0; /** * 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)=0; /** * 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::Type 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)=0; /** * Method to create the ShowerKinematics object for a final-state branching */ virtual ShoKinPtr createFinalStateBranching(Energy scale,double z, double phi, Energy pt)=0; /** * Method to create the ShowerKinematics object for an initial-state branching */ virtual ShoKinPtr createInitialStateBranching(Energy scale,double z, double phi, Energy pt)=0; /** * Method to create the ShowerKinematics object for a decay branching */ virtual ShoKinPtr createDecayBranching(Energy scale,double z, double phi, Energy pt)=0; 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 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) const; + double enhance, bool identical, const 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 { - return UseRandom::rnd()>splittingFn_->ratioP(z_, t, ids,mass); + const bool mass, + const double & detune) const { + return UseRandom::rnd()>SplittingFnVetoRatio(t,ids,mass,detune); } /** * The Splitting function veto ratio */ double SplittingFnVetoRatio(const Energy2 t, - const IdList &ids, - const bool mass) const { - return splittingFn_->ratioP(z_, t, ids,mass); + const IdList &ids, + const bool mass, + const double & detune) const { + return splittingFn_->ratioP(z_, t, ids,mass)/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; //@} /** * Methods to set the kinematic variables for the branching */ //@{ /** * The energy fraction */ void z(double in) { z_=in; } /** * The azimuthal angle */ void phi(double in) { phi_=in; } /** * The transverse momentum */ void pT(Energy in) { pT_=in; } //@} /** * Set/Get the limits on the energy fraction for the splitting */ //@{ /** * Get the limits */ pair<double,double> zLimits() const { return zlimits_;} /** * Set the limits */ void zLimits(pair<double,double> in) { zlimits_=in; } //@} /** * 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<IdList> & particles() const { return particles_; } /** * 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 particle The particle * @param showerkin The ShowerKinematics object */ bool getMapping(SpinPtr &, RhoDMatrix & map, ShowerParticle & particle,ShoKinPtr showerkin); 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<Energy> & virtualMasses(const IdList & ids); //@} /** * Set the PDF */ void setPDF(tcPDFPtr pdf, Energy scale) { pdf_ = pdf; freeze_ = scale; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SudakovFormFactor & operator=(const SudakovFormFactor &); 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<IdList> 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<double,double> zlimits_; /** * Stuff for the PDFs */ //@{ /** * PDf */ tcPDFPtr pdf_; /** * Freezing scale */ Energy freeze_; //@} public: /** * Get the factorization scale factor */ double factorizationScaleFactor() const { return theFactorizationScaleFactor; } /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; } /** * Get the renormalization scale factor */ double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; } private: /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; }; } #endif /* HERWIG_SudakovFormFactor_H */ diff --git a/Shower/Default/QTildeSudakov.cc b/Shower/Default/QTildeSudakov.cc --- a/Shower/Default/QTildeSudakov.cc +++ b/Shower/Default/QTildeSudakov.cc @@ -1,1113 +1,1123 @@ // -*- C++ -*- // // QTildeSudakov.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 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 QTildeSudakov class. // #include "QTildeSudakov.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Shower/Default/FS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/Default/IS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/Default/Decay_QTildeShowerKinematics1to2.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/Base/ShowerVertex.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/Base/Evolver.h" #include "Herwig/Shower/Base/PartnerFinder.h" #include "Herwig/Shower/Base/ShowerModel.h" #include "Herwig/Shower/Base/KinematicsReconstructor.h" using namespace Herwig; DescribeNoPIOClass<QTildeSudakov,Herwig::SudakovFormFactor> describeQTildeSudakov ("Herwig::QTildeSudakov","HwShower.so"); void QTildeSudakov::Init() { static ClassDocumentation<QTildeSudakov> documentation ("The QTildeSudakov class implements the Sudakov form factor for ordering it" " qtilde"); } -bool QTildeSudakov::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance) { +bool QTildeSudakov::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance, + const 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]); + 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(t<tmin) { t=-1.0*GeV2; return false; } else return true; } bool QTildeSudakov::guessSpaceLike(Energy2 &t, Energy2 tmin, const double x, - double enhance) { + double enhance, + const double & detune) { Energy2 told = t; // calculate limits on z if lower>upper return if(!computeSpaceLikeLimits(t,x)) return false; // guess values of t and z - t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2]); + 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<tmin) { t=-1.0*GeV2; return false; } else return true; } bool QTildeSudakov::PSVeto(const Energy2 t, const Energy2 maxQ2) { // still inside PS, return true if outside // check vs overestimated limits if(z() < zLimits().first || z() > zLimits().second) return true; Energy2 q2 = z()*(1.-z())*t; if(ids_[0]!=ParticleID::g && ids_[0]!=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<pT2min()) return true; // otherwise calculate pt and return pT(sqrt(pt2)); return false; } + + ShoKinPtr QTildeSudakov::generateNextTimeBranching(const Energy startingScale, const IdList &ids,const bool cc, - double enhance, Energy2 maxQ2) { + double enhance, + double detuning, + Energy2 maxQ2) { // 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 initialization Energy2 tmax(sqr(startingScale)),tmin; initialize(ids,tmin,cc); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax); bool calcVariations=!ShowerHandler::currentHandler()->showerVariations().empty(); if(!calcVariations){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { - if(!guessTimeLike(t,tmin,enhance)) break; + if(!guessTimeLike(t,tmin,enhance,detuning)) break; } while(PSVeto(t,maxQ2) || - SplittingFnVeto(z()*(1.-z())*t,ids,true) || + SplittingFnVeto(z()*(1.-z())*t,ids,true,detuning) || alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); }else{ bool alphaRew(true),PSRew(true),SplitRew(true); do { - if(!guessTimeLike(t,tmin,enhance)) break; + if(!guessTimeLike(t,tmin,enhance,detuning)) break; PSRew=PSVeto(t,maxQ2); if (PSRew) continue; - SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true); + SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,detuning); alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t); double factor=alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)* - SplittingFnVetoRatio(z()*(1.-z())*t,ids,true); + SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,detuning); ShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map<string,ShowerHandler::ShowerVariation>::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()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,var->second.renormalizationScaleFactor) - * SplittingFnVetoRatio(z()*(1.-z())*t,ids,true); + * SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,detuning); double varied; if ( SplitRew || alphaRew ) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map<string,double>::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 QTildeSudakov:: generateNextSpaceBranching(const Energy startingQ, const IdList &ids, double x,bool cc, double enhance, - Ptr<BeamParticleData>::transient_const_pointer beam) { + Ptr<BeamParticleData>::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,cc); // check max > min if(tmax<=tmin) return ShoKinPtr(); // extract the partons which are needed for the PDF veto // Different order, incoming parton is id = 1, outgoing are id=0,2 tcPDPtr parton0 = getParticleData(ids[0]); tcPDPtr parton1 = getParticleData(ids[1]); if(cc) { if(parton0->CC()) parton0 = parton0->CC(); if(parton1->CC()) parton1 = parton1->CC(); - } + } // calculate next value of t using veto algorithm Energy2 t(tmax),pt2(ZERO); bool calcVariations=!ShowerHandler::currentHandler()->showerVariations().empty(); if(!calcVariations){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { - if(!guessSpaceLike(t,tmin,x,enhance)) break; + 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,true)|| + SplittingFnVeto((1.-z())*t/z(),ids,true,detuning)|| alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t)|| PDFVeto(t,x,parton0,parton1,beam)); }else{ bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true); do { - if(!guessSpaceLike(t,tmin,x,enhance)) break; + 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,true); + SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,true,detuning); alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t); PDFRew=PDFVeto(t,x,parton0,parton1,beam); double factor=PDFVetoRatio(t,x,parton0,parton1,beam,1.)* alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t,1.)* - SplittingFnVetoRatio((1.-z())*t/z(),ids,true); + SplittingFnVetoRatio((1.-z())*t/z(),ids,true,detuning); ShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(PDFRew || SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } for ( map<string,ShowerHandler::ShowerVariation>::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,parton0,parton1,beam,var->second.factorizationScaleFactor)* alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t,var->second.renormalizationScaleFactor) - *SplittingFnVetoRatio((1.-z())*t/z(),ids,true); + *SplittingFnVetoRatio((1.-z())*t/z(),ids,true,detuning); double varied; if( PDFRew || SplitRew || alphaRew) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map<string,double>::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 QTildeSudakov::initialize(const IdList & ids, Energy2 & tmin,const bool cc) { ids_=ids; if(cc) { for(unsigned int ix=0;ix<ids.size();++ix) { if(getParticleData(ids[ix])->CC()) ids_[ix]*=-1; } } tmin = cutOffOption() != 2 ? ZERO : 4.*pT2min(); masses_ = virtualMasses(ids); masssquared_.clear(); for(unsigned int ix=0;ix<masses_.size();++ix) { masssquared_.push_back(sqr(masses_[ix])); if(ix>0) tmin=max(masssquared_[ix],tmin); } } ShoKinPtr QTildeSudakov::generateNextDecayBranching(const Energy startingScale, - const Energy stoppingScale, - const Energy minmass, - const IdList &ids, - const bool cc, - double enhance) { + const Energy stoppingScale, + const Energy minmass, + const IdList &ids, + const bool cc, + 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,cc); 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)) break; + 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)|| + while(SplittingFnVeto((1.-z())*t/z(),ids,true,detuning)|| alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t ) || pt2<pT2min() || t*(1.-z())>masssquared_[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 QTildeSudakov::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass, - double enhance) { + double enhance, const double & detune) { // previous scale Energy2 told = t; // overestimated limits on z if(tmax<masssquared_[0]) { t=-1.0*GeV2; return false; } Energy2 tm2 = tmax-masssquared_[0]; Energy tm = sqrt(tm2); pair<double,double> limits=make_pair(sqr(minmass/masses_[0]), 1.-sqrt(masssquared_[2]+pT2min()+ 0.25*sqr(masssquared_[2])/tm2)/tm +0.5*masssquared_[2]/tm2); zLimits(limits); if(zLimits().second<zLimits().first) { t=-1.0*GeV2; return false; } // guess values of t and z - t = guesst(told,2,ids_,enhance,ids_[1]==ids_[2]); + t = guesst(told,2,ids_,enhance,ids_[1]==ids_[2],detune); z(guessz(2,ids_)); // actual values for z-limits if(t<masssquared_[0]) { t=-1.0*GeV2; return false; } tm2 = t-masssquared_[0]; tm = sqrt(tm2); limits=make_pair(sqr(minmass/masses_[0]), 1.-sqrt(masssquared_[2]+pT2min()+ 0.25*sqr(masssquared_[2])/tm2)/tm +0.5*masssquared_[2]/tm2); zLimits(limits); if(t>tmax||zLimits().second<zLimits().first) { t=-1.0*GeV2; return false; } else return true; } bool QTildeSudakov::computeTimeLikeLimits(Energy2 & t) { if (t < 1e-20 * GeV2) { t=-1.*GeV2; return false; } // special case for gluon radiating pair<double,double> limits; if(ids_[0]==ParticleID::g||ids_[0]==ParticleID::gamma) { // no emission possible if(t<16.*(masssquared_[1]+pT2min())) { t=-1.*GeV2; return false; } // overestimate of the limits limits.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min())/t))); limits.second = 1.-limits.first; } // special case for radiated particle is gluon else if(ids_[2]==ParticleID::g||ids_[2]==ParticleID::gamma) { limits.first = sqrt((masssquared_[1]+pT2min())/t); limits.second = 1.-sqrt((masssquared_[2]+pT2min())/t); } else if(ids_[1]==ParticleID::g||ids_[1]==ParticleID::gamma) { limits.second = sqrt((masssquared_[2]+pT2min())/t); limits.first = 1.-sqrt((masssquared_[1]+pT2min())/t); } else { limits.first = (masssquared_[1]+pT2min())/t; limits.second = 1.-(masssquared_[2]+pT2min())/t; } if(limits.first>=limits.second) { t=-1.*GeV2; return false; } zLimits(limits); return true; } bool QTildeSudakov::computeSpaceLikeLimits(Energy2 & t, double x) { if (t < 1e-20 * GeV2) { t=-1.*GeV2; return false; } pair<double,double> limits; // compute the limits limits.first = x; double yy = 1.+0.5*masssquared_[2]/t; limits.second = yy - sqrt(sqr(yy)-1.+pT2min()/t); // return false if lower>upper zLimits(limits); if(limits.second<limits.first) { t=-1.*GeV2; return false; } else return true; } namespace { tShowerParticlePtr findCorrelationPartner(ShowerParticle & particle, bool forward, ShowerInteraction::Type inter) { tPPtr child = &particle; tShowerParticlePtr mother; if(forward) { mother = !particle.parents().empty() ? dynamic_ptr_cast<tShowerParticlePtr>(particle.parents()[0]) : tShowerParticlePtr(); } else { mother = particle.children().size()==2 ? dynamic_ptr_cast<tShowerParticlePtr>(&particle) : tShowerParticlePtr(); } tShowerParticlePtr partner; while(mother) { tPPtr otherChild; if(forward) { for (unsigned int ix=0;ix<mother->children().size();++ix) { if(mother->children()[ix]!=child) { otherChild = mother->children()[ix]; break; } } } else { otherChild = mother->children()[1]; } tShowerParticlePtr other = dynamic_ptr_cast<tShowerParticlePtr>(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<tShowerParticlePtr>(mother); break; } child = mother; if(forward) { mother = ! mother->parents().empty() ? dynamic_ptr_cast<tShowerParticlePtr>(mother->parents()[0]) : tShowerParticlePtr(); } else { if(mother->children()[0]->children().size()!=2) break; tShowerParticlePtr mtemp = dynamic_ptr_cast<tShowerParticlePtr>(mother->children()[0]); if(!mtemp) break; else mother=mtemp; } } if(!partner) { if(forward) { partner = dynamic_ptr_cast<tShowerParticlePtr>( child)->partner(); } else { if(mother) { tShowerParticlePtr parent; if(!mother->children().empty()) { parent = dynamic_ptr_cast<tShowerParticlePtr>(mother->children()[0]); } if(!parent) { parent = dynamic_ptr_cast<tShowerParticlePtr>(mother); } partner = parent->partner(); } else { partner = dynamic_ptr_cast<tShowerParticlePtr>(&particle)->partner(); } } } return partner; } pair<double,double> 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); 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 QTildeSudakov::generatePhiForward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics) { // no correlations, return flat phi if(! ShowerHandler::currentHandler()->evolver()->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]==ParticleID::g || ids[1]==ParticleID::gamma, ids[2]==ParticleID::g || ids[2]==ParticleID::gamma }; vector<Energy2> pjk(3,ZERO); vector<Energy> Ek(3,ZERO); Energy Ei,Ej; Energy2 m12(ZERO),m22(ZERO); InvEnergy2 aziMax(ZERO); bool softAllowed = ShowerHandler::currentHandler()->evolver()->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 vector<Lorentz5Momentum> basis = kinematics->getBasis(); Lorentz5Momentum pVect = basis[0], nVect = basis[1]; Boost beta_bb; if(kinematics->frame()==ShowerKinematics::BackToBack) { beta_bb = -(pVect + nVect).boostVector(); } else if(kinematics->frame()==ShowerKinematics::Rest) { beta_bb = -pVect.boostVector(); } else assert(false); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis; if(kinematics->frame()==ShowerKinematics::BackToBack) { axis = pVect.vect().unit(); } else if(kinematics->frame()==ShowerKinematics::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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->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<double,double> 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<pair<int,Complex> > wgts; if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { // get the spin density matrix and the mapping RhoDMatrix mapping; SpinPtr inspin; bool needMapping = getMapping(inspin,mapping,particle,kinematics); // set the decayed flag inspin->decay(); // get the spin density matrix RhoDMatrix rho=inspin->rhoMatrix(); // map to the shower basis if needed if(needMapping) { RhoDMatrix rhop(rho.iSpin(),false); for(int ixa=0;ixa<rho.iSpin();++ixa) { for(int ixb=0;ixb<rho.iSpin();++ixb) { for(int iya=0;iya<rho.iSpin();++iya) { for(int iyb=0;iyb<rho.iSpin();++iyb) { rhop(ixa,ixb) += rho(iya,iyb)*mapping(iya,ixa)*conj(mapping(iyb,ixb)); } } } } rhop.normalize(); rho = rhop; } // calculate the weights wgts = splittingFn()->generatePhiForward(z,t,ids,rho); } else { wgts = vector<pair<int,Complex> >(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;ix<wgts.size();++ix) { if(wgts[ix].first==0) spinWgt += wgts[ix].second; else spinWgt += exp(double(wgts[ix].first)*ii*phi)*wgts[ix].second; } wgt = spinWgt.real(); if(wgt-1.>1e-10) { generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1. << " " << ids[0] << " " << ids[1] << " " << ids[2] << " " << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ix<wgts.size();++ix) generator()->log() << 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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->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] << " " << ids[1] << " " << ids[2] << " " << " " << phi << "\n"; } } else { aziWgt = 0.; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgt<UseRandom::rnd()&&ntry<10000); if(ntry==10000) { generator()->log() << "Too many tries to generate phi in forward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double QTildeSudakov::generatePhiBackward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics) { // no correlations, return flat phi if(! ShowerHandler::currentHandler()->evolver()->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 = ShowerHandler::currentHandler()->evolver()->softCorrelations() && (ids[2]==ParticleID::g || ids[2]==ParticleID::gamma); Energy2 pipj,pik,m12(ZERO),m22(ZERO); vector<Energy2> pjk(3,ZERO); 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 vector<Lorentz5Momentum> basis = kinematics->getBasis(); Lorentz5Momentum pVect = basis[0]; Lorentz5Momentum nVect = basis[1]; assert(kinematics->frame()==ShowerKinematics::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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==0); } } // if spin correlations vector<pair<int,Complex> > wgts; if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { // get the spin density matrix and the mapping RhoDMatrix mapping; SpinPtr inspin; bool needMapping = getMapping(inspin,mapping,particle,kinematics); // set the decayed flag (counterintuitive but going backward) inspin->decay(); // get the spin density matrix RhoDMatrix rho=inspin->DMatrix(); // map to the shower basis if needed if(needMapping) { RhoDMatrix rhop(rho.iSpin(),false); for(int ixa=0;ixa<rho.iSpin();++ixa) { for(int ixb=0;ixb<rho.iSpin();++ixb) { for(int iya=0;iya<rho.iSpin();++iya) { for(int iyb=0;iyb<rho.iSpin();++iyb) { rhop(ixa,ixb) += rho(iya,iyb)*mapping(iya,ixa)*conj(mapping(iyb,ixb)); } } } } rhop.normalize(); rho = rhop; } wgts = splittingFn()->generatePhiBackward(z,t,ids,rho); } else { wgts = vector<pair<int,Complex> >(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;ix<wgts.size();++ix) { if(wgts[ix].first==0) spinWgt += wgts[ix].second; else spinWgt += exp(double(wgts[ix].first)*ii*phi)*wgts[ix].second; } wgt = spinWgt.real(); if(wgt-1.>1e-10) { generator()->log() << "Backward weight problem " << wgt << " " << wgt-1. << " " << ids[0] << " " << ids[1] << " " << ids[2] << " " << " " << z << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ix<wgts.size();++ix) generator()->log() << 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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->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] << " " << ids[1] << " " << ids[2] << " " << " " << phi << "\n"; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgt<UseRandom::rnd()&&ntry<10000); if(ntry==10000) { generator()->log() << "Too many tries to generate phi in backward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double QTildeSudakov::generatePhiDecay(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics) { // only soft correlations in this case // no correlations, return flat phi if( !(ShowerHandler::currentHandler()->evolver()->softCorrelations() && (ids[2]==ParticleID::g || ids[2]==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); vector<Lorentz5Momentum> basis = kinematics->getBasis(); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = basis[0]; Lorentz5Momentum nVect = basis[1]; assert(kinematics->frame()==ShowerKinematics::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 vector<Energy2> pjk(3,ZERO); 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; vector<Energy> Ek(3,ZERO); Energy Ei,Ej; if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->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(ShowerHandler::currentHandler()->evolver()->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(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->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] << " " << ids[1] << " " << ids[2] << " " << " " << phi << "\n"; } if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgt<UseRandom::rnd()&&ntry<10000); if(ntry==10000) { phi = phiMax; generator()->log() << "Too many tries to generate phi\n"; } // return the azimuthal angle return phi; } Energy QTildeSudakov::calculateScale(double zin, Energy pt, IdList ids, unsigned int iopt) { Energy2 tmin; initialize(ids,tmin,false); // final-state branching if(iopt==0) { Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin); if(ids[0]!=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 QTildeSudakov::calculateScale() " << "iopt = " << iopt << Exception::runerror; } } ShoKinPtr QTildeSudakov::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 QTildeSudakov::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 QTildeSudakov::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/Default/QTildeSudakov.h b/Shower/Default/QTildeSudakov.h --- a/Shower/Default/QTildeSudakov.h +++ b/Shower/Default/QTildeSudakov.h @@ -1,287 +1,291 @@ // -*- C++ -*- // // QTildeSudakov.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_QTildeSudakov_H #define HERWIG_QTildeSudakov_H // // This is the declaration of the QTildeSudakov class. // #include "Herwig/Shower/Base/SudakovFormFactor.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * The QTildeSudakov class implements the Sudakov form factor for evolution in * \f$\tilde{q}^2\f$ using the veto algorithm. * * @see \ref QTildeSudakovInterfaces "The interfaces" * defined for QTildeSudakov. */ class QTildeSudakov: public SudakovFormFactor { public: /** * The default constructor. */ inline QTildeSudakov() {} /** * 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 cc Whether this is the charge conjugate of the branching * defined. * @param enhance The radiation enhancement factor * @param maxQ2 The maximum \f$Q^2\f$ for the emission */ virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale, const IdList &ids,const bool cc, - double enhance, Energy2 maxQ2); + 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 * @param cc Whether this is the charge conjugate of the branching * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, - const Energy stoppingScale, - const Energy minmass, - const IdList &ids, - const bool cc, - double enhance); + const Energy stoppingScale, + const Energy minmass, + const IdList &ids, + const bool cc, + 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 * @param cc Whether this is the charge conjugate of the branching * defined. * @param enhance The radiation enhancement factor * @param beam The beam particle */ virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale, const IdList &ids,double x, const bool cc, double enhance, - tcBeamPtr beam); + tcBeamPtr beam, + double detuning); //@} /** * Generate the azimuthal angle of the branching for forward branching * @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); /** * Generate the azimuthal angle of the branching for backward branching * @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); /** * 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); /** * 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: /** * 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); + bool guessTimeLike(Energy2 &t, Energy2 tmin, double enhance, const 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 enhance, const 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 enhance, const 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 * @param cc Whether this is the charge conjugate of the branching */ void initialize(const IdList & ids,Energy2 &tmin, const bool cc); /** * 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: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ inline 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. */ inline 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. */ QTildeSudakov & operator=(const QTildeSudakov &); 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<Energy> masses_; /** * The mass squared of the particles in the current branching */ vector<Energy2> masssquared_; }; } #endif /* HERWIG_QTildeSudakov_H */ diff --git a/Shower/SplittingFunctions/SplittingGenerator.cc b/Shower/SplittingFunctions/SplittingGenerator.cc --- a/Shower/SplittingFunctions/SplittingGenerator.cc +++ b/Shower/SplittingFunctions/SplittingGenerator.cc @@ -1,577 +1,585 @@ // -*- C++ -*- // // SplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 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 SplittingGenerator class. // #include "SplittingGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" +#include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/Repository.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "ThePEG/Utilities/Rebinder.h" #include <cassert> #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeClass<SplittingGenerator,Interfaced> describeSplittingGenerator ("Herwig::SplittingGenerator",""); IBPtr SplittingGenerator::clone() const { return new_ptr(*this); } IBPtr SplittingGenerator::fullclone() const { return new_ptr(*this); } void SplittingGenerator::persistentOutput(PersistentOStream & os) const { - os << _isr_Mode << _fsr_Mode << _bbranchings << _fbranchings; + os << _isr_Mode << _fsr_Mode << _bbranchings << _fbranchings << _deTuning; } void SplittingGenerator::persistentInput(PersistentIStream & is, int) { - is >> _isr_Mode >> _fsr_Mode >> _bbranchings >> _fbranchings; + is >> _isr_Mode >> _fsr_Mode >> _bbranchings >> _fbranchings >> _deTuning; } void SplittingGenerator::Init() { static ClassDocumentation<SplittingGenerator> documentation ("There class is responsible for initializing the Sudakov form factors ", "and generating splittings."); static Switch<SplittingGenerator, bool> interfaceISRMode ("ISR", "Include initial-state radiation?", &SplittingGenerator::_isr_Mode, 1, false, false); static SwitchOption interfaceISRMode0 (interfaceISRMode,"No","ISR (Initial State Radiation) is OFF", 0); static SwitchOption interfaceISRMode1 (interfaceISRMode,"Yes","ISR (Initial State Radiation) is ON", 1); static Switch<SplittingGenerator, bool> interfaceFSRMode ("FSR", "Include final-state radiation?", &SplittingGenerator::_fsr_Mode, 1, false, false); static SwitchOption interfaceFSRMode0 (interfaceFSRMode,"No","FSR (Final State Radiation) is OFF", 0); static SwitchOption interfaceFSRMode1 (interfaceFSRMode,"Yes","FSR (Final State Radiation) is ON", 1); static Command<SplittingGenerator> interfaceAddSplitting ("AddFinalSplitting", "Adds another splitting to the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::addFinalSplitting); static Command<SplittingGenerator> interfaceAddInitialSplitting ("AddInitialSplitting", "Adds another splitting to the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::addInitialSplitting); static Command<SplittingGenerator> interfaceDeleteSplitting ("DeleteFinalSplitting", "Deletes a splitting from the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::deleteFinalSplitting); static Command<SplittingGenerator> interfaceDeleteInitialSplitting ("DeleteInitialSplitting", "Deletes a splitting from the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::deleteInitialSplitting); + + static Parameter<SplittingGenerator,double> interfaceDetuning + ("Detuning", + "The Detuning parameter to make the veto algorithm less efficient to improve the weight variations", + &SplittingGenerator::_deTuning, 1.0, 1.0, 10.0, + false, false, Interface::limited); + } string SplittingGenerator::addSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector<tPDPtr> products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent->id()); for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back((*it)->id()); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + "can't handle particles\n"; // add to map addToMap(ids,s,final); return ""; } string SplittingGenerator::deleteSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector<tPDPtr> products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent->id()); for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back((*it)->id()); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + "can't handle particles\n"; // delete from map deleteFromMap(ids,s,final); return ""; } void SplittingGenerator::addToMap(const IdList &ids, const SudakovPtr &s, bool final) { if(isISRadiationON() && !final) { _bbranchings.insert(BranchingInsert(ids[1],BranchingElement(s,ids))); s->addSplitting(ids); } if(isFSRadiationON() && final) { _fbranchings.insert(BranchingInsert(ids[0],BranchingElement(s,ids))); s->addSplitting(ids); } } void SplittingGenerator::deleteFromMap(const IdList &ids, const SudakovPtr &s, bool final) { if(isISRadiationON() && !final) { pair<BranchingList::iterator,BranchingList::iterator> range = _bbranchings.equal_range(ids[1]); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_bbranchings.end()&&it->first==ids[1];++it) { if(it->second.first==s&&it->second.second==ids) { BranchingList::iterator it2=it; --it; _bbranchings.erase(it2); } } s->removeSplitting(ids); } if(isFSRadiationON() && final) { pair<BranchingList::iterator,BranchingList::iterator> range = _fbranchings.equal_range(ids[0]); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_fbranchings.end()&&it->first==ids[0];++it) { if(it->second.first==s&&it->second.second==ids) { BranchingList::iterator it2 = it; --it; _fbranchings.erase(it2); } } s->removeSplitting(ids); } } Branching SplittingGenerator::chooseForwardBranching(ShowerParticle &particle, double enhance, ShowerInteraction::Type type) const { Energy newQ = ZERO; ShoKinPtr kinematics = ShoKinPtr(); ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov = SudakovPtr(); IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if( _fbranchings.find(index) == _fbranchings.end() ) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check either right interaction or doing both if(type != cit->second.first->interactionType() && type != ShowerInteraction::Both ) continue; // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.first->splittingFn()->angularOrdered(); ShoKinPtr newKin; ShowerPartnerType::Type type; // work out which starting scale we need if(cit->second.first->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin = cit->second.first-> generateNextTimeBranching(startingScale,cit->second.second, - particle.id()!=cit->first,enhance, + particle.id()!=cit->first,enhance,_deTuning, particle.scales().Max_Q2); } else if(cit->second.first->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.first->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin= cit->second.first-> generateNextTimeBranching(startingScale,cit->second.second, - particle.id()!=cit->first,0.5*enhance, + particle.id()!=cit->first,0.5*enhance,_deTuning, particle.scales().Max_Q2); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.first-> generateNextTimeBranching(startingScale,cit->second.second, - particle.id()!=cit->first,0.5*enhance, + particle.id()!=cit->first,0.5*enhance,_deTuning, particle.scales().Max_Q2); // pick the one with the highest scale if( ( newKin && newKin2 && newKin2->scale() > newKin->scale()) || (!newKin && newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other g -> q qbar else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); newKin= cit->second.first-> generateNextTimeBranching(startingScale, cit->second.second, - particle.id()!=cit->first,enhance, + particle.id()!=cit->first,enhance,_deTuning, particle.scales().Max_Q2); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; } } // everything else q-> qg etc else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin= cit->second.first-> generateNextTimeBranching(startingScale,cit->second.second, - particle.id()!=cit->first,enhance, + particle.id()!=cit->first,enhance,_deTuning, particle.scales().Max_Q2); } } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if( newKin->scale() > newQ ) { kinematics = newKin; newQ = newKin->scale(); ids = cit->second.second; sudakov = cit->second.first; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // If a branching has been selected initialize it kinematics->initialize(particle,PPtr()); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseDecayBranching(ShowerParticle &particle, const ShowerParticle::EvolutionScales & stoppingScales, Energy minmass, double enhance, ShowerInteraction::Type interaction) const { Energy newQ = Constants::MaxEnergy; ShoKinPtr kinematics; SudakovPtr sudakov; ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); IdList ids; // First, find the eventual branching, corresponding to the lowest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if(_fbranchings.find(index) == _fbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check interaction doesn't change flavour if(cit->second.second[1]!=index&&cit->second.second[2]!=index) continue; // check either right interaction or doing both if(interaction != cit->second.first->interactionType() && interaction != ShowerInteraction::Both ) continue; // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.first->splittingFn()->angularOrdered(); ShoKinPtr newKin; ShowerPartnerType::Type type; // work out which starting scale we need if(cit->second.first->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy stoppingScale = angularOrdered ? stoppingScales.QED : stoppingScales.QED_noAO; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; if(startingScale < stoppingScale ) { newKin = cit->second.first-> generateNextDecayBranching(startingScale,stoppingScale,minmass,cit->second.second, - particle.id()!=cit->first,enhance); + particle.id()!=cit->first,enhance,_deTuning); } } else if(cit->second.first->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.first->splittingFn()->colourStructure()==OctetOctetOctet) { Energy stoppingColour = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; Energy stoppingAnti = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; Energy startingColour = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; Energy startingAnti = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; type = ShowerPartnerType::QCDColourLine; if(startingColour<stoppingColour) { newKin= cit->second.first-> generateNextDecayBranching(startingColour,stoppingColour,minmass, cit->second.second, - particle.id()!=cit->first,0.5*enhance); + particle.id()!=cit->first,0.5*enhance,_deTuning); } ShoKinPtr newKin2; if(startingAnti<stoppingAnti) { newKin2 = cit->second.first-> generateNextDecayBranching(startingAnti,stoppingAnti,minmass, cit->second.second, - particle.id()!=cit->first,0.5*enhance); + particle.id()!=cit->first,0.5*enhance,_deTuning); } // pick the one with the lowest scale if( (newKin&&newKin2&&newKin2->scale()<newKin->scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other else { assert(false); } } // everything else else { Energy startingScale,stoppingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } if(startingScale < stoppingScale ) { newKin = cit->second.first-> generateNextDecayBranching(startingScale,stoppingScale,minmass,cit->second.second, - particle.id()!=cit->first,enhance); + particle.id()!=cit->first,enhance,_deTuning); } } } // shouldn't be anything else else assert(false); if(!newKin) continue; // select highest scale if(newKin->scale() < newQ ) { newQ = newKin->scale(); ids = cit->second.second; kinematics=newKin; sudakov=cit->second.first; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // initialize the branching kinematics->initialize(particle,PPtr()); // and generate phi kinematics->phi(sudakov->generatePhiDecay(particle,ids,kinematics)); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseBackwardBranching(ShowerParticle &particle,PPtr beamparticle, double enhance, Ptr<BeamParticleData>::transient_const_pointer beam, ShowerInteraction::Type type, tcPDFPtr pdf, Energy freeze) const { Energy newQ=ZERO; ShoKinPtr kinematics=ShoKinPtr(); ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov; IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.id()); // if no possible branching return if(_bbranchings.find(index) == _bbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _bbranchings.lower_bound(index); cit != _bbranchings.upper_bound(index); ++cit ) { // check either right interaction or doing both if(type != cit->second.first->interactionType() && type != ShowerInteraction::Both ) continue; // setup the PDF cit->second.first->setPDF(pdf,freeze); // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.first->splittingFn()->angularOrdered(); ShoKinPtr newKin; ShowerPartnerType::Type type; if(cit->second.first->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin=cit->second.first-> generateNextSpaceBranching(startingScale,cit->second.second, particle.x(), - particle.id()!=cit->first,enhance,beam); + particle.id()!=cit->first,enhance,beam,_deTuning); } else if(cit->second.first->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.first->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin = cit->second.first-> generateNextSpaceBranching(startingScale,cit->second.second, particle.x(), - particle.id()!=cit->first,0.5*enhance,beam); + particle.id()!=cit->first,0.5*enhance,beam,_deTuning); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.first-> generateNextSpaceBranching(startingScale,cit->second.second, particle.x(), - particle.id()!=cit->first,0.5*enhance,beam); + particle.id()!=cit->first,0.5*enhance,beam,_deTuning); // pick the one with the highest scale if( (newKin&&newKin2&&newKin2->scale()>newKin->scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; newKin=cit->second.first-> generateNextSpaceBranching(startingScale,cit->second.second, particle.x(), - particle.id()!=cit->first,enhance,beam); + particle.id()!=cit->first,enhance,beam,_deTuning); } } // everything else else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin=cit->second.first-> generateNextSpaceBranching(startingScale,cit->second.second, particle.x(), - particle.id()!=cit->first,enhance,beam); + particle.id()!=cit->first,enhance,beam,_deTuning); } } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if(newKin->scale() > newQ) { newQ = newKin->scale(); kinematics=newKin; ids = cit->second.second; sudakov=cit->second.first; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // initialize the ShowerKinematics // and return it kinematics->initialize(particle,beamparticle); // and generate phi kinematics->phi(sudakov->generatePhiBackward(particle,ids,kinematics)); // return the answer return Branching(kinematics, ids,sudakov,partnerType); } void SplittingGenerator::rebind(const TranslationMap & trans) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {(cit->second).first=trans.translate((cit->second).first);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {(cit->second).first=trans.translate((cit->second).first);} Interfaced::rebind(trans); } IVector SplittingGenerator::getReferences() { IVector ret = Interfaced::getReferences(); BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {ret.push_back((cit->second).first);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {ret.push_back((cit->second).first);} return ret; } void SplittingGenerator::factorizationScaleFactor(double f) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {(cit->second).first->factorizationScaleFactor(f);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {(cit->second).first->factorizationScaleFactor(f);} } void SplittingGenerator::renormalizationScaleFactor(double f) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {(cit->second).first->renormalizationScaleFactor(f);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {(cit->second).first->renormalizationScaleFactor(f);} } diff --git a/Shower/SplittingFunctions/SplittingGenerator.h b/Shower/SplittingFunctions/SplittingGenerator.h --- a/Shower/SplittingFunctions/SplittingGenerator.h +++ b/Shower/SplittingFunctions/SplittingGenerator.h @@ -1,355 +1,360 @@ // -*- C++ -*- // // SplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 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/Base/Branching.h" #include "Herwig/Shower/Base/SudakovFormFactor.h" #include "SplittingGenerator.fh" #include "Herwig/Shower/Base/ShowerParticle.h" #include "Herwig/Shower/Base/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() : _isr_Mode(1), _fsr_Mode(1) {} + SplittingGenerator() : _isr_Mode(1), _fsr_Mode(1), _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 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 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<BeamParticleData>::transient_const_pointer beam, ShowerInteraction::Type type, tcPDFPtr , Energy ) const; //@} public: /** * Access to the switches */ //@{ /** * It returns true/false if the initial-state radiation is on/off. */ bool isISRadiationON() const { return _isr_Mode; } /** * It returns true/false if the final-state radiation is on/off. */ bool isFSRadiationON() const { return _fsr_Mode; } //@} /** * 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; } //@} /** * Set the factorization scale factor */ void factorizationScaleFactor(double f); /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f); 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: /** * Switches to control the radiation */ //@{ /** * Is inqitial-state radiation on/off */ bool _isr_Mode; /** * Is final-state radiation on/off */ bool _fsr_Mode; //@} /** * 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/src/DIS-Matchbox.in b/src/DIS-Matchbox.in --- a/src/DIS-Matchbox.in +++ b/src/DIS-Matchbox.in @@ -1,147 +1,151 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Matchbox example input file ################################################## ################################################## ## Collider type ################################################## read Matchbox/EPCollider.in ################################################## ## Beam energies ################################################## cd /Herwig/EventHandlers set EventHandler:BeamA /Herwig/Particles/e+ set EventHandler:LuminosityFunction:BeamEMaxA 27.5.*GeV set EventHandler:BeamB /Herwig/Particles/p+ set EventHandler:LuminosityFunction:BeamEMaxB 820.*GeV # no pdfs for leptons set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. +## Model assumptions +read Matchbox/StandardModelLike.in +read Matchbox/DiagonalCKM.in + ## Set the order of the couplings cd /Herwig/MatrixElements/Matchbox set Factory:OrderInAlphaS 0 set Factory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do Factory:Process e+ p -> e+ j ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in # read Matchbox/MadGraph-OpenLoops.in ################################################## ## Cut selection ## See the documentation for more options ################################################## ## cuts on additional jets # read Matchbox/DefaultEPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonQ2Scale ################################################## ## Matching and shower selection ## Please also see flavour scheme settings ## towards the end of the input file. ################################################## read Matchbox/MCatNLO-DefaultShower.in # read Matchbox/Powheg-DefaultShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DefaultShower.in ## use for improved LO showering # read Matchbox/LO-DefaultShower.in # read Matchbox/MCatNLO-DipoleShower.in # read Matchbox/Powheg-DipoleShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DipoleShower.in ## use for improved LO showering # read Matchbox/LO-DipoleShower.in # read Matchbox/NLO-NoShower.in # read Matchbox/LO-NoShower.in ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourScheme.in ## required for dipole shower and fixed order in five flavour scheme # read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## # cd /Herwig/Analysis # insert Rivet:Analyses 0 XXX_2015_ABC123 # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC ################################################## ## Save the generator ################################################## do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode cd /Herwig/Generators saverun DIS-Matchbox EventGenerator diff --git a/src/Herwig.cc b/src/Herwig.cc --- a/src/Herwig.cc +++ b/src/Herwig.cc @@ -1,302 +1,303 @@ // -*- C++ -*- // // Herwig.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "Herwig.h" #include "HerwigUI.h" #include <ThePEG/Persistency/PersistentIStream.h> #include <ThePEG/Repository/EventGenerator.h> #include <ThePEG/Utilities/DynamicLoader.h> #include <ThePEG/Utilities/Debug.h> #include <ThePEG/Repository/Repository.h> #include <ThePEG/Handlers/SamplerBase.h> #include <ThePEG/Handlers/StandardEventHandler.h> #include <iostream> #include <sstream> #include <unistd.h> #include <sys/wait.h> #include <boost/filesystem.hpp> #include "Herwig/Utilities/RunDirectories.h" using namespace ThePEG; namespace { /** * Search paths for Repository read * * You can pass two string vectors with directories which Herwig will use to look in for files. * A vector with directories which will be prepended and a vector with directories which will be appended. * Both vectors are optional. */ void setSearchPaths(const Herwig::HerwigUI & ui, bool usePWD = true); void HerwigGenericRead(const Herwig::HerwigUI & ui); void HerwigGenericRun(const Herwig::HerwigUI & ui); } namespace Herwig { namespace API { void init(const HerwigUI & ui) { setSearchPaths(ui, false); SamplerBase::setRunLevel(SamplerBase::InitMode); string infile = ui.inputfile(); // If status is INIT, we need an infile name / runname if (infile.empty()) infile = "HerwigDefaults.in"; breakThePEG(); { # ifdef HERWIG_PKGLIBDIR DynamicLoader::appendPath(HERWIG_PKGLIBDIR); # endif # ifdef THEPEG_PKGLIBDIR DynamicLoader::appendPath(THEPEG_PKGLIBDIR); # endif HoldFlag<> setup(InterfaceBase::NoReadOnly); string msg = Repository::read(infile, cout); if ( ! msg.empty() ) cerr << msg << '\n'; Repository::update(); } Repository::save(ui.repository()); } void read(const HerwigUI & ui) { setSearchPaths(ui); SamplerBase::setRunLevel(SamplerBase::ReadMode); HerwigGenericRead(ui); } void build(const HerwigUI & ui) { setSearchPaths(ui); SamplerBase::setRunLevel(SamplerBase::BuildMode); HerwigGenericRead(ui); } void integrate(const HerwigUI & ui) { setSearchPaths(ui); SamplerBase::setRunLevel(SamplerBase::IntegrationMode); HerwigGenericRun(ui); } void mergegrids(const HerwigUI & ui) { setSearchPaths(ui); SamplerBase::setRunLevel(SamplerBase::RunMode); HerwigGenericRun(ui); } void run(const HerwigUI & ui) { setSearchPaths(ui); SamplerBase::setRunLevel(SamplerBase::RunMode); HerwigGenericRun(ui); } } } namespace { void setSearchPaths(const Herwig::HerwigUI & ui, bool usePWD) { // Search path for read command uses CWD first if ( usePWD ) { string cwd = boost::filesystem::current_path().string(); Repository::prependReadDir( cwd ); } // append command line choices for directories from which Herwig will read. Repository::appendReadDir(ui.appendReadDirectories()); Repository::prependReadDir(ui.prependReadDirectories()); } //void HerwigGenericRead(string reponame, string runname, const gengetopt_args_info & args_info) void HerwigGenericRead(const Herwig::HerwigUI & ui) { string reponame = ui.repository(); #ifdef HERWIG_PKGDATADIR ifstream test(reponame.c_str()); if ( !test ) { reponame = string(HERWIG_PKGDATADIR) + '/' + reponame; } test.close(); #endif string msg = Repository::load(reponame); if ( ! msg.empty() ) cerr << msg << '\n'; // Repeated invocation of setSearchPaths is necessary since Repository::load revokes all setted paths. setSearchPaths(ui); breakThePEG(); if ( !ui.inputfile().empty() && ui.inputfile() != "-" ) { string msg = Repository::read(ui.inputfile(), std::cout); if ( ! msg.empty() ) cerr << msg << '\n'; } else { Repository::exitOnError() = 0; Repository::read(std::cin, std::cout, "Herwig> "); } } void HerwigGenericRun(const Herwig::HerwigUI & ui) { // If runMode is integration or run, we need a runname const string runname = ui.inputfile(); if (runname.empty() ) { std::cerr << "Error: You need to supply a runfile name.\n"; ui.quitWithHelp(); } if ( ui.integrationJob() && ui.jobs() > 1 ) { std::cerr << "parallel event generation is not applicable to integrate\n"; ui.quit(); } PersistentIStream is(runname); ThePEG::EGPtr eg; is >> eg; // debugging breakpoint breakThePEG(); if ( !eg ) { std::cerr << "Herwig: EventGenerator not available.\n" << "Check if '" << runname << "' is a valid run file.\n"; ui.quit(); } Herwig::RunDirectories::pushRunId(eg->runName()); if ( !ui.setupfile().empty() ) Herwig::RunDirectories::pushRunId(ui.setupfile()); if ( !ui.tag().empty() ) Herwig::RunDirectories::pushRunId(ui.tag()); - if ( !ui.integrationList().empty() ) - Herwig::RunDirectories::pushRunId(ui.integrationList()); if ( ui.seed() > 0 ) { ostringstream sseed; sseed << ui.seed(); Herwig::RunDirectories::pushRunId(sseed.str()); } + if ( !ui.integrationList().empty() ) + Herwig::RunDirectories::pushRunId(ui.integrationList()); + if ( ui.seed() > 0 ) eg->setSeed(ui.seed()); if ( !ui.setupfile().empty() ) eg->addTag("-" + ui.setupfile()); if ( !ui.tag().empty() ) eg->addTag("-" + ui.tag()); if ( ui.integrationJob() || ui.runMode() == Herwig::RunMode::MERGEGRIDS ) { Ptr<StandardEventHandler>::tptr eh = dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eg->eventHandler()); if ( !eh ) { std::cerr << "Herwig: Cannot enter sampler modes for a non-standard EventHandler.\n"; ui.quit(); } if ( ui.integrationJob() && !ui.integrationList().empty() ) eh->sampler()->integrationList(ui.integrationList()); if ( ui.runMode() == Herwig::RunMode::MERGEGRIDS ) { eh->sampler()->prepare(); return; } } if ( ! ui.setupfile().empty() ) { SamplerBase::setupFileUsed(); string msg = Repository::modifyEventGenerator(*eg, ui.setupfile(), cout, true); if ( ! msg.empty() ) cerr << msg << '\n'; if ( ui.integrationJob() ) return; } if ( ui.integrationJob() ) { Repository::resetEventGenerator(*eg); return; } if (ui.jobs() <= 1) { eg->go( ui.resume() ? -1 : 1, ui.N(), ui.tics() ); if ( ui.tics() ) std::cout << '\n'; } else { // forked jobs pid_t pid = 0; const int maxlen = log10(ui.jobs()) + 1; // make sure the parent got initialized once so e.g. grid combination is // working eg->initialize(true); for (int n=0; n<ui.jobs(); n++) { ostringstream tmp; tmp << std::setfill('0') << std::setw(maxlen) << n+1; const string nstr = tmp.str(); pid = fork(); if (pid == -1) { // fork failed std::perror("Herwig: fork"); ui.quit(); } else if ( pid == 0 ) { // we're the child if ( ui.tics() ) std::cout << "Forked child " << n << ", PID " << getpid() << std::endl; eg->setSeed( ui.seed() + n ); eg->addTag( "-" + nstr ); Herwig::RunDirectories::pushRunId( nstr ); eg->go( ui.resume() ? -1 : 1, ui.N() / ui.jobs(), false ); break; // avoid sub-forks } // nothing to do here if we're the parent } // children have nothing else to do if (pid == 0) return; if ( ui.tics() ) std::cout << "Waiting for forked jobs." << std::endl; int status; pid_t child; bool cleanrun = true; while (true) { child = wait(&status); if (child == -1) { if (errno == ECHILD) { if ( ui.tics() ) std::cout << "No more forked jobs." << std::endl; break; } else { std::perror("Herwig: waitpid"); ui.quit(); } } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) cleanrun = false; if ( ui.tics() ) std::cout << "PID " << child << " exited, status=" << WEXITSTATUS(status) << std::endl; } else if (WIFSIGNALED(status)) { // a clean SIGTERM is handled in the child // and will count as exit above, so... cleanrun = false; if ( ui.tics() ) std::cout << "PID " << child << " killed by signal " << WTERMSIG(status) << std::endl; } } if (! cleanrun) { ui.quit(); } } } } diff --git a/src/LEP-Matchbox.in b/src/LEP-Matchbox.in --- a/src/LEP-Matchbox.in +++ b/src/LEP-Matchbox.in @@ -1,140 +1,144 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Matchbox example input file ################################################## ################################################## ## Collider type ################################################## read Matchbox/EECollider.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 91.2*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. +## Model assumptions +read Matchbox/StandardModelLike.in +read Matchbox/DiagonalCKM.in + ## Set the order of the couplings cd /Herwig/MatrixElements/Matchbox set Factory:OrderInAlphaS 0 set Factory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do Factory:Process e- e+ -> j j ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in # read Matchbox/MadGraph-OpenLoops.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## ## cuts on additional jets # read Matchbox/DefaultEEJets.in # set NJetsCut:NJetsMin 3 ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/SHatScale ################################################## ## Matching and shower selection ################################################## read Matchbox/MCatNLO-DefaultShower.in # read Matchbox/Powheg-DefaultShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DefaultShower.in ## use for improved LO showering # read Matchbox/LO-DefaultShower.in # read Matchbox/MCatNLO-DipoleShower.in # read Matchbox/Powheg-DipoleShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DipoleShower.in ## use for improved LO showering # read Matchbox/LO-DipoleShower.in # read Matchbox/NLO-NoShower.in # read Matchbox/LO-NoShower.in ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## Analyses ################################################## # cd /Herwig/Analysis # insert Rivet:Analyses 0 XXX_2015_ABC123 # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC ################################################## ## Do not apply profile scales for LEP as hard ## scale coincides with kinematic limit ################################################## set /Herwig/Shower/ShowerHandler:HardScaleProfile NULL set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile NULL ################################################## ## Save the generator ################################################## do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode cd /Herwig/Generators saverun LEP-Matchbox EventGenerator diff --git a/src/LHC-Matchbox.in b/src/LHC-Matchbox.in --- a/src/LHC-Matchbox.in +++ b/src/LHC-Matchbox.in @@ -1,153 +1,157 @@ # -*- ThePEG-repository -*- ################################################## ## Herwig/Matchbox example input file ################################################## ################################################## ## Collider type ################################################## read Matchbox/PPCollider.in ################################################## ## Beam energy sqrt(s) ################################################## cd /Herwig/EventHandlers set EventHandler:LuminosityFunction:Energy 13000*GeV ################################################## ## Process selection ################################################## ## Note that event generation may fail if no matching matrix element has ## been found. Coupling orders are with respect to the Born process, ## i.e. NLO QCD does not require an additional power of alphas. +## Model assumptions +read Matchbox/StandardModelLike.in +read Matchbox/DiagonalCKM.in + ## Set the order of the couplings cd /Herwig/MatrixElements/Matchbox set Factory:OrderInAlphaS 0 set Factory:OrderInAlphaEW 2 ## Select the process ## You may use identifiers such as p, pbar, j, l, mu+, h0 etc. do Factory:Process p p -> e+ e- ## Special settings required for on-shell production of unstable particles ## enable for on-shell top production # read Matchbox/OnShellTopProduction.in ## enable for on-shell W, Z or h production # read Matchbox/OnShellWProduction.in # read Matchbox/OnShellZProduction.in # read Matchbox/OnShellHProduction.in # Special settings for the VBF approximation # read Matchbox/VBFDiagramsOnly.in ################################################## ## Matrix element library selection ################################################## ## Select a generic tree/loop combination or a ## specialized NLO package # read Matchbox/MadGraph-GoSam.in # read Matchbox/MadGraph-MadGraph.in # read Matchbox/MadGraph-NJet.in # read Matchbox/MadGraph-OpenLoops.in # read Matchbox/HJets.in # read Matchbox/VBFNLO.in ## Uncomment this to use ggh effective couplings ## currently only supported by MadGraph-GoSam # read Matchbox/HiggsEffective.in ################################################## ## Cut selection ## See the documentation for more options ################################################## set /Herwig/Cuts/ChargedLeptonPairMassCut:MinMass 60*GeV set /Herwig/Cuts/ChargedLeptonPairMassCut:MaxMass 120*GeV ## cuts on additional jets # read Matchbox/DefaultPPJets.in # insert JetCuts:JetRegions 0 FirstJet # insert JetCuts:JetRegions 1 SecondJet # insert JetCuts:JetRegions 2 ThirdJet # insert JetCuts:JetRegions 3 FourthJet ################################################## ## Scale choice ## See the documentation for more options ################################################## cd /Herwig/MatrixElements/Matchbox set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale ################################################## ## Matching and shower selection ## Please also see flavour scheme settings ## towards the end of the input file. ################################################## read Matchbox/MCatNLO-DefaultShower.in # read Matchbox/Powheg-DefaultShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DefaultShower.in ## use for improved LO showering # read Matchbox/LO-DefaultShower.in # read Matchbox/MCatNLO-DipoleShower.in # read Matchbox/Powheg-DipoleShower.in ## use for strict LO/NLO comparisons # read Matchbox/MCatLO-DipoleShower.in ## use for improved LO showering # read Matchbox/LO-DipoleShower.in # read Matchbox/NLO-NoShower.in # read Matchbox/LO-NoShower.in ################################################## ## Scale uncertainties ################################################## # read Matchbox/MuDown.in # read Matchbox/MuUp.in ################################################## ## Shower scale uncertainties ################################################## # read Matchbox/MuQDown.in # read Matchbox/MuQUp.in ################################################## ## PDF choice ################################################## read Matchbox/FiveFlavourScheme.in ## required for dipole shower and fixed order in five flavour scheme # read Matchbox/FiveFlavourNoBMassScheme.in read Matchbox/MMHT2014.in ################################################## ## Analyses ################################################## # cd /Herwig/Analysis # insert Rivet:Analyses 0 XXX_2015_ABC123 # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet # insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC ################################################## ## Save the generator ################################################## do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode cd /Herwig/Generators saverun LHC-Matchbox EventGenerator diff --git a/src/Matchbox/DiagonalCKM.in b/src/Matchbox/DiagonalCKM.in new file mode 100644 --- /dev/null +++ b/src/Matchbox/DiagonalCKM.in @@ -0,0 +1,6 @@ +# -*- ThePEG-repository -*- + +set /Herwig/MatrixElements/Matchbox/Factory:QuarkFlavourDiagonal Yes + +set /Herwig/Vertices/FFWMatchboxVertex:Diagonal Yes + diff --git a/src/Matchbox/MCatLO-DipoleShower.in.in b/src/Matchbox/MCatLO-DipoleShower.in.in --- a/src/Matchbox/MCatLO-DipoleShower.in.in +++ b/src/Matchbox/MCatLO-DipoleShower.in.in @@ -1,33 +1,30 @@ # -*- ThePEG-repository -*- read Matchbox/LO.in -set /Herwig/DipoleShower/Kinematics/IFLightKinematics:CollinearScheme On -set /Herwig/DipoleShower/Kinematics/IILightKinematics:CollinearScheme On - cd /Herwig/EventHandlers insert EventHandler:PreCascadeHandlers[0] /Herwig/Decays/DecayHandler set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace On set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme On diff --git a/src/Matchbox/MCatNLO-DipoleShower.in.in b/src/Matchbox/MCatNLO-DipoleShower.in.in --- a/src/Matchbox/MCatNLO-DipoleShower.in.in +++ b/src/Matchbox/MCatNLO-DipoleShower.in.in @@ -1,37 +1,34 @@ # -*- ThePEG-repository -*- cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler insert EventHandler:PreCascadeHandlers[0] /Herwig/Decays/DecayHandler -set /Herwig/DipoleShower/Kinematics/IFLightKinematics:CollinearScheme On -set /Herwig/DipoleShower/Kinematics/IILightKinematics:CollinearScheme On - set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace On set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/MatrixElements/Matchbox set Factory:ShowerApproximation DipoleMatching # tunes read Matchbox/MCatNLO-Dipole-HardAlphaSTune.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme On diff --git a/src/Matchbox/Makefile.am b/src/Matchbox/Makefile.am --- a/src/Matchbox/Makefile.am +++ b/src/Matchbox/Makefile.am @@ -1,69 +1,72 @@ BUILT_SOURCES = done-all-links Matchboxdir = ${pkgdatadir}/Matchbox INPUTFILES = \ DefaultEEJets.in \ DefaultEPJets.in \ DefaultPPJets.in \ EECollider.in \ EPCollider.in \ FiveFlavourScheme.in \ FiveFlavourNoBMassScheme.in \ FourFlavourScheme.in \ GenericCollider.in \ HiggsEffective.in \ HJets.in \ IdentifiedBs.in \ InclusiveDurhamJets.in \ IncreaseVerbosity.in \ LO-DefaultShower.in \ LO-DipoleShower.in \ MCatLO-DefaultShower.in \ MCatLO-DipoleShower.in \ LO.in \ LO-NoShower.in \ MadGraph-MadGraph.in \ GoSam-GoSam.in \ OpenLoops-OpenLoops.in \ MadGraph-GoSam.in \ MadGraph-NJet.in \ NJet-NJet.in \ MadGraph-OpenLoops.in \ MCatNLO-DefaultShower.in \ MCatNLO-DipoleShower.in \ MuDown.in \ MuQDown.in \ MuQUp.in \ MuUp.in \ NLO-NoShower.in \ OnShellHProduction.in \ OnShellWProduction.in \ OnShellZProduction.in \ OnShellTopProduction.in \ Powheg-DefaultShower.in \ Powheg-DipoleShower.in \ Powheg.in \ PPCollider.in \ PQCDLevel.in \ VBFNLO.in \ VBFNLOPhasespace.in \ VBFDiagramsOnly.in \ MMHT2014.in \ MCatNLO-Default-HardAlphaSTune.in \ MCatNLO-Default-ShowerAlphaSTune.in \ Powheg-Default-HardAlphaSTune.in \ Powheg-Default-ShowerAlphaSTune.in \ MCatNLO-Dipole-HardAlphaSTune.in \ -MCatNLO-Dipole-ShowerAlphaSTune.in +MCatNLO-Dipole-ShowerAlphaSTune.in \ +StandardModelLike.in \ +DiagonalCKM.in \ +NonDiagonalCKM.in dist_Matchbox_DATA = $(INPUTFILES) CLEANFILES = done-all-links done-all-links: $(INPUTFILES) @echo "Linking input files" @for i in $(INPUTFILES); do \ if test -f $(srcdir)/$$i -a ! -e $$i; then \ $(LN_S) -f $(srcdir)/$$i; fi; done @touch done-all-links diff --git a/src/Matchbox/NonDiagonalCKM.in b/src/Matchbox/NonDiagonalCKM.in new file mode 100644 --- /dev/null +++ b/src/Matchbox/NonDiagonalCKM.in @@ -0,0 +1,6 @@ +# -*- ThePEG-repository -*- + +set /Herwig/MatrixElements/Matchbox/Factory:QuarkFlavourDiagonal No + +set /Herwig/Vertices/FFWMatchboxVertex:Diagonal No + diff --git a/src/Matchbox/Powheg-DipoleShower.in.in b/src/Matchbox/Powheg-DipoleShower.in.in --- a/src/Matchbox/Powheg-DipoleShower.in.in +++ b/src/Matchbox/Powheg-DipoleShower.in.in @@ -1,33 +1,30 @@ # -*- ThePEG-repository -*- read Matchbox/Powheg.in set /Herwig/MatrixElements/Matchbox/MEMatching:TruncatedShower No cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler insert EventHandler:PreCascadeHandlers[0] /Herwig/Decays/DecayHandler -set /Herwig/DipoleShower/Kinematics/IFLightKinematics:CollinearScheme On -set /Herwig/DipoleShower/Kinematics/IILightKinematics:CollinearScheme On - set /Herwig/DipoleShower/DipoleShowerHandler:RestrictPhasespace On set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleProfile NULL cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so cd /Herwig/Particles do c:UnsetHardProcessMass do cbar:UnsetHardProcessMass set c:NominalMass 0*GeV set cbar:NominalMass 0*GeV cd /Herwig/UnderlyingEvent set MEQCD2to2Fast:StrictFlavourScheme On diff --git a/src/Matchbox/StandardModelLike.in b/src/Matchbox/StandardModelLike.in new file mode 100644 --- /dev/null +++ b/src/Matchbox/StandardModelLike.in @@ -0,0 +1,10 @@ +# -*- ThePEG-repository -*- + +set /Herwig/MatrixElements/Matchbox/Factory:EnforceChargeConservation Yes +set /Herwig/MatrixElements/Matchbox/Factory:EnforceColourConservation Yes + +set /Herwig/MatrixElements/Matchbox/Factory:EnforceLeptonNumberConservation Yes +set /Herwig/MatrixElements/Matchbox/Factory:EnforceQuarkNumberConservation Yes + +set /Herwig/MatrixElements/Matchbox/Factory:LeptonFlavourDiagonal Yes + diff --git a/src/defaults/MatchboxDefaults.in.in b/src/defaults/MatchboxDefaults.in.in --- a/src/defaults/MatchboxDefaults.in.in +++ b/src/defaults/MatchboxDefaults.in.in @@ -1,775 +1,774 @@ # -*- ThePEG-repository -*- ################################################################################ # # Default setup for Matchbox matrix element generation. # You do not need to make any change in here; processes of # interest can be chosen in the standard input files. # ################################################################################ ################################################################################ # Load libraries ################################################################################ library JetCuts.so library FastJetFinder.so library HwMatchboxScales.so library HwMatchboxCuts.so library HwSampling.so library HwColorFull.so library HwMatchboxBuiltin.so ################################################################################ # Integration/sampling ################################################################################ mkdir /Herwig/Samplers cd /Herwig/Samplers create Herwig::BinSampler FlatBinSampler set FlatBinSampler:InitialPoints 1000 set FlatBinSampler:UseAllIterations No create Herwig::CellGridSampler CellGridSampler set CellGridSampler:InitialPoints 10000 set CellGridSampler:ExplorationPoints 500 set CellGridSampler:ExplorationSteps 4 set CellGridSampler:Gain 0.3 set CellGridSampler:Epsilon 1.0 set CellGridSampler:MinimumSelection 0.000001 set CellGridSampler:NIterations 1 set CellGridSampler:EnhancementFactor 1 set CellGridSampler:UseAllIterations No set CellGridSampler:RemapperPoints 50000 set CellGridSampler:RemapperMinSelection 0.00001 set CellGridSampler:RemapChannelDimension Yes set CellGridSampler:LuminosityMapperBins 20 set CellGridSampler:GeneralMapperBins 0 set CellGridSampler:HalfPoints No set CellGridSampler:MaxNewMax 30 set CellGridSampler:NonZeroInPresampling Yes create Herwig::MonacoSampler MonacoSampler set MonacoSampler:InitialPoints 15000 set MonacoSampler:NIterations 4 set MonacoSampler:EnhancementFactor 1.2 set MonacoSampler:UseAllIterations No set MonacoSampler:RemapChannelDimension No set MonacoSampler:LuminosityMapperBins 0 set MonacoSampler:HalfPoints No set MonacoSampler:MaxNewMax 30 set MonacoSampler:NonZeroInPresampling Yes create Herwig::GeneralSampler Sampler set Sampler:UpdateAfter 1000 set Sampler:BinSampler CellGridSampler set Sampler:AddUpSamplers Off set Sampler:GlobalMaximumWeight Off set Sampler:FlatSubprocesses Off set Sampler:MinSelection 0.000001 set Sampler:AlmostUnweighted Off set Sampler:RunCombinationData Off set Sampler:WriteGridsOnFinish No set Sampler:MaxEnhancement 1.1 ################################################################################ # Setup the factory object ################################################################################ mkdir /Herwig/MatrixElements/Matchbox cd /Herwig/MatrixElements/Matchbox create Herwig::MatchboxFactory Factory do Factory:StartParticleGroup p insert Factory:ParticleGroup 0 /Herwig/Particles/b insert Factory:ParticleGroup 0 /Herwig/Particles/bbar insert Factory:ParticleGroup 0 /Herwig/Particles/c insert Factory:ParticleGroup 0 /Herwig/Particles/cbar insert Factory:ParticleGroup 0 /Herwig/Particles/s insert Factory:ParticleGroup 0 /Herwig/Particles/sbar insert Factory:ParticleGroup 0 /Herwig/Particles/d insert Factory:ParticleGroup 0 /Herwig/Particles/dbar insert Factory:ParticleGroup 0 /Herwig/Particles/u insert Factory:ParticleGroup 0 /Herwig/Particles/ubar insert Factory:ParticleGroup 0 /Herwig/Particles/g do Factory:EndParticleGroup do Factory:StartParticleGroup pbar insert Factory:ParticleGroup 0 /Herwig/Particles/b insert Factory:ParticleGroup 0 /Herwig/Particles/bbar insert Factory:ParticleGroup 0 /Herwig/Particles/c insert Factory:ParticleGroup 0 /Herwig/Particles/cbar insert Factory:ParticleGroup 0 /Herwig/Particles/s insert Factory:ParticleGroup 0 /Herwig/Particles/sbar insert Factory:ParticleGroup 0 /Herwig/Particles/d insert Factory:ParticleGroup 0 /Herwig/Particles/dbar insert Factory:ParticleGroup 0 /Herwig/Particles/u insert Factory:ParticleGroup 0 /Herwig/Particles/ubar insert Factory:ParticleGroup 0 /Herwig/Particles/g do Factory:EndParticleGroup do Factory:StartParticleGroup j insert Factory:ParticleGroup 0 /Herwig/Particles/b insert Factory:ParticleGroup 0 /Herwig/Particles/bbar insert Factory:ParticleGroup 0 /Herwig/Particles/c insert Factory:ParticleGroup 0 /Herwig/Particles/cbar insert Factory:ParticleGroup 0 /Herwig/Particles/s insert Factory:ParticleGroup 0 /Herwig/Particles/sbar insert Factory:ParticleGroup 0 /Herwig/Particles/d insert Factory:ParticleGroup 0 /Herwig/Particles/dbar insert Factory:ParticleGroup 0 /Herwig/Particles/u insert Factory:ParticleGroup 0 /Herwig/Particles/ubar insert Factory:ParticleGroup 0 /Herwig/Particles/g do Factory:EndParticleGroup do Factory:StartParticleGroup u insert Factory:ParticleGroup 0 /Herwig/Particles/u do Factory:EndParticleGroup do Factory:StartParticleGroup ubar insert Factory:ParticleGroup 0 /Herwig/Particles/ubar do Factory:EndParticleGroup do Factory:StartParticleGroup d insert Factory:ParticleGroup 0 /Herwig/Particles/d do Factory:EndParticleGroup do Factory:StartParticleGroup dbar insert Factory:ParticleGroup 0 /Herwig/Particles/dbar do Factory:EndParticleGroup do Factory:StartParticleGroup s insert Factory:ParticleGroup 0 /Herwig/Particles/s do Factory:EndParticleGroup do Factory:StartParticleGroup sbar insert Factory:ParticleGroup 0 /Herwig/Particles/sbar do Factory:EndParticleGroup do Factory:StartParticleGroup c insert Factory:ParticleGroup 0 /Herwig/Particles/c do Factory:EndParticleGroup do Factory:StartParticleGroup cbar insert Factory:ParticleGroup 0 /Herwig/Particles/cbar do Factory:EndParticleGroup do Factory:StartParticleGroup b insert Factory:ParticleGroup 0 /Herwig/Particles/b do Factory:EndParticleGroup do Factory:StartParticleGroup bbar insert Factory:ParticleGroup 0 /Herwig/Particles/bbar do Factory:EndParticleGroup do Factory:StartParticleGroup t insert Factory:ParticleGroup 0 /Herwig/Particles/t do Factory:EndParticleGroup do Factory:StartParticleGroup tbar insert Factory:ParticleGroup 0 /Herwig/Particles/tbar do Factory:EndParticleGroup do Factory:StartParticleGroup g insert Factory:ParticleGroup 0 /Herwig/Particles/g do Factory:EndParticleGroup do Factory:StartParticleGroup gamma insert Factory:ParticleGroup 0 /Herwig/Particles/gamma do Factory:EndParticleGroup do Factory:StartParticleGroup h0 insert Factory:ParticleGroup 0 /Herwig/Particles/h0 do Factory:EndParticleGroup do Factory:StartParticleGroup W+ insert Factory:ParticleGroup 0 /Herwig/Particles/W+ do Factory:EndParticleGroup do Factory:StartParticleGroup W- insert Factory:ParticleGroup 0 /Herwig/Particles/W- do Factory:EndParticleGroup do Factory:StartParticleGroup Z0 insert Factory:ParticleGroup 0 /Herwig/Particles/Z0 do Factory:EndParticleGroup do Factory:StartParticleGroup e+ insert Factory:ParticleGroup 0 /Herwig/Particles/e+ do Factory:EndParticleGroup do Factory:StartParticleGroup e- insert Factory:ParticleGroup 0 /Herwig/Particles/e- do Factory:EndParticleGroup do Factory:StartParticleGroup mu+ insert Factory:ParticleGroup 0 /Herwig/Particles/mu+ do Factory:EndParticleGroup do Factory:StartParticleGroup mu- insert Factory:ParticleGroup 0 /Herwig/Particles/mu- do Factory:EndParticleGroup do Factory:StartParticleGroup tau+ insert Factory:ParticleGroup 0 /Herwig/Particles/tau+ do Factory:EndParticleGroup do Factory:StartParticleGroup tau- insert Factory:ParticleGroup 0 /Herwig/Particles/tau- do Factory:EndParticleGroup do Factory:StartParticleGroup nu_e insert Factory:ParticleGroup 0 /Herwig/Particles/nu_e do Factory:EndParticleGroup do Factory:StartParticleGroup nu_mu insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mu do Factory:EndParticleGroup do Factory:StartParticleGroup nu_tau insert Factory:ParticleGroup 0 /Herwig/Particles/nu_tau do Factory:EndParticleGroup do Factory:StartParticleGroup nu_ebar insert Factory:ParticleGroup 0 /Herwig/Particles/nu_ebar do Factory:EndParticleGroup do Factory:StartParticleGroup nu_mubar insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mubar do Factory:EndParticleGroup do Factory:StartParticleGroup nu_taubar insert Factory:ParticleGroup 0 /Herwig/Particles/nu_taubar do Factory:EndParticleGroup do Factory:StartParticleGroup l insert Factory:ParticleGroup 0 /Herwig/Particles/e+ insert Factory:ParticleGroup 0 /Herwig/Particles/mu+ insert Factory:ParticleGroup 0 /Herwig/Particles/e- insert Factory:ParticleGroup 0 /Herwig/Particles/mu- do Factory:EndParticleGroup do Factory:StartParticleGroup nu insert Factory:ParticleGroup 0 /Herwig/Particles/nu_e insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mu insert Factory:ParticleGroup 0 /Herwig/Particles/nu_ebar insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mubar do Factory:EndParticleGroup do Factory:StartParticleGroup l+ insert Factory:ParticleGroup 0 /Herwig/Particles/e+ insert Factory:ParticleGroup 0 /Herwig/Particles/mu+ do Factory:EndParticleGroup do Factory:StartParticleGroup l- insert Factory:ParticleGroup 0 /Herwig/Particles/e- insert Factory:ParticleGroup 0 /Herwig/Particles/mu- do Factory:EndParticleGroup ################################################################################ # Default settings for hard process widths ################################################################################ set /Herwig/Particles/mu+:HardProcessWidth 0*GeV set /Herwig/Particles/mu-:HardProcessWidth 0*GeV set /Herwig/Particles/tau+:HardProcessWidth 0*GeV set /Herwig/Particles/tau-:HardProcessWidth 0*GeV ################################################################################ # Setup amplitudes ################################################################################ cd /Herwig/MatrixElements/Matchbox mkdir Amplitudes cd Amplitudes create ColorFull::TraceBasis TraceBasis create Herwig::MatchboxHybridAmplitude GenericProcesses @LOAD_MADGRAPH@ HwMatchboxMadGraph.so @CREATE_MADGRAPH@ Herwig::MadGraphAmplitude MadGraph @SET_MADGRAPH@ MadGraph:ColourBasis TraceBasis @LOAD_GOSAM@ HwMatchboxGoSam.so @CREATE_GOSAM@ Herwig::GoSamAmplitude GoSam @LOAD_NJET@ HwMatchboxNJet.so @CREATE_NJET@ Herwig::NJetsAmplitude NJet @DO_NJET@ NJet:Massless 5 @DO_NJET@ NJet:Massless -5 @LOAD_OPENLOOPS@ HwMatchboxOpenLoops.so @CREATE_OPENLOOPS@ Herwig::OpenLoopsAmplitude OpenLoops @LOAD_VBFNLO@ HwMatchboxVBFNLO.so @CREATE_VBFNLO@ Herwig::VBFNLOAmplitude VBFNLO mkdir Builtin cd Builtin create Herwig::SimpleColourBasis SimpleColourBasis create Herwig::SimpleColourBasis2 SimpleColourBasis2 create Herwig::MatchboxAmplitudellbarqqbar Amplitudellbarqqbar set Amplitudellbarqqbar:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudellbarqqbarg Amplitudellbarqqbarg set Amplitudellbarqqbarg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudellbarqqbargg Amplitudellbarqqbargg set Amplitudellbarqqbargg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudellbarqqbarqqbar Amplitudellbarqqbarqqbar set Amplitudellbarqqbarqqbar:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudelnuqqbar Amplitudelnuqqbar set Amplitudelnuqqbar:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudelnuqqbarg Amplitudelnuqqbarg set Amplitudelnuqqbarg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudelnuqqbargg Amplitudelnuqqbargg set Amplitudelnuqqbargg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudelnuqqbarqqbar Amplitudelnuqqbarqqbar set Amplitudelnuqqbarqqbar:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudehgg Amplitudehgg set Amplitudehgg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudehggg Amplitudehggg set Amplitudehggg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudehqqbarg Amplitudehqqbarg set Amplitudehqqbarg:ColourBasis SimpleColourBasis create Herwig::MatchboxAmplitudeqqbarttbar Amplitudeqqbarttbar set Amplitudeqqbarttbar:ColourBasis SimpleColourBasis2 create Herwig::MatchboxAmplitudeqqbarttbarg Amplitudeqqbarttbarg set Amplitudeqqbarttbarg:ColourBasis SimpleColourBasis2 create Herwig::MatchboxAmplitudeggttbar Amplitudeggttbar set Amplitudeggttbar:ColourBasis SimpleColourBasis2 create Herwig::MatchboxAmplitudeggttbarg Amplitudeggttbarg set Amplitudeggttbarg:ColourBasis SimpleColourBasis2 insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbarg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbargg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbarqqbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbarg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbargg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbarqqbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehgg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehggg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehqqbarg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeqqbarttbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeqqbarttbarg insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeggttbar insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeggttbarg ################################################################################ # Setup phasespace generators ################################################################################ cd /Herwig/MatrixElements/Matchbox mkdir Phasespace cd Phasespace create Herwig::PhasespaceCouplings PhasespaceCouplings create Herwig::MatchboxRambo Rambo set Rambo:CouplingData PhasespaceCouplings create Herwig::FlatInvertiblePhasespace InvertiblePhasespace set InvertiblePhasespace:CouplingData PhasespaceCouplings create Herwig::FlatInvertibleLabframePhasespace InvertibleLabframePhasespace set InvertibleLabframePhasespace:CouplingData PhasespaceCouplings set InvertibleLabframePhasespace:LogSHat False create Herwig::TreePhasespaceChannels TreePhasespaceChannels create Herwig::TreePhasespace TreePhasespace set TreePhasespace:ChannelMap TreePhasespaceChannels set TreePhasespace:M0 0.0001*GeV set TreePhasespace:MC 0.000001*GeV set TreePhasespace:CouplingData PhasespaceCouplings do TreePhasespace:SetPhysicalCoupling 21 -1 1 0.059 do TreePhasespace:SetPhysicalCoupling 21 -2 2 0.059 do TreePhasespace:SetPhysicalCoupling 21 -3 3 0.059 do TreePhasespace:SetPhysicalCoupling 21 -4 4 0.059 do TreePhasespace:SetPhysicalCoupling 21 -5 5 0.059 do TreePhasespace:SetPhysicalCoupling 21 -6 6 0.059 do TreePhasespace:SetPhysicalCoupling 21 1 -1 0.059 do TreePhasespace:SetPhysicalCoupling 21 2 -2 0.059 do TreePhasespace:SetPhysicalCoupling 21 3 -3 0.059 do TreePhasespace:SetPhysicalCoupling 21 4 -4 0.059 do TreePhasespace:SetPhysicalCoupling 21 5 -5 0.059 do TreePhasespace:SetPhysicalCoupling 21 6 -6 0.059 do TreePhasespace:SetPhysicalCoupling 1 21 1 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 2 21 2 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 3 21 3 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 4 21 4 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 5 21 5 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 6 21 6 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -1 21 -1 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -2 21 -2 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -3 21 -3 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -4 21 -4 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -5 21 -5 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -6 21 -6 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 1 1 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 2 2 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 3 3 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 4 4 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 5 5 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling 6 6 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -1 -1 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -2 -2 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -3 -3 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -4 -4 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -5 -5 21 0.15733333333333333333 do TreePhasespace:SetPhysicalCoupling -6 -6 21 0.15733333333333333333 do TreePhasespace:SetCoupling 25 -1 1 0 do TreePhasespace:SetCoupling 25 -2 2 0 do TreePhasespace:SetCoupling 25 -3 3 0.00000001184279069851 do TreePhasespace:SetCoupling 25 -4 4 0.00000205034465001885 do TreePhasespace:SetCoupling 25 -5 5 0.00002314757096085280 do TreePhasespace:SetCoupling 25 -6 6 0.03982017320025470767 do TreePhasespace:SetCoupling 25 -11 11 0.00000000000034264835 do TreePhasespace:SetCoupling 25 -12 12 0 do TreePhasespace:SetCoupling 25 -13 13 0.00000001464912263400 do TreePhasespace:SetCoupling 25 -14 14 0 do TreePhasespace:SetCoupling 25 -15 15 0.00000414359033108195 do TreePhasespace:SetCoupling 25 -16 16 0 do TreePhasespace:SetCoupling 22 -1 1 0.00083932358497608365 do TreePhasespace:SetCoupling 22 -2 2 0.00335729433990433461 do TreePhasespace:SetCoupling 22 -3 3 0.00083932358497608365 do TreePhasespace:SetCoupling 22 -4 4 0.00335729433990433461 do TreePhasespace:SetCoupling 22 -5 5 0.00083932358497608365 do TreePhasespace:SetCoupling 22 -6 6 0.00335729433990433461 do TreePhasespace:SetCoupling 22 -11 11 0.00755391226478475287 do TreePhasespace:SetCoupling 22 -13 13 0.00755391226478475287 do TreePhasespace:SetCoupling 22 -15 15 0.00755391226478475287 do TreePhasespace:SetCoupling 24 -2 1 0.01652748072644379386 do TreePhasespace:SetCoupling 24 -4 1 0.00382028458188709739 do TreePhasespace:SetCoupling 24 -6 1 0.00014707756360995175 do TreePhasespace:SetCoupling 24 -2 3 0.00382265953677814621 do TreePhasespace:SetCoupling 24 -4 3 0.01651340063673257587 do TreePhasespace:SetCoupling 24 -6 3 0.00068534412570265868 do TreePhasespace:SetCoupling 24 -2 5 0.00005954351191129535 do TreePhasespace:SetCoupling 24 -4 5 0.00069891529650865192 do TreePhasespace:SetCoupling 24 -6 5 0.01694947628265615369 do TreePhasespace:SetCoupling 24 -12 11 0.01696396350749155147 do TreePhasespace:SetCoupling 24 -14 13 0.01696396350749155147 do TreePhasespace:SetCoupling 24 -16 15 0.01696396350749155147 do TreePhasespace:SetCoupling -24 2 -1 0.01652748072644379386 do TreePhasespace:SetCoupling -24 4 -1 0.00382028458188709739 do TreePhasespace:SetCoupling -24 6 -1 0.00014707756360995175 do TreePhasespace:SetCoupling -24 2 -3 0.00382265953677814621 do TreePhasespace:SetCoupling -24 4 -3 0.01651340063673257587 do TreePhasespace:SetCoupling -24 6 -3 0.00068534412570265868 do TreePhasespace:SetCoupling -24 2 -5 0.00005954351191129535 do TreePhasespace:SetCoupling -24 4 -5 0.00069891529650865192 do TreePhasespace:SetCoupling -24 6 -5 0.01694947628265615369 do TreePhasespace:SetCoupling -24 12 -11 0.01696396350749155147 do TreePhasespace:SetCoupling -24 14 -13 0.01696396350749155147 do TreePhasespace:SetCoupling -24 16 -15 0.01696396350749155147 do TreePhasespace:SetCoupling 23 -1 1 0.00407649129960709158 do TreePhasespace:SetCoupling 23 -2 2 0.00317809816318353030 do TreePhasespace:SetCoupling 23 -3 3 0.00407649129960709158 do TreePhasespace:SetCoupling 23 -4 4 0.00317809816318353030 do TreePhasespace:SetCoupling 23 -5 5 0.00407649129960709158 do TreePhasespace:SetCoupling 23 -6 6 0.00317809816318353030 do TreePhasespace:SetCoupling 23 -11 11 0.00276049468148072129 do TreePhasespace:SetCoupling 23 -12 12 0.00545567409075140513 do TreePhasespace:SetCoupling 23 -13 13 0.00276049468148072129 do TreePhasespace:SetCoupling 23 -14 14 0.00545567409075140513 do TreePhasespace:SetCoupling 23 -15 15 0.00276049468148072129 do TreePhasespace:SetCoupling 23 -16 16 0.00545567409075140513 do TreePhasespace:SetCoupling 21 21 21 0.354 do TreePhasespace:SetCoupling 25 21 21 0.00000000016160437564 do TreePhasespace:SetCoupling 25 25 25 0.18719783125611995353 do TreePhasespace:SetCoupling 25 22 22 0.00000000006295673620 do TreePhasespace:SetCoupling 25 24 -24 219.30463760755686425818 do TreePhasespace:SetCoupling 25 23 23 362.91922658249853887524 do TreePhasespace:SetCoupling 22 24 -24 0.00755391226478475287 do TreePhasespace:SetCoupling 23 24 -24 0.02637401475019835008 @CREATE_VBFNLO@ Herwig::VBFNLOPhasespace VBFNLOPhasespace @SET_VBFNLO@ VBFNLOPhasespace:CouplingData PhasespaceCouplings set /Herwig/MatrixElements/Matchbox/Factory:Phasespace TreePhasespace ################################################################################ # Setup utilities for matching ################################################################################ cd /Herwig/MatrixElements/Matchbox create Herwig::HardScaleProfile HardScaleProfile create Herwig::MEMatching MEMatching set MEMatching:RestrictPhasespace On set MEMatching:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile set MEMatching:BornScaleInSubtraction BornScale set MEMatching:RealEmissionScaleInSubtraction RealScale set MEMatching:EmissionScaleInSubtraction RealScale set MEMatching:BornScaleInSplitting ShowerScale set MEMatching:RealEmissionScaleInSplitting ShowerScale set MEMatching:EmissionScaleInSplitting ShowerScale set MEMatching:TruncatedShower Yes set MEMatching:MaxPtIsMuF Yes set MEMatching:FFPtCut 1.0*GeV set MEMatching:FIPtCut 1.0*GeV set MEMatching:IIPtCut 1.0*GeV set MEMatching:SafeCut 0.*GeV create Herwig::ShowerApproximationGenerator MECorrectionHandler set MECorrectionHandler:ShowerApproximation MEMatching set MECorrectionHandler:Phasespace /Herwig/MatrixElements/Matchbox/Phasespace/InvertiblePhasespace set MECorrectionHandler:PresamplingPoints 50000 set MECorrectionHandler:FreezeGrid 100000 create Herwig::DipoleMatching DipoleMatching HwDipoleMatching.so # set in DipoleShowerDefaults.in as not available at this point # set DipoleMatching:ShowerHandler /Herwig/DipoleShower/DipoleShowerHandler set DipoleMatching:BornScaleInSubtraction BornScale set DipoleMatching:RealEmissionScaleInSubtraction BornScale set DipoleMatching:EmissionScaleInSubtraction BornScale set DipoleMatching:FFPtCut 1.0*GeV set DipoleMatching:FIPtCut 1.0*GeV set DipoleMatching:IIPtCut 1.0*GeV set DipoleMatching:SafeCut 4.*GeV create Herwig::QTildeMatching QTildeMatching HwQTildeMatching.so set QTildeMatching:ShowerHandler /Herwig/Shower/ShowerHandler set QTildeMatching:BornScaleInSubtraction BornScale set QTildeMatching:RealEmissionScaleInSubtraction BornScale set QTildeMatching:EmissionScaleInSubtraction BornScale set QTildeMatching:QTildeFinder /Herwig/Shower/PartnerFinder set QTildeMatching:SafeCut 4.*GeV # just a dummy, since SudakovCommonn can't be used # it's only used to get the value of the kinCutoffScale set QTildeMatching:QTildeSudakov /Herwig/Shower/QtoQGSudakov ################################################################################ # Setup utilities for process generation ################################################################################ cd /Herwig/MatrixElements/Matchbox mkdir Utility cd Utility create Herwig::Tree2toNGenerator DiagramGenerator insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFGVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/GGGVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFPVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFZVertex -cp /Herwig/Vertices/FFWVertex /Herwig/Vertices/FFWDiagonalVertex -set /Herwig/Vertices/FFWDiagonalVertex:Diagonal Yes -insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFWDiagonalVertex +cp /Herwig/Vertices/FFWVertex /Herwig/Vertices/FFWMatchboxVertex +insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFWMatchboxVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWHVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWWVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HGGVertex insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HHHVertex cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/TTHVertex set /Herwig/Vertices/TTHVertex:Fermion 6 insert DiagramGenerator:Vertices 0 /Herwig/Vertices/TTHVertex cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/BBHVertex set /Herwig/Vertices/BBHVertex:Fermion 5 create Herwig::ProcessData ProcessData set /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator DiagramGenerator set /Herwig/MatrixElements/Matchbox/Factory:ProcessData ProcessData ################################################################################ # Setup jet cuts ################################################################################ cd /Herwig/Cuts create Herwig::MatchboxFactoryMatcher MatchboxJetMatcher set MatchboxJetMatcher:Group j create ThePEG::FastJetFinder JetFinder set JetFinder:UnresolvedMatcher MatchboxJetMatcher set JetFinder:Variant AntiKt set JetFinder:RecombinationScheme E set JetFinder:Mode Inclusive set JetFinder:ConeRadius 0.7 create ThePEG::JetRegion FirstJet set FirstJet:PtMin 20.*GeV do FirstJet:YRange -5.0 5.0 set FirstJet:Fuzzy Yes set FirstJet:EnergyCutWidth 4.0*GeV set FirstJet:RapidityCutWidth 0.4 insert FirstJet:Accepts[0] 1 create ThePEG::JetRegion SecondJet set SecondJet:PtMin 20.*GeV do SecondJet:YRange -5.0 5.0 set SecondJet:Fuzzy Yes set SecondJet:EnergyCutWidth 4.0*GeV set SecondJet:RapidityCutWidth 0.4 insert SecondJet:Accepts[0] 2 create ThePEG::JetRegion ThirdJet set ThirdJet:PtMin 20.*GeV do ThirdJet:YRange -5.0 5.0 set ThirdJet:Fuzzy Yes set ThirdJet:EnergyCutWidth 4.0*GeV set ThirdJet:RapidityCutWidth 0.4 insert ThirdJet:Accepts[0] 3 create ThePEG::JetRegion FourthJet set FourthJet:PtMin 20.*GeV do FourthJet:YRange -5.0 5.0 set FourthJet:Fuzzy Yes set FourthJet:EnergyCutWidth 4.0*GeV set FourthJet:RapidityCutWidth 0.4 insert FourthJet:Accepts[0] 4 create ThePEG::FuzzyTheta FuzzyTheta set FuzzyTheta:EnergyWidth 4.0*GeV set FuzzyTheta:RapidityWidth 0.4 set FuzzyTheta:AngularWidth 0.4 create ThePEG::NJetsCut NJetsCut set NJetsCut:UnresolvedMatcher MatchboxJetMatcher set NJetsCut:NJetsMin 2 create ThePEG::JetCuts JetCuts set JetCuts:UnresolvedMatcher MatchboxJetMatcher set JetCuts:Ordering OrderPt create Herwig::IdentifiedParticleCut IdentifiedParticleCut cp IdentifiedParticleCut LeptonCut set LeptonCut:Matcher /Herwig/Matchers/Lepton cp IdentifiedParticleCut ChargedLeptonCut set ChargedLeptonCut:Matcher /Herwig/Matchers/ChargedLepton cp IdentifiedParticleCut TopQuarkCut set TopQuarkCut:Matcher /Herwig/Matchers/Top cp IdentifiedParticleCut WBosonCut set WBosonCut:Matcher /Herwig/Matchers/WBoson cp IdentifiedParticleCut ZBosonCut set ZBosonCut:Matcher /Herwig/Matchers/ZBoson cp IdentifiedParticleCut HiggsBosonCut set HiggsBosonCut:Matcher /Herwig/Matchers/HiggsBoson cp IdentifiedParticleCut PhotonCut set PhotonCut:Matcher /Herwig/Matchers/Photon create Herwig::FrixionePhotonSeparationCut PhotonIsolationCut set PhotonIsolationCut:UnresolvedMatcher MatchboxJetMatcher create Herwig::MatchboxDeltaRCut MatchboxDeltaRCut cp MatchboxDeltaRCut LeptonDeltaRCut set LeptonDeltaRCut:FirstMatcher /Herwig/Matchers/Lepton set LeptonDeltaRCut:SecondMatcher /Herwig/Matchers/Lepton cp MatchboxDeltaRCut ChargedLeptonDeltaRCut set ChargedLeptonDeltaRCut:FirstMatcher /Herwig/Matchers/ChargedLepton set ChargedLeptonDeltaRCut:SecondMatcher /Herwig/Matchers/ChargedLepton create Herwig::InvariantMassCut InvariantMassCut cp InvariantMassCut LeptonPairMassCut set LeptonPairMassCut:FirstMatcher /Herwig/Matchers/Lepton set LeptonPairMassCut:SecondMatcher /Herwig/Matchers/Lepton cp InvariantMassCut ChargedLeptonPairMassCut set ChargedLeptonPairMassCut:FirstMatcher /Herwig/Matchers/ChargedLepton set ChargedLeptonPairMassCut:SecondMatcher /Herwig/Matchers/ChargedLepton create Herwig::MissingPtCut MissingPtCut set MissingPtCut:Matcher /Herwig/Matchers/Neutrino ################################################################################ # Setup scale choices ################################################################################ cd /Herwig/MatrixElements/Matchbox mkdir Scales cd Scales create Herwig::MatchboxScaleChoice SHatScale cp SHatScale FixedScale set FixedScale:FixedScale 100.*GeV create Herwig::MatchboxPtScale MaxJetPtScale set MaxJetPtScale:JetFinder /Herwig/Cuts/JetFinder create Herwig::MatchboxLeptonMassScale LeptonPairMassScale create Herwig::MatchboxLeptonPtScale LeptonPairPtScale create Herwig::MatchboxHtScale HTScale create Herwig::MatchboxTopMassScale TopPairMassScale create Herwig::MatchboxTopMTScale TopPairMTScale set HTScale:JetFinder /Herwig/Cuts/JetFinder set HTScale:IncludeMT No cp HTScale HTPrimeScale set HTPrimeScale:IncludeMT Yes cp LeptonPairMassScale LeptonQ2Scale set /Herwig/MatrixElements/Matchbox/Factory:ScaleChoice LeptonPairMassScale ################################################################################ # Factories for different colliders # only provided for backwards compatibility; refer to Matchbox/*.in input file # snippets for generic handling ################################################################################ cd /Herwig/MatrixElements/Matchbox cp Factory EEFactory set EEFactory:PartonExtractor /Herwig/Partons/EEExtractor set EEFactory:Cuts /Herwig/Cuts/EECuts set EEFactory:FirstPerturbativePDF No set EEFactory:SecondPerturbativePDF No cp Factory DISFactory set DISFactory:PartonExtractor /Herwig/Partons/DISExtractor set DISFactory:Cuts /Herwig/Cuts/DISCuts set DISFactory:FirstPerturbativePDF No set DISFactory:SecondPerturbativePDF Yes cp Factory PPFactory set PPFactory:PartonExtractor /Herwig/Partons/QCDExtractor set PPFactory:Cuts /Herwig/Cuts/QCDCuts set PPFactory:FirstPerturbativePDF Yes set PPFactory:SecondPerturbativePDF Yes cd /